From 1fb138de1f6905925f2b566c43385576582ab0a7 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Tue, 20 Mar 2018 00:01:28 +0100 Subject: [PATCH] IBusSimplePlugin fully functional Need to restore branch prediction --- src/main/scala/vexriscv/Pipeline.scala | 2 +- src/main/scala/vexriscv/Stage.scala | 2 +- src/main/scala/vexriscv/TestsWorkspace.scala | 4 +-- src/main/scala/vexriscv/VexRiscv.scala | 1 + .../scala/vexriscv/plugin/CsrPlugin.scala | 19 +++++++----- .../scala/vexriscv/plugin/DebugPlugin.scala | 10 +++--- .../vexriscv/plugin/IBusSimplePlugin.scala | 28 ++++++++++++++--- .../plugin/PcManagerSimplePlugin.scala | 2 +- src/test/cpp/regression/main.cpp | 31 ++++++++++++------- src/test/cpp/regression/makefile | 7 +++++ 10 files changed, 72 insertions(+), 34 deletions(-) diff --git a/src/main/scala/vexriscv/Pipeline.scala b/src/main/scala/vexriscv/Pipeline.scala index 86a2018..992609d 100644 --- a/src/main/scala/vexriscv/Pipeline.scala +++ b/src/main/scala/vexriscv/Pipeline.scala @@ -126,7 +126,7 @@ trait Pipeline { for(stageIndex <- 1 until stages.length){ val stageBefore = stages(stageIndex - 1) val stage = stages(stageIndex) - + stage.arbitration.isValid.setAsReg() init(False) when(!stage.arbitration.isStuck || stage.arbitration.removeIt) { stage.arbitration.isValid := False } diff --git a/src/main/scala/vexriscv/Stage.scala b/src/main/scala/vexriscv/Stage.scala index c820754..22a7e9f 100644 --- a/src/main/scala/vexriscv/Stage.scala +++ b/src/main/scala/vexriscv/Stage.scala @@ -49,7 +49,7 @@ class Stage() extends Area{ val removeIt = False //When settable, unschedule the instruction as if it was never executed (no side effect) val flushAll = False //When settable, unschedule instructions in the current stage and all prior ones val redoIt = False //Allow to notify that a given instruction in a pipeline is rescheduled - val isValid = RegInit(False) //Inform if a instruction is in the current stage + val isValid = Bool //Inform if a instruction is in the current stage val isStuck = Bool //Inform if the instruction is stuck (haltItself || haltByOther) val isStuckByOthers = Bool //Inform if the instruction is stuck by sombody else def isRemoved = removeIt //Inform if the instruction is going to be unschedule the current cycle diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index 0ed35b0..7b6e7b4 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -57,7 +57,7 @@ object TestsWorkspace { // portTlbSize = 4 // ) // ), -//// new DBusSimplePlugin( +// new DBusSimplePlugin( // catchAddressMisaligned = true, // catchAccessFault = true, // earlyInjection = false @@ -122,7 +122,7 @@ object TestsWorkspace { ), // new DivPlugin, new CsrPlugin(CsrPluginConfig.all(0x80000020l).copy(deterministicInteruptionEntry = false)), -// new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), + new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new BranchPlugin( earlyBranch = true, catchAddressMisaligned = true, diff --git a/src/main/scala/vexriscv/VexRiscv.scala b/src/main/scala/vexriscv/VexRiscv.scala index f9f6a49..412d3a4 100644 --- a/src/main/scala/vexriscv/VexRiscv.scala +++ b/src/main/scala/vexriscv/VexRiscv.scala @@ -22,6 +22,7 @@ case class VexRiscvConfig(plugins : Seq[Plugin[VexRiscv]]){ object REGFILE_WRITE_VALID extends Stageable(Bool) object REGFILE_WRITE_DATA extends Stageable(Bits(32 bits)) + object SRC1 extends Stageable(Bits(32 bits)) object SRC2 extends Stageable(Bits(32 bits)) object SRC_ADD_SUB extends Stageable(Bits(32 bits)) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 81c95a9..5ed12f7 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -291,7 +291,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio override def build(pipeline: VexRiscv): Unit = { import pipeline._ import pipeline.config._ - + val fetcher = service(classOf[IBusFetcher]) pipeline plug new Area{ //Define CSR mapping utilities @@ -376,8 +376,11 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio //Used to make the pipeline empty softly (for interrupts) val pipelineLiberator = new Area{ val enable = False.noBackendCombMerge //Verilator Perf - decode.arbitration.haltByOther setWhen(enable) //TODO FETCH - val done = ! List(execute, memory, writeBack).map(_.arbitration.isValid).orR + when(enable){ + fetcher.haltIt() + } + val done = ! List(decode, execute, memory, writeBack).map(_.arbitration.isValid).orR && fetcher.nextPc()._1 +// val done = History(doneAsync, 0 to 0).andR } @@ -389,7 +392,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio val exceptionValidsRegs = Vec(Reg(Bool) init(False), stages.length).allowUnsetRegToAvoidLatch val exceptionContext = Reg(ExceptionCause()) - pipelineLiberator.enable setWhen(exceptionValidsRegs.tail.orR) + pipelineLiberator.enable setWhen(exceptionValidsRegs.orR) val groupedByStage = exceptionPortsInfos.map(_.stage).distinct.map(s => { val stagePortsInfos = exceptionPortsInfos.filter(_.stage == s).sortWith(_.priority > _.priority) @@ -497,7 +500,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio mstatus.MPP := privilege mepc := exception mux( True -> writeBack.input(PC), - False -> (writeBackWasWfi ? writeBack.input(PC) | decode.input(PC)) + False -> fetcher.nextPc()._2 ) mcause.interrupt := interrupt @@ -529,10 +532,10 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio } //Manage WFI instructions - if(wfiGen) when(execute.arbitration.isValid && execute.input(ENV_CTRL) === EnvCtrlEnum.WFI){ + if(wfiGen) when(decode.arbitration.isValid && decode.input(ENV_CTRL) === EnvCtrlEnum.WFI){ when(!interrupt){ - execute.arbitration.haltItself := True - decode.arbitration.flushAll := True + fetcher.haltIt() + decode.arbitration.haltItself := True } } diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index 44ea0b2..e21538e 100644 --- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala @@ -134,6 +134,7 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w import pipeline.config._ val logic = debugClockDomain {pipeline plug new Area{ + val iBusFetcher = service(classOf[IBusFetcher]) val insertDecodeInstruction = False val firstCycle = RegNext(False) setWhen (io.bus.cmd.ready) val secondCycle = RegNext(firstCycle) @@ -141,7 +142,7 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w val haltIt = RegInit(False) val stepIt = RegInit(False) - val isPipActive = RegNext(List(decode, execute, memory, writeBack).map(_.arbitration.isValid).orR) + val isPipActive = RegNext(List(decode,execute, memory, writeBack).map(_.arbitration.isValid).orR) val isPipBusy = isPipActive || RegNext(isPipActive) val haltedByBreak = RegInit(False) @@ -173,9 +174,9 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w is(1) { when(io.bus.cmd.wr) { insertDecodeInstruction := True - decode.arbitration.isValid setWhen (firstCycle) + decode.arbitration.isValid.getDrivingReg setWhen (firstCycle) decode.arbitration.haltItself setWhen (secondCycle) - io.bus.cmd.ready := !(firstCycle || secondCycle || decode.arbitration.isValid) + io.bus.cmd.ready := !firstCycle && !secondCycle && execute.arbitration.isValid } } } @@ -209,7 +210,8 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w } when(haltIt) { - decode.arbitration.haltByOther := True + iBusFetcher.haltIt() +// decode.arbitration.haltByOther := True } when(stepIt && decode.arbitration.isFiring) { diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index 2c08223..ada2ac8 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -96,7 +96,9 @@ object IBusSimpleBus{ maximumPendingReadTransactions = 8 ) } -case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMasterSlave{ + + +case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMasterSlave { var cmd = Stream(IBusSimpleCmd()) var rsp = Flow(IBusSimpleRsp()) @@ -148,12 +150,24 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste } } -class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean, pendingMax : Int = 7) extends Plugin[VexRiscv] with JumpService{ +trait IBusFetcher{ + def haltIt() : Unit + def nextPc() : (Bool, UInt) +} + +class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean, pendingMax : Int = 7) extends Plugin[VexRiscv] with JumpService with IBusFetcher{ var iBus : IBusSimpleBus = null var prefetchExceptionPort : Flow[ExceptionCause] = null def resetVector = BigInt(0x80000000l) def keepPcPlus4 = false + lazy val fetcherHalt = False + lazy val decodeNextPcValid = Bool + lazy val decodeNextPc = UInt(32 bits) + def nextPc() = (decodeNextPcValid, decodeNextPc) + + override def haltIt(): Unit = fetcherHalt := True + case class JumpInfo(interface : Flow[UInt], stage: Stage, priority : Int) val jumpInfos = ArrayBuffer[JumpInfo]() override def createJumpInterface(stage: Stage, priority : Int = 0): Flow[UInt] = { @@ -258,10 +272,14 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean, val injector = new Area { - val input = iBusRsp.output.s2mPipe(flush) - val stage = input.m2sPipe(flush, false) + val inputBeforeHalt = iBusRsp.output.s2mPipe(flush) + val input = inputBeforeHalt.haltWhen(fetcherHalt) + val stage = input.m2sPipe(flush || decode.arbitration.isRemoved) + + decodeNextPcValid := RegNext(inputBeforeHalt.isStall) + decodeNextPc := decode.input(PC) + stage.ready := !decode.arbitration.isStuck - decode.arbitration.isValid.setAsComb().removeAssignments() decode.arbitration.isValid := stage.valid decode.insert(PC) := stage.pc decode.insert(INSTRUCTION) := stage.rsp.inst diff --git a/src/main/scala/vexriscv/plugin/PcManagerSimplePlugin.scala b/src/main/scala/vexriscv/plugin/PcManagerSimplePlugin.scala index 956fa1a..08adb7f 100644 --- a/src/main/scala/vexriscv/plugin/PcManagerSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/PcManagerSimplePlugin.scala @@ -25,7 +25,7 @@ object KeepAttribute{ class PcManagerSimplePlugin(resetVector : BigInt, relaxedPcCalculation : Boolean = false, keepPcPlus4 : Boolean = true) extends Plugin[VexRiscv]{ - override def build(pipeline: VexRiscv): Unit = ??? + override def build(pipeline: VexRiscv): Unit = {println("PcManagerSimplePlugin is now useless")} } diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index ce737b6..14a46d6 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -182,7 +182,7 @@ public: double cyclesPerSecond = 10e6; double allowedCycles = 0.0; uint32_t bootPc = -1; - uint32_t iStall = 1,dStall = 1; + uint32_t iStall = STALL,dStall = STALL; #ifdef TRACE VerilatedVcdC* tfp; #endif @@ -433,14 +433,21 @@ public: dump(i + 1); - - if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address != 0){ - regTraces << - #ifdef TRACE_WITH_TIME - currentTime << - #endif - " PC " << hex << setw(8) << top->VexRiscv->writeBack_PC << " : reg[" << dec << setw(2) << (uint32_t)top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address << "] = " << hex << setw(8) << top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data << endl; - } + if(top->VexRiscv->writeBack_arbitration_isFiring){ + if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address != 0){ + regTraces << + #ifdef TRACE_WITH_TIME + currentTime << + #endif + " PC " << hex << setw(8) << top->VexRiscv->writeBack_PC << " : reg[" << dec << setw(2) << (uint32_t)top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address << "] = " << hex << setw(8) << top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data << endl; + } else { + regTraces << + #ifdef TRACE_WITH_TIME + currentTime << + #endif + " PC " << hex << setw(8) << top->VexRiscv->writeBack_PC << endl; + } + } for(SimElement* simElement : simElements) simElement->preCycle(); @@ -1429,7 +1436,7 @@ public: int error; if((error = recv(clientSocket, buffer, 4, 0)) != 4){ printf("Should read 4 bytes, had %d", error); - fail(); + while(1); } return *((uint32_t*) buffer); @@ -1502,7 +1509,7 @@ public: while((readCmd(2,debugAddress) & RISCV_SPINAL_FLAGS_HALT) == 0){usleep(100);} if((readValue = readCmd(2,debugAddress + 4)) != 0x80000014){ - printf("wrong break PC 2 %x\n",readValue); + printf("wrong break PC 3 %x\n",readValue); clientFail = true; return; } @@ -1523,7 +1530,7 @@ public: while((readCmd(2,debugAddress) & RISCV_SPINAL_FLAGS_HALT) == 0){usleep(100);} if((readValue = readCmd(2,debugAddress + 4)) != 0x80000024){ - printf("wrong break PC 2 %x\n",readValue); + printf("wrong break PC 3 %x\n",readValue); clientFail = true; return; } diff --git a/src/test/cpp/regression/makefile b/src/test/cpp/regression/makefile index e6d27c1..7c8b7b5 100644 --- a/src/test/cpp/regression/makefile +++ b/src/test/cpp/regression/makefile @@ -9,6 +9,7 @@ DIV?=yes CSR?=yes MMU?=yes ATOMIC?=no +NO_STALL?=no DEBUG_PLUGIN?=STD DEBUG_PLUGIN_EXTERNAL?=no CUSTOM_SIMD_ADD?=no @@ -34,6 +35,12 @@ ifeq ($(DHRYSTONE),yes) ADDCFLAGS += -CFLAGS -DDHRYSTONE endif +ifeq ($(NO_STALL),yes) + ADDCFLAGS += -CFLAGS -DSTALL=0 +else + ADDCFLAGS += -CFLAGS -DSTALL=1 +endif + ifneq ($(MTIME_INSTR_FACTOR),no) ADDCFLAGS += -CFLAGS -DMTIME_INSTR_FACTOR=${MTIME_INSTR_FACTOR} endif