diff --git a/src/main/scala/SpinalRiscv/Plugin/CsrPlugin.scala b/src/main/scala/SpinalRiscv/Plugin/CsrPlugin.scala index 5110634..6242e5f 100644 --- a/src/main/scala/SpinalRiscv/Plugin/CsrPlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/CsrPlugin.scala @@ -76,7 +76,7 @@ case class CsrMapping(){ -class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService{ +class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor{ import config._ import CsrAccess._ @@ -107,6 +107,8 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti object ENV_CTRL extends Stageable(EnvCtrlEnum()) object IS_CSR extends Stageable(Bool) + var allowInterrupts : Bool = null + override def setup(pipeline: VexRiscv): Unit = { import pipeline.config._ @@ -162,8 +164,11 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti if(catchIllegalAccess) selfException = newExceptionPort(pipeline.execute) + + allowInterrupts = True } + def inhibateInterrupts() : Unit = allowInterrupts := False def isUser(stage : Stage) : Bool = privilege === 0 @@ -315,7 +320,7 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti - val interrupt = ((mip.MSIP && mie.MSIE) || (mip.MEIP && mie.MEIE) || (mip.MTIP && mie.MTIE)) && mstatus.MIE + val interrupt = ((mip.MSIP && mie.MSIE) || (mip.MEIP && mie.MEIE) || (mip.MTIP && mie.MTIE)) && mstatus.MIE && allowInterrupts val exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last else False val writeBackWfi = if(wfiGen) writeBack.arbitration.isValid && writeBack.input(ENV_CTRL) === EnvCtrlEnum.WFI else False diff --git a/src/main/scala/SpinalRiscv/Plugin/DebugPlugin.scala b/src/main/scala/SpinalRiscv/Plugin/DebugPlugin.scala index db065b6..a8e11cb 100644 --- a/src/main/scala/SpinalRiscv/Plugin/DebugPlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/DebugPlugin.scala @@ -1,5 +1,6 @@ package SpinalRiscv.Plugin +import SpinalRiscv.Plugin.IntAluPlugin.{AluCtrlEnum, ALU_CTRL} import SpinalRiscv._ import SpinalRiscv.ip._ import spinal.core._ @@ -39,8 +40,24 @@ class DebugPlugin() extends Plugin[VexRiscv] { var io : DebugExtensionIo = null + + object IS_EBREAK extends Stageable(Bool) override def setup(pipeline: VexRiscv): Unit = { + import Riscv._ + import pipeline.config._ + io = slave(DebugExtensionIo()) + + val decoderService = pipeline.service(classOf[DecoderService]) + + decoderService.addDefault(IS_EBREAK, False) + decoderService.add(EBREAK,List( + IS_EBREAK -> True, + SRC_USE_SUB_LESS -> False, + SRC1_CTRL -> Src1CtrlEnum.RS, // Zero + SRC2_CTRL -> Src2CtrlEnum.PC, + ALU_CTRL -> AluCtrlEnum.ADD_SUB //Used to get the PC value in busReadDataReg + )) } override def build(pipeline: VexRiscv): Unit = { @@ -63,8 +80,7 @@ class DebugPlugin() extends Plugin[VexRiscv] { val isPipActive = RegNext(List(fetch,decode,execute,memory,writeBack).map(_.arbitration.isValid).orR) val isPipBusy = isPipActive || RegNext(isPipActive) -// val isInBreakpoint = core.writeBack.inInst.valid && isMyTag(core.writeBack.inInst.ctrl) - + val haltedByBreak = RegInit(False) when(io.bus.cmd.valid) { switch(io.bus.cmd.address(2 downto 2)) { @@ -74,11 +90,12 @@ class DebugPlugin() extends Plugin[VexRiscv] { stepIt := io.bus.cmd.data(4) resetIt setWhen(io.bus.cmd.data(16)) clearWhen(io.bus.cmd.data(24)) haltIt setWhen(io.bus.cmd.data(17)) clearWhen(io.bus.cmd.data(25)) + haltedByBreak clearWhen(io.bus.cmd.data(25)) } otherwise{ busReadDataReg(0) := resetIt busReadDataReg(1) := haltIt busReadDataReg(2) := isPipBusy -// busReadDataReg(3) := isInBreakpoint + busReadDataReg(3) := haltedByBreak busReadDataReg(4) := stepIt } } @@ -86,7 +103,7 @@ class DebugPlugin() extends Plugin[VexRiscv] { when(io.bus.cmd.wr){ insertDecodeInstruction := True val injectedInstructionSent = RegNext(decode.arbitration.isFiring) init(False) - decode.arbitration.haltIt setWhen(!injectedInstructionSent && !RegNext(decode.arbitration.isValid) init(False)) + decode.arbitration.haltIt setWhen(!injectedInstructionSent && !RegNext(decode.arbitration.isValid).init(False)) decode.arbitration.isValid setWhen(firstCycle) io.bus.cmd.ready := injectedInstructionSent } @@ -94,28 +111,23 @@ class DebugPlugin() extends Plugin[VexRiscv] { } } + //Assign the bus write data into the register who drive the decode instruction, even if it need to cross some hierarchy (caches) Component.current.addPrePopTask(() => { - when(insertDecodeInstruction) { - decode.input(INSTRUCTION).getDrivingReg := io.bus.cmd.data + val reg = decode.input(INSTRUCTION).getDrivingReg + reg.component.rework{ + when(insertDecodeInstruction.pull()) { + reg := io.bus.cmd.data.pull() + } } }) - - //Keep the execution pipeline empty after break instruction -// when(core.execute1.inInst.valid && isMyTag(core.execute1.inInst.ctrl)){ -// core.execute0.halt := True -// } -// -// when(isInBreakpoint){ -// core.execute0.halt := True -// core.writeBack.halt := True -// } -// -// when(flushIt) { -// core.writeBack.flush := True -// } - + when(execute.arbitration.isFiring && execute.input(IS_EBREAK)){ + prefetch.arbitration.haltIt := True + decode.arbitration.flushAll := True + haltIt := True + haltedByBreak := True + } when(haltIt){ prefetch.arbitration.haltIt := True @@ -127,6 +139,8 @@ class DebugPlugin() extends Plugin[VexRiscv] { io.resetOut := RegNext(resetIt) -// core.writeBack.irq.inhibate setWhen(haltIt || stepIt) + when(haltIt || stepIt){ + service(classOf[InterruptionInhibitor]).inhibateInterrupts() + } } } diff --git a/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala b/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala index 258a34f..f1ece24 100644 --- a/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala @@ -43,7 +43,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean) extends Plugin[VexR 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 = { assert(!encodings.contains(key)) - encodings(key) = values.map{case (a,b) => (a,b match{ + encodings.getOrElseUpdate(key,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]()) ++= values.map{case (a,b) => (a,b match{ case e : SpinalEnumElement[_] => e() case e : BaseType => e })} @@ -58,7 +58,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean) extends Plugin[VexR } val defaults = mutable.HashMap[Stageable[_ <: BaseType], BaseType]() - val encodings = mutable.HashMap[MaskedLiteral,Seq[(Stageable[_ <: BaseType], BaseType)]]() + val encodings = mutable.HashMap[MaskedLiteral,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]]() var decodeExceptionPort : Flow[ExceptionCause] = null diff --git a/src/main/scala/SpinalRiscv/Services.scala b/src/main/scala/SpinalRiscv/Services.scala index f091eb9..f9c8ef3 100644 --- a/src/main/scala/SpinalRiscv/Services.scala +++ b/src/main/scala/SpinalRiscv/Services.scala @@ -26,6 +26,11 @@ trait PrivilegeService{ def isUser(stage : Stage) : Bool } +trait InterruptionInhibitor{ + def inhibateInterrupts() : Unit +} + + case class MemoryTranslatorCmd() extends Bundle{ val isValid = Bool val virtualAddress = UInt(32 bits) diff --git a/src/main/scala/SpinalRiscv/TopLevel.scala b/src/main/scala/SpinalRiscv/TopLevel.scala index d3969fa..72e6cfd 100644 --- a/src/main/scala/SpinalRiscv/TopLevel.scala +++ b/src/main/scala/SpinalRiscv/TopLevel.scala @@ -183,6 +183,7 @@ object TopLevel { new MulPlugin, new DivPlugin, new CsrPlugin(csrConfigAll), +// new DebugPlugin(), new BranchPlugin( earlyBranch = false, catchAddressMisaligned = true,