From 0d92a5e5cddee85255673fa742db7bc558c97fca Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Mon, 12 Nov 2018 14:14:34 +0100 Subject: [PATCH] Add many little options to reduce area --- src/main/scala/vexriscv/Services.scala | 5 ++++ .../scala/vexriscv/plugin/BranchPlugin.scala | 6 ++-- .../scala/vexriscv/plugin/CsrPlugin.scala | 14 +++++---- .../vexriscv/plugin/DBusSimplePlugin.scala | 17 +++++++---- .../plugin/HazardPessimisticPlugin.scala | 2 +- .../vexriscv/plugin/HazardSimplePlugin.scala | 28 +++++++++--------- .../vexriscv/plugin/IBusSimplePlugin.scala | 17 ++++++++--- .../vexriscv/plugin/NoPipeliningPlugin.scala | 23 +++++++++++++++ .../scala/vexriscv/plugin/RegFilePlugin.scala | 29 ++++++++++++++----- .../scala/vexriscv/plugin/ShiftPlugins.scala | 3 +- src/test/python/gcloud/run.sh | 2 +- 11 files changed, 105 insertions(+), 41 deletions(-) create mode 100644 src/main/scala/vexriscv/plugin/NoPipeliningPlugin.scala diff --git a/src/main/scala/vexriscv/Services.scala b/src/main/scala/vexriscv/Services.scala index 5a6dba2..33adf07 100644 --- a/src/main/scala/vexriscv/Services.scala +++ b/src/main/scala/vexriscv/Services.scala @@ -47,6 +47,11 @@ trait ExceptionInhibitor{ def inhibateException() : Unit } +trait RegFileService{ + def readStage() : Stage +} + + case class MemoryTranslatorCmd() extends Bundle{ val isValid = Bool val virtualAddress = UInt(32 bits) diff --git a/src/main/scala/vexriscv/plugin/BranchPlugin.scala b/src/main/scala/vexriscv/plugin/BranchPlugin.scala index 287e0e2..876a07e 100644 --- a/src/main/scala/vexriscv/plugin/BranchPlugin.scala +++ b/src/main/scala/vexriscv/plugin/BranchPlugin.scala @@ -192,7 +192,7 @@ class BranchPlugin(earlyBranch : Boolean, //Apply branchs (JAL,JALR, Bxx) branchStage plug new Area { import branchStage._ - jumpInterface.valid := arbitration.isFiring && input(BRANCH_DO) + jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO) jumpInterface.payload := input(BRANCH_CALC) when(jumpInterface.valid) { @@ -272,7 +272,7 @@ class BranchPlugin(earlyBranch : Boolean, val branchStage = if(earlyBranch) execute else memory branchStage plug new Area { import branchStage._ - jumpInterface.valid := input(BRANCH_DO) && arbitration.isFiring + jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO) jumpInterface.payload := input(BRANCH_CALC) when(jumpInterface.valid) { @@ -349,7 +349,7 @@ class BranchPlugin(earlyBranch : Boolean, input(PC) } - jumpInterface.valid := arbitration.isFiring && predictionMissmatch //Probably just isValid instead of isFiring is better + jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && predictionMissmatch //Probably just isValid instead of isFiring is better jumpInterface.payload := (input(BRANCH_DO) ? input(BRANCH_CALC) | input(NEXT_PC)) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 8bd32ae..7a68af6 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -763,9 +763,13 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception val illegalAccess = arbitration.isValid && input(IS_CSR) val illegalInstruction = False if(selfException != null) { - selfException.valid := illegalAccess || illegalInstruction - selfException.code := 2 + selfException.valid := False + selfException.code.assignDontCare() selfException.badAddr.assignDontCare() + if(catchIllegalAccess) when(illegalAccess || illegalInstruction){ + selfException.valid := True + selfException.code := 2 + } } //Manage MRET / SRET instructions @@ -796,9 +800,9 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception val readData = B(0, 32 bits) val writeInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE) val readInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) - val writeEnable = writeInstruction && ! blockedBySideEffects // && readDataRegValid - val readEnable = readInstruction && ! blockedBySideEffects // && !readDataRegValid - + val writeEnable = writeInstruction && ! blockedBySideEffects && !arbitration.isStuckByOthers// && readDataRegValid + val readEnable = readInstruction && ! blockedBySideEffects && !arbitration.isStuckByOthers// && !readDataRegValid + //arbitration.isStuckByOthers, in case of the hazardPlugin is in the executeStage // def readDataReg = memory.input(REGFILE_WRITE_DATA) //PIPE OPT diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala index fd8bc3d..4c9ad88 100644 --- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala @@ -197,9 +197,12 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, object ALIGNEMENT_FAULT extends Stageable(Bool) var memoryExceptionPort : Flow[ExceptionCause] = null + var rspStage : Stage = null + override def setup(pipeline: VexRiscv): Unit = { import Riscv._ import pipeline.config._ + import pipeline._ val decoderService = pipeline.service(classOf[DecoderService]) @@ -230,7 +233,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, - val rspStage = if(emitCmdInMemoryStage) pipeline.writeBack else pipeline.memory + rspStage = if(stages.last == execute) execute else (if(emitCmdInMemoryStage) writeBack else memory) if(catchAccessFault || catchAddressMisaligned) { val exceptionService = pipeline.service(classOf[ExceptionService]) memoryExceptionPort = exceptionService.newExceptionPort(rspStage) @@ -243,11 +246,14 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, dBus = master(DBusSimpleBus()).setName("dBus") + //Emit dBus.cmd request val cmdStage = if(emitCmdInMemoryStage) memory else execute cmdStage plug new Area{ import cmdStage._ + val cmdSent = if(rspStage == execute) RegInit(False) setWhen(dBus.cmd.fire) clearWhen(!execute.arbitration.isStuck) else False + insert(ALIGNEMENT_FAULT) := { if (catchAddressMisaligned) (dBus.cmd.size === 2 && dBus.cmd.address(1 downto 0) =/= 0) || (dBus.cmd.size === 1 && dBus.cmd.address(0 downto 0) =/= 0) @@ -255,7 +261,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, False } - dBus.cmd.valid := arbitration.isValid && input(MEMORY_ENABLE) && !arbitration.isStuckByOthers && !arbitration.isFlushed && !input(ALIGNEMENT_FAULT) + dBus.cmd.valid := arbitration.isValid && input(MEMORY_ENABLE) && !arbitration.isStuckByOthers && !arbitration.isFlushed && !input(ALIGNEMENT_FAULT) && !cmdSent dBus.cmd.wr := input(INSTRUCTION)(5) dBus.cmd.address := input(SRC_ADD).asUInt dBus.cmd.size := input(INSTRUCTION)(13 downto 12).asUInt @@ -264,7 +270,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, U(1) -> input(RS2)(15 downto 0) ## input(RS2)(15 downto 0), default -> input(RS2)(31 downto 0) ) - when(arbitration.isValid && input(MEMORY_ENABLE) && !dBus.cmd.ready && !input(ALIGNEMENT_FAULT)){ + when(arbitration.isValid && input(MEMORY_ENABLE) && !dBus.cmd.ready && !input(ALIGNEMENT_FAULT) && !cmdSent){ arbitration.haltItself := True } @@ -283,9 +289,8 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, } //Collect dBus.rsp read responses - val rspStage = if(emitCmdInMemoryStage) writeBack else memory rspStage plug new Area { - import rspStage._ + val s = rspStage; import s._ insert(MEMORY_READ_DATA) := dBus.rsp.data @@ -313,7 +318,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, } - assert(!(dBus.rsp.ready && input(MEMORY_ENABLE) && arbitration.isValid && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend") + if(rspStage != execute) assert(!(dBus.rsp.ready && input(MEMORY_ENABLE) && arbitration.isValid && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend") } //Reformat read responses, REGFILE_WRITE_DATA overriding diff --git a/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala b/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala index a16324f..5a8f4d3 100644 --- a/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala +++ b/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala @@ -19,6 +19,6 @@ class HazardPessimisticPlugin() extends Plugin[VexRiscv] { import pipeline.config._ val writesInPipeline = stages.dropWhile(_ != execute).map(s => s.arbitration.isValid && s.input(REGFILE_WRITE_VALID)) :+ RegNext(stages.last.arbitration.isValid && stages.last.input(REGFILE_WRITE_VALID)) - decode.arbitration.haltItself.setWhen(decode.arbitration.isValid && writesInPipeline.orR) + decode.arbitration.haltByOther.setWhen(decode.arbitration.isValid && writesInPipeline.orR) } } diff --git a/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala b/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala index 51d059d..fecdcca 100644 --- a/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala @@ -26,18 +26,20 @@ class HazardSimplePlugin(bypassExecute : Boolean = false, val src0Hazard = False val src1Hazard = False + val readStage = service(classOf[RegFileService]).readStage() + def trackHazardWithStage(stage : Stage,bypassable : Boolean, runtimeBypassable : Stageable[Bool]): Unit ={ val runtimeBypassableValue = if(runtimeBypassable != null) stage.input(runtimeBypassable) else True - val addr0Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === decode.input(INSTRUCTION)(rs1Range) - val addr1Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === decode.input(INSTRUCTION)(rs2Range) + val addr0Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs1Range) + val addr1Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs2Range) when(stage.arbitration.isValid && stage.input(REGFILE_WRITE_VALID)) { if (bypassable) { when(runtimeBypassableValue) { when(addr0Match) { - decode.input(RS1) := stage.output(REGFILE_WRITE_DATA) + readStage.input(RS1) := stage.output(REGFILE_WRITE_DATA) } when(addr1Match) { - decode.input(RS2) := stage.output(REGFILE_WRITE_DATA) + readStage.input(RS2) := stage.output(REGFILE_WRITE_DATA) } } } @@ -64,15 +66,15 @@ class HazardSimplePlugin(bypassExecute : Boolean = false, writeBackWrites.data := stages.last.output(REGFILE_WRITE_DATA) val writeBackBuffer = writeBackWrites.stage() - val addr0Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === decode.input(INSTRUCTION)(rs1Range) - val addr1Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === decode.input(INSTRUCTION)(rs2Range) + val addr0Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === readStage.input(INSTRUCTION)(rs1Range) + val addr1Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === readStage.input(INSTRUCTION)(rs2Range) when(writeBackBuffer.valid) { if (bypassWriteBackBuffer) { when(addr0Match) { - decode.input(RS1) := writeBackBuffer.data + readStage.input(RS1) := writeBackBuffer.data } when(addr1Match) { - decode.input(RS2) := writeBackBuffer.data + readStage.input(RS2) := writeBackBuffer.data } } else { when(addr0Match) { @@ -86,20 +88,20 @@ class HazardSimplePlugin(bypassExecute : Boolean = false, if(withWriteBackStage) trackHazardWithStage(writeBack,bypassWriteBack,null) if(withMemoryStage) trackHazardWithStage(memory ,bypassMemory ,BYPASSABLE_MEMORY_STAGE) - trackHazardWithStage(execute ,bypassExecute , if(stages.last == execute) null else BYPASSABLE_EXECUTE_STAGE) + if(readStage != execute) trackHazardWithStage(execute ,bypassExecute , if(stages.last == execute) null else BYPASSABLE_EXECUTE_STAGE) if(!pessimisticUseSrc) { - when(!decode.input(RS1_USE)) { + when(!readStage.input(RS1_USE)) { src0Hazard := False } - when(!decode.input(RS2_USE)) { + when(!readStage.input(RS2_USE)) { src1Hazard := False } } - when(decode.arbitration.isValid && (src0Hazard || src1Hazard)){ - decode.arbitration.haltItself := True + when(readStage.arbitration.isValid && (src0Hazard || src1Hazard)){ + readStage.arbitration.haltByOther := True } } } diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index 41b4de3..cffc86a 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -153,7 +153,8 @@ class IBusSimplePlugin(resetVector : BigInt, busLatencyMin : Int = 1, pendingMax : Int = 7, injectorStage : Boolean = true, - rspHoldValue : Boolean = false + rspHoldValue : Boolean = false, + singleInstructionPipeline : Boolean = false ) extends IBusFetcherImpl( resetVector = resetVector, keepPcPlus4 = keepPcPlus4, @@ -168,7 +169,7 @@ class IBusSimplePlugin(resetVector : BigInt, var iBus : IBusSimpleBus = null var decodeExceptionPort : Flow[ExceptionCause] = null - if(rspHoldValue) assert(busLatencyMin == 1) + if(rspHoldValue) assert(busLatencyMin <= 1) override def setup(pipeline: VexRiscv): Unit = { super.setup(pipeline) @@ -197,7 +198,12 @@ class IBusSimplePlugin(resetVector : BigInt, //This implementation keep the cmd on the bus until it's executed or the the pipeline is flushed def stage = iBusRsp.stages(if(cmdForkOnSecondStage) 1 else 0) stage.halt setWhen(stage.input.valid && (!cmd.valid || !cmd.ready)) - cmd.valid := stage.input.valid && stage.output.ready && pendingCmd =/= pendingMax + if(singleInstructionPipeline) { + cmd.valid := stage.input.valid && pendingCmd =/= pendingMax && !stages.map(_.arbitration.isValid).orR + assert(injectorStage == false) + assert(iBusRsp.stages.dropWhile(_ != stage).length <= 2) + }else + cmd.valid := stage.input.valid && stage.output.ready && pendingCmd =/= pendingMax cmd.pc := stage.input.payload(31 downto 2) @@ "00" } else new Area{ //This implementation keep the cmd on the bus until it's executed, even if the pipeline is flushed @@ -230,7 +236,10 @@ class IBusSimplePlugin(resetVector : BigInt, c.io.flush := flush rspBufferOutput << c.io.pop } else new Area{ - rspBufferOutput << iBus.rsp.throwWhen(discardCounter =/= 0).toStream + val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream + val validReg = RegInit(False) setWhen(rspStream.valid) clearWhen(rspBufferOutput.ready) + rspBufferOutput << rspStream + rspBufferOutput.valid setWhen(validReg) } val fetchRsp = FetchRsp() diff --git a/src/main/scala/vexriscv/plugin/NoPipeliningPlugin.scala b/src/main/scala/vexriscv/plugin/NoPipeliningPlugin.scala new file mode 100644 index 0000000..b4ad22b --- /dev/null +++ b/src/main/scala/vexriscv/plugin/NoPipeliningPlugin.scala @@ -0,0 +1,23 @@ +package vexriscv.plugin + +import spinal.core._ +import spinal.lib._ +import vexriscv._ + + +class NoPipeliningPlugin() extends Plugin[VexRiscv] { + + override def setup(pipeline: VexRiscv): Unit = { + import pipeline.config._ + val decoderService = pipeline.service(classOf[DecoderService]) + decoderService.addDefault(HAS_SIDE_EFFECT, False) + } + + override def build(pipeline: VexRiscv): Unit = { + import pipeline._ + import pipeline.config._ + + val writesInPipeline = stages.dropWhile(_ != execute).map(s => s.arbitration.isValid && s.input(REGFILE_WRITE_VALID)) :+ RegNext(stages.last.arbitration.isValid && stages.last.input(REGFILE_WRITE_VALID)) + decode.arbitration.haltByOther.setWhen(stagesFromExecute.map(_.arbitration.isValid).orR) + } +} diff --git a/src/main/scala/vexriscv/plugin/RegFilePlugin.scala b/src/main/scala/vexriscv/plugin/RegFilePlugin.scala index 74d0050..5f202b6 100644 --- a/src/main/scala/vexriscv/plugin/RegFilePlugin.scala +++ b/src/main/scala/vexriscv/plugin/RegFilePlugin.scala @@ -13,13 +13,17 @@ object SYNC extends RegFileReadKind class RegFilePlugin(regFileReadyKind : RegFileReadKind, zeroBoot : Boolean = false, + x0Init : Boolean = true, writeRfInMemoryStage : Boolean = false, - readInExecute : Boolean = false) extends Plugin[VexRiscv]{ + readInExecute : Boolean = false, + syncUpdateOnStall : Boolean = true) extends Plugin[VexRiscv] with RegFileService{ import Riscv._ // assert(!writeRfInMemoryStage) + override def readStage(): Stage = if(readInExecute) pipeline.execute else pipeline.decode + override def setup(pipeline: VexRiscv): Unit = { import pipeline.config._ val decoderService = pipeline.service(classOf[DecoderService]) @@ -51,7 +55,7 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind, val srcInstruction = regFileReadyKind match{ case `ASYNC` => input(INSTRUCTION) case `SYNC` if !readInExecute => input(INSTRUCTION_ANTICIPATED) - case `SYNC` if readInExecute => Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION)) + case `SYNC` if readInExecute => if(syncUpdateOnStall) Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION)) else decode.input(INSTRUCTION) } val regFileReadAddress1 = srcInstruction(Riscv.rs1Range).asUInt @@ -59,7 +63,9 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind, val (rs1Data,rs2Data) = regFileReadyKind match{ case `ASYNC` => (global.regFile.readAsync(regFileReadAddress1),global.regFile.readAsync(regFileReadAddress2)) - case `SYNC` => (global.regFile.readSync(regFileReadAddress1),global.regFile.readSync(regFileReadAddress2)) + case `SYNC` => + val enable = if(!syncUpdateOnStall) !readStage.arbitration.isStuck else null + (global.regFile.readSync(regFileReadAddress1, enable),global.regFile.readSync(regFileReadAddress2, enable)) } insert(RS1) := rs1Data @@ -77,10 +83,19 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind, regFileWrite.data := output(REGFILE_WRITE_DATA) //CPU will initialise constant register zero in the first cycle - regFileWrite.valid setWhen(RegNext(False) init(True)) - inputInit[Bits](REGFILE_WRITE_DATA, 0) - inputInit[Bits](INSTRUCTION, 0) + if(x0Init) { + val boot = RegNext(False) init (True) + regFileWrite.valid setWhen (boot) + if (writeStage != execute) { + inputInit[Bits](REGFILE_WRITE_DATA, 0) + inputInit[Bits](INSTRUCTION, 0) + } else { + when(boot) { + regFileWrite.address := 0 + regFileWrite.data := 0 + } + } + } } - } } \ No newline at end of file diff --git a/src/main/scala/vexriscv/plugin/ShiftPlugins.scala b/src/main/scala/vexriscv/plugin/ShiftPlugins.scala index 4f34847..563ba27 100644 --- a/src/main/scala/vexriscv/plugin/ShiftPlugins.scala +++ b/src/main/scala/vexriscv/plugin/ShiftPlugins.scala @@ -152,7 +152,8 @@ class LightShifterPlugin extends Plugin[VexRiscv]{ val isShift = input(SHIFT_CTRL) =/= ShiftCtrlEnum.DISABLE val amplitudeReg = Reg(UInt(5 bits)) val amplitude = isActive ? amplitudeReg | input(SRC2)(4 downto 0).asUInt - val shiftInput = isActive ? memory.input(REGFILE_WRITE_DATA) | input(SRC1) + val shiftReg = ifGen(!withMemoryStage) (RegNextWhen(execute.output(REGFILE_WRITE_DATA), !arbitration.isStuckByOthers)) + val shiftInput = isActive ? (if(withMemoryStage) memory.input(REGFILE_WRITE_DATA) else shiftReg) | input(SRC1) val done = amplitude(4 downto 1) === 0 diff --git a/src/test/python/gcloud/run.sh b/src/test/python/gcloud/run.sh index 0408d1d..cd16afb 100644 --- a/src/test/python/gcloud/run.sh +++ b/src/test/python/gcloud/run.sh @@ -10,7 +10,7 @@ cd VexRiscv sudo git init sudo git add * sudo git commit -m miaou -export VEXRISCV_REGRESSION_CONFIG_COUNT=16 +export VEXRISCV_REGRESSION_CONFIG_COUNT=64 export VEXRISCV_REGRESSION_FREERTOS_COUNT=yes sbt test cd ..