diff --git a/src/main/scala/vexriscv/Services.scala b/src/main/scala/vexriscv/Services.scala index 5da43af..59a8162 100644 --- a/src/main/scala/vexriscv/Services.scala +++ b/src/main/scala/vexriscv/Services.scala @@ -56,6 +56,7 @@ trait InterruptionInhibitor{ trait ExceptionInhibitor{ def inhibateException() : Unit + def inhibateEbreakException() : Unit } diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 456d688..71f3c8a 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -32,6 +32,8 @@ object CsrAccess { object NONE extends CsrAccess } + + case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int) case class CsrPluginConfig( catchIllegalAccess : Boolean, @@ -457,6 +459,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep var allowInterrupts : Bool = null var allowException : Bool = null + var allowEbreakException : Bool = null val csrMapping = new CsrMapping() @@ -565,6 +568,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep allowInterrupts = True allowException = True + allowEbreakException = True for (i <- interruptSpecs) i.cond = i.cond.pull() @@ -577,6 +581,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep def inhibateInterrupts() : Unit = allowInterrupts := False def inhibateException() : Unit = allowException := False + def inhibateEbreakException() : Unit = allowEbreakException := False override def isUser() : Bool = privilege === 0 override def isSupervisor(): Bool = privilege === 1 @@ -1097,7 +1102,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep } - if(ebreakGen) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.EBREAK){ + if(ebreakGen) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.EBREAK && allowEbreakException){ selfException.valid := True selfException.code := 3 } diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index c75db10..b7f621c 100644 --- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala @@ -176,8 +176,6 @@ case class DebugExtensionIo() extends Bundle with IMasterSlave{ } } - - class DebugPlugin(var debugClockDomain : ClockDomain, hardwareBreakpointCount : Int = 0) extends Plugin[VexRiscv] { var io : DebugExtensionIo = null @@ -226,6 +224,10 @@ class DebugPlugin(var debugClockDomain : ClockDomain, hardwareBreakpointCount : val isPipBusy = RegNext(stages.map(_.arbitration.isValid).orR || iBusFetcher.incoming()) val godmode = RegInit(False) setWhen(haltIt && !isPipBusy) val haltedByBreak = RegInit(False) + val debugUsed = RegInit(False) setWhen(io.bus.cmd.valid) addAttribute(Verilator.public) + val disableEbreak = RegInit(False) + + val allowEBreak = debugUsed && !disableEbreak val hardwareBreakpoints = Vec(Reg(new Bundle{ val valid = Bool() @@ -259,6 +261,7 @@ class DebugPlugin(var debugClockDomain : ClockDomain, hardwareBreakpointCount : haltIt setWhen (io.bus.cmd.data(17)) clearWhen (io.bus.cmd.data(25)) haltedByBreak clearWhen (io.bus.cmd.data(25)) godmode clearWhen(io.bus.cmd.data(25)) + disableEbreak setWhen (io.bus.cmd.data(18)) clearWhen (io.bus.cmd.data(26)) } } is(0x1) { @@ -277,8 +280,6 @@ class DebugPlugin(var debugClockDomain : ClockDomain, hardwareBreakpointCount : } } - val allowEBreak = if(!pipeline.serviceExist(classOf[PrivilegeService])) True else pipeline.service(classOf[PrivilegeService]).isMachine() - decode.insert(DO_EBREAK) := !haltIt && (decode.input(IS_EBREAK) || hardwareBreakpoints.map(hb => hb.valid && hb.pc === (decode.input(PC) >> 1)).foldLeft(False)(_ || _)) && allowEBreak when(execute.arbitration.isValid && execute.input(DO_EBREAK)){ execute.arbitration.haltByOther := True @@ -328,6 +329,12 @@ class DebugPlugin(var debugClockDomain : ClockDomain, hardwareBreakpointCount : } if(pipeline.things.contains(DEBUG_BYPASS_CACHE)) pipeline(DEBUG_BYPASS_CACHE) := True } + when(allowEBreak) { + pipeline.plugins.foreach { + case p: ExceptionInhibitor => p.inhibateEbreakException() + case _ => + } + } val wakeService = serviceElse(classOf[IWake], null) if(wakeService != null) when(haltIt){ diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index e58aba3..c8ad579 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -1673,6 +1673,7 @@ public: } #endif + bool failed = false; try { // run simulation for 100 clock periods @@ -3496,6 +3497,11 @@ public: if(clientSuccess) pass(); if(clientFail) fail(); } + + virtual void postReset(){ + Workspace::postReset(); + top->VexRiscv->DebugPlugin_debugUsed = 1; + } }; #endif