diff --git a/src/main/scala/vexriscv/VexRiscv.scala b/src/main/scala/vexriscv/VexRiscv.scala index bd1ef1c..7077096 100644 --- a/src/main/scala/vexriscv/VexRiscv.scala +++ b/src/main/scala/vexriscv/VexRiscv.scala @@ -45,8 +45,7 @@ case class VexRiscvConfig(){ object SRC_LESS_UNSIGNED extends Stageable(Bool) - object DISRUPT_IN_MEMORY_STAGE extends Stageable(Bool) - object DISRUPT_IN_WRITEBACK_STAGE extends Stageable(Bool) + object HAS_SIDE_EFFECT extends Stageable(Bool) //Formal verification purposes object FORMAL_HALT extends Stageable(Bool) diff --git a/src/main/scala/vexriscv/demo/SynthesisBench.scala b/src/main/scala/vexriscv/demo/SynthesisBench.scala index 7b2bdd9..07f22fb 100644 --- a/src/main/scala/vexriscv/demo/SynthesisBench.scala +++ b/src/main/scala/vexriscv/demo/SynthesisBench.scala @@ -104,17 +104,17 @@ object VexRiscvSynthesisBench { // val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full) val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache) // val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full) -// val rtls = List(smallAndProductive, full) +// val rtls = List(smallestNoCsr) - val targets =/* XilinxStdTargets( + val targets = 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" - ) ++ */IcestormStdTargets().take(1) + ) ++ IcestormStdTargets().take(1) // val targets = IcestormStdTargets() - Bench(rtls, targets, "/home/spinalvm/tmp/") + Bench(rtls, targets, "/eda/tmp/") } } diff --git a/src/main/scala/vexriscv/plugin/BranchPlugin.scala b/src/main/scala/vexriscv/plugin/BranchPlugin.scala index 55e69ad..50df75a 100644 --- a/src/main/scala/vexriscv/plugin/BranchPlugin.scala +++ b/src/main/scala/vexriscv/plugin/BranchPlugin.scala @@ -90,14 +90,16 @@ class BranchPlugin(earlyBranch : Boolean, SRC2_CTRL -> Src2CtrlEnum.RS, SRC_USE_SUB_LESS -> True, RS1_USE -> True, - RS2_USE -> True + RS2_USE -> True, + HAS_SIDE_EFFECT -> True ) val jActions = List[(Stageable[_ <: BaseType],Any)]( SRC1_CTRL -> Src1CtrlEnum.PC_INCREMENT, SRC2_CTRL -> Src2CtrlEnum.PC, SRC_USE_SUB_LESS -> False, - REGFILE_WRITE_VALID -> True + REGFILE_WRITE_VALID -> True, + HAS_SIDE_EFFECT -> True ) import IntAluPlugin._ diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 43f6754..e047a20 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -277,7 +277,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio REGFILE_WRITE_VALID -> True, ALU_BITWISE_CTRL -> AluBitwiseCtrlEnum.SRC1, ALU_CTRL -> AluCtrlEnum.BITWISE - ) + ) ++ (if(catchIllegalAccess) List(HAS_SIDE_EFFECT -> True) else Nil) val nonImmediatActions = defaultCsrActions ++ List( SRC1_CTRL -> Src1CtrlEnum.RS, @@ -299,11 +299,11 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio CSRRWI -> immediatActions, CSRRSI -> immediatActions, CSRRCI -> immediatActions, - MRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.XRET)), - SRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.XRET)) + MRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.XRET, HAS_SIDE_EFFECT -> True)), + SRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.XRET, HAS_SIDE_EFFECT -> True)) )) if(wfiGen) decoderService.add(WFI, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.WFI)) - if(ecallGen) decoderService.add(ECALL, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.ECALL)) + if(ecallGen) decoderService.add(ECALL, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.ECALL, HAS_SIDE_EFFECT -> True)) val pcManagerService = pipeline.service(classOf[JumpService]) jumpInterface = pcManagerService.createJumpInterface(pipeline.writeBack) @@ -322,7 +322,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio privilege = RegInit(U"11").setName("CsrPlugin_privilege") if(catchIllegalAccess || ecallGen) - selfException = newExceptionPort(pipeline.writeBack) + selfException = newExceptionPort(pipeline.execute) allowInterrupts = True allowException = True @@ -555,31 +555,31 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio 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 + if(indexOf(stage) != 0) stages(indexOf(stage) - 1).arbitration.flushAll := True stage.arbitration.removeIt := True exceptionValids(stageId) := True - when(!exceptionValidsRegs.takeRight(stages.length-stageId-1).fold(False)(_ || _)) { - exceptionContext := port.payload - } + exceptionContext := port.payload } } for(stageId <- firstStageIndexWithExceptionPort until stages.length; stage = stages(stageId) ){ - when(stage.arbitration.isFlushed){ - exceptionValids(stageId) := False - } val previousStage = if(stageId == firstStageIndexWithExceptionPort) stage else stages(stageId-1) when(!stage.arbitration.isStuck){ exceptionValidsRegs(stageId) := (if(stageId != firstStageIndexWithExceptionPort) exceptionValids(stageId-1) && !previousStage.arbitration.isStuck else False) }otherwise{ - exceptionValidsRegs(stageId) := exceptionValids(stageId) + if(stage != stages.last) + exceptionValidsRegs(stageId) := exceptionValids(stageId) + else + exceptionValidsRegs(stageId) := False } + if(stage != stages.last) when(stage.arbitration.isFlushed){ + exceptionValids(stageId) := False + } + } - if(stageId != 0){ - when(exceptionValidsRegs(stageId)){ - stages(stageId-1).arbitration.haltByOther := True - } - } + when(exceptionValids.orR){ + fetcher.haltIt() + fetcher.flushIt() } } else null @@ -627,8 +627,6 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio interruptJump := interrupt && pipelineLiberator.done val hadException = RegNext(exception) init(False) - exception clearWhen(hadException) - writeBack.arbitration.haltItself setWhen(exception) val targetPrivilege = CombInit(interruptTargetPrivilege) @@ -641,11 +639,21 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio trapCause := exceptionPortCtrl.exceptionContext.code } + when(exception || interruptJump){ + switch(privilege){ + if(supervisorGen) is(1) { + sepc := mepcCaptureStage.input(PC) + } + is(3){ + mepc := mepcCaptureStage.input(PC) + } + } + } + when(hadException || (interruptJump && !exception)){ jumpInterface.valid := True jumpInterface.payload := mtvec memory.arbitration.flushAll := True - if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValidsRegs.last := False switch(targetPrivilege){ if(supervisorGen) is(1) { @@ -654,7 +662,6 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio sstatus.SPP := privilege(0 downto 0) scause.interrupt := !hadException scause.exceptionCode := trapCause - sepc := mepcCaptureStage.input(PC) if (exceptionPortCtrl != null) { stval := exceptionPortCtrl.exceptionContext.badAddr } @@ -666,13 +673,36 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio mstatus.MPP := privilege mcause.interrupt := !hadException mcause.exceptionCode := trapCause - mepc := mepcCaptureStage.input(PC) if(exceptionPortCtrl != null) { mtval := exceptionPortCtrl.exceptionContext.badAddr } } } + } + writeBack plug new Area{ + import writeBack._ + def previousStage = memory + //Manage MRET / SRET instructions + when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) { + jumpInterface.payload := mepc + jumpInterface.valid := True + previousStage.arbitration.flushAll := True + switch(input(INSTRUCTION)(29 downto 28)){ + is(3){ + mstatus.MIE := mstatus.MPIE + mstatus.MPP := U"00" + mstatus.MPIE := True + privilege := mstatus.MPP + } + if(supervisorGen) is(1){ + sstatus.SIE := sstatus.SPIE + sstatus.SPP := U"0" + sstatus.SPIE := True + privilege := U"0" @@ sstatus.SPP + } + } + } } @@ -701,12 +731,11 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio } } -// writeBack plug new Area { -// import writeBack._ -// def previousStage = memory + execute plug new Area { import execute._ def previousStage = decode + val blockedBySideEffects = List(memory, writeBack).map(s => s.arbitration.isValid && s.input(HAS_SIDE_EFFECT)).orR val illegalAccess = arbitration.isValid && input(IS_CSR) val illegalInstruction = False @@ -718,29 +747,13 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio //Manage MRET / SRET instructions when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) { - jumpInterface.payload := mepc + //TODO check MPP value too when(input(INSTRUCTION)(29 downto 28).asUInt =/= privilege) { illegalInstruction := True - } otherwise{ - jumpInterface.valid := True - previousStage.arbitration.flushAll := True - switch(input(INSTRUCTION)(29 downto 28)){ - is(3){ - mstatus.MIE := mstatus.MPIE - mstatus.MPP := U"00" - mstatus.MPIE := True - privilege := mstatus.MPP //TODO check MPP value - } - if(supervisorGen) is(1){ - sstatus.SIE := sstatus.SPIE - sstatus.SPP := U"0" - sstatus.SPIE := True - privilege := U"0" @@ sstatus.SPP - } - } } } + //Manage ECALL instructions if(ecallGen) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.ECALL){ selfException.valid := True @@ -762,11 +775,12 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio val readInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) // arbitration.haltItself setWhen(writeInstruction && !readDataRegValid) - val writeEnable = writeInstruction// && readDataRegValid - val readEnable = readInstruction// && !readDataRegValid + val writeEnable = writeInstruction && ! arbitration.isStuck// && readDataRegValid + val readEnable = readInstruction && ! arbitration.isStuck// && !readDataRegValid when(arbitration.isValid && input(IS_CSR)) { output(REGFILE_WRITE_DATA) := readData + arbitration.haltItself setWhen(blockedBySideEffects) } //Translation of the csrMapping into real logic diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 02f47eb..752552a 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -53,7 +53,7 @@ class DBusCachedPlugin(config : DataCacheConfig, BYPASSABLE_MEMORY_STAGE -> False, MEMORY_WR -> False, MEMORY_MANAGMENT -> False - ) + ) ++ (if(catchSomething) List(HAS_SIDE_EFFECT -> True) else Nil) val storeActions = stdActions ++ List( SRC2_CTRL -> Src2CtrlEnum.IMS, diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala index 102bbe9..f86fcc6 100644 --- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala @@ -211,7 +211,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul REGFILE_WRITE_VALID -> True, BYPASSABLE_EXECUTE_STAGE -> False, BYPASSABLE_MEMORY_STAGE -> Bool(earlyInjection) - ) + ) ++ (if(catchAccessFault || catchAddressMisaligned) List(HAS_SIDE_EFFECT -> True) else Nil) val storeActions = stdActions ++ List( SRC2_CTRL -> Src2CtrlEnum.IMS, diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index 70aef22..7d28b24 100644 --- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala @@ -197,11 +197,11 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount : decode.insert(DO_EBREAK) := !haltIt && (decode.input(IS_EBREAK) || hardwareBreakpoints.map(hb => hb.valid && hb.pc === (execute.input(PC) >> 1)).foldLeft(False)(_ || _)) when(execute.arbitration.isValid && execute.input(DO_EBREAK)){ - iBusFetcher.flushIt() - iBusFetcher.haltIt() execute.arbitration.haltByOther := True busReadDataReg := execute.input(PC).asBits when(List(memory, writeBack).map(_.arbitration.isValid).orR === False){ + iBusFetcher.flushIt() + iBusFetcher.haltIt() execute.arbitration.flushAll := True haltIt := True haltedByBreak := True diff --git a/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala b/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala index cb013b8..b18ae8e 100644 --- a/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala @@ -4,7 +4,6 @@ import vexriscv._ import spinal.core._ import spinal.lib._ - class HazardSimplePlugin(bypassExecute : Boolean = false, bypassMemory: Boolean = false, bypassWriteBack: Boolean = false, @@ -13,6 +12,14 @@ class HazardSimplePlugin(bypassExecute : Boolean = false, pessimisticWriteRegFile : Boolean = false, pessimisticAddressMatch : Boolean = false) 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) //TODO implement it in each plugin + } + override def build(pipeline: VexRiscv): Unit = { import pipeline._ import pipeline.config._