From 6922f80a87c140ce1cf7f878eff276d29dc6e6a9 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Wed, 8 Apr 2020 18:12:13 +0200 Subject: [PATCH] DataCache now implement fence operations --- src/main/scala/vexriscv/ip/DataCache.scala | 10 +++++- .../vexriscv/plugin/DBusCachedPlugin.scala | 35 ++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index a69f897..85d7d0c 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -31,6 +31,7 @@ case class DataCacheConfig(cacheSize : Int, mergeExecuteMemory : Boolean = false){ assert(!(mergeExecuteMemory && (earlyDataMux || earlyWaysHits))) assert(!(earlyDataMux && !earlyWaysHits)) + def withWriteResponse = withExclusive def burstSize = bytePerLine*8/memDataWidth val burstLength = bytePerLine/(memDataWidth/8) def catchSomething = catchUnaligned || catchIllegal || catchAccessError @@ -95,9 +96,10 @@ case class DataCacheCpuExecute(p : DataCacheConfig) extends Bundle with IMasterS val address = UInt(p.addressWidth bit) val haltIt = Bool val args = DataCacheCpuExecuteArgs(p) + val fence = Bool() override def asMaster(): Unit = { - out(isValid, args, address) + out(isValid, args, address, fence) in(haltIt) } } @@ -490,6 +492,12 @@ class DataCache(p : DataCacheConfig) extends Component{ ) |<< io.cpu.execute.address(1 downto 0) val dataColisions = collisionProcess(io.cpu.execute.address(lineRange.high downto wordRange.low), mask) val wayInvalidate = B(0, wayCount bits) //Used if invalidate enabled + + if(withWriteResponse) when(io.cpu.execute.fence){ + when(pending.counter =/= 0 || io.cpu.memory.isValid || io.cpu.writeBack.isValid){ + io.cpu.execute.haltIt := True + } + } } val stageA = new Area{ diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 7df58ce..0d7c930 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -50,6 +50,8 @@ class DBusCachedPlugin(val config : DataCacheConfig, object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits)) object MEMORY_LRSC extends Stageable(Bool) object MEMORY_AMO extends Stageable(Bool) + object MEMORY_FENCE extends Stageable(Bool) + object MEMORY_FENCE_DECODED extends Stageable(Bool) object IS_DBUS_SHARING extends Stageable(Bool()) object MEMORY_VIRTUAL_ADDRESS extends Stageable(UInt(32 bits)) @@ -143,7 +145,13 @@ class DBusCachedPlugin(val config : DataCacheConfig, MEMORY_MANAGMENT -> True )) - decoderService.add(FENCE, Nil) + withWriteResponse match { + case false => decoderService.add(FENCE, Nil) + case true => { + decoderService.addDefault(MEMORY_FENCE, False) + decoderService.add(FENCE, List(MEMORY_FENCE -> True)) + } + } mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig) redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.writeBack != null) pipeline.writeBack else pipeline.memory) @@ -189,6 +197,30 @@ class DBusCachedPlugin(val config : DataCacheConfig, when(mmuBus.busy && arbitration.isValid && input(MEMORY_ENABLE)) { arbitration.haltItself := True } + + case class FenceFlags() extends Bundle { + val SW,SR,SO,SI,PW,PR,PO,PI = Bool() + val FM = Bits(4 bits) + + def SL = SR || SI + def SS = SW || SO + def PL = PR || PI + def PS = PW || PO + } + + val fence = new Area{ + val hazard = False + val ff = input(INSTRUCTION)(31 downto 20).as(FenceFlags()) + if(withWriteResponse){ + hazard setWhen(input(MEMORY_FENCE) && (ff.PS && ff.SL)) //Manage write to read hit ordering (ensure invalidation timings) +// Not required as LR SC AMO naturaly enforce ordering +// when(input(INSTRUCTION)(26 downto 25) =/= 0){ +// if(withLrSc) hazard setWhen(input(MEMORY_LRSC)) +// if(withAmo) hazard setWhen(input(MEMORY_AMO)) +// } + } + insert(MEMORY_FENCE_DECODED) := hazard + } } execute plug new Area { @@ -207,6 +239,7 @@ class DBusCachedPlugin(val config : DataCacheConfig, cache.io.cpu.flush.valid := arbitration.isValid && input(MEMORY_MANAGMENT) + cache.io.cpu.execute.fence := arbitration.isValid && input(MEMORY_FENCE_DECODED) arbitration.haltItself setWhen(cache.io.cpu.flush.isStall || cache.io.cpu.execute.haltIt) if(withLrSc) {