diff --git a/src/main/scala/vexriscv/ip/InstructionCache.scala b/src/main/scala/vexriscv/ip/InstructionCache.scala index 6053c0f..43f5130 100644 --- a/src/main/scala/vexriscv/ip/InstructionCache.scala +++ b/src/main/scala/vexriscv/ip/InstructionCache.scala @@ -112,16 +112,15 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig, mmuParameter : M val data = Bits(p.cpuDataWidth bits) val dataBypassValid = p.bypassGen generate Bool() val dataBypass = p.bypassGen generate Bits(p.cpuDataWidth bits) - val mmuBus = MemoryTranslatorBus(mmuParameter) + val mmuRsp = MemoryTranslatorRsp(mmuParameter) val physicalAddress = UInt(p.addressWidth bits) val cacheMiss, error, mmuRefilling, mmuException, isUser = ifGen(!p.twoCycleCache)(Bool) - val haltIt = Bool() //Used to wait on the MMU rsp busy override def asMaster(): Unit = { out(isValid, isStuck, isRemoved, pc) - inWithNull(error,mmuRefilling,mmuException,data, cacheMiss,physicalAddress, haltIt) + inWithNull(error,mmuRefilling,mmuException,data, cacheMiss,physicalAddress) outWithNull(isUser, dataBypass, dataBypassValid) - slaveWithNull(mmuBus) + out(mmuRsp) } } @@ -321,7 +320,6 @@ class InstructionCache(p : InstructionCacheConfig, mmuParameter : MemoryTranslat } }) - io.cpu.fetch.haltIt := io.cpu.fetch.mmuBus.busy val lineLoader = new Area{ val fire = False @@ -412,7 +410,7 @@ class InstructionCache(p : InstructionCacheConfig, mmuParameter : MemoryTranslat val hit = (!twoCycleRam) generate new Area{ - val hits = read.waysValues.map(way => way.tag.valid && way.tag.address === io.cpu.fetch.mmuBus.rsp.physicalAddress(tagRange)) + val hits = read.waysValues.map(way => way.tag.valid && way.tag.address === io.cpu.fetch.mmuRsp.physicalAddress(tagRange)) val valid = Cat(hits).orR val id = OHToUInt(hits) val error = read.waysValues.map(_.tag.error).read(id) @@ -429,14 +427,10 @@ 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.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 + io.cpu.fetch.physicalAddress := io.cpu.fetch.mmuRsp.physicalAddress val resolution = ifGen(!twoCycleCache)( new Area{ - val mmuRsp = io.cpu.fetch.mmuBus.rsp + val mmuRsp = io.cpu.fetch.mmuRsp io.cpu.fetch.cacheMiss := !hit.valid io.cpu.fetch.error := hit.error @@ -449,7 +443,7 @@ class InstructionCache(p : InstructionCacheConfig, mmuParameter : MemoryTranslat val decodeStage = ifGen(twoCycleCache) (new Area{ def stage[T <: Data](that : T) = RegNextWhen(that,!io.cpu.decode.isStuck) - val mmuRsp = stage(io.cpu.fetch.mmuBus.rsp) + val mmuRsp = stage(io.cpu.fetch.mmuRsp) val hit = if(!twoCycleRam) new Area{ val valid = stage(fetchStage.hit.valid) diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index 4d41790..e23cec7 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -155,8 +155,13 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, cache.io.cpu.prefetch.pc := stages(0).input.payload stages(0).halt setWhen (cache.io.cpu.prefetch.haltIt) - - cache.io.cpu.fetch.isRemoved := externalFlush + if(mmuBus != null && mmuBus.p.latency == 1) { + stages(0).halt setWhen(mmuBus.busy) + mmuBus.cmd(0).isValid := cache.io.cpu.prefetch.isValid + mmuBus.cmd(0).isStuck := !stages(0).input.ready + mmuBus.cmd(0).virtualAddress := cache.io.cpu.prefetch.pc + mmuBus.cmd(0).bypassTranslation := False + } } @@ -172,8 +177,15 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, cache.io.cpu.fetch.isStuck := !stages(1).input.ready cache.io.cpu.fetch.pc := stages(1).input.payload + if(mmuBus != null) { + mmuBus.cmd.last.isValid := cache.io.cpu.fetch.isValid + mmuBus.cmd.last.isStuck := !stages(1).input.ready + mmuBus.cmd.last.virtualAddress := cache.io.cpu.fetch.pc + mmuBus.cmd.last.bypassTranslation := False + mmuBus.end := stages(1).input.ready || externalFlush + if (mmuBus.p.latency == 0) stages(1).halt setWhen (mmuBus.busy) + } - stages(1).halt setWhen(cache.io.cpu.fetch.haltIt) if (!twoCycleCache) { cache.io.cpu.fetch.isUser := privilegeService.isUser() @@ -249,16 +261,15 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, } if (mmuBus != null) { - cache.io.cpu.fetch.mmuBus <> mmuBus + cache.io.cpu.fetch.mmuRsp <> mmuBus.rsp } else { - 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 - cache.io.cpu.fetch.mmuBus.rsp.isIoAccess := False - cache.io.cpu.fetch.mmuBus.rsp.exception := False - cache.io.cpu.fetch.mmuBus.rsp.refilling := False - cache.io.cpu.fetch.mmuBus.busy := False + cache.io.cpu.fetch.mmuRsp.physicalAddress := cache.io.cpu.fetch.pc + cache.io.cpu.fetch.mmuRsp.allowExecute := True + cache.io.cpu.fetch.mmuRsp.allowRead := True + cache.io.cpu.fetch.mmuRsp.allowWrite := True + cache.io.cpu.fetch.mmuRsp.isIoAccess := False + cache.io.cpu.fetch.mmuRsp.exception := False + cache.io.cpu.fetch.mmuRsp.refilling := False } val flushStage = decode diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index 33a3857..66b308b 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -321,9 +321,12 @@ class IBusDimension(rvcRate : Double) extends VexRiscvDimension("IBus") { 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.5){ + val mmuConfig = if(universes.contains(VexRiscvUniverse.MMU)) MmuPortConfig( portTlbSize = 4) else null val latency = r.nextInt(5) + 1 val compressed = r.nextDouble() < rvcRate val injectorStage = r.nextBoolean() || latency == 1 @@ -347,6 +350,9 @@ class IBusDimension(rvcRate : Double) extends VexRiscvDimension("IBus") { override def instructionAnticipatedOk() = injectorStage } } else { + val twoStageMmu = r.nextBoolean() + 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 catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL) val compressed = r.nextDouble() < rvcRate val tighlyCoupled = r.nextBoolean() && !catchAll