diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index f6839d9..80836e4 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -33,14 +33,14 @@ object TestsWorkspace { plugins = List( new IBusSimplePlugin( resetVector = 0x80000000l, - cmdForkOnSecondStage = true, - cmdForkPersistence = true, + cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = NONE, historyRamSizeLog2 = 10, catchAccessFault = true, compressedGen = false, busLatencyMin = 1, - injectorStage = true + injectorStage = false ), // new IBusCachedPlugin( // resetVector = 0x80000000l, diff --git a/src/main/scala/vexriscv/demo/FormalSimple.scala b/src/main/scala/vexriscv/demo/FormalSimple.scala index 7c6aa4f..9a4167e 100644 --- a/src/main/scala/vexriscv/demo/FormalSimple.scala +++ b/src/main/scala/vexriscv/demo/FormalSimple.scala @@ -16,6 +16,7 @@ object FormalSimple extends App{ new IBusSimplePlugin( resetVector = 0x00000000l, cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = DYNAMIC_TARGET, catchAccessFault = false, compressedGen = true diff --git a/src/main/scala/vexriscv/demo/GenCustomCsr.scala b/src/main/scala/vexriscv/demo/GenCustomCsr.scala index 4ee5546..11db86d 100644 --- a/src/main/scala/vexriscv/demo/GenCustomCsr.scala +++ b/src/main/scala/vexriscv/demo/GenCustomCsr.scala @@ -19,6 +19,7 @@ object GenCustomCsr extends App{ new IBusSimplePlugin( resetVector = 0x00000000l, cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = NONE, catchAccessFault = false, compressedGen = false diff --git a/src/main/scala/vexriscv/demo/GenCustomSimdAdd.scala b/src/main/scala/vexriscv/demo/GenCustomSimdAdd.scala index 3321a9d..8b137f5 100644 --- a/src/main/scala/vexriscv/demo/GenCustomSimdAdd.scala +++ b/src/main/scala/vexriscv/demo/GenCustomSimdAdd.scala @@ -15,6 +15,7 @@ object GenCustomSimdAdd extends App{ new IBusSimplePlugin( resetVector = 0x00000000l, cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = NONE, catchAccessFault = false, compressedGen = false diff --git a/src/main/scala/vexriscv/demo/GenDeterministicVex.scala b/src/main/scala/vexriscv/demo/GenDeterministicVex.scala index 6e3ec39..943ba16 100644 --- a/src/main/scala/vexriscv/demo/GenDeterministicVex.scala +++ b/src/main/scala/vexriscv/demo/GenDeterministicVex.scala @@ -14,6 +14,7 @@ object GenDeterministicVex extends App{ new IBusSimplePlugin( resetVector = 0x80000000l, cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = STATIC, catchAccessFault = true, compressedGen = false diff --git a/src/main/scala/vexriscv/demo/GenFullNoMmuNoCache.scala b/src/main/scala/vexriscv/demo/GenFullNoMmuNoCache.scala index a69c024..77ed87a 100644 --- a/src/main/scala/vexriscv/demo/GenFullNoMmuNoCache.scala +++ b/src/main/scala/vexriscv/demo/GenFullNoMmuNoCache.scala @@ -15,6 +15,7 @@ object GenFullNoMmuNoCache extends App{ new IBusSimplePlugin( resetVector = 0x80000000l, cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = STATIC, catchAccessFault = false, compressedGen = false diff --git a/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala b/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala index 0def2a8..b727b37 100644 --- a/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala +++ b/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala @@ -15,6 +15,7 @@ object GenNoCacheNoMmuMaxPerf extends App{ new IBusSimplePlugin( resetVector = 0x80000000l, cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = DYNAMIC_TARGET, historyRamSizeLog2 = 8, catchAccessFault = true, diff --git a/src/main/scala/vexriscv/demo/GenSmallAndPerformant.scala b/src/main/scala/vexriscv/demo/GenSmallAndPerformant.scala index f0d7c6d..9bd6f72 100644 --- a/src/main/scala/vexriscv/demo/GenSmallAndPerformant.scala +++ b/src/main/scala/vexriscv/demo/GenSmallAndPerformant.scala @@ -14,6 +14,7 @@ object GenSmallAndProductive extends App{ new IBusSimplePlugin( resetVector = 0x80000000l, cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = NONE, catchAccessFault = false, compressedGen = false diff --git a/src/main/scala/vexriscv/demo/GenSmallest.scala b/src/main/scala/vexriscv/demo/GenSmallest.scala index e4131d0..9813ccf 100644 --- a/src/main/scala/vexriscv/demo/GenSmallest.scala +++ b/src/main/scala/vexriscv/demo/GenSmallest.scala @@ -14,6 +14,7 @@ object GenSmallest extends App{ new IBusSimplePlugin( resetVector = 0x80000000l, cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = NONE, catchAccessFault = false, compressedGen = false diff --git a/src/main/scala/vexriscv/demo/GenSmallestNoCsr.scala b/src/main/scala/vexriscv/demo/GenSmallestNoCsr.scala index f5acf98..cd1ee31 100644 --- a/src/main/scala/vexriscv/demo/GenSmallestNoCsr.scala +++ b/src/main/scala/vexriscv/demo/GenSmallestNoCsr.scala @@ -19,6 +19,7 @@ object GenSmallestNoCsr extends App{ new IBusSimplePlugin( resetVector = 0x80000000l, cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = NONE, catchAccessFault = false, compressedGen = false diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala index 8bbd57a..63023ec 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -498,6 +498,7 @@ object MuraxDhrystoneReadyMulDivStatic{ config.cpuPlugins += new IBusSimplePlugin( resetVector = 0x80000000l, cmdForkOnSecondStage = true, + cmdForkPersistence = false, prediction = STATIC, catchAccessFault = false, compressedGen = false diff --git a/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala b/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala index 0aacae6..304a360 100644 --- a/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala +++ b/src/main/scala/vexriscv/demo/VexRiscvAvalonForSim.scala @@ -29,6 +29,7 @@ object VexRiscvAvalonForSim{ new IBusSimplePlugin( resetVector = 0x00000000l, cmdForkOnSecondStage = false, + cmdForkPersistence = false, prediction = STATIC, catchAccessFault = false, compressedGen = false diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala index 9ef683b..1df4272 100644 --- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala @@ -182,7 +182,10 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{ } -class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFault : Boolean = false, earlyInjection : Boolean = false/*, idempotentRegions : (UInt) => Bool = (x) => False*/) extends Plugin[VexRiscv]{ +class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, + catchAccessFault : Boolean = false, + earlyInjection : Boolean = false,/*, idempotentRegions : (UInt) => Bool = (x) => False*/ + onlyLoadWords : Boolean = false) extends Plugin[VexRiscv]{ var dBus : DBusSimpleBus = null @@ -220,7 +223,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul decoderService.addDefault(MEMORY_ENABLE, False) decoderService.add( - List(LB, LH, LW, LBU, LHU, LWU).map(_ -> loadActions) ++ + (if(onlyLoadWords) List(LW) else List(LB, LH, LW, LBU, LHU, LWU)).map(_ -> loadActions) ++ List(SB, SH, SW).map(_ -> storeActions) ) @@ -329,7 +332,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul ) when(arbitration.isValid && input(MEMORY_ENABLE)) { - output(REGFILE_WRITE_DATA) := rspFormated + output(REGFILE_WRITE_DATA) := (if(!onlyLoadWords) rspFormated else input(MEMORY_READ_DATA)) } if(!earlyInjection) diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 572270b..13c8742 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -28,7 +28,7 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean, var dynamicTargetFailureCorrection : Flow[UInt] = null var externalResetVector : UInt = null assert(cmdToRspStageCount >= 1) - assert(!(cmdToRspStageCount == 1 && !injectorStage)) +// assert(!(cmdToRspStageCount == 1 && !injectorStage)) assert(!(compressedGen && !decodePcGen)) var fetcherHalt : Bool = null var fetcherflushIt : Bool = null diff --git a/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala b/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala index e65aaec..9fb11a6 100644 --- a/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala +++ b/src/main/scala/vexriscv/plugin/HazardPessimisticPlugin.scala @@ -7,6 +7,13 @@ import spinal.lib._ class HazardPessimisticPlugin() extends Plugin[VexRiscv] { import Riscv._ + + 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._ diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index fa985cb..5c4b476 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -143,16 +143,17 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste class IBusSimplePlugin(resetVector : BigInt, + cmdForkOnSecondStage : Boolean, + cmdForkPersistence : Boolean, catchAccessFault : Boolean = false, - cmdForkOnSecondStage : Boolean = false, - cmdForkPersistence : Boolean = false, prediction : BranchPrediction = NONE, historyRamSizeLog2 : Int = 10, keepPcPlus4 : Boolean = false, compressedGen : Boolean = false, busLatencyMin : Int = 1, pendingMax : Int = 7, - injectorStage : Boolean = true + injectorStage : Boolean = true, + rspHoldValue : Boolean = false ) extends IBusFetcherImpl( catchAccessFault = catchAccessFault, resetVector = resetVector, @@ -168,6 +169,7 @@ class IBusSimplePlugin(resetVector : BigInt, var iBus : IBusSimpleBus = null var decodeExceptionPort : Flow[ExceptionCause] = null + if(rspHoldValue) assert(busLatencyMin == 1) override def setup(pipeline: VexRiscv): Unit = { super.setup(pipeline) @@ -221,22 +223,29 @@ class IBusSimplePlugin(resetVector : BigInt, discardCounter := (if(cmdForkOnSecondStage) pendingCmdNext else pendingCmd - iBus.rsp.fire.asUInt) } - val rspBuffer = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0)) - rspBuffer.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream - rspBuffer.io.flush := flush + val rspBufferOutput = Stream(IBusSimpleRsp()) + + val rspBuffer = if(!rspHoldValue) new Area{ + val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0)) + c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream + c.io.flush := flush + rspBufferOutput << c.io.pop + } else new Area{ + rspBufferOutput << iBus.rsp.throwWhen(discardCounter =/= 0).toStream + } val fetchRsp = FetchRsp() fetchRsp.pc := stages.last.output.payload - fetchRsp.rsp := rspBuffer.io.pop.payload - fetchRsp.rsp.error.clearWhen(!rspBuffer.io.pop.valid) //Avoid interference with instruction injection from the debug plugin + fetchRsp.rsp := rspBufferOutput.payload + fetchRsp.rsp.error.clearWhen(!rspBufferOutput.valid) //Avoid interference with instruction injection from the debug plugin var issueDetected = False val join = Stream(FetchRsp()) - join.valid := stages.last.output.valid && rspBuffer.io.pop.valid + join.valid := stages.last.output.valid && rspBufferOutput.valid join.payload := fetchRsp stages.last.output.ready := stages.last.output.valid ? join.fire | join.ready - rspBuffer.io.pop.ready := join.fire + rspBufferOutput.ready := join.fire output << join.haltWhen(issueDetected) if(catchAccessFault){ diff --git a/src/main/scala/vexriscv/plugin/RegFilePlugin.scala b/src/main/scala/vexriscv/plugin/RegFilePlugin.scala index c1a4409..12793b9 100644 --- a/src/main/scala/vexriscv/plugin/RegFilePlugin.scala +++ b/src/main/scala/vexriscv/plugin/RegFilePlugin.scala @@ -11,10 +11,14 @@ trait RegFileReadKind object ASYNC extends RegFileReadKind object SYNC extends RegFileReadKind -class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = false, writeRfInMemoryStage : Boolean = false) extends Plugin[VexRiscv]{ +class RegFilePlugin(regFileReadyKind : RegFileReadKind, + zeroBoot : Boolean = false, + writeRfInMemoryStage : Boolean = false, + readInExecute : Boolean = false) extends Plugin[VexRiscv]{ import Riscv._ - assert(!writeRfInMemoryStage) +// assert(!writeRfInMemoryStage) + override def setup(pipeline: VexRiscv): Unit = { import pipeline.config._ @@ -33,19 +37,21 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = fals if(zeroBoot) regFile.init(List.fill(32)(B(0, 32 bits))) } - //Read register file - decode plug new Area{ - import decode._ + //Disable rd0 write in decoding stage + when(decode.input(INSTRUCTION)(rdRange) === 0) { + decode.input(REGFILE_WRITE_VALID) := False + } - //Disable rd0 write in decoding stage - when(decode.input(INSTRUCTION)(rdRange) === 0) { - decode.input(REGFILE_WRITE_VALID) := False - } + //Read register file + val readStage = if(readInExecute) execute else decode + readStage plug new Area{ + import readStage._ //read register file val srcInstruction = regFileReadyKind match{ case `ASYNC` => input(INSTRUCTION) - case `SYNC` => input(INSTRUCTION_ANTICIPATED) + case `SYNC` if !readInExecute => input(INSTRUCTION_ANTICIPATED) + case `SYNC` if readInExecute => Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION)) } val regFileReadAddress1 = srcInstruction(Riscv.rs1Range).asUInt @@ -61,8 +67,9 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = fals } //Write register file - (if(writeRfInMemoryStage) memory else writeBack) plug new Area { - import writeBack._ + val writeStage = if(writeRfInMemoryStage) memory else writeBack + writeStage plug new Area { + import writeStage._ val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public) regFileWrite.valid := output(REGFILE_WRITE_VALID) && arbitration.isFiring diff --git a/src/test/scala/vexriscv/experimental/GenMicro.scala b/src/test/scala/vexriscv/experimental/GenMicro.scala new file mode 100644 index 0000000..e5a9eaf --- /dev/null +++ b/src/test/scala/vexriscv/experimental/GenMicro.scala @@ -0,0 +1,113 @@ +package vexriscv.experimental + +import spinal.core._ +import spinal.lib.eda.bench.{AlteraStdTargets, Bench, Rtl, XilinxStdTargets} +import spinal.lib.eda.icestorm.IcestormStdTargets +import vexriscv.demo.{GenSmallestNoCsr, Murax, MuraxConfig} +import vexriscv.plugin._ +import vexriscv.{VexRiscv, VexRiscvConfig, plugin} + +/** + * Created by spinalvm on 15.06.17. + */ +object GenMicro extends App{ + def cpu() = { + val removeOneFetchStage = true + val writeBackOpt = true + val onlyLoadWords = true + val rspHoldValue = true + val earlyBranch = false + val noShifter = true + val pessimisticHazard = true + new VexRiscv( + config = VexRiscvConfig( + plugins = List( + // new PcManagerSimplePlugin( + // resetVector = 0x00000000l, + // relaxedPcCalculation = false + // ), + + new IBusSimplePlugin( + resetVector = 0x80000000l, + cmdForkOnSecondStage = false, + cmdForkPersistence = false, + prediction = NONE, + catchAccessFault = false, + compressedGen = false, + injectorStage = !removeOneFetchStage, + rspHoldValue = rspHoldValue + ), + new DBusSimplePlugin( + catchAddressMisaligned = false, + catchAccessFault = false, + earlyInjection = writeBackOpt, + onlyLoadWords = onlyLoadWords + ), + new DecoderSimplePlugin( + catchIllegalInstruction = false + ), + new RegFilePlugin( + regFileReadyKind = plugin.SYNC, + zeroBoot = false, + readInExecute = removeOneFetchStage, + writeRfInMemoryStage = writeBackOpt + ), + new IntAluPlugin, + new SrcPlugin( + separatedAddSub = false, + executeInsertion = removeOneFetchStage + ), + if(!pessimisticHazard) + new HazardSimplePlugin( + bypassExecute = false, + bypassMemory = false, + bypassWriteBack = false, + bypassWriteBackBuffer = false, + pessimisticUseSrc = false, + pessimisticWriteRegFile = false, + pessimisticAddressMatch = false + ) + else + new HazardPessimisticPlugin(), + new BranchPlugin( + earlyBranch = earlyBranch, + catchAddressMisaligned = false + ), + new YamlPlugin("cpu0.yaml") + ) ++ (if(noShifter) Nil else List(new LightShifterPlugin)) + ) + ) + } + SpinalConfig(mergeAsyncProcess = false).generateVerilog(cpu()) +} + + + +object GenMicroSynthesis { + def main(args: Array[String]) { + val microNoCsr = new Rtl { + override def getName(): String = "MicroNoCsr" + override def getRtlPath(): String = "MicroNoCsr.v" + SpinalVerilog(GenMicro.cpu().setDefinitionName(getRtlPath().split("\\.").head)) + } + + val smallestNoCsr = new Rtl { + override def getName(): String = "SmallestNoCsr" + override def getRtlPath(): String = "SmallestNoCsr.v" + SpinalVerilog(GenSmallestNoCsr.cpu().setDefinitionName(getRtlPath().split("\\.").head)) + } + + val rtls = List(microNoCsr) +// val rtls = List(smallestNoCsr) + + val targets = IcestormStdTargets().take(1) ++ XilinxStdTargets( + vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin" + ) ++ AlteraStdTargets( + quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin/", + quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin/" + ) + + + Bench(rtls, targets, "/eda/tmp/") + } +} \ No newline at end of file diff --git a/src/test/scala/vexriscv/experimental/config.scala b/src/test/scala/vexriscv/experimental/config.scala index b44e662..d6eca55 100644 --- a/src/test/scala/vexriscv/experimental/config.scala +++ b/src/test/scala/vexriscv/experimental/config.scala @@ -12,7 +12,7 @@ object Presentation extends App{ val config = VexRiscvConfig() config.plugins ++= List( - new IBusSimplePlugin(resetVector = 0x80000000l), +// new IBusSimplePlugin(resetVector = 0x80000000l), new DBusSimplePlugin, new CsrPlugin(CsrPluginConfig.smallest), new DecoderSimplePlugin,