From 010ba568f05bcc08bb38ed51cbfe3f54d937380d Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Fri, 28 Apr 2017 16:41:23 +0200 Subject: [PATCH] MMU implemented Datacached using MMU implemented It compile, but nothing is tested --- src/main/scala/SpinalRiscv/Pipeline.scala | 1 + .../SpinalRiscv/Plugin/BranchPlugin.scala | 2 +- .../SpinalRiscv/Plugin/DBusCachedPlugin.scala | 72 ++++++++++++------- .../scala/SpinalRiscv/Plugin/Plugin.scala | 1 + src/main/scala/SpinalRiscv/Services.scala | 23 ++++++ src/main/scala/SpinalRiscv/TopLevel.scala | 61 +++++++++------- src/test/cpp/testA/makefile | 2 +- 7 files changed, 109 insertions(+), 53 deletions(-) diff --git a/src/main/scala/SpinalRiscv/Pipeline.scala b/src/main/scala/SpinalRiscv/Pipeline.scala index e54fe35..d01eeeb 100644 --- a/src/main/scala/SpinalRiscv/Pipeline.scala +++ b/src/main/scala/SpinalRiscv/Pipeline.scala @@ -29,6 +29,7 @@ trait Pipeline { } def build(): Unit ={ + plugins.foreach(_.pipeline = this.asInstanceOf[T]) plugins.foreach(_.setup(this.asInstanceOf[T])) //Build plugins diff --git a/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala b/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala index d6d730d..dfd7144 100644 --- a/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala @@ -79,7 +79,7 @@ class BranchPlugin(earlyBranch : Boolean, } override def build(pipeline: VexRiscv): Unit = prediction match { - case NONE => buildWithoutPrediction(pipeline) + case `NONE` => buildWithoutPrediction(pipeline) case `STATIC` => buildWithPrediction(pipeline) case `DYNAMIC` => buildWithPrediction(pipeline) } diff --git a/src/main/scala/SpinalRiscv/Plugin/DBusCachedPlugin.scala b/src/main/scala/SpinalRiscv/Plugin/DBusCachedPlugin.scala index a1a9127..56d5ed1 100644 --- a/src/main/scala/SpinalRiscv/Plugin/DBusCachedPlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/DBusCachedPlugin.scala @@ -1,7 +1,7 @@ package SpinalRiscv.Plugin import SpinalRiscv.Riscv._ -import SpinalRiscv.{Stageable, DecoderService, Riscv, VexRiscv} +import SpinalRiscv._ import spinal.core._ import spinal.lib._ @@ -12,17 +12,20 @@ case class DataCacheConfig( cacheSize : Int, addressWidth : Int, cpuDataWidth : Int, memDataWidth : Int, - catchAccessFault : Boolean = false){ + catchAccessFault : Boolean = false, + tagSizeShift : Int = 0){ //Used to force infering ram def burstSize = bytePerLine*8/memDataWidth val burstLength = bytePerLine/(memDataWidth/8) assert(catchAccessFault == false) } +case class DataMmuConfig(dTlbSize : Int) -class DBusCachedPlugin(config : DataCacheConfig) extends Plugin[VexRiscv]{ + +class DBusCachedPlugin(config : DataCacheConfig, mmuConfig : DataMmuConfig = null) extends Plugin[VexRiscv]{ import config._ var dBus : DataCacheMemBus = null - + var mmuBus : MemoryTranslatorBus = null object MEMORY_ENABLE extends Stageable(Bool) object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits)) @@ -56,6 +59,9 @@ class DBusCachedPlugin(config : DataCacheConfig) extends Plugin[VexRiscv]{ List(LB, LH, LW, LBU, LHU, LWU).map(_ -> loadActions) ++ List(SB, SH, SW).map(_ -> storeActions) ) + + if(mmuConfig != null) + mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.memory,mmuConfig.dTlbSize) } override def build(pipeline: VexRiscv): Unit = { @@ -98,6 +104,15 @@ class DBusCachedPlugin(config : DataCacheConfig) extends Plugin[VexRiscv]{ import memory._ cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE) cache.io.cpu.memory.isStuck := arbitration.isStuck + cache.io.cpu.memory.isRemoved := arbitration.removeIt + if(mmuBus != null){ + cache.io.cpu.memory.mmuBus <> mmuBus + } else { + cache.io.cpu.memory.mmuBus.rsp.physicalAddress := cache.io.cpu.memory.mmuBus.cmd.virtualAddress + cache.io.cpu.memory.mmuBus.rsp.allowExecute := True + cache.io.cpu.memory.mmuBus.rsp.allowRead := True + cache.io.cpu.memory.mmuBus.rsp.allowWrite := True + } } writeBack plug new Area{ @@ -236,9 +251,12 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{ case class DataCacheCpuMemory(p : DataCacheConfig) extends Bundle with IMasterSlave{ val isValid = Bool val isStuck = Bool + val isRemoved = Bool + val mmuBus = MemoryTranslatorBus() override def asMaster(): Unit = { - out(isValid, isStuck) + out(isValid, isStuck, isRemoved) + slave(mmuBus) } } @@ -435,7 +453,7 @@ class DataCache(p : DataCacheConfig) extends Component{ val request = requestIn.stage() //TODO FMAX half pipe ? request.ready := False - val buffer = Mem(Bits(p.memDataWidth bits),memTransactionPerLine << 1) // WARNING << 1 could resolve cyclone II issue, //.add(new AttributeString("ramstyle","M4K")) + val buffer = Mem(Bits(p.memDataWidth bits),memTransactionPerLine << tagSizeShift) // WARNING << tagSizeShift could resolve cyclone II issue, //.add(new AttributeString("ramstyle","M4K")) //Send line read commands to fill the buffer val readLineCmdCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0) @@ -513,21 +531,23 @@ class DataCache(p : DataCacheConfig) extends Component{ val stageA = new Area{ val request = RegNextWhen(io.cpu.execute.args, !io.cpu.memory.isStuck) + io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid //TODO filter request kind + io.cpu.memory.mmuBus.cmd.virtualAddress := request.address } val stageB = new Area { io.flushDone := False val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck) - -// val waysHit = RegNextWhen(way.tagReadRspTwoRegIn.used && stageA.request.address(tagRange) === way.tagReadRspTwoRegIn.address,!io.cpu.writeBack.isStuck) //Manual retiming - val waysHit = way.tagReadRspTwo.used && request.address(tagRange) === way.tagReadRspTwo.address + val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck) +// val waysHit = RegNextWhen(way.tagReadRspTwoRegIn.used && stageA.mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwoRegIn.address,!io.cpu.writeBack.isStuck) //Manual retiming + val waysHit = way.tagReadRspTwo.used && mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwo.address //Evict the cache after reset val requestValid = io.cpu.writeBack.isValid || RegNextWhen(False, !io.cpu.writeBack.isStuck, True) request.kind init(DataCacheCpuCmdKind.EVICT) request.all init(True) - request.address init(0) + mmuRsp.physicalAddress init(0) io.cpu.writeBack.haltIt := requestValid @@ -551,17 +571,17 @@ class DataCache(p : DataCacheConfig) extends Component{ is(EVICT){ when(request.all){ tagsWriteCmd.valid := True - tagsWriteCmd.address := request.address(lineRange) + tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange) tagsWriteCmd.data.used := False - when(request.address(lineRange) =/= lineCount-1){ - request.address.getDrivingReg(lineRange) := request.address(lineRange) + 1 + when(mmuRsp.physicalAddress(lineRange) =/= lineCount-1){ + mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1 }otherwise{ io.cpu.writeBack.haltIt := False } }otherwise{ when(waysHit) { tagsWriteCmd.valid := True - tagsWriteCmd.address := request.address(lineRange) + tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange) tagsWriteCmd.data.used := False } io.cpu.writeBack.haltIt := False @@ -572,15 +592,15 @@ class DataCache(p : DataCacheConfig) extends Component{ // when(!flushAllState){ // victim.requestIn.valid := waysRead(0).tag.used && waysRead(0).tag.dirty // victim.requestIn.way := writebackWayId -// victim.requestIn.address := writebackWayInfo.address @@ request.address(lineRange) @@ U((lineRange.low - 1 downto 0) -> false) +// victim.requestIn.address := writebackWayInfo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false) // // tagsWriteCmd.way := writebackWayId -// tagsWriteCmd.address := request.address(lineRange) +// tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange) // tagsWriteCmd.data.used := False // // when(!victim.requestIn.isStall) { -// request.address.getDrivingReg(lineRange) := request.address(lineRange) + 1 -// flushAllDone := request.address(lineRange) === lineCount-1 +// mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1 +// flushAllDone := mmuRsp.physicalAddress(lineRange) === lineCount-1 // flushAllState := True // tagsWriteCmd.valid := True // } @@ -597,11 +617,11 @@ class DataCache(p : DataCacheConfig) extends Component{ // // victim.requestIn.valid := True // victim.requestIn.way := writebackWayId -// victim.requestIn.address := writebackWayInfo.address @@ request.address(lineRange) @@ U((lineRange.low - 1 downto 0) -> false) +// victim.requestIn.address := writebackWayInfo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false) // // tagsWriteCmd.valid := victim.requestIn.ready // tagsWriteCmd.way := writebackWayId -// tagsWriteCmd.address := request.address(lineRange) +// tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange) // tagsWriteCmd.data.used := False // } otherwise{ // io.cpu.memory.haltIt := False @@ -615,7 +635,7 @@ class DataCache(p : DataCacheConfig) extends Component{ val memCmdSent = RegInit(False) when(!victim.request.valid) { //Avoid mixing memory request while victim is pending io.mem.cmd.wr := request.wr - io.mem.cmd.address := request.address(tagRange.high downto wordRange.low) @@ U(0,wordRange.low bit) + io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0,wordRange.low bit) io.mem.cmd.mask := request.mask io.mem.cmd.data := request.data io.mem.cmd.length := 1 @@ -632,20 +652,20 @@ class DataCache(p : DataCacheConfig) extends Component{ when(waysHit || !loadingNotDone){ io.cpu.writeBack.haltIt := False dataWriteCmd.valid := request.wr - dataWriteCmd.address := request.address(lineRange.high downto wordRange.low) + dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low) dataWriteCmd.data := request.data dataWriteCmd.mask := request.mask tagsWriteCmd.valid := !loadingNotDone || request.wr - tagsWriteCmd.address := request.address(lineRange) + tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange) tagsWriteCmd.data.used := True tagsWriteCmd.data.dirty := request.wr - tagsWriteCmd.data.address := request.address(tagRange) + tagsWriteCmd.data.address := mmuRsp.physicalAddress(tagRange) } otherwise { val victimRequired = way.tagReadRspTwo.used && way.tagReadRspTwo.dirty loaderValid := loadingNotDone && !(victimNotSent && victim.request.isStall) //Additional condition used to be sure of that all previous victim are written into the RAM victim.requestIn.valid := victimRequired && victimNotSent - victim.requestIn.address := way.tagReadRspTwo.address @@ request.address(lineRange) @@ U((lineRange.low - 1 downto 0) -> false) + victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false) } } } @@ -660,7 +680,7 @@ class DataCache(p : DataCacheConfig) extends Component{ //The whole life of a loading task, the corresponding manager request is present val loader = new Area{ val valid = RegNext(stageB.loaderValid) init(False) - val baseAddress = stageB.request.address + val baseAddress = stageB.mmuRsp.physicalAddress val memCmdSent = RegInit(False) when(valid && !memCmdSent) { diff --git a/src/main/scala/SpinalRiscv/Plugin/Plugin.scala b/src/main/scala/SpinalRiscv/Plugin/Plugin.scala index cb12883..023a59e 100644 --- a/src/main/scala/SpinalRiscv/Plugin/Plugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/Plugin.scala @@ -7,6 +7,7 @@ import spinal.core.Area * Created by PIC32F_USER on 03/03/2017. */ trait Plugin[T <: Pipeline] { + var pipeline : T = null.asInstanceOf[T] def getName() = this.getClass.getSimpleName.replace("$","") def setup(pipeline: T) : Unit = {} diff --git a/src/main/scala/SpinalRiscv/Services.scala b/src/main/scala/SpinalRiscv/Services.scala index 6d6ec83..4013878 100644 --- a/src/main/scala/SpinalRiscv/Services.scala +++ b/src/main/scala/SpinalRiscv/Services.scala @@ -21,3 +21,26 @@ case class ExceptionCause() extends Bundle{ trait ExceptionService{ def newExceptionPort(stage : Stage, priority : Int = 0) : Flow[ExceptionCause] } + +case class MemoryTranslatorCmd() extends Bundle{ + val isValid = Bool + val virtualAddress = UInt(32 bits) +} +case class MemoryTranslatorRsp() extends Bundle{ + val physicalAddress = UInt(32 bits) + val allowRead, allowWrite, allowExecute = Bool +} + +case class MemoryTranslatorBus() extends Bundle with IMasterSlave{ + val cmd = MemoryTranslatorCmd() + val rsp = MemoryTranslatorRsp() + + override def asMaster() : Unit = { + out(cmd) + in(rsp) + } +} + +trait MemoryTranslator{ + def newTranslationPort(stage : Stage, cacheSize : Int) : MemoryTranslatorBus +} diff --git a/src/main/scala/SpinalRiscv/TopLevel.scala b/src/main/scala/SpinalRiscv/TopLevel.scala index ea9c70c..38b56b2 100644 --- a/src/main/scala/SpinalRiscv/TopLevel.scala +++ b/src/main/scala/SpinalRiscv/TopLevel.scala @@ -203,24 +203,24 @@ object TopLevel { configTest.plugins ++= List( new PcManagerSimplePlugin(0x00000000l, true), - new IBusSimplePlugin( - interfaceKeepData = true, - catchAccessFault = false - ), -// new IBusCachedPlugin( -// config = InstructionCacheConfig( -// cacheSize = 4096, -// bytePerLine =32, -// wayCount = 1, -// wrappedMemAccess = true, -// addressWidth = 32, -// cpuDataWidth = 32, -// memDataWidth = 32, -// catchAccessFault = false, -// asyncTagMemory = false, -// twoStageLogic = true -// ) +// new IBusSimplePlugin( +// interfaceKeepData = true, +// catchAccessFault = false // ), + new IBusCachedPlugin( + config = InstructionCacheConfig( + cacheSize = 4096, + bytePerLine =32, + wayCount = 1, + wrappedMemAccess = true, + addressWidth = 32, + cpuDataWidth = 32, + memDataWidth = 32, + catchAccessFault = false, + asyncTagMemory = false, + twoStageLogic = true + ) + ), // new DBusSimplePlugin( // catchAddressMisaligned = false, @@ -239,15 +239,26 @@ object TopLevel { // ), new DBusCachedPlugin( config = new DataCacheConfig( - cacheSize = 128, + cacheSize = 4096, bytePerLine = 32, wayCount = 1, addressWidth = 32, cpuDataWidth = 32, memDataWidth = 32, - catchAccessFault = false + catchAccessFault = false, + tagSizeShift = 2 + ), + mmuConfig = DataMmuConfig( + dTlbSize = 6 ) ), + + new MemoryTranslatorPlugin( + tlbSize = 32, + exceptionCode = 13, + mmuRange = !_(31) + ), + new MachineCsr(csrConfigAll), new DecoderSimplePlugin( catchIllegalInstruction = false ), @@ -264,10 +275,10 @@ object TopLevel { // new HazardSimplePlugin(true, true, true, true), // new HazardSimplePlugin(false, true, false, true), new HazardSimplePlugin( - bypassExecute = false, - bypassMemory = false, - bypassWriteBack = false, - bypassWriteBackBuffer = false, + bypassExecute = true, + bypassMemory = true, + bypassWriteBack = true, + bypassWriteBackBuffer = true, pessimisticUseSrc = false, pessimisticWriteRegFile = false, pessimisticAddressMatch = false @@ -282,9 +293,9 @@ object TopLevel { ) ) - val toplevel = new VexRiscv(configFull) +// val toplevel = new VexRiscv(configFull) // val toplevel = new VexRiscv(configLight) -// val toplevel = new VexRiscv(configTest) + val toplevel = new VexRiscv(configTest) toplevel.decode.input(toplevel.config.INSTRUCTION).addAttribute(Verilator.public) toplevel.decode.input(toplevel.config.PC).addAttribute(Verilator.public) toplevel.decode.arbitration.isValid.addAttribute(Verilator.public) diff --git a/src/test/cpp/testA/makefile b/src/test/cpp/testA/makefile index 008a89a..77f13c9 100644 --- a/src/test/cpp/testA/makefile +++ b/src/test/cpp/testA/makefile @@ -1,4 +1,4 @@ -IBUS=IBUS_SIMPLE +IBUS=IBUS_CACHED DBUS=DBUS_CACHED TRACE=no TRACE_START=0