From 41ee8fd2265e533784b33c50ef1572ec776cc9ed Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Thu, 7 May 2020 13:37:53 +0200 Subject: [PATCH] MmuPlugin now support multiple stages, D$ can now take advantage of that --- src/main/scala/vexriscv/Services.scala | 5 +- src/main/scala/vexriscv/TestsWorkspace.scala | 6 ++- .../demo/smp/VexRiscvSmpCluster.scala | 5 +- src/main/scala/vexriscv/ip/DataCache.scala | 23 ++++---- .../scala/vexriscv/ip/InstructionCache.scala | 6 +-- .../vexriscv/plugin/DBusCachedPlugin.scala | 24 +++++++-- .../vexriscv/plugin/DBusSimplePlugin.scala | 7 +-- .../vexriscv/plugin/IBusCachedPlugin.scala | 4 +- .../vexriscv/plugin/IBusSimplePlugin.scala | 6 +-- .../plugin/MemoryTranslatorPlugin.scala | 12 ++--- .../scala/vexriscv/plugin/MmuPlugin.scala | 52 +++++++++++++------ .../plugin/StaticMemoryTranslatorPlugin.scala | 2 +- .../vexriscv/TestIndividualFeatures.scala | 7 +-- 13 files changed, 97 insertions(+), 62 deletions(-) diff --git a/src/main/scala/vexriscv/Services.scala b/src/main/scala/vexriscv/Services.scala index 5bf763e..51dbe6b 100644 --- a/src/main/scala/vexriscv/Services.scala +++ b/src/main/scala/vexriscv/Services.scala @@ -65,6 +65,7 @@ trait RegFileService{ case class MemoryTranslatorCmd() extends Bundle{ val isValid = Bool + val isStuck = Bool val virtualAddress = UInt(32 bits) val bypassTranslation = Bool } @@ -82,9 +83,9 @@ case class MemoryTranslatorRspWay() extends Bundle{ val physical = UInt(32 bits) } -case class MemoryTranslatorBusParameter(wayCount : Int) +case class MemoryTranslatorBusParameter(wayCount : Int = 0, latency : Int = 0) case class MemoryTranslatorBus(p : MemoryTranslatorBusParameter) extends Bundle with IMasterSlave{ - val cmd = MemoryTranslatorCmd() + val cmd = Vec(MemoryTranslatorCmd(), p.latency + 1) val rsp = MemoryTranslatorRsp(p) val end = Bool val busy = Bool diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index 40f8b33..b97936d 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -73,7 +73,8 @@ object TestsWorkspace { // ) ), memoryTranslatorPortConfig = MmuPortConfig( - portTlbSize = 4 + portTlbSize = 4, + latency = 0 ) ), // ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))), @@ -108,7 +109,8 @@ object TestsWorkspace { // ) ), memoryTranslatorPortConfig = MmuPortConfig( - portTlbSize = 4 + portTlbSize = 4, + latency = 1 ) ), diff --git a/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala b/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala index 2f694cc..3f23a23 100644 --- a/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala +++ b/src/main/scala/vexriscv/demo/smp/VexRiscvSmpCluster.scala @@ -193,7 +193,10 @@ object VexRiscvSmpClusterGen { // ) ), memoryTranslatorPortConfig = MmuPortConfig( - portTlbSize = 4 + portTlbSize = 4, + latency = 1, + earlyRequireMmuLockup = true, + earlyCacheHits = true ) ), diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index a99a929..2f2e8c2 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -128,15 +128,14 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{ case class DataCacheCpuMemory(p : DataCacheConfig, mmu : MemoryTranslatorBusParameter) extends Bundle with IMasterSlave{ val isValid = Bool val isStuck = Bool - val isRemoved = Bool val isWrite = Bool val address = UInt(p.addressWidth bit) - val mmuBus = MemoryTranslatorBus(mmu) + val mmuRsp = MemoryTranslatorRsp(mmu) override def asMaster(): Unit = { - out(isValid, isStuck, isRemoved, address) + out(isValid, isStuck, address) in(isWrite) - slave(mmuBus) + out(mmuRsp) } } @@ -619,10 +618,6 @@ class DataCache(val p : DataCacheConfig, mmuParameter : MemoryTranslatorBusParam def stagePipe[T <: Data](that : T) = if(mergeExecuteMemory) CombInit(that) else RegNextWhen(that, !io.cpu.memory.isStuck) val request = stagePipe(io.cpu.execute.args) val mask = stagePipe(stage0.mask) - io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid - io.cpu.memory.mmuBus.cmd.virtualAddress := io.cpu.memory.address - io.cpu.memory.mmuBus.cmd.bypassTranslation := False - io.cpu.memory.mmuBus.end := !io.cpu.memory.isStuck || io.cpu.memory.isRemoved io.cpu.memory.isWrite := request.wr val isAmo = if(withAmo) request.isAmo else False @@ -634,8 +629,8 @@ class DataCache(val p : DataCacheConfig, mmuParameter : MemoryTranslatorBusParam val o = CombInit(sync.w2o.busy) val i = CombInit(sync.w2i.busy) - val s = io.cpu.memory.mmuBus.rsp.isIoAccess ? o | w - val l = io.cpu.memory.mmuBus.rsp.isIoAccess ? i | r + val s = io.cpu.memory.mmuRsp.isIoAccess ? o | w + val l = io.cpu.memory.mmuRsp.isIoAccess ? i | r when(isAmo? (s || l) | (request.wr ? s | l)){ hazard := True @@ -647,15 +642,15 @@ class DataCache(val p : DataCacheConfig, mmuParameter : MemoryTranslatorBusParam val wayHits = earlyWaysHits generate Bits(wayCount bits) val indirectTlbHitGen = (earlyWaysHits && !directTlbHit) generate new Area { - wayHits := B(ways.map(way => (io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagsReadRsp.address && way.tagsReadRsp.valid))) + wayHits := B(ways.map(way => (io.cpu.memory.mmuRsp.physicalAddress(tagRange) === way.tagsReadRsp.address && way.tagsReadRsp.valid))) } val directTlbHitGen = (earlyWaysHits && directTlbHit) generate new Area { - val wayTlbHits = for (way <- ways) yield for (tlb <- io.cpu.memory.mmuBus.rsp.ways) yield { + val wayTlbHits = for (way <- ways) yield for (tlb <- io.cpu.memory.mmuRsp.ways) yield { way.tagsReadRsp.address === tlb.physical(tagRange) && tlb.sel } val translatedHits = B(wayTlbHits.map(_.orR)) val bypassHits = B(ways.map(_.tagsReadRsp.address === io.cpu.memory.address(tagRange))) - wayHits := (io.cpu.memory.mmuBus.rsp.bypassTranslation ? bypassHits | translatedHits) & B(ways.map(_.tagsReadRsp.valid)) + wayHits := (io.cpu.memory.mmuRsp.bypassTranslation ? bypassHits | translatedHits) & B(ways.map(_.tagsReadRsp.valid)) } val dataMux = earlyDataMux generate MuxOH(wayHits, ways.map(_.dataReadRsp)) @@ -673,7 +668,7 @@ class DataCache(val p : DataCacheConfig, mmuParameter : MemoryTranslatorBusParam def ramPipe[T <: Data](that : T) = if(mergeExecuteMemory) CombInit(that) else RegNextWhen(that, !io.cpu.writeBack.isStuck) val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck) val mmuRspFreeze = False - val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck && !mmuRspFreeze) + val mmuRsp = RegNextWhen(io.cpu.memory.mmuRsp, !io.cpu.writeBack.isStuck && !mmuRspFreeze) val tagsReadRsp = ways.map(w => ramPipe(w.tagsReadRsp)) val dataReadRsp = !earlyDataMux generate ways.map(w => ramPipe(w.dataReadRsp)) val wayInvalidate = stagePipe(stageA. wayInvalidate) diff --git a/src/main/scala/vexriscv/ip/InstructionCache.scala b/src/main/scala/vexriscv/ip/InstructionCache.scala index aedd6af..6053c0f 100644 --- a/src/main/scala/vexriscv/ip/InstructionCache.scala +++ b/src/main/scala/vexriscv/ip/InstructionCache.scala @@ -429,9 +429,9 @@ class InstructionCache(p : InstructionCacheConfig, mmuParameter : MemoryTranslat io.cpu.fetch.data := (if(p.bypassGen) (io.cpu.fetch.dataBypassValid ? io.cpu.fetch.dataBypass | cacheData) else cacheData) } - io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid - io.cpu.fetch.mmuBus.cmd.virtualAddress := io.cpu.fetch.pc - io.cpu.fetch.mmuBus.cmd.bypassTranslation := False + io.cpu.fetch.mmuBus.cmd.last.isValid := io.cpu.fetch.isValid + io.cpu.fetch.mmuBus.cmd.last.virtualAddress := io.cpu.fetch.pc + io.cpu.fetch.mmuBus.cmd.last.bypassTranslation := False io.cpu.fetch.mmuBus.end := !io.cpu.fetch.isStuck || io.cpu.fetch.isRemoved io.cpu.fetch.physicalAddress := io.cpu.fetch.mmuBus.rsp.physicalAddress diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 96e1b1b..f133616 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -170,6 +170,10 @@ class DBusCachedPlugin(val config : DataCacheConfig, import pipeline._ import pipeline.config._ + val twoStageMmu = mmuBus.p.latency match { + case 0 => false + case 1 => true + } val cache = new DataCache( this.config.copy( @@ -242,6 +246,12 @@ class DBusCachedPlugin(val config : DataCacheConfig, ) cache.io.cpu.execute.args.size := size + if(twoStageMmu) { + mmuBus.cmd(0).isValid := cache.io.cpu.execute.isValid + mmuBus.cmd(0).isStuck := arbitration.isStuck + mmuBus.cmd(0).virtualAddress := cache.io.cpu.execute.address + mmuBus.cmd(0).bypassTranslation := False + } cache.io.cpu.flush.valid := arbitration.isValid && input(MEMORY_MANAGMENT) cache.io.cpu.execute.args.totalyConsistent := input(MEMORY_FORCE_CONSTISTENCY) @@ -281,11 +291,15 @@ class DBusCachedPlugin(val config : DataCacheConfig, cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE) cache.io.cpu.memory.isStuck := arbitration.isStuck - cache.io.cpu.memory.isRemoved := arbitration.removeIt cache.io.cpu.memory.address := (if(relaxedMemoryTranslationRegister) input(MEMORY_VIRTUAL_ADDRESS) else if(mmuAndBufferStage == execute) cache.io.cpu.execute.address else U(input(REGFILE_WRITE_DATA))) - cache.io.cpu.memory.mmuBus <> mmuBus - cache.io.cpu.memory.mmuBus.rsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite) + mmuBus.cmd.last.isValid := cache.io.cpu.memory.isValid + mmuBus.cmd.last.isStuck := cache.io.cpu.memory.isStuck + mmuBus.cmd.last.virtualAddress := cache.io.cpu.memory.address + mmuBus.cmd.last.bypassTranslation := False + mmuBus.end := !arbitration.isStuck || arbitration.removeIt + cache.io.cpu.memory.mmuRsp := mmuBus.rsp + cache.io.cpu.memory.mmuRsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite) } val managementStage = stages.last @@ -397,9 +411,9 @@ class DBusCachedPlugin(val config : DataCacheConfig, } } execute.insert(IS_DBUS_SHARING) := dBusAccess.cmd.fire + mmuBus.cmd.last.bypassTranslation setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING)) + if(twoStageMmu) mmuBus.cmd(0).bypassTranslation setWhen(execute.input(IS_DBUS_SHARING)) - - mmuBus.cmd.bypassTranslation setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING)) if(mmuAndBufferStage != execute) (cache.io.cpu.memory.isValid setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING))) cache.io.cpu.writeBack.isValid setWhen(managementStage.input(IS_DBUS_SHARING)) dBusAccess.rsp.valid := managementStage.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt) diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala index 819fc8f..ba896fa 100644 --- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala @@ -449,9 +449,10 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, insert(FORMAL_MEM_WDATA) := dBus.cmd.payload.data val mmu = (mmuBus != null) generate new Area { - mmuBus.cmd.isValid := arbitration.isValid && input(MEMORY_ENABLE) - mmuBus.cmd.virtualAddress := input(SRC_ADD).asUInt - mmuBus.cmd.bypassTranslation := False + mmuBus.cmd.last.isValid := arbitration.isValid && input(MEMORY_ENABLE) + mmuBus.cmd.last.isStuck := arbitration.isStuck + mmuBus.cmd.last.virtualAddress := input(SRC_ADD).asUInt + mmuBus.cmd.last.bypassTranslation := False mmuBus.end := !arbitration.isStuck || arbitration.isRemoved dBus.cmd.address := mmuBus.rsp.physicalAddress diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index be08cda..4d41790 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -124,7 +124,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, import pipeline.config._ pipeline plug new FetchArea(pipeline) { - val cache = new InstructionCache(IBusCachedPlugin.this.config.copy(bypassGen = tightlyGen), mmuBus.p) + val cache = new InstructionCache(IBusCachedPlugin.this.config.copy(bypassGen = tightlyGen), if(mmuBus != null) mmuBus.p else MemoryTranslatorBusParameter(0,0)) iBus = master(new InstructionCacheMemBus(IBusCachedPlugin.this.config)).setName("iBus") iBus <> cache.io.mem iBus.cmd.address.allowOverride := cache.io.mem.cmd.address @@ -251,7 +251,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, if (mmuBus != null) { cache.io.cpu.fetch.mmuBus <> mmuBus } else { - cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress + cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.last.virtualAddress cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True cache.io.cpu.fetch.mmuBus.rsp.allowRead := True cache.io.cpu.fetch.mmuBus.rsp.allowWrite := True diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index b8bc978..19145f5 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -318,9 +318,9 @@ class IBusSimplePlugin( resetVector : BigInt, } val mmu = (mmuBus != null) generate new Area { - mmuBus.cmd.isValid := cmdForkStage.input.valid - mmuBus.cmd.virtualAddress := cmdForkStage.input.payload - mmuBus.cmd.bypassTranslation := False + mmuBus.cmd.last.isValid := cmdForkStage.input.valid + mmuBus.cmd.last.virtualAddress := cmdForkStage.input.payload + mmuBus.cmd.last.bypassTranslation := False mmuBus.end := cmdForkStage.output.fire || externalFlush cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ U"00" diff --git a/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala b/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala index c8c00ec..081b11d 100644 --- a/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala +++ b/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala @@ -70,17 +70,17 @@ class MemoryTranslatorPlugin(tlbSize : Int, val ports = for ((port, portId) <- sortedPortsInfo.zipWithIndex) yield new Area { val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize) - val cacheHits = cache.map(line => line.valid && line.virtualAddress === port.bus.cmd.virtualAddress(31 downto 12)) + val cacheHits = cache.map(line => line.valid && line.virtualAddress === port.bus.cmd.last.virtualAddress(31 downto 12)) val cacheHit = cacheHits.asBits.orR val cacheLine = MuxOH(cacheHits, cache) - val isInMmuRange = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation + val isInMmuRange = virtualRange(port.bus.cmd.last.virtualAddress) && !port.bus.cmd.last.bypassTranslation val sharedMiss = RegInit(False) val sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits)) val sharedAccessed = RegInit(B"00") val entryToReplace = Counter(port.args.portTlbSize) - val sharedAccessAsked = RegNext(port.bus.cmd.isValid && !cacheHit && sharedIterator < tlbSize && isInMmuRange) + val sharedAccessAsked = RegNext(port.bus.cmd.last.isValid && !cacheHit && sharedIterator < tlbSize && isInMmuRange) val sharedAccessGranted = sharedAccessAsked && shared.free when(sharedAccessGranted) { shared.readAddr := sharedIterator.resized @@ -92,7 +92,7 @@ class MemoryTranslatorPlugin(tlbSize : Int, } when(sharedAccessed.msb){ - when(shared.readData.virtualAddress === port.bus.cmd.virtualAddress(31 downto 12)){ + when(shared.readData.virtualAddress === port.bus.cmd.last.virtualAddress(31 downto 12)){ cache(entryToReplace) := shared.readData entryToReplace.increment() } @@ -108,7 +108,7 @@ class MemoryTranslatorPlugin(tlbSize : Int, when(isInMmuRange) { - port.bus.rsp.physicalAddress := cacheLine.physicalAddress @@ port.bus.cmd.virtualAddress(11 downto 0) + port.bus.rsp.physicalAddress := cacheLine.physicalAddress @@ port.bus.cmd.last.virtualAddress(11 downto 0) port.bus.rsp.allowRead := cacheLine.allowRead port.bus.rsp.allowWrite := cacheLine.allowWrite port.bus.rsp.allowExecute := cacheLine.allowExecute @@ -116,7 +116,7 @@ class MemoryTranslatorPlugin(tlbSize : Int, // port.bus.rsp.hit := cacheHit // port.stage.arbitration.haltItself setWhen (port.bus.cmd.isValid && !cacheHit && !sharedMiss) } otherwise { - port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress + port.bus.rsp.physicalAddress := port.bus.cmd.last.virtualAddress port.bus.rsp.allowRead := True port.bus.rsp.allowWrite := True port.bus.rsp.allowExecute := True diff --git a/src/main/scala/vexriscv/plugin/MmuPlugin.scala b/src/main/scala/vexriscv/plugin/MmuPlugin.scala index 884a2d5..e797bcf 100644 --- a/src/main/scala/vexriscv/plugin/MmuPlugin.scala +++ b/src/main/scala/vexriscv/plugin/MmuPlugin.scala @@ -34,9 +34,9 @@ object MmuPort{ val PRIORITY_DATA = 1 val PRIORITY_INSTRUCTION = 0 } -case class MmuPort(bus : MemoryTranslatorBus, priority : Int, args : MmuPortConfig, id : Int/*, exceptionBus: Flow[ExceptionCause]*/) +case class MmuPort(bus : MemoryTranslatorBus, priority : Int, args : MmuPortConfig, id : Int) -case class MmuPortConfig(portTlbSize : Int) +case class MmuPortConfig(portTlbSize : Int, latency : Int = 0, earlyRequireMmuLockup : Boolean = false, earlyCacheHits : Boolean = false) class MmuPlugin(ioRange : UInt => Bool, virtualRange : UInt => Bool = address => True, @@ -48,7 +48,7 @@ class MmuPlugin(ioRange : UInt => Bool, override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = { val config = args.asInstanceOf[MmuPortConfig] - val port = MmuPort(MemoryTranslatorBus(MemoryTranslatorBusParameter(wayCount = config.portTlbSize)),priority, config, portsInfo.length) + val port = MmuPort(MemoryTranslatorBus(MemoryTranslatorBusParameter(wayCount = config.portTlbSize, latency = config.latency)),priority, config, portsInfo.length) portsInfo += port port.bus } @@ -103,33 +103,51 @@ class MmuPlugin(ioRange : UInt => Bool, val ports = for (port <- sortedPortsInfo) yield new Area { val handle = port val id = port.id - val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize) - val cacheHits = cache.map(line => line.valid && line.virtualAddress(1) === port.bus.cmd.virtualAddress(31 downto 22) && (line.superPage || line.virtualAddress(0) === port.bus.cmd.virtualAddress(21 downto 12))) - val cacheHit = cacheHits.asBits.orR - val cacheLine = MuxOH(cacheHits, cache) val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault()) - val entryToReplace = Counter(port.args.portTlbSize) - val requireMmuLockup = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation && csr.satp.mode + val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize) + + def toRsp[T <: Data](data : T, from : MemoryTranslatorCmd) : T = from match { + case _ if from == port.bus.cmd.last => data + case _ => { + val next = port.bus.cmd.dropWhile(_ != from)(1) + toRsp(RegNextWhen(data, !next.isStuck), next) + } + } + val requireMmuLockupCmd = port.bus.cmd.takeRight(if(port.args.earlyRequireMmuLockup) 2 else 1).head + + val requireMmuLockupCalc = virtualRange(requireMmuLockupCmd.virtualAddress) && !requireMmuLockupCmd.bypassTranslation && csr.satp.mode if(!enableMmuInMachineMode) { - requireMmuLockup clearWhen(!csr.status.mprv && privilegeService.isMachine()) + requireMmuLockupCalc clearWhen(!csr.status.mprv && privilegeService.isMachine()) when(privilegeService.isMachine()) { if (port.priority == MmuPort.PRIORITY_DATA) { - requireMmuLockup clearWhen (!csr.status.mprv || pipeline(MPP) === 3) + requireMmuLockupCalc clearWhen (!csr.status.mprv || pipeline(MPP) === 3) } else { - requireMmuLockup := False + requireMmuLockupCalc := False } } } + val cacheHitsCmd = port.bus.cmd.takeRight(if(port.args.earlyCacheHits) 2 else 1).head + val cacheHitsCalc = B(cache.map(line => line.valid && line.virtualAddress(1) === cacheHitsCmd.virtualAddress(31 downto 22) && (line.superPage || line.virtualAddress(0) === cacheHitsCmd.virtualAddress(21 downto 12)))) + + + val requireMmuLockup = toRsp(requireMmuLockupCalc, requireMmuLockupCmd) + val cacheHits = toRsp(cacheHitsCalc, cacheHitsCmd) + + val cacheHit = cacheHits.asBits.orR + val cacheLine = MuxOH(cacheHits, cache) + val entryToReplace = Counter(port.args.portTlbSize) + + when(requireMmuLockup) { - port.bus.rsp.physicalAddress := cacheLine.physicalAddress(1) @@ (cacheLine.superPage ? port.bus.cmd.virtualAddress(21 downto 12) | cacheLine.physicalAddress(0)) @@ port.bus.cmd.virtualAddress(11 downto 0) + port.bus.rsp.physicalAddress := cacheLine.physicalAddress(1) @@ (cacheLine.superPage ? port.bus.cmd.last.virtualAddress(21 downto 12) | cacheLine.physicalAddress(0)) @@ port.bus.cmd.last.virtualAddress(11 downto 0) port.bus.rsp.allowRead := cacheLine.allowRead || csr.status.mxr && cacheLine.allowExecute port.bus.rsp.allowWrite := cacheLine.allowWrite port.bus.rsp.allowExecute := cacheLine.allowExecute port.bus.rsp.exception := cacheHit && (cacheLine.exception || cacheLine.allowUser && privilegeService.isSupervisor() && !csr.status.sum || !cacheLine.allowUser && privilegeService.isUser()) port.bus.rsp.refilling := !cacheHit } otherwise { - port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress + port.bus.rsp.physicalAddress := port.bus.cmd.last.virtualAddress port.bus.rsp.allowRead := True port.bus.rsp.allowWrite := True port.bus.rsp.allowExecute := True @@ -141,7 +159,7 @@ class MmuPlugin(ioRange : UInt => Bool, port.bus.rsp.bypassTranslation := !requireMmuLockup for(wayId <- 0 until port.args.portTlbSize){ port.bus.rsp.ways(wayId).sel := cacheHits(wayId) - port.bus.rsp.ways(wayId).physical := cache(wayId).physicalAddress(1) @@ (cache(wayId).superPage ? port.bus.cmd.virtualAddress(21 downto 12) | cache(wayId).physicalAddress(0)) @@ port.bus.cmd.virtualAddress(11 downto 0) + port.bus.rsp.ways(wayId).physical := cache(wayId).physicalAddress(1) @@ (cache(wayId).superPage ? port.bus.cmd.last.virtualAddress(21 downto 12) | cache(wayId).physicalAddress(0)) @@ port.bus.cmd.last.virtualAddress(11 downto 0) } // Avoid keeping any invalid line in the cache after an exception. @@ -186,13 +204,13 @@ class MmuPlugin(ioRange : UInt => Bool, dBusAccess.cmd.data.assignDontCare() dBusAccess.cmd.writeMask.assignDontCare() - val refills = OHMasking.last(B(sortedPortsInfo.map(port => port.bus.cmd.isValid && port.bus.rsp.refilling))) + val refills = OHMasking.last(B(sortedPortsInfo.map(port => port.bus.cmd.last.isValid && port.bus.rsp.refilling))) switch(state){ is(State.IDLE){ when(refills.orR){ portSortedOh := refills state := State.L1_CMD - val address = MuxOH(refills, sortedPortsInfo.map(_.bus.cmd.virtualAddress)) + val address = MuxOH(refills, sortedPortsInfo.map(_.bus.cmd.last.virtualAddress)) vpn(1) := address(31 downto 22) vpn(0) := address(21 downto 12) } diff --git a/src/main/scala/vexriscv/plugin/StaticMemoryTranslatorPlugin.scala b/src/main/scala/vexriscv/plugin/StaticMemoryTranslatorPlugin.scala index cbe55f9..bc910c0 100644 --- a/src/main/scala/vexriscv/plugin/StaticMemoryTranslatorPlugin.scala +++ b/src/main/scala/vexriscv/plugin/StaticMemoryTranslatorPlugin.scala @@ -26,7 +26,7 @@ class StaticMemoryTranslatorPlugin(ioRange : UInt => Bool) extends Plugin[VexRis val core = pipeline plug new Area { val ports = for ((port, portId) <- portsInfo.zipWithIndex) yield new Area { - port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress + port.bus.rsp.physicalAddress := port.bus.cmd.last.virtualAddress port.bus.rsp.allowRead := True port.bus.rsp.allowWrite := True port.bus.rsp.allowExecute := True diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index c31a30a..33a3857 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -405,13 +405,12 @@ class DBusDimension extends VexRiscvDimension("DBus") { override def randomPositionImpl(universes: Seq[ConfigUniverse], r: Random) = { val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL) - val mmuConfig = if(universes.contains(VexRiscvUniverse.MMU)) MmuPortConfig( portTlbSize = 4) else null val noMemory = universes.contains(VexRiscvUniverse.NO_MEMORY) val noWriteBack = universes.contains(VexRiscvUniverse.NO_WRITEBACK) - if(r.nextDouble() < 0.4 || noMemory){ + val mmuConfig = if(universes.contains(VexRiscvUniverse.MMU)) MmuPortConfig( portTlbSize = 4, latency = 0) else null val withLrSc = catchAll val earlyInjection = r.nextBoolean() && !universes.contains(VexRiscvUniverse.NO_WRITEBACK) new VexRiscvPosition("Simple" + (if(earlyInjection) "Early" else "Late")) { @@ -426,6 +425,8 @@ class DBusDimension extends VexRiscvDimension("DBus") { // override def isCompatibleWith(positions: Seq[ConfigPosition[VexRiscvConfig]]) = catchAll == positions.exists(_.isInstanceOf[CatchAllPosition]) } } else { + val twoStageMmu = r.nextBoolean() && !noMemory && !noWriteBack + val mmuConfig = if(universes.contains(VexRiscvUniverse.MMU)) MmuPortConfig(portTlbSize = 4, latency = if(twoStageMmu) 1 else 0, earlyRequireMmuLockup = Random.nextBoolean() && twoStageMmu, earlyCacheHits = Random.nextBoolean() && twoStageMmu) else null val memDataWidth = List(32,64,128)(r.nextInt(3)) val bytePerLine = Math.max(memDataWidth/8, List(8,16,32,64)(r.nextInt(4))) var cacheSize = 0 @@ -443,7 +444,7 @@ class DBusDimension extends VexRiscvDimension("DBus") { cacheSize = 512 << r.nextInt(5) wayCount = 1 << r.nextInt(3) }while(cacheSize/wayCount < 512 || (catchAll && cacheSize/wayCount > 4096)) - new VexRiscvPosition(s"Cached${memDataWidth}d" + "S" + cacheSize + "W" + wayCount + "BPL" + bytePerLine + (if(dBusCmdMasterPipe) "Cmp " else "") + (if(dBusCmdSlavePipe) "Csp " else "") + (if(dBusRspSlavePipe) "Rsp " else "") + (if(relaxedMemoryTranslationRegister) "Rmtr " else "") + (if(earlyWaysHits) "Ewh " else "") + (if(withAmo) "Amo " else "") + (if(withSmp) "Smp " else "") + (if(directTlbHit) "Dtlb " else "")) { + new VexRiscvPosition(s"Cached${memDataWidth}d" + "S" + cacheSize + "W" + wayCount + "BPL" + bytePerLine + (if(dBusCmdMasterPipe) "Cmp " else "") + (if(dBusCmdSlavePipe) "Csp " else "") + (if(dBusRspSlavePipe) "Rsp " else "") + (if(relaxedMemoryTranslationRegister) "Rmtr " else "") + (if(earlyWaysHits) "Ewh " else "") + (if(withAmo) "Amo " else "") + (if(withSmp) "Smp " else "") + (if(directTlbHit) "Dtlb " else "") + (if(twoStageMmu) "Tsmmu " else "")) { override def testParam = s"DBUS=CACHED DBUS_DATA_WIDTH=$memDataWidth " + (if(withLrSc) "LRSC=yes " else "") + (if(withAmo) "AMO=yes " else "") + (if(withSmp) "DBUS_EXCLUSIVE=yes DBUS_INVALIDATE=yes " else "") override def applyOn(config: VexRiscvConfig): Unit = {