DebugPlugin fully implemented
This commit is contained in:
parent
619739d33a
commit
6c1d953647
|
@ -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 config._
|
||||||
import CsrAccess._
|
import CsrAccess._
|
||||||
|
|
||||||
|
@ -107,6 +107,8 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
|
||||||
object ENV_CTRL extends Stageable(EnvCtrlEnum())
|
object ENV_CTRL extends Stageable(EnvCtrlEnum())
|
||||||
object IS_CSR extends Stageable(Bool)
|
object IS_CSR extends Stageable(Bool)
|
||||||
|
|
||||||
|
var allowInterrupts : Bool = null
|
||||||
|
|
||||||
override def setup(pipeline: VexRiscv): Unit = {
|
override def setup(pipeline: VexRiscv): Unit = {
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
|
|
||||||
|
@ -162,8 +164,11 @@ class CsrPlugin(config : MachineCsrConfig) extends Plugin[VexRiscv] with Excepti
|
||||||
|
|
||||||
if(catchIllegalAccess)
|
if(catchIllegalAccess)
|
||||||
selfException = newExceptionPort(pipeline.execute)
|
selfException = newExceptionPort(pipeline.execute)
|
||||||
|
|
||||||
|
allowInterrupts = True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def inhibateInterrupts() : Unit = allowInterrupts := False
|
||||||
|
|
||||||
def isUser(stage : Stage) : Bool = privilege === 0
|
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 exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last else False
|
||||||
val writeBackWfi = if(wfiGen) writeBack.arbitration.isValid && writeBack.input(ENV_CTRL) === EnvCtrlEnum.WFI else False
|
val writeBackWfi = if(wfiGen) writeBack.arbitration.isValid && writeBack.input(ENV_CTRL) === EnvCtrlEnum.WFI else False
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package SpinalRiscv.Plugin
|
package SpinalRiscv.Plugin
|
||||||
|
|
||||||
|
import SpinalRiscv.Plugin.IntAluPlugin.{AluCtrlEnum, ALU_CTRL}
|
||||||
import SpinalRiscv._
|
import SpinalRiscv._
|
||||||
import SpinalRiscv.ip._
|
import SpinalRiscv.ip._
|
||||||
import spinal.core._
|
import spinal.core._
|
||||||
|
@ -39,8 +40,24 @@ class DebugPlugin() extends Plugin[VexRiscv] {
|
||||||
|
|
||||||
var io : DebugExtensionIo = null
|
var io : DebugExtensionIo = null
|
||||||
|
|
||||||
|
|
||||||
|
object IS_EBREAK extends Stageable(Bool)
|
||||||
override def setup(pipeline: VexRiscv): Unit = {
|
override def setup(pipeline: VexRiscv): Unit = {
|
||||||
|
import Riscv._
|
||||||
|
import pipeline.config._
|
||||||
|
|
||||||
io = slave(DebugExtensionIo())
|
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 = {
|
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 isPipActive = RegNext(List(fetch,decode,execute,memory,writeBack).map(_.arbitration.isValid).orR)
|
||||||
val isPipBusy = isPipActive || RegNext(isPipActive)
|
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) {
|
when(io.bus.cmd.valid) {
|
||||||
switch(io.bus.cmd.address(2 downto 2)) {
|
switch(io.bus.cmd.address(2 downto 2)) {
|
||||||
|
@ -74,11 +90,12 @@ class DebugPlugin() extends Plugin[VexRiscv] {
|
||||||
stepIt := io.bus.cmd.data(4)
|
stepIt := io.bus.cmd.data(4)
|
||||||
resetIt setWhen(io.bus.cmd.data(16)) clearWhen(io.bus.cmd.data(24))
|
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))
|
haltIt setWhen(io.bus.cmd.data(17)) clearWhen(io.bus.cmd.data(25))
|
||||||
|
haltedByBreak clearWhen(io.bus.cmd.data(25))
|
||||||
} otherwise{
|
} otherwise{
|
||||||
busReadDataReg(0) := resetIt
|
busReadDataReg(0) := resetIt
|
||||||
busReadDataReg(1) := haltIt
|
busReadDataReg(1) := haltIt
|
||||||
busReadDataReg(2) := isPipBusy
|
busReadDataReg(2) := isPipBusy
|
||||||
// busReadDataReg(3) := isInBreakpoint
|
busReadDataReg(3) := haltedByBreak
|
||||||
busReadDataReg(4) := stepIt
|
busReadDataReg(4) := stepIt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +103,7 @@ class DebugPlugin() extends Plugin[VexRiscv] {
|
||||||
when(io.bus.cmd.wr){
|
when(io.bus.cmd.wr){
|
||||||
insertDecodeInstruction := True
|
insertDecodeInstruction := True
|
||||||
val injectedInstructionSent = RegNext(decode.arbitration.isFiring) init(False)
|
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)
|
decode.arbitration.isValid setWhen(firstCycle)
|
||||||
io.bus.cmd.ready := injectedInstructionSent
|
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(() => {
|
Component.current.addPrePopTask(() => {
|
||||||
when(insertDecodeInstruction) {
|
val reg = decode.input(INSTRUCTION).getDrivingReg
|
||||||
decode.input(INSTRUCTION).getDrivingReg := io.bus.cmd.data
|
reg.component.rework{
|
||||||
|
when(insertDecodeInstruction.pull()) {
|
||||||
|
reg := io.bus.cmd.data.pull()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
when(execute.arbitration.isFiring && execute.input(IS_EBREAK)){
|
||||||
//Keep the execution pipeline empty after break instruction
|
prefetch.arbitration.haltIt := True
|
||||||
// when(core.execute1.inInst.valid && isMyTag(core.execute1.inInst.ctrl)){
|
decode.arbitration.flushAll := True
|
||||||
// core.execute0.halt := True
|
haltIt := True
|
||||||
// }
|
haltedByBreak := True
|
||||||
//
|
}
|
||||||
// when(isInBreakpoint){
|
|
||||||
// core.execute0.halt := True
|
|
||||||
// core.writeBack.halt := True
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// when(flushIt) {
|
|
||||||
// core.writeBack.flush := True
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
when(haltIt){
|
when(haltIt){
|
||||||
prefetch.arbitration.haltIt := True
|
prefetch.arbitration.haltIt := True
|
||||||
|
@ -127,6 +139,8 @@ class DebugPlugin() extends Plugin[VexRiscv] {
|
||||||
|
|
||||||
io.resetOut := RegNext(resetIt)
|
io.resetOut := RegNext(resetIt)
|
||||||
|
|
||||||
// core.writeBack.irq.inhibate setWhen(haltIt || stepIt)
|
when(haltIt || stepIt){
|
||||||
|
service(classOf[InterruptionInhibitor]).inhibateInterrupts()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(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 = {
|
override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: BaseType], Any)]): Unit = {
|
||||||
assert(!encodings.contains(key))
|
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 : SpinalEnumElement[_] => e()
|
||||||
case e : BaseType => e
|
case e : BaseType => e
|
||||||
})}
|
})}
|
||||||
|
@ -58,7 +58,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean) extends Plugin[VexR
|
||||||
}
|
}
|
||||||
|
|
||||||
val defaults = mutable.HashMap[Stageable[_ <: BaseType], BaseType]()
|
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
|
var decodeExceptionPort : Flow[ExceptionCause] = null
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,11 @@ trait PrivilegeService{
|
||||||
def isUser(stage : Stage) : Bool
|
def isUser(stage : Stage) : Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait InterruptionInhibitor{
|
||||||
|
def inhibateInterrupts() : Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
case class MemoryTranslatorCmd() extends Bundle{
|
case class MemoryTranslatorCmd() extends Bundle{
|
||||||
val isValid = Bool
|
val isValid = Bool
|
||||||
val virtualAddress = UInt(32 bits)
|
val virtualAddress = UInt(32 bits)
|
||||||
|
|
|
@ -183,6 +183,7 @@ object TopLevel {
|
||||||
new MulPlugin,
|
new MulPlugin,
|
||||||
new DivPlugin,
|
new DivPlugin,
|
||||||
new CsrPlugin(csrConfigAll),
|
new CsrPlugin(csrConfigAll),
|
||||||
|
// new DebugPlugin(),
|
||||||
new BranchPlugin(
|
new BranchPlugin(
|
||||||
earlyBranch = false,
|
earlyBranch = false,
|
||||||
catchAddressMisaligned = true,
|
catchAddressMisaligned = true,
|
||||||
|
|
Loading…
Reference in New Issue