DebugPlugin fully implemented

This commit is contained in:
Charles Papon 2017-05-20 18:15:15 +02:00
parent 619739d33a
commit 6c1d953647
5 changed files with 51 additions and 26 deletions

View File

@ -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

View File

@ -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()
}
} }
} }

View File

@ -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

View File

@ -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)

View File

@ -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,