diff --git a/README.md b/README.md index 3fbfef0..6ed4a4f 100644 --- a/README.md +++ b/README.md @@ -66,53 +66,53 @@ The CPU configurations used below can be found in the `src/scala/vexriscv/demo` ``` VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) -> - Artix 7 -> 366 Mhz 488 LUT 505 FF - Cyclone V -> 181 Mhz 350 ALMs - Cyclone IV -> 177 Mhz 732 LUT 494 FF - iCE40 -> 85 Mhz 1131 LC + Artix 7 -> 324 Mhz 496 LUT 505 FF + Cyclone V -> 193 Mhz 347 ALMs + Cyclone IV -> 179 Mhz 730 LUT 494 FF + iCE40 -> 92 Mhz 1130 LC VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) -> - Artix 7 -> 317 Mhz 539 LUT 559 FF - Cyclone V -> 191 Mhz 393 ALMs - Cyclone IV -> 171 Mhz 826 LUT 547 FF - iCE40 -> 72 Mhz 1284 LC + Artix 7 -> 328 Mhz 539 LUT 562 FF + Cyclone V -> 189 Mhz 387 ALMs + Cyclone IV -> 175 Mhz 829 LUT 550 FF + iCE40 -> 85 Mhz 1292 LC VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) -> - Artix 7 -> 338 Mhz 697 LUT 527 FF - Cyclone V -> 149 Mhz 495 ALMs - Cyclone IV -> 137 Mhz 1,103 LUT 522 FF - iCE40 -> 65 Mhz 1593 LC + Artix 7 -> 324 Mhz 701 LUT 531 FF + Cyclone V -> 145 Mhz 499 ALMs + Cyclone IV -> 150 Mhz 1,111 LUT 525 FF + iCE40 -> 63 Mhz 1596 LC VexRiscv small and productive with I$ (RV32I, 0.70 DMIPS/Mhz, 4KB-I$) -> - Artix 7 -> 314 Mhz 721 LUT 562 FF - Cyclone V -> 152 Mhz 504 ALMs - Cyclone IV -> 142 Mhz 1,146 LUT 528 FF - iCE40 -> 69 Mhz 1661 LC + Artix 7 -> 336 Mhz 764 LUT 562 FF + Cyclone V -> 145 Mhz 511 ALMs + Cyclone IV -> 144 Mhz 1,145 LUT 531 FF + iCE40 -> 66 Mhz 1680 LC VexRiscv full no cache (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz, single cycle barrel shifter, debug module, catch exceptions, static branch) -> - Artix 7 -> 325 Mhz 1448 LUT 976 FF - Cyclone V -> 141 Mhz 957 ALMs - Cyclone IV -> 139 Mhz 2,001 LUT 966 FF + Artix 7 -> 326 Mhz 1544 LUT 977 FF + Cyclone V -> 139 Mhz 958 ALMs + Cyclone IV -> 135 Mhz 2,011 LUT 968 FF VexRiscv full (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz with cache trashing, 4KB-I$,4KB-D$, single cycle barrel shifter, debug module, catch exceptions, static branch) -> - Artix 7 -> 241 Mhz 1692 LUT 1202 FF - Cyclone V -> 132 Mhz 1,127 ALMs - Cyclone IV -> 124 Mhz 2,296 LUT 1,115 FF + Artix 7 -> 279 Mhz 1686 LUT 1172 FF + Cyclone V -> 144 Mhz 1,128 ALMs + Cyclone IV -> 133 Mhz 2,298 LUT 1,096 FF VexRiscv full max dmips/mhz -> (RV32IM, 1.44 DMIPS/Mhz 2.70 Coremark/Mhz,, 16KB-I$,16KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch prediction in the fetch stage, branch and shift operations done in the Execute stage) -> - Artix 7 -> 195 Mhz 1824 LUT 1110 FF - Cyclone V -> 83 Mhz 1,067 ALMs - Cyclone IV -> 78 Mhz 2,335 LUT 1,045 FF + Artix 7 -> 195 Mhz 1943 LUT 1111 FF + Cyclone V -> 90 Mhz 1,089 ALMs + Cyclone IV -> 80 Mhz 2,335 LUT 1,048 FF VexRiscv full with MMU (RV32IM, 1.24 DMIPS/Mhz 2.35 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch, MMU) -> - Artix 7 -> 218 Mhz 1966 LUT 1551 FF - Cyclone V -> 123 Mhz 1,298 ALMs - Cyclone IV -> 109 Mhz 2,703 LUT 1,498 FF + Artix 7 -> 239 Mhz 2029 LUT 1585 FF + Cyclone V -> 124 Mhz 1,319 ALMs + Cyclone IV -> 122 Mhz 2,710 LUT 1,501 FF VexRiscv linux balanced (RV32IMA, 1.21 DMIPS/Mhz 2.27 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, catch exceptions, static branch, MMU, Supervisor, Compatible with mainstream linux) -> - Artix 7 -> 239 Mhz 2483 LUT 2134 FF - Cyclone V -> 130 Mhz 1,636 ALMs - Cyclone IV -> 116 Mhz 3,324 LUT 2,010 FF + Artix 7 -> 249 Mhz 2549 LUT 2014 FF + Cyclone V -> 125 Mhz 1,618 ALMs + Cyclone IV -> 116 Mhz 3,314 LUT 2,016 FF ``` @@ -296,9 +296,9 @@ You can find some FPGA projects which instantiate the Briey SoC here (DE1-SoC, D Here are some measurements of Briey SoC timings and area : ``` - Artix 7 -> 232 Mhz 3042 LUT 3281 FF - Cyclone V -> 138 Mhz 2,179 ALMs - Cyclone IV -> 120 Mhz 4,333 LUT 3,167 FF + Artix 7 -> 275 Mhz 3072 LUT 3291 FF + Cyclone V -> 139 Mhz 2,175 ALMs + Cyclone IV -> 129 Mhz 4,337 LUT 3,170 FF ``` ## Murax SoC @@ -351,16 +351,16 @@ Here are some timing and area measurements of the Murax SoC: ``` Murax interlocked stages (0.45 DMIPS/Mhz, 8 bits GPIO) -> - Artix 7 - > 301 Mhz 1032 LUT 1199 FF - Cyclone V -> 183 Mhz 736 ALMs - Cyclone IV -> 148 Mhz 1,481 LUT 1,204 FF - iCE40 -> 69 Mhz 2403 LC (nextpnr) + Artix 7 -> 313 Mhz 1039 LUT 1200 FF + Cyclone V -> 173 Mhz 737 ALMs + Cyclone IV -> 144 Mhz 1,484 LUT 1,206 FF + iCE40 -> 64 Mhz 2422 LC (nextpnr) MuraxFast bypassed stages (0.65 DMIPS/Mhz, 8 bits GPIO) -> - Artix 7 -> 321 Mhz 1198 LUT 1298 FF - Cyclone V -> 165 Mhz 873 ALMs - Cyclone IV -> 145 Mhz 1,691 LUT 1,239 FF - iCE40 -> 61 Mhz 2778 LC (nextpnr) + Artix 7 -> 323 Mhz 1241 LUT 1301 FF + Cyclone V -> 159 Mhz 864 ALMs + Cyclone IV -> 137 Mhz 1,688 LUT 1,241 FF + iCE40 -> 66 Mhz 2799 LC (nextpnr) ``` Some scripts to generate the SoC and call the icestorm toolchain can be found here: `scripts/Murax/` diff --git a/src/main/scala/vexriscv/Pipeline.scala b/src/main/scala/vexriscv/Pipeline.scala index 14fe071..2a04ef2 100644 --- a/src/main/scala/vexriscv/Pipeline.scala +++ b/src/main/scala/vexriscv/Pipeline.scala @@ -17,6 +17,8 @@ trait Pipeline { val things = mutable.HashMap[PipelineThing[_], Any]() // val services = ArrayBuffer[Any]() + def stageBefore(stage : Stage) = stages(indexOf(stage)-1) + def indexOf(stage : Stage) = stages.indexOf(stage) def service[T](clazz : Class[T]) = { @@ -127,7 +129,7 @@ trait Pipeline { //Arbitration for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)) { - stage.arbitration.isFlushed := stages.drop(stageIndex).map(_.arbitration.flushAll).orR + stage.arbitration.isFlushed := stages.drop(stageIndex+1).map(_.arbitration.flushNext).orR || stages.drop(stageIndex).map(_.arbitration.flushIt).orR if(!unremovableStages.contains(stage)) stage.arbitration.removeIt setWhen stage.arbitration.isFlushed else diff --git a/src/main/scala/vexriscv/Stage.scala b/src/main/scala/vexriscv/Stage.scala index f036dfb..d86c256 100644 --- a/src/main/scala/vexriscv/Stage.scala +++ b/src/main/scala/vexriscv/Stage.scala @@ -49,7 +49,8 @@ class Stage() extends Area{ val haltItself = False //user settable, stuck the instruction, should only be set by the instruction itself val haltByOther = False //When settable, stuck the instruction, should only be set by something else than the stucked instruction 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 flushIt = False //When settable, unschedule the current instruction + val flushNext = False //When settable, unschedule instruction above in the pipeline 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 diff --git a/src/main/scala/vexriscv/VexRiscv.scala b/src/main/scala/vexriscv/VexRiscv.scala index 26d9489..1e38791 100644 --- a/src/main/scala/vexriscv/VexRiscv.scala +++ b/src/main/scala/vexriscv/VexRiscv.scala @@ -109,7 +109,7 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{ if(withMemoryStage){ memory.arbitration.removeIt.noBackendCombMerge } - execute.arbitration.flushAll.noBackendCombMerge + execute.arbitration.flushNext.noBackendCombMerge this(RVC_GEN) = false } diff --git a/src/main/scala/vexriscv/plugin/BranchPlugin.scala b/src/main/scala/vexriscv/plugin/BranchPlugin.scala index 6885f2a..6559a7f 100644 --- a/src/main/scala/vexriscv/plugin/BranchPlugin.scala +++ b/src/main/scala/vexriscv/plugin/BranchPlugin.scala @@ -84,6 +84,8 @@ class BranchPlugin(earlyBranch : Boolean, decodePrediction } + def hasHazardOnBranch = if(earlyBranch) pipeline.service(classOf[HazardService]).hazardOnExecuteRS else False + override def setup(pipeline: VexRiscv): Unit = { import Riscv._ import pipeline.config._ @@ -200,12 +202,9 @@ class BranchPlugin(earlyBranch : Boolean, //Apply branchs (JAL,JALR, Bxx) branchStage plug new Area { import branchStage._ - jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO) + jumpInterface.valid := arbitration.isValid && input(BRANCH_DO) && !hasHazardOnBranch jumpInterface.payload := input(BRANCH_CALC) - - when(jumpInterface.valid) { - stages(indexOf(branchStage) - 1).arbitration.flushAll := True - } + arbitration.flushNext setWhen(jumpInterface.valid) if(catchAddressMisalignedForReal) { branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1) @@ -282,12 +281,9 @@ class BranchPlugin(earlyBranch : Boolean, val branchStage = if(earlyBranch) execute else memory branchStage plug new Area { import branchStage._ - jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO) + jumpInterface.valid := arbitration.isValid && input(BRANCH_DO) && !hasHazardOnBranch jumpInterface.payload := input(BRANCH_CALC) - - when(jumpInterface.valid) { - stages(indexOf(branchStage) - 1).arbitration.flushAll := True - } + arbitration.flushNext setWhen(jumpInterface.valid) if(catchAddressMisalignedForReal) { val unalignedJump = input(BRANCH_DO) && input(BRANCH_CALC)(1) @@ -361,14 +357,11 @@ class BranchPlugin(earlyBranch : Boolean, input(PC) } - jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && predictionMissmatch //Probably just isValid instead of isFiring is better + jumpInterface.valid := arbitration.isValid && predictionMissmatch && !hasHazardOnBranch jumpInterface.payload := (input(BRANCH_DO) ? input(BRANCH_CALC) | input(NEXT_PC)) + arbitration.flushNext setWhen(jumpInterface.valid) - when(jumpInterface.valid) { - stages(indexOf(branchStage) - 1).arbitration.flushAll := True - } - if(catchAddressMisalignedForReal) { branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && input(BRANCH_CALC)(1) branchExceptionPort.code := 0 diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 5f81f6f..5c7e032 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -68,11 +68,13 @@ case class CsrPluginConfig( medelegAccess : CsrAccess = CsrAccess.NONE, midelegAccess : CsrAccess = CsrAccess.NONE, pipelineCsrRead : Boolean = false, + pipelinedInterrupt : Boolean = true, deterministicInteruptionEntry : Boolean = false //Only used for simulatation purposes ){ assert(!ucycleAccess.canWrite) def privilegeGen = userGen || supervisorGen def noException = this.copy(ecallGen = false, ebreakGen = false, catchIllegalAccess = false) + def noExceptionButEcall = this.copy(ecallGen = true, ebreakGen = false, catchIllegalAccess = false) } object CsrPluginConfig{ @@ -693,7 +695,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep exceptionValids := exceptionValidsRegs for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) { when(port.valid) { - if(indexOf(stage) != 0) stages(indexOf(stage) - 1).arbitration.flushAll := True + stage.arbitration.flushNext := True stage.arbitration.removeIt := True exceptionValids(stageId) := True exceptionContext := port.payload @@ -715,7 +717,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep } } - when(exceptionValidsRegs.orR){ + when(exceptionValids.orR){ fetcher.haltIt() } @@ -729,32 +731,37 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep //Process interrupt request, code and privilege - val interrupt = False - val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public) - var interruptPrivilegs = if (supervisorGen) List(1, 3) else List(3) - val interruptTargetPrivilege = UInt(2 bits).assignDontCare() - val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]() - if(supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === "01") || privilege < "01") - privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < "11") - while(interruptPrivilegs.nonEmpty){ - val p = interruptPrivilegs.head - when(privilegeAllowInterrupts(p)){ - for(i <- interruptSpecs - if i.privilege <= p //EX : Machine timer interrupt can't go into supervisor mode - if interruptPrivilegs.tail.forall(e => i.delegators.exists(_.privilege == e))){ // EX : Supervisor timer need to have machine mode delegator - val delegUpOn = i.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _) - val delegDownOff = !i.delegators.filter(_.privilege <= p).map(_.enable).orR - when(i.cond && delegUpOn && delegDownOff){ - interrupt := True - interruptCode := i.id - interruptTargetPrivilege := p + val interrupt = new Area { + val valid = if(pipelinedInterrupt) RegNext(False) init(False) else False + val code = if(pipelinedInterrupt) Reg(UInt(4 bits)) else UInt(4 bits).assignDontCare() + var privilegs = if (supervisorGen) List(1, 3) else List(3) + val targetPrivilege = if(pipelinedInterrupt) Reg(UInt(2 bits)) else UInt(2 bits).assignDontCare() + val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]() + if (supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === "01") || privilege < "01") + privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < "11") + while (privilegs.nonEmpty) { + val p = privilegs.head + when(privilegeAllowInterrupts(p)) { + for (i <- interruptSpecs + if i.privilege <= p //EX : Machine timer interrupt can't go into supervisor mode + if privilegs.tail.forall(e => i.delegators.exists(_.privilege == e))) { // EX : Supervisor timer need to have machine mode delegator + val delegUpOn = i.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _) + val delegDownOff = !i.delegators.filter(_.privilege <= p).map(_.enable).orR + when(i.cond && delegUpOn && delegDownOff) { + valid := True + code := i.id + targetPrivilege := p + } } } + privilegs = privilegs.tail } - interruptPrivilegs = interruptPrivilegs.tail + + code.addTag(Verilator.public) } - interrupt.clearWhen(!allowInterrupts) + + val exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last && allowException else False val lastStageWasWfi = if(wfiGenAsWait) RegNext(lastStage.arbitration.isFiring && lastStage.input(ENV_CTRL) === EnvCtrlEnum.WFI) init(False) else False @@ -763,7 +770,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep //Used to make the pipeline empty softly (for interrupts) val pipelineLiberator = new Area{ - when(interrupt){ + when(interrupt.valid && allowInterrupts){ decode.arbitration.haltByOther := decode.arbitration.isValid } @@ -773,18 +780,18 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep //Interrupt/Exception entry logic val interruptJump = Bool.addTag(Verilator.public) - interruptJump := interrupt && pipelineLiberator.done + interruptJump := interrupt.valid && pipelineLiberator.done && allowInterrupts val hadException = RegNext(exception) init(False) pipelineLiberator.done.clearWhen(hadException) - val targetPrivilege = CombInit(interruptTargetPrivilege) + val targetPrivilege = CombInit(interrupt.targetPrivilege) if(exceptionPortCtrl != null) when(hadException) { targetPrivilege := exceptionPortCtrl.exceptionTargetPrivilege } - val trapCause = CombInit(interruptCode) + val trapCause = CombInit(interrupt.code) if(exceptionPortCtrl != null) when( hadException){ trapCause := exceptionPortCtrl.exceptionContext.code } @@ -800,7 +807,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep jumpInterface.valid := True jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ "00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ "00") | ((xtvec.base + trapCause) @@ "00") ) - beforeLastStage.arbitration.flushAll := True + lastStage.arbitration.flushNext := True if(privilegeGen) privilegeReg := targetPrivilege @@ -839,7 +846,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) { fetcher.haltIt() jumpInterface.valid := True - beforeLastStage.arbitration.flushAll := True + lastStage.arbitration.flushNext := True switch(input(INSTRUCTION)(29 downto 28)){ is(3){ mstatus.MPP := U"00" diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 8c681b6..10e4550 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -247,7 +247,8 @@ class DBusCachedPlugin(val config : DataCacheConfig, redoBranch.valid := False redoBranch.payload := input(PC) - arbitration.flushAll setWhen(redoBranch.valid) + arbitration.flushIt setWhen(redoBranch.valid) + arbitration.flushNext setWhen(redoBranch.valid) if(catchSomething) { exceptionBus.valid := False //cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala index 0ded35e..fe5ac77 100644 --- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala @@ -516,7 +516,8 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, memoryExceptionPort.code := (input(MEMORY_STORE) ? U(15) | U(13)).resized } - arbitration.flushAll setWhen(redoBranch.valid) + arbitration.flushIt setWhen(redoBranch.valid) + arbitration.flushNext setWhen(redoBranch.valid) } when(!(arbitration.isValid && input(MEMORY_ENABLE) && (Bool(cmdStage != rspStage) || !arbitration.isStuckByOthers))){ diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index 454d352..4088cec 100644 --- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala @@ -203,7 +203,8 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount : when(stagesFromExecute.tail.map(_.arbitration.isValid).orR === False){ iBusFetcher.flushIt() iBusFetcher.haltIt() - execute.arbitration.flushAll := True + execute.arbitration.flushIt := True + execute.arbitration.flushNext := True haltIt := True haltedByBreak := True } diff --git a/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala index 22afa26..a1076e7 100644 --- a/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala @@ -28,7 +28,7 @@ case class Masked(value : BigInt,care : BigInt){ def mergeOneBitDifSmaller(x: Masked) = { val bit = value - x.value val ret = new Masked(value &~ bit, care & ~bit) -// ret.isPrime = isPrime || x.isPrime + // ret.isPrime = isPrime || x.isPrime isPrime = false x.isPrime = false ret @@ -44,7 +44,10 @@ case class Masked(value : BigInt,care : BigInt){ def toString(bitCount : Int) = (0 until bitCount).map(i => if(care.testBit(i)) (if(value.testBit(i)) "1" else "0") else "-").reverseIterator.reduce(_+_) } -class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalInstructionComputation : Boolean = false) extends Plugin[VexRiscv] with DecoderService { +class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, + throwIllegalInstruction : Boolean = false, + assertIllegalInstruction : Boolean = false, + forceLegalInstructionComputation : Boolean = false) extends Plugin[VexRiscv] with DecoderService { override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: BaseType], Any)])]): Unit = encoding.foreach(e => this.add(e._1,e._2)) override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: BaseType], Any)]): Unit = { val instructionModel = encodings.getOrElseUpdate(key,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]()) @@ -78,6 +81,10 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI } } + val detectLegalInstructions = catchIllegalInstruction || throwIllegalInstruction || forceLegalInstructionComputation || assertIllegalInstruction + + object ASSERT_ERROR extends Stageable(Bool) + override def build(pipeline: VexRiscv): Unit = { import pipeline.config._ import pipeline.decode._ @@ -86,7 +93,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI val stupidDecoder = false if(stupidDecoder){ - if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := False + if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := False for(stageable <- stageables){ if(defaults.contains(stageable)){ insert(stageable).assignFrom(defaults(stageable)) @@ -96,7 +103,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI } for((key, tasks) <- encodings){ when(input(INSTRUCTION) === key){ - if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := True + if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := True for((stageable, value) <- tasks){ insert(stageable).assignFrom(value) } @@ -145,8 +152,15 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI // logic implementation val decodedBits = Bits(stageables.foldLeft(0)(_ + _.dataType.getBitsWidth) bits) decodedBits := Symplify(input(INSTRUCTION), spec, decodedBits.getWidth) - if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := Symplify.logicOf(input(INSTRUCTION), SymplifyBit.getPrimeImplicantsByTrueAndDontCare(spec.unzip._1.toSeq, Nil, 32)) - + if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := Symplify.logicOf(input(INSTRUCTION), SymplifyBit.getPrimeImplicantsByTrueAndDontCare(spec.unzip._1.toSeq, Nil, 32)) + if (throwIllegalInstruction) { + input(LEGAL_INSTRUCTION) //Fill the request for later (prePopTask) + Component.current.addPrePopTask(() => arbitration.isValid clearWhen(!input(LEGAL_INSTRUCTION))) + } + if(assertIllegalInstruction){ + val reg = RegInit(False) setWhen(arbitration.isValid) clearWhen(arbitration.isRemoved || !arbitration.isStuck) + insert(ASSERT_ERROR) := arbitration.isValid || reg + } //Unpack decodedBits and insert fields in the pipeline offset = 0 @@ -162,6 +176,10 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI decodeExceptionPort.code := 2 decodeExceptionPort.badAddr := input(INSTRUCTION).asUInt } + if(assertIllegalInstruction){ + pipeline.stages.tail.foreach(s => s.output(ASSERT_ERROR) clearWhen(s.arbitration.isRemoved)) + assert(!pipeline.stages.last.output(ASSERT_ERROR)) + } } def bench(toplevel : VexRiscv): Unit ={ @@ -176,7 +194,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI val stageables = encodings.flatMap(_._2.map(_._1)).toSet stageables.foreach(e => out(RegNext(RegNext(toplevel.decode.insert(e)).setName(e.getName())))) if(catchIllegalInstruction) out(RegNext(RegNext(toplevel.decode.insert(LEGAL_INSTRUCTION)).setName(LEGAL_INSTRUCTION.getName()))) - // toplevel.getAdditionalNodesRoot.clear() + // toplevel.getAdditionalNodesRoot.clear() } } } @@ -345,14 +363,14 @@ object SymplifyBit{ def main(args: Array[String]) { { -// val default = Masked(0, 0xF) -// val primeImplicants = List(4, 8, 10, 11, 12, 15).map(v => Masked(v, 0xF)) -// val dcImplicants = List(9, 14).map(v => Masked(v, 0xF).setPrime(false)) -// val reducedPrimeImplicants = getPrimeImplicantsByTrueAndDontCare(primeImplicants, dcImplicants, 4) -// println("UUT") -// println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n")) -// println("REF") -// println("-100\n10--\n1--0\n1-1-") + // val default = Masked(0, 0xF) + // val primeImplicants = List(4, 8, 10, 11, 12, 15).map(v => Masked(v, 0xF)) + // val dcImplicants = List(9, 14).map(v => Masked(v, 0xF).setPrime(false)) + // val reducedPrimeImplicants = getPrimeImplicantsByTrueAndDontCare(primeImplicants, dcImplicants, 4) + // println("UUT") + // println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n")) + // println("REF") + // println("-100\n10--\n1--0\n1-1-") } { diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 62d4aa7..5df80e7 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -103,64 +103,47 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs) } - def flush = jump.pcLoad.valid || fetcherflushIt + fetcherflushIt setWhen(stages.map(_.arbitration.flushNext).orR) - class PcFetch extends Area{ - val preOutput = Stream(UInt(32 bits)) - val output = preOutput.haltWhen(fetcherHalt) - val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) - } - - val fetchPc = new PcFetch{ + //The fetchPC pcReg can also be use for the second stage of the fetch + //When the fetcherHalt is set and the pipeline isn't stalled,, the pc is propagated to to the pcReg, which allow + //using the pc pipeline to get the next PC value for interrupts + val fetchPc = new Area{ //PC calculation without Jump + val output = Stream(UInt(32 bits)) val pcReg = Reg(UInt(32 bits)) init(if(resetVector != null) resetVector else externalResetVector) addAttribute(Verilator.public) - val inc = RegInit(False) - val propagatePc = False - + val corrected = False + val pcRegPropagate = False + val booted = RegNext(True) init (False) + val inc = RegInit(False) clearWhen(corrected || pcRegPropagate) setWhen(output.fire) clearWhen(!output.valid && output.ready) val pc = pcReg + (inc ## B"00").asUInt - val samplePcNext = False + val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) - if(compressedGen) { - when(inc) { - pc(1) := False - } - } - - when(propagatePc){ - samplePcNext := True - inc := False + if(compressedGen) when(inc) { + pc(1) := False } if(predictionPcLoad != null) { when(predictionPcLoad.valid) { - inc := False - samplePcNext := True + corrected := True pc := predictionPcLoad.payload } } when(jump.pcLoad.valid) { - inc := False - samplePcNext := True + corrected := True pc := jump.pcLoad.payload } - when(preOutput.fire){ - inc := True - samplePcNext := True - } - - - when(samplePcNext) { + when(booted && (output.ready || fetcherflushIt || pcRegPropagate)){ pcReg := pc } pc(0) := False if(!pipeline(RVC_GEN)) pc(1) := False - preOutput.valid := RegNext(True) init (False) - preOutput.payload := pc - + output.valid := !fetcherHalt && booted + output.payload := pc } val decodePc = ifGen(decodePcGen)(new Area { @@ -185,7 +168,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } //application of the selected jump request - when(jump.pcLoad.valid) { + when(jump.pcLoad.valid && (!decode.arbitration.isStuck || decode.arbitration.isRemoved)) { pcReg := jump.pcLoad.payload } }) @@ -226,11 +209,11 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, for((s,sNext) <- (stages, stages.tail).zipped) { if(s == stages.head && pcRegReusedForSecondStage) { - sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(flush, s != stages.head, collapsBubble = false)) + sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(fetcherflushIt, s != stages.head, collapsBubble = false)) sNext.input.payload := fetchPc.pcReg - fetchPc.propagatePc setWhen(sNext.input.fire) + fetchPc.pcRegPropagate setWhen(sNext.input.ready) } else { - sNext.input << s.output.m2sPipeWithFlush(flush, s != stages.head, collapsBubble = false) + sNext.input << s.output.m2sPipeWithFlush(fetcherflushIt, s != stages.head, collapsBubble = false) } } @@ -273,7 +256,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, // input.ready := (bufferValid ? (!isRvc && output.ready) | (input.pc(1) || output.ready)) input.ready := !output.valid || !(!output.ready || (isRvc && !input.pc(1) && input.rsp.inst(16, 2 bits) =/= 3) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3)) addPrePopTask(() => { - when(!input.ready && output.fire && !flush /* && ((isRvc && !bufferValid && !input.pc(1)) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))*/) { + when(!input.ready && output.fire && !fetcherflushIt /* && ((isRvc && !bufferValid && !input.pc(1)) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))*/) { input.pc.getDrivingReg(1) := True } }) @@ -284,7 +267,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, bufferValid := !(!isRvc && !input.pc(1) && !bufferValid) && !(isRvc && input.pc(1) && output.ready) bufferData := input.rsp.inst(31 downto 16) } - bufferValid.clearWhen(flush) + bufferValid.clearWhen(fetcherflushIt) iBusRsp.readyForError.clearWhen(bufferValid && isRvc) //Can't emit error, as there is a earlier instruction pending incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3) }) @@ -292,13 +275,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, def condApply[T](that : T, cond : Boolean)(func : (T) => T) = if(cond)func(that) else that val injector = new Area { - val inputBeforeStage = condApply(if (decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(flush)) + val inputBeforeStage = condApply(if (decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(fetcherflushIt)) if (injectorReadyCutGen) { iBusRsp.readyForError.clearWhen(inputBeforeStage.valid) //Can't emit error if there is a instruction pending in the s2mPipe incomingInstruction setWhen (inputBeforeStage.valid) } val decodeInput = (if (injectorStage) { - val decodeInput = inputBeforeStage.m2sPipeWithFlush(flush, collapsBubble = false) + val decodeInput = inputBeforeStage.m2sPipeWithFlush(fetcherflushIt, collapsBubble = false) decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeStage.rsp.inst) iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer incomingInstruction setWhen (decodeInput.valid) @@ -313,13 +296,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, def pcUpdatedGen(input : Bool, stucks : Seq[Bool], relaxedInput : Boolean) : Seq[Bool] = { stucks.scanLeft(input)((i, stuck) => { val reg = RegInit(False) - if(!relaxedInput) when(flush) { + if(!relaxedInput) when(fetcherflushIt) { reg := False } when(!stuck) { reg := i } - if(relaxedInput || i != input) when(flush) { + if(relaxedInput || i != input) when(fetcherflushIt) { reg := False } reg @@ -335,7 +318,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pcValids := Vec(valids.takeRight(stages.size)) } - val decodeRemoved = RegInit(False) setWhen(decode.arbitration.isRemoved) clearWhen(flush) //!decode.arbitration.isStuck || decode.arbitration.isFlushed + val decodeRemoved = RegInit(False) setWhen(decode.arbitration.isRemoved) clearWhen(fetcherflushIt) //!decode.arbitration.isStuck || decode.arbitration.isFlushed decodeInput.ready := !decode.arbitration.isStuck decode.arbitration.isValid := decodeInput.valid && !decodeRemoved @@ -461,7 +444,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, } val fetchContext = DynamicContext() fetchContext.hazard := hazard - fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || flush) + fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) object PREDICTION_CONTEXT extends Stageable(DynamicContext()) decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2 @@ -499,13 +482,14 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, decodePrediction.cmd.hadBranch clearWhen(missaligned) } - predictionJumpInterface.valid := decodePrediction.cmd.hadBranch && decode.arbitration.isFiring //TODO OH Doublon de priorité + //TODO no more fireing depedancies + predictionJumpInterface.valid := decode.arbitration.isValid && decodePrediction.cmd.hadBranch //TODO OH Doublon de priorité predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload) -// when(predictionJumpInterface.payload((if(pipeline(RVC_GEN)) 0 else 1) downto 0) =/= 0){ -// decodePrediction.cmd.hadBranch := False -// } + when(predictionJumpInterface.valid && decode.arbitration.isFiring){ + flushIt() + } } case DYNAMIC_TARGET => new Area{ // assert(!compressedGen || cmdToRspStageCount == 1, "Can't combine DYNAMIC_TARGET and RVC as it could stop the instruction fetch mid-air") @@ -520,7 +504,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) val historyWrite = history.writePort - val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready || flush) + val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt) val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.stages(1).input.payload(1))) else True) //Avoid stoping instruction fetch in the middle patch @@ -532,7 +516,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized //TODO improve predictionPcLoad way of doing things - fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).output.fire //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1)) + fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).output.valid //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1)) fetchPc.predictionPcLoad.payload := line.target case class PredictionResult() extends Bundle{ @@ -600,7 +584,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, when(decompressor.input.fire){ decompressorFailure := decompressorContext.hit && !decompressorContext.hazard && !decompressor.output.valid && decompressorContext.line.branchWish(1) } - decompressorFailure clearWhen(flush || decompressor.output.fire) + decompressorFailure clearWhen(fetcherflushIt || decompressor.output.fire) val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) @@ -612,6 +596,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, historyWrite.data.branchWish := 0 decode.arbitration.isValid := False + decode.arbitration.flushNext := True dynamicTargetFailureCorrection.valid := True } }) diff --git a/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala b/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala index c051aa0..f674ae8 100644 --- a/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala @@ -19,7 +19,7 @@ class HazardSimplePlugin(bypassExecute : Boolean = false, def hazardOnExecuteRS = { - if(pipeline.service(classOf[RegFileService]).readStage() == pipeline.execute) pipeline.execute.arbitration.isStuckByOthers else False + if(pipeline.service(classOf[RegFileService]).readStage() == pipeline.execute) pipeline.execute.arbitration.isStuckByOthers else False //TODO not so nice } override def setup(pipeline: VexRiscv): Unit = { diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index 4005fb9..6a582c8 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -157,7 +157,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, stages(0).halt setWhen (cache.io.cpu.prefetch.haltIt) - cache.io.cpu.fetch.isRemoved := flush + cache.io.cpu.fetch.isRemoved := fetcherflushIt } @@ -237,12 +237,20 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, decodeExceptionPort.code := 1 } - redoFetch clearWhen(!iBusRsp.readyForError) - cache.io.cpu.fill.valid clearWhen(!iBusRsp.readyForError) - if (catchSomething) decodeExceptionPort.valid clearWhen(fetcherHalt) + when(!iBusRsp.readyForError){ + redoFetch := False + cache.io.cpu.fill.valid := False + } +// when(pipeline.stages.map(_.arbitration.flushIt).orR){ +// cache.io.cpu.fill.valid := False +// } + + redoBranch.valid := redoFetch redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc) + decode.arbitration.flushNext setWhen(redoBranch.valid) + cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt) iBusRsp.output.valid := cacheRspArbitration.output.valid diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index 0033882..fa74f6c 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -314,7 +314,7 @@ class IBusSimplePlugin( resetVector : BigInt, mmuBus.cmd.isValid := cmdForkStage.input.valid mmuBus.cmd.virtualAddress := cmdForkStage.input.payload mmuBus.cmd.bypassTranslation := False - mmuBus.end := cmdForkStage.output.fire || flush + mmuBus.end := cmdForkStage.output.fire || fetcherflushIt cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ "00" @@ -341,7 +341,7 @@ class IBusSimplePlugin( resetVector : BigInt, //Manage flush for iBus transactions in flight val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0) discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt - when(flush) { + when(fetcherflushIt) { if(secondStagePersistence) discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt else @@ -353,7 +353,7 @@ class IBusSimplePlugin( resetVector : BigInt, 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 + c.io.flush := fetcherflushIt rspBufferOutput << c.io.pop } else new Area{ val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream @@ -381,7 +381,9 @@ class IBusSimplePlugin( resetVector : BigInt, redoRequired setWhen( stages.last.input.valid && mmu.joinCtx.refilling) redoBranch.valid := redoRequired && iBusRsp.readyForError redoBranch.payload := decode.input(PC) - decode.arbitration.flushAll setWhen(redoBranch.valid) + + decode.arbitration.flushIt setWhen(redoBranch.valid) + decode.arbitration.flushNext setWhen(redoBranch.valid) } @@ -400,7 +402,7 @@ class IBusSimplePlugin( resetVector : BigInt, exceptionDetected := True } } - decodeExceptionPort.valid := exceptionDetected && iBusRsp.readyForError && !fetcherHalt + decodeExceptionPort.valid := exceptionDetected && iBusRsp.readyForError } } } diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index 6f50a1c..421a433 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -1550,7 +1550,7 @@ public: riscvRef.liveness(top->VexRiscv->execute_CsrPlugin_inWfi); if(top->VexRiscv->CsrPlugin_interruptJump){ - if(riscvRefEnable) riscvRef.trap(true, top->VexRiscv->CsrPlugin_interruptCode); + if(riscvRefEnable) riscvRef.trap(true, top->VexRiscv->CsrPlugin_interrupt_code); } } #endif @@ -3443,7 +3443,7 @@ string freeRtosTests[] = { // "test1","test1","test1","test1","test1","test1","test1","test1" "AltQTest", "AltBlock", "AltPollQ", "blocktim", "countsem", "dead", "EventGroupsDemo", "flop", "integer", "QPeek", - "QueueSet", "recmutex", "semtest", "TaskNotify", "BlockQ", "crhook", "dynamic", + "QueueSet", "recmutex", "semtest", "TaskNotify", "crhook", "dynamic", "GenQTest", "PollQ", "QueueOverwrite", "QueueSetPolling", "sp_flop", "test1" //"BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ" // "flop" @@ -3625,14 +3625,18 @@ static void multiThreading(queue> *lambdas, std::mutex *mu static void multiThreadedExecute(queue> &lambdas){ - std::mutex mutex; - std::thread * t[THREAD_COUNT]; - for(int id = 0;id < THREAD_COUNT;id++){ - t[id] = new thread(multiThreading,&lambdas,&mutex); - } - for(int id = 0;id < THREAD_COUNT;id++){ - t[id]->join(); - delete t[id]; + std::mutex mutex; + if(THREAD_COUNT == 1){ + multiThreading(&lambdas, &mutex); + } else { + std::thread * t[THREAD_COUNT]; + for(int id = 0;id < THREAD_COUNT;id++){ + t[id] = new thread(multiThreading,&lambdas,&mutex); + } + for(int id = 0;id < THREAD_COUNT;id++){ + t[id]->join(); + delete t[id]; + } } } @@ -3847,7 +3851,9 @@ int main(int argc, char **argv, char **env) { #endif #ifdef DEBUG_PLUGIN + #ifndef CONCURRENT_OS_EXECUTIONS redo(REDO,DebugPluginTest().run(1e6);); + #endif #endif #endif diff --git a/src/test/cpp/regression/makefile b/src/test/cpp/regression/makefile index f8db6db..ad05707 100644 --- a/src/test/cpp/regression/makefile +++ b/src/test/cpp/regression/makefile @@ -51,7 +51,9 @@ else ADDCFLAGS += -CFLAGS -O3 -O3 endif - +ifeq ($(CONCURRENT_OS_EXECUTIONS),yes) + ADDCFLAGS += -CFLAGS -DCONCURRENT_OS_EXECUTIONS +endif ifeq ($(LITEX),yes) ADDCFLAGS += -CFLAGS -DLITEX diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index 52097e9..33e4aa6 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -474,7 +474,7 @@ class CsrDimension(freertos : String, zephyr : String) extends VexRiscvDimension if(supervisor){ new VexRiscvPosition("Supervisor") with CatchAllPosition{ override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new CsrPlugin(CsrPluginConfig.linuxFull(0x80000020l)) - override def testParam = s"FREERTOS=$freertos ZEPHYR=$zephyr LINUX_REGRESSION=yes SUPERVISOR=yes" + override def testParam = s"FREERTOS=$freertos ZEPHYR=$zephyr LINUX_REGRESSION=${sys.env.getOrElse("VEXRISCV_REGRESSION_LINUX_REGRESSION", "yes")} SUPERVISOR=yes" } } else if(catchAll){ new VexRiscvPosition("MachineOs") with CatchAllPosition{ @@ -483,8 +483,8 @@ class CsrDimension(freertos : String, zephyr : String) extends VexRiscvDimension } } else if(r.nextDouble() < 0.3){ new VexRiscvPosition("AllNoException") with CatchAllPosition{ - override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new CsrPlugin(CsrPluginConfig.all(0x80000020l).noException) - override def testParam = s"CSR=yes CSR_SKIP_TEST=yes FREERTOS=$freertos" + override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new CsrPlugin(CsrPluginConfig.all(0x80000020l).noExceptionButEcall) + override def testParam = s"CSR=yes CSR_SKIP_TEST=yes FREERTOS=$freertos ZEPHYR=$zephyr" } } else { new VexRiscvPosition("None") { @@ -514,7 +514,8 @@ class DecoderDimension extends VexRiscvDimension("Decoder") { val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL) new VexRiscvPosition("") { override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new DecoderSimplePlugin( - catchIllegalInstruction = catchAll + catchIllegalInstruction = catchAll, + throwIllegalInstruction = false ) // override def isCompatibleWith(positions: Seq[ConfigPosition[VexRiscvConfig]]) = catchAll == positions.exists(_.isInstanceOf[CatchAllPosition]) @@ -555,23 +556,13 @@ class TestIndividualFeatures extends FunSuite { new HazardDimension, new RegFileDimension, new SrcDimension, - new CsrDimension(sys.env.getOrElse("VEXRISCV_REGRESSION_FREERTOS_COUNT", "1"), sys.env.getOrElse("VEXRISCV_REGRESSION_ZEPHYR_COUNT", "4")), + new CsrDimension(/*sys.env.getOrElse("VEXRISCV_REGRESSION_FREERTOS_COUNT", "1")*/ "0", sys.env.getOrElse("VEXRISCV_REGRESSION_ZEPHYR_COUNT", "4")), //Freertos old port software is broken new DecoderDimension, new DebugDimension, new MmuDimension ) - -// def genDefaultsPositions(dims : Seq[VexRiscvDimension], stack : List[VexRiscvPosition] = Nil) : Seq[List[VexRiscvPosition]] = dims match { -// case head :: tail => head.default.flatMap(p => genDefaultsPositions(tail, p :: stack)) -// case Nil => List(stack) -// } - -// val usedPositions = mutable.HashSet[VexRiscvPosition](); -// val positionsCount = dimensions.map(d => d.positions.length).sum - def doTest(positionsToApply : List[VexRiscvPosition], prefix : String = "", testSeed : Int, universes : mutable.HashSet[VexRiscvUniverse]): Unit ={ -// usedPositions ++= positionsToApply val noMemory = universes.contains(VexRiscvUniverse.NO_MEMORY) val noWriteback = universes.contains(VexRiscvUniverse.NO_WRITEBACK) def gen = { @@ -597,8 +588,9 @@ class TestIndividualFeatures extends FunSuite { test(prefix + name + "_test") { + println("START TEST " + prefix + name) val debug = true - val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=9999924910246l FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=yes THREAD_COUNT=${sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", 1)} ") + s" SEED=${testSeed} " + val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=9999924910246l STOP_ON_ERROR=no FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${sys.env.getOrElse("VEXRISCV_REGRESSION_COREMARK", "yes")} THREAD_COUNT=${sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", 1)} ") + s" SEED=${testSeed} " val testCmd = stdCmd + (positionsToApply).map(_.testParam).mkString(" ") println(testCmd) val str = doCmd(testCmd) @@ -606,14 +598,12 @@ class TestIndividualFeatures extends FunSuite { } } -// dimensions.foreach(d => d.positions.foreach(p => p.dimension = d)) - val testId : Option[mutable.HashSet[Int]] = None - val seed = Random.nextLong() + val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong -// val testId = Some(mutable.HashSet(18,34,77,85,118,129,132,134,152,167,175,188,191,198,199)) //37/29 sp_flop_rv32i_O3 -//val testId = Some(mutable.HashSet(0)) -// val testId = Some(mutable.HashSet(4)) +// val testId = Some(mutable.HashSet(3,4,9,11,13,16,18,19,20,21)) +// val testId = Some(mutable.HashSet(24, 43, 49)) +// val testId = Some(mutable.HashSet(11)) // val seed = -8309068850561113754l @@ -655,31 +645,4 @@ class TestIndividualFeatures extends FunSuite { doTest(positions," random_" + i + "_", testSeed, universe) Hack.dCounter += 1 } - -// println(s"${usedPositions.size}/$positionsCount positions") - -// for (dimension <- dimensions) { -// for (position <- dimension.positions/* if position.name.contains("Cached")*/) { -// for(defaults <- genDefaultsPositions(dimensions.filter(_ != dimension))){ -// doTest(position :: defaults) -// } -// } -// } -} - - - -/* -val seed = -2412372746600605141l - -129 -FAIL AltQTest_rv32i_O3 -FAIL AltQTest_rv32ic_O3 -FAIL GenQTest_rv32i_O0 - -134 -FAIL AltQTest_rv32i_O3 - - val seed = 4331444545509090137l -1 => flops i O0 - */ \ No newline at end of file +} \ No newline at end of file