preliminary DebugPlugin
This commit is contained in:
parent
cabf602efc
commit
619739d33a
|
@ -0,0 +1,132 @@
|
||||||
|
package SpinalRiscv.Plugin
|
||||||
|
|
||||||
|
import SpinalRiscv._
|
||||||
|
import SpinalRiscv.ip._
|
||||||
|
import spinal.core._
|
||||||
|
import spinal.lib._
|
||||||
|
|
||||||
|
|
||||||
|
case class DebugExtensionCmd() extends Bundle{
|
||||||
|
val wr = Bool
|
||||||
|
val address = UInt(8 bit)
|
||||||
|
val data = Bits(32 bit)
|
||||||
|
}
|
||||||
|
case class DebugExtensionRsp() extends Bundle{
|
||||||
|
val data = Bits(32 bit)
|
||||||
|
}
|
||||||
|
|
||||||
|
case class DebugExtensionBus() extends Bundle with IMasterSlave{
|
||||||
|
val cmd = Stream(DebugExtensionCmd())
|
||||||
|
val rsp = DebugExtensionRsp() //One cycle latency
|
||||||
|
|
||||||
|
override def asMaster(): Unit = {
|
||||||
|
master(cmd)
|
||||||
|
in(rsp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case class DebugExtensionIo() extends Bundle with IMasterSlave{
|
||||||
|
val bus = DebugExtensionBus()
|
||||||
|
val resetOut = Bool
|
||||||
|
|
||||||
|
override def asMaster(): Unit = {
|
||||||
|
master(bus)
|
||||||
|
in(resetOut)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DebugPlugin() extends Plugin[VexRiscv] {
|
||||||
|
|
||||||
|
var io : DebugExtensionIo = null
|
||||||
|
|
||||||
|
override def setup(pipeline: VexRiscv): Unit = {
|
||||||
|
io = slave(DebugExtensionIo())
|
||||||
|
}
|
||||||
|
|
||||||
|
override def build(pipeline: VexRiscv): Unit = {
|
||||||
|
import pipeline._
|
||||||
|
import pipeline.config._
|
||||||
|
|
||||||
|
val busReadDataReg = Reg(Bits(32 bit))
|
||||||
|
when(writeBack.arbitration.isValid){
|
||||||
|
busReadDataReg := writeBack.output(REGFILE_WRITE_DATA)
|
||||||
|
}
|
||||||
|
io.bus.cmd.ready := True
|
||||||
|
io.bus.rsp.data := busReadDataReg
|
||||||
|
|
||||||
|
val insertDecodeInstruction = False
|
||||||
|
val firstCycle = RegNext(False) setWhen(io.bus.cmd.ready)
|
||||||
|
val resetIt = RegInit(False)
|
||||||
|
val haltIt = RegInit(False)
|
||||||
|
val flushIt = RegNext(False)
|
||||||
|
val stepIt = RegInit(False)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
when(io.bus.cmd.valid) {
|
||||||
|
switch(io.bus.cmd.address(2 downto 2)) {
|
||||||
|
is(0){
|
||||||
|
when(io.bus.cmd.wr){
|
||||||
|
flushIt := io.bus.cmd.data(2)
|
||||||
|
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))
|
||||||
|
} otherwise{
|
||||||
|
busReadDataReg(0) := resetIt
|
||||||
|
busReadDataReg(1) := haltIt
|
||||||
|
busReadDataReg(2) := isPipBusy
|
||||||
|
// busReadDataReg(3) := isInBreakpoint
|
||||||
|
busReadDataReg(4) := stepIt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is(1) {
|
||||||
|
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.isValid setWhen(firstCycle)
|
||||||
|
io.bus.cmd.ready := injectedInstructionSent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.current.addPrePopTask(() => {
|
||||||
|
when(insertDecodeInstruction) {
|
||||||
|
decode.input(INSTRUCTION).getDrivingReg := io.bus.cmd.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//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(haltIt){
|
||||||
|
prefetch.arbitration.haltIt := True
|
||||||
|
}
|
||||||
|
|
||||||
|
when(stepIt && prefetch.arbitration.isFiring){
|
||||||
|
haltIt := True
|
||||||
|
}
|
||||||
|
|
||||||
|
io.resetOut := RegNext(resetIt)
|
||||||
|
|
||||||
|
// core.writeBack.irq.inhibate setWhen(haltIt || stepIt)
|
||||||
|
}
|
||||||
|
}
|
|
@ -80,7 +80,7 @@ class IBusCachedPlugin(config : InstructionCacheConfig, askMemoryTranslation : B
|
||||||
|
|
||||||
|
|
||||||
if(twoStageLogic){
|
if(twoStageLogic){
|
||||||
cache.io.cpu.decode.isValid := decode.arbitration.isValid
|
cache.io.cpu.decode.isValid := decode.arbitration.isValid && RegNextWhen(fetch.arbitration.isValid, !decode.arbitration.isStuck) //avoid inserted instruction from debug module
|
||||||
decode.arbitration.haltIt.setWhen(cache.io.cpu.decode.haltIt)
|
decode.arbitration.haltIt.setWhen(cache.io.cpu.decode.haltIt)
|
||||||
cache.io.cpu.decode.isStuck := decode.arbitration.isStuck
|
cache.io.cpu.decode.isStuck := decode.arbitration.isStuck
|
||||||
cache.io.cpu.decode.isUser := (if(privilegeService != null) privilegeService.isUser(writeBack) else False)
|
cache.io.cpu.decode.isUser := (if(privilegeService != null) privilegeService.isUser(writeBack) else False)
|
||||||
|
@ -108,7 +108,6 @@ class IBusCachedPlugin(config : InstructionCacheConfig, askMemoryTranslation : B
|
||||||
|
|
||||||
memory plug new Area{
|
memory plug new Area{
|
||||||
import memory._
|
import memory._
|
||||||
|
|
||||||
cache.io.flush.cmd.valid := False
|
cache.io.flush.cmd.valid := False
|
||||||
when(arbitration.isValid && input(FLUSH_ALL)){
|
when(arbitration.isValid && input(FLUSH_ALL)){
|
||||||
cache.io.flush.cmd.valid := True
|
cache.io.flush.cmd.valid := True
|
||||||
|
|
Loading…
Reference in New Issue