diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index d21ff8f..f8de090 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -35,28 +35,28 @@ object TestsWorkspace { // resetVector = 0x80000000l, // relaxedPcCalculation = false // ), - new IBusSimplePlugin( - interfaceKeepData = false, - catchAccessFault = true - ), -// new IBusCachedPlugin( -// config = InstructionCacheConfig( -// cacheSize = 1024*16, -// bytePerLine = 32, -// wayCount = 1, -// addressWidth = 32, -// cpuDataWidth = 32, -// memDataWidth = 32, -// catchIllegalAccess = true, -// catchAccessFault = true, -// catchMemoryTranslationMiss = true, -// asyncTagMemory = false, -// twoCycleRam = false -// ), +// new IBusSimplePlugin( +// interfaceKeepData = false, +// catchAccessFault = true +// ), + new IBusCachedPlugin( + config = InstructionCacheConfig( + cacheSize = 1024*16, + bytePerLine = 32, + wayCount = 1, + addressWidth = 32, + cpuDataWidth = 32, + memDataWidth = 32, + catchIllegalAccess = false, + catchAccessFault = false, + catchMemoryTranslationMiss = false, + asyncTagMemory = false, + twoCycleRam = false + )//, // memoryTranslatorPortConfig = MemoryTranslatorPortConfig( // portTlbSize = 4 // ) -// ), + ), // new DBusSimplePlugin( // catchAddressMisaligned = true, // catchAccessFault = true, diff --git a/src/main/scala/vexriscv/ip/InstructionCache.scala b/src/main/scala/vexriscv/ip/InstructionCache.scala index 5fa61ec..e8194ab 100644 --- a/src/main/scala/vexriscv/ip/InstructionCache.scala +++ b/src/main/scala/vexriscv/ip/InstructionCache.scala @@ -340,6 +340,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ lineLoader.valid := True lineLoader.address := mmuRsp.physicalAddress //Could be optimise if mmu not used } +// when(io.cpu) io.cpu.decode.error := hit.error io.cpu.decode.mmuMiss := mmuRsp.miss diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 6e02739..a2d5c11 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -189,12 +189,12 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean, val iBusRsp = new Area { val input = Stream(UInt(32 bits)) - val pipeline = Vec(Stream(UInt(32 bits)), cmdToRspStageCount) + val inputPipeline = Vec(Stream(UInt(32 bits)), cmdToRspStageCount) for(i <- 0 until cmdToRspStageCount) { // val doFlush = if(i == cmdToRspStageCount- 1 && ???) killLastStage else flush - pipeline(i) << {i match { + inputPipeline(i) << {i match { case 0 => input.m2sPipeWithFlush(flush, relaxedPcCalculation) - case _ => pipeline(i-1)/*.haltWhen(fetcherHalt)*/.m2sPipeWithFlush(flush) + case _ => inputPipeline(i-1)/*.haltWhen(fetcherHalt)*/.m2sPipeWithFlush(flush) }} } @@ -255,7 +255,7 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean, }else { val lastStageStream = if(injectorStage) inputBeforeHalt else if(rspStageGen) iBusRsp.outputBeforeStage - else if(cmdToRspStageCount > 1)iBusRsp.pipeline(cmdToRspStageCount-2) + else if(cmdToRspStageCount > 1)iBusRsp.inputPipeline(cmdToRspStageCount-2) else throw new Exception("Fetch should at least have two stages") // when(fetcherHalt){ diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index 32e1ca2..a3a72cf 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -5,149 +5,167 @@ import vexriscv.ip._ import spinal.core._ import spinal.lib._ -class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] { - var iBus : InstructionCacheMemBus = null - override def build(pipeline: VexRiscv): Unit = ??? -} //class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] { -// import config._ -// // var iBus : InstructionCacheMemBus = null -// var mmuBus : MemoryTranslatorBus = null -// var decodeExceptionPort : Flow[ExceptionCause] = null -// var privilegeService : PrivilegeService = null -// var redoBranch : Flow[UInt] = null -// -// object FLUSH_ALL extends Stageable(Bool) -// object IBUS_ACCESS_ERROR extends Stageable(Bool) -// object IBUS_MMU_MISS extends Stageable(Bool) -// object IBUS_ILLEGAL_ACCESS extends Stageable(Bool) -// override def setup(pipeline: VexRiscv): Unit = { -// import Riscv._ -// import pipeline.config._ -// -// def MANAGEMENT = M"-----------------100-----0001111" -// -// val decoderService = pipeline.service(classOf[DecoderService]) -// decoderService.addDefault(FLUSH_ALL, False) -// decoderService.add(MANAGEMENT, List( -// FLUSH_ALL -> True -// )) -// -// -// redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.decode, priority = 1) //Priority 1 will win against branch predictor -// -// if(catchSomething) { -// val exceptionService = pipeline.service(classOf[ExceptionService]) -// decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1) -// } -// -// if(pipeline.serviceExist(classOf[MemoryTranslator])) -// mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.fetch, memoryTranslatorPortConfig) -// -// if(pipeline.serviceExist(classOf[PrivilegeService])) -// privilegeService = pipeline.service(classOf[PrivilegeService]) -// -// if(pipeline.serviceExist(classOf[ReportService])){ -// val report = pipeline.service(classOf[ReportService]) -// report.add("iBus" -> { -// val e = new BusReport() -// val c = new CacheReport() -// e.kind = "cached" -// e.flushInstructions.add(0x400F) //invalid instruction cache -// e.flushInstructions.add(0x13) -// e.flushInstructions.add(0x13) -// e.flushInstructions.add(0x13) -// -// e.info = c -// c.size = cacheSize -// c.bytePerLine = bytePerLine -// -// e -// }) -// } -// } -// -// override def build(pipeline: VexRiscv): Unit = { -// import pipeline._ -// import pipeline.config._ -//// val debugAddressOffset = 28 -// val cache = new InstructionCache(this.config) -// iBus = master(new InstructionCacheMemBus(this.config)).setName("iBus") -// iBus <> cache.io.mem -// iBus.cmd.address.allowOverride := cache.io.mem.cmd.address // - debugAddressOffset -// -// //Connect prefetch cache side -// cache.io.cpu.prefetch.isValid := prefetch.arbitration.isValid -// cache.io.cpu.prefetch.pc := prefetch.output(PC)// + debugAddressOffset -// prefetch.arbitration.haltItself setWhen(cache.io.cpu.prefetch.haltIt) -// -// //Connect fetch cache side -// cache.io.cpu.fetch.isValid := fetch.arbitration.isValid -// cache.io.cpu.fetch.isStuck := fetch.arbitration.isStuck -// cache.io.cpu.fetch.pc := fetch.output(PC) // + debugAddressOffset -// -// 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 -// } -// -// if(dataOnDecode){ -// decode.insert(INSTRUCTION) := cache.io.cpu.decode.data -// }else{ -// fetch.insert(INSTRUCTION) := cache.io.cpu.fetch.data -// decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck,decode.input(INSTRUCTION),fetch.output(INSTRUCTION)) -// } -// decode.insert(INSTRUCTION_READY) := True -// -// cache.io.cpu.decode.pc := decode.output(PC) -// -// val ownDecode = pipeline.plugins.filter(_.isInstanceOf[InstructionInjector]).foldLeft(True)(_ && !_.asInstanceOf[InstructionInjector].isInjecting(decode)) -// cache.io.cpu.decode.isValid := decode.arbitration.isValid && ownDecode -// cache.io.cpu.decode.isStuck := decode.arbitration.isStuck -// cache.io.cpu.decode.isUser := (if(privilegeService != null) privilegeService.isUser(decode) else False) -//// cache.io.cpu.decode.pc := decode.input(PC) -// -// redoBranch.valid := decode.arbitration.isValid && ownDecode && cache.io.cpu.decode.cacheMiss && !cache.io.cpu.decode.mmuMiss && !cache.io.cpu.decode.illegalAccess -// redoBranch.payload := decode.input(PC) -// when(redoBranch.valid){ -// decode.arbitration.redoIt := True -// decode.arbitration.flushAll := True -// } -// -//// val redo = RegInit(False) clearWhen(decode.arbitration.isValid) setWhen(redoBranch.valid) -//// when(redoBranch.valid || redo){ -//// service(classOf[InterruptionInhibitor]).inhibateInterrupts() -//// } -// -// if(catchSomething){ -// val accessFault = if(catchAccessFault) cache.io.cpu.decode.error else False -// val mmuMiss = if(catchMemoryTranslationMiss) cache.io.cpu.decode.mmuMiss else False -// val illegalAccess = if(catchIllegalAccess) cache.io.cpu.decode.illegalAccess else False -// -// decodeExceptionPort.valid := decode.arbitration.isValid && ownDecode && (accessFault || mmuMiss || illegalAccess) -// decodeExceptionPort.code := mmuMiss ? U(14) | 1 -// decodeExceptionPort.badAddr := decode.input(PC) -// } -// -// memory plug new Area{ -// import memory._ -// cache.io.flush.cmd.valid := False -// when(arbitration.isValid && input(FLUSH_ALL)){ -// cache.io.flush.cmd.valid := True -// decode.arbitration.flushAll := True -// -// when(!cache.io.flush.cmd.ready){ -// arbitration.haltItself := True -// } -// } -// } -// } +// override def build(pipeline: VexRiscv): Unit = ??? //} +class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends IBusFetcherImpl( + catchAccessFault = config.catchAccessFault, + resetVector = BigInt(0x80000000l), + keepPcPlus4 = false, + decodePcGen = true, + compressedGen = true, + cmdToRspStageCount = 1, + rspStageGen = false, + injectorReadyCutGen = false, + relaxedPcCalculation = false, + prediction = NONE, + catchAddressMisaligned = false, + injectorStage = true){ + import config._ + + var iBus : InstructionCacheMemBus = null + var mmuBus : MemoryTranslatorBus = null + var privilegeService : PrivilegeService = null + var redoBranch : Flow[UInt] = null + + object FLUSH_ALL extends Stageable(Bool) + object IBUS_ACCESS_ERROR extends Stageable(Bool) + object IBUS_MMU_MISS extends Stageable(Bool) + object IBUS_ILLEGAL_ACCESS extends Stageable(Bool) + override def setup(pipeline: VexRiscv): Unit = { + import Riscv._ + import pipeline.config._ + + super.setup(pipeline) + + def MANAGEMENT = M"-----------------100-----0001111" + + val decoderService = pipeline.service(classOf[DecoderService]) + decoderService.addDefault(FLUSH_ALL, False) + decoderService.add(MANAGEMENT, List( + FLUSH_ALL -> True + )) + + + redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.decode, priority = 1) //Priority 1 will win against branch predictor + + if(catchSomething) { + val exceptionService = pipeline.service(classOf[ExceptionService]) + 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[PrivilegeService])) + privilegeService = pipeline.service(classOf[PrivilegeService]) + + if(pipeline.serviceExist(classOf[ReportService])){ + val report = pipeline.service(classOf[ReportService]) + report.add("iBus" -> { + val e = new BusReport() + val c = new CacheReport() + e.kind = "cached" + e.flushInstructions.add(0x400F) //invalid instruction cache + e.flushInstructions.add(0x13) + e.flushInstructions.add(0x13) + e.flushInstructions.add(0x13) + + e.info = c + c.size = cacheSize + c.bytePerLine = bytePerLine + + e + }) + } + } + + override def build(pipeline: VexRiscv): Unit = { + import pipeline._ + import pipeline.config._ + + pipeline plug new FetchArea(pipeline) { + val cache = new InstructionCache(IBusCachedPlugin.this.config) + iBus = master(new InstructionCacheMemBus(IBusCachedPlugin.this.config)).setName("iBus") + iBus <> cache.io.mem + iBus.cmd.address.allowOverride := cache.io.mem.cmd.address // - debugAddressOffset + + //Connect prefetch cache side + cache.io.cpu.prefetch.isValid := fetchPc.output.valid + cache.io.cpu.prefetch.pc := fetchPc.output.payload + iBusRsp.input << fetchPc.output.haltWhen(cache.io.cpu.prefetch.haltIt) + + //Connect fetch cache side + cache.io.cpu.fetch.isValid := iBusRsp.inputPipeline(0).valid + cache.io.cpu.fetch.isStuck := !iBusRsp.inputPipeline(0).ready + cache.io.cpu.fetch.pc := iBusRsp.inputPipeline(0).payload + + 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 + } + + if (dataOnDecode) { + decode.insert(INSTRUCTION) := cache.io.cpu.decode.data + } else { + iBusRsp.outputBeforeStage.arbitrationFrom(iBusRsp.inputPipeline(0)) + iBusRsp.outputBeforeStage.rsp.inst := cache.io.cpu.fetch.data + iBusRsp.outputBeforeStage.pc := iBusRsp.inputPipeline(0).payload + } + + cache.io.cpu.decode.pc := injector.inputBeforeHalt.pc + + val ownDecode = pipeline.plugins.filter(_.isInstanceOf[InstructionInjector]).foldLeft(True)(_ && !_.asInstanceOf[InstructionInjector].isInjecting(decode)) + cache.io.cpu.decode.isValid := decode.arbitration.isValid && ownDecode + cache.io.cpu.decode.isStuck := !injector.inputBeforeHalt.ready + cache.io.cpu.decode.isUser := (if (privilegeService != null) privilegeService.isUser(decode) else False) + // cache.io.cpu.decode.pc := decode.input(PC) + + redoBranch.valid := decode.arbitration.isValid && ownDecode && cache.io.cpu.decode.cacheMiss && !cache.io.cpu.decode.mmuMiss && !cache.io.cpu.decode.illegalAccess + redoBranch.payload := decode.input(PC) + when(redoBranch.valid) { + decode.arbitration.redoIt := True + decode.arbitration.flushAll := True + } + + // val redo = RegInit(False) clearWhen(decode.arbitration.isValid) setWhen(redoBranch.valid) + // when(redoBranch.valid || redo){ + // service(classOf[InterruptionInhibitor]).inhibateInterrupts() + // } + + if (catchSomething) { + val accessFault = if (catchAccessFault) cache.io.cpu.decode.error else False + val mmuMiss = if (catchMemoryTranslationMiss) cache.io.cpu.decode.mmuMiss else False + val illegalAccess = if (catchIllegalAccess) cache.io.cpu.decode.illegalAccess else False + + decodeExceptionPort.valid := decode.arbitration.isValid && ownDecode && (accessFault || mmuMiss || illegalAccess) + decodeExceptionPort.code := mmuMiss ? U(14) | 1 + decodeExceptionPort.badAddr := decode.input(PC) + } + + memory plug new Area { + + import memory._ + + cache.io.flush.cmd.valid := False + when(arbitration.isValid && input(FLUSH_ALL)) { + cache.io.flush.cmd.valid := True + decode.arbitration.flushAll := True + + when(!cache.io.flush.cmd.ready) { + arbitration.haltItself := True + } + } + } + } + } +} diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index 18b558e..49978f0 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -163,12 +163,12 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean, rspBuffer.io.flush := flush val fetchRsp = FetchRsp() - fetchRsp.pc := pipeline.last.payload + fetchRsp.pc := inputPipeline.last.payload fetchRsp.rsp := rspBuffer.io.pop.payload fetchRsp.rsp.error.clearWhen(!rspBuffer.io.pop.valid) //Avoid interference with instruction injection from the debug plugin - val join = StreamJoin(Seq(pipeline.last, rspBuffer.io.pop), fetchRsp) + val join = StreamJoin(Seq(inputPipeline.last, rspBuffer.io.pop), fetchRsp) output << (if(rspStageGen) join.m2sPipeWithFlush(flush) else join) } } diff --git a/src/test/cpp/regression/icache.gtkw b/src/test/cpp/regression/icache.gtkw new file mode 100644 index 0000000..5a7020f --- /dev/null +++ b/src/test/cpp/regression/icache.gtkw @@ -0,0 +1,67 @@ +[*] +[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI +[*] Wed Apr 11 18:53:23 2018 +[*] +[dumpfile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/rv32ui-p-lui.vcd" +[dumpfile_mtime] "Wed Apr 11 18:52:18 2018" +[dumpfile_size] 325049 +[savefile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/icache.gtkw" +[timestart] 1006 +[size] 1784 950 +[pos] -383 -155 +*-5.000000 1046 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] TOP. +[treeopen] TOP.VexRiscv. +[sst_width] 370 +[signals_width] 349 +[sst_expanded] 1 +[sst_vpaned_height] 271 +@28 +TOP.VexRiscv.decode_arbitration_isValid +TOP.VexRiscv.decode_arbitration_redoIt +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_haltIt +@22 +TOP.VexRiscv.iBus_cmd_payload_address[31:0] +@28 +TOP.VexRiscv.iBus_cmd_payload_size[2:0] +TOP.VexRiscv.iBus_cmd_ready +@29 +TOP.VexRiscv.iBus_cmd_valid +@22 +TOP.VexRiscv.iBus_rsp_payload_data[31:0] +@28 +TOP.VexRiscv.iBus_rsp_payload_error +TOP.VexRiscv.iBus_rsp_valid +[color] 2 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_isValid +[color] 2 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_haltIt +@22 +[color] 2 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_pc[31:0] +@28 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_isValid +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_isStuck +@22 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_data[31:0] +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_pc[31:0] +@28 +[color] 6 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_isValid +[color] 6 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_cacheMiss +[color] 6 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_error +[color] 6 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_illegalAccess +[color] 6 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_isStuck +[color] 6 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_isUser +[color] 6 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_mmuMiss +@22 +[color] 6 +TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_pc[31:0] +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index e0322fb..ceb88b2 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -387,10 +387,17 @@ public: if(bootPc != -1) top->VexRiscv->core->prefetch_pc = bootPc; #else if(bootPc != -1) { - top->VexRiscv->IBusSimplePlugin_fetchPc_pcReg = bootPc; - #ifdef COMPRESSED - top->VexRiscv->IBusSimplePlugin_decodePc_pcReg = bootPc; - #endif + #ifdef IBUS_SIMPLE + top->VexRiscv->IBusSimplePlugin_fetchPc_pcReg = bootPc; + #ifdef COMPRESSED + top->VexRiscv->IBusSimplePlugin_decodePc_pcReg = bootPc; + #endif + #else + top->VexRiscv->IBusCachedPlugin_fetchPc_pcReg = bootPc; + #ifdef COMPRESSED + top->VexRiscv->IBusCachedPlugin_decodePc_pcReg = bootPc; + #endif + #endif } #endif