From 7ffbfab3129995a82a229e65702bdd19f02b236d Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Wed, 16 May 2018 20:32:12 +0200 Subject: [PATCH] Reintroduce MMU feature (pass tests) --- src/main/scala/vexriscv/Services.scala | 6 ++- src/main/scala/vexriscv/TestsWorkspace.scala | 9 ++-- src/main/scala/vexriscv/ip/DataCache.scala | 1 + .../scala/vexriscv/ip/InstructionCache.scala | 13 ++++-- .../vexriscv/plugin/DBusCachedPlugin.scala | 3 +- src/main/scala/vexriscv/plugin/Fetcher.scala | 3 +- .../vexriscv/plugin/IBusCachedPlugin.scala | 42 +++++++++++-------- .../plugin/MemoryTranslatorPlugin.scala | 19 ++++++--- .../plugin/StaticMemoryTranslatorPlugin.scala | 7 ++-- 9 files changed, 66 insertions(+), 37 deletions(-) diff --git a/src/main/scala/vexriscv/Services.scala b/src/main/scala/vexriscv/Services.scala index 2b9bc00..44e9a80 100644 --- a/src/main/scala/vexriscv/Services.scala +++ b/src/main/scala/vexriscv/Services.scala @@ -56,20 +56,22 @@ case class MemoryTranslatorRsp() extends Bundle{ val isIoAccess = Bool val allowRead, allowWrite, allowExecute, allowUser = Bool val miss = Bool + val hit = Bool } case class MemoryTranslatorBus() extends Bundle with IMasterSlave{ val cmd = MemoryTranslatorCmd() val rsp = MemoryTranslatorRsp() + val end = Bool override def asMaster() : Unit = { - out(cmd) + out(cmd, end) in(rsp) } } trait MemoryTranslator{ - def newTranslationPort(stage : Stage, args : Any) : MemoryTranslatorBus + def newTranslationPort(priority : Int, args : Any) : MemoryTranslatorBus } diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index 8220c44..51b0084 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -41,6 +41,7 @@ object TestsWorkspace { // ), new IBusCachedPlugin( resetVector = 0x80000000l, + compressedGen = true, config = InstructionCacheConfig( cacheSize = 1024*16, bytePerLine = 32, @@ -54,10 +55,10 @@ object TestsWorkspace { asyncTagMemory = false, twoCycleRam = false, twoCycleCache = true - )//, -// memoryTranslatorPortConfig = MemoryTranslatorPortConfig( -// portTlbSize = 4 -// ) + ), + memoryTranslatorPortConfig = MemoryTranslatorPortConfig( + portTlbSize = 4 + ) ), // new DBusSimplePlugin( // catchAddressMisaligned = true, diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index 769d089..dc58c95 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -511,6 +511,7 @@ class DataCache(p : DataCacheConfig) extends Component{ io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid && request.kind === MEMORY //TODO filter request kind io.cpu.memory.mmuBus.cmd.virtualAddress := request.address io.cpu.memory.mmuBus.cmd.bypassTranslation := request.way + io.cpu.memory.mmuBus.end := !io.cpu.memory.isStuck || io.cpu.memory.isRemoved cpuMemoryStageNeedReadData := io.cpu.memory.isValid && request.kind === MEMORY && !request.wr } diff --git a/src/main/scala/vexriscv/ip/InstructionCache.scala b/src/main/scala/vexriscv/ip/InstructionCache.scala index f137e43..e992d20 100644 --- a/src/main/scala/vexriscv/ip/InstructionCache.scala +++ b/src/main/scala/vexriscv/ip/InstructionCache.scala @@ -63,6 +63,7 @@ trait InstructionCacheCommons{ val isValid : Bool val isStuck : Bool val pc : UInt + val physicalAddress : UInt val data : Bits val cacheMiss, error, mmuMiss, illegalAccess,isUser : Bool } @@ -70,14 +71,16 @@ trait InstructionCacheCommons{ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle with IMasterSlave with InstructionCacheCommons { val isValid = Bool val isStuck = Bool + val isRemoved = Bool val pc = UInt(p.addressWidth bits) val data = Bits(p.cpuDataWidth bits) val mmuBus = MemoryTranslatorBus() + val physicalAddress = UInt(p.addressWidth bits) val cacheMiss, error, mmuMiss, illegalAccess,isUser = ifGen(!p.twoCycleCache)(Bool) override def asMaster(): Unit = { - out(isValid, isStuck, pc) - inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss) + out(isValid, isStuck, isRemoved, pc) + inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss,physicalAddress) outWithNull(isUser) slaveWithNull(mmuBus) } @@ -88,13 +91,14 @@ case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle val isValid = Bool val isStuck = Bool val pc = UInt(p.addressWidth bits) + val physicalAddress = UInt(p.addressWidth bits) val data = Bits(p.cpuDataWidth bits) val cacheMiss, error, mmuMiss, illegalAccess, isUser = ifGen(p.twoCycleCache)(Bool) override def asMaster(): Unit = { out(isValid, isStuck, pc) outWithNull(isUser) - inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss) + inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss, physicalAddress) } } @@ -328,6 +332,8 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ 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.end := !io.cpu.fetch.isStuck || io.cpu.fetch.isRemoved + io.cpu.fetch.physicalAddress := io.cpu.fetch.mmuBus.rsp.physicalAddress val resolution = ifGen(!twoCycleCache)( new Area{ def stage[T <: Data](that : T) = RegNextWhen(that,!io.cpu.decode.isStuck) @@ -371,6 +377,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ io.cpu.decode.error := hit.error io.cpu.decode.mmuMiss := mmuRsp.miss io.cpu.decode.illegalAccess := !mmuRsp.allowExecute || (io.cpu.decode.isUser && !mmuRsp.allowUser) + io.cpu.decode.physicalAddress := mmuRsp.physicalAddress }) } diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index bdd60f1..1085c30 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -95,7 +95,7 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An MEMORY_MANAGMENT -> True )) - mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.memory,memoryTranslatorPortConfig) + mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig) if(catchSomething) exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.writeBack) @@ -171,6 +171,7 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An arbitration.haltItself setWhen(cache.io.cpu.memory.haltIt) cache.io.cpu.memory.mmuBus <> mmuBus + arbitration.haltItself setWhen (mmuBus.cmd.isValid && !mmuBus.rsp.hit && !mmuBus.rsp.miss) } writeBack plug new Area{ diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 4cea558..89c4f6e 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -200,11 +200,12 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean, val iBusRsp = new Area { val input = Stream(UInt(32 bits)) val inputPipeline = Vec(Stream(UInt(32 bits)), cmdToRspStageCount) + val inputPipelineHalt = Vec(False, cmdToRspStageCount-1) for(i <- 0 until cmdToRspStageCount) { // val doFlush = if(i == cmdToRspStageCount- 1 && ???) killLastStage else flush inputPipeline(i) << {i match { case 0 => input.m2sPipeWithFlush(flush, relaxedPcCalculation, collapsBubble = false) - case _ => inputPipeline(i-1)/*.haltWhen(fetcherHalt)*/.m2sPipeWithFlush(flush,collapsBubble = false) + case _ => inputPipeline(i-1).haltWhen(inputPipelineHalt(i-1)).m2sPipeWithFlush(flush,collapsBubble = false) }} } diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index 8b03ddb..71d93ab 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -62,9 +62,8 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1) } -// if(pipeline.serviceExist(classOf[MemoryTranslator])) -// ??? //TODO - //mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.fetch, memoryTranslatorPortConfig) + if(pipeline.serviceExist(classOf[MemoryTranslator])) + mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_INSTRUCTION, memoryTranslatorPortConfig) if(pipeline.serviceExist(classOf[PrivilegeService])) privilegeService = pipeline.service(classOf[PrivilegeService]) @@ -105,6 +104,22 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, cache.io.cpu.prefetch.pc := fetchPc.output.payload iBusRsp.input << fetchPc.output.haltWhen(cache.io.cpu.prefetch.haltIt) + + cache.io.cpu.fetch.isRemoved := flush + if (mmuBus != null) { + cache.io.cpu.fetch.mmuBus <> mmuBus + iBusRsp.inputPipelineHalt(0) setWhen(mmuBus.cmd.isValid && !mmuBus.rsp.hit && !mmuBus.rsp.miss) + } else { + cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.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.allowUser := True + cache.io.cpu.fetch.mmuBus.rsp.isIoAccess := False + cache.io.cpu.fetch.mmuBus.rsp.miss := False + cache.io.cpu.fetch.mmuBus.rsp.hit := False + } + //Connect fetch cache side cache.io.cpu.fetch.isValid := iBusRsp.inputPipeline(0).valid cache.io.cpu.fetch.isStuck := !iBusRsp.input.ready @@ -123,17 +138,6 @@ 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 //- debugAddressOffset - 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.allowUser := True - cache.io.cpu.fetch.mmuBus.rsp.isIoAccess := False - cache.io.cpu.fetch.mmuBus.rsp.miss := False - } // val missHalt = cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.cacheMiss val cacheRsp = if(twoCycleCache) cache.io.cpu.decode else cache.io.cpu.fetch @@ -148,13 +152,17 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, redoBranch.valid := redoFetch assert(decodePcGen == compressedGen) redoBranch.payload := (if(decodePcGen) decode.input(PC) else cacheRsp.pc) - cache.io.cpu.fill.payload := cacheRsp.pc + cache.io.cpu.fill.payload := cacheRsp.physicalAddress if(catchSomething){ + val accessFault = if (catchAccessFault) cacheRsp.error else False + val mmuMiss = if (catchMemoryTranslationMiss) cacheRsp.mmuMiss else False + val illegalAccess = if (catchIllegalAccess) cacheRsp.illegalAccess else False + decodeExceptionPort.valid := False - decodeExceptionPort.code := 1 + decodeExceptionPort.code := mmuMiss ? U(14) | 1 decodeExceptionPort.badAddr := cacheRsp.pc - when(cacheRsp.isValid && cacheRsp.error && !issueDetected){ + when(cacheRsp.isValid && (accessFault || mmuMiss || illegalAccess) && !issueDetected){ issueDetected \= True decodeExceptionPort.valid := iBusRsp.readyForError } diff --git a/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala b/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala index 22beaf5..1d74c2b 100644 --- a/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala +++ b/src/main/scala/vexriscv/plugin/MemoryTranslatorPlugin.scala @@ -5,7 +5,12 @@ import spinal.core._ import spinal.lib._ import scala.collection.mutable.ArrayBuffer -case class MemoryTranslatorPort(bus : MemoryTranslatorBus, stage : Stage, args : MemoryTranslatorPortConfig/*, exceptionBus: Flow[ExceptionCause]*/) + +object MemoryTranslatorPort{ + val PRIORITY_DATA = 1 + val PRIORITY_INSTRUCTION = 0 +} +case class MemoryTranslatorPort(bus : MemoryTranslatorBus, priority : Int, args : MemoryTranslatorPortConfig/*, exceptionBus: Flow[ExceptionCause]*/) case class MemoryTranslatorPortConfig(portTlbSize : Int) @@ -16,9 +21,9 @@ class MemoryTranslatorPlugin(tlbSize : Int, val portsInfo = ArrayBuffer[MemoryTranslatorPort]() - override def newTranslationPort(stage : Stage,args : Any): MemoryTranslatorBus = { + override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = { // val exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(stage) - val port = MemoryTranslatorPort(MemoryTranslatorBus(),stage,args.asInstanceOf[MemoryTranslatorPortConfig]/*,exceptionBus*/) + val port = MemoryTranslatorPort(MemoryTranslatorBus(),priority,args.asInstanceOf[MemoryTranslatorPortConfig]/*,exceptionBus*/) portsInfo += port port.bus } @@ -41,7 +46,7 @@ class MemoryTranslatorPlugin(tlbSize : Int, import Riscv._ //Sorted by priority - val sortedPortsInfo = portsInfo.sortWith((a,b) => indexOf(a.stage) > indexOf(b.stage)) + val sortedPortsInfo = portsInfo.sortWith((a,b) => a.priority > b.priority) case class CacheLine() extends Bundle { val valid = Bool @@ -94,7 +99,7 @@ class MemoryTranslatorPlugin(tlbSize : Int, } sharedMiss.setWhen(sharedIterator >= tlbSize && sharedAccessed === B"00") - when(!port.stage.arbitration.isStuck){ + when(port.bus.end){ sharedIterator := 0 sharedMiss.clear() sharedAccessAsked.clear() @@ -108,13 +113,15 @@ class MemoryTranslatorPlugin(tlbSize : Int, port.bus.rsp.allowWrite := cacheLine.allowWrite port.bus.rsp.allowExecute := cacheLine.allowExecute port.bus.rsp.allowUser := cacheLine.allowUser - port.stage.arbitration.haltItself setWhen (port.bus.cmd.isValid && !cacheHit && !sharedMiss) + 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.allowRead := True port.bus.rsp.allowWrite := True port.bus.rsp.allowExecute := True port.bus.rsp.allowUser := True + port.bus.rsp.hit := True } port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress) port.bus.rsp.miss := sharedMiss diff --git a/src/main/scala/vexriscv/plugin/StaticMemoryTranslatorPlugin.scala b/src/main/scala/vexriscv/plugin/StaticMemoryTranslatorPlugin.scala index a4e96e0..71d2312 100644 --- a/src/main/scala/vexriscv/plugin/StaticMemoryTranslatorPlugin.scala +++ b/src/main/scala/vexriscv/plugin/StaticMemoryTranslatorPlugin.scala @@ -5,14 +5,14 @@ import spinal.core._ import spinal.lib._ import scala.collection.mutable.ArrayBuffer -case class StaticMemoryTranslatorPort(bus : MemoryTranslatorBus, stage : Stage) +case class StaticMemoryTranslatorPort(bus : MemoryTranslatorBus, priority : Int) class StaticMemoryTranslatorPlugin(ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator { val portsInfo = ArrayBuffer[StaticMemoryTranslatorPort]() - override def newTranslationPort(stage : Stage,args : Any): MemoryTranslatorBus = { + override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = { // val exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(stage) - val port = StaticMemoryTranslatorPort(MemoryTranslatorBus(),stage) + val port = StaticMemoryTranslatorPort(MemoryTranslatorBus(),priority) portsInfo += port port.bus } @@ -34,6 +34,7 @@ class StaticMemoryTranslatorPlugin(ioRange : UInt => Bool) extends Plugin[VexRis port.bus.rsp.allowUser := True port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress) port.bus.rsp.miss := False + port.bus.rsp.hit := True } } }