RVC debug pass tets

This commit is contained in:
Dolu1990 2018-05-09 00:28:14 +02:00
parent 0056da1342
commit acccbf40e2
5 changed files with 94 additions and 49 deletions

View File

@ -95,19 +95,13 @@ case class DebugExtensionIo() extends Bundle with IMasterSlave{
} }
//Allow to avoid instruction cache plugin to be confused by new instruction poping in the pipeline
trait InstructionInjector{
def isInjecting(stage : Stage) : Bool
}
class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] with InstructionInjector { class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] {
var io : DebugExtensionIo = null var io : DebugExtensionIo = null
val injectionAsks = ArrayBuffer[(Stage, Bool)]() val injectionAsks = ArrayBuffer[(Stage, Bool)]()
var isInjectingOnDecode : Bool = null
var injectionPort : Stream[Bits] = null var injectionPort : Stream[Bits] = null
override def isInjecting(stage: Stage) : Bool = if(stage == pipeline.decode) isInjectingOnDecode else False
object IS_EBREAK extends Stageable(Bool) object IS_EBREAK extends Stageable(Bool)
override def setup(pipeline: VexRiscv): Unit = { override def setup(pipeline: VexRiscv): Unit = {
@ -127,7 +121,6 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w
ALU_CTRL -> AluCtrlEnum.ADD_SUB //Used to get the PC value in busReadDataReg ALU_CTRL -> AluCtrlEnum.ADD_SUB //Used to get the PC value in busReadDataReg
)) ))
isInjectingOnDecode = Bool()
injectionPort = pipeline.service(classOf[IBusFetcher]).getInjectionPort() injectionPort = pipeline.service(classOf[IBusFetcher]).getInjectionPort()
} }
@ -138,7 +131,6 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w
val logic = debugClockDomain {pipeline plug new Area{ val logic = debugClockDomain {pipeline plug new Area{
val iBusFetcher = service(classOf[IBusFetcher]) val iBusFetcher = service(classOf[IBusFetcher])
val insertDecodeInstruction = False
val firstCycle = RegNext(False) setWhen (io.bus.cmd.ready) val firstCycle = RegNext(False) setWhen (io.bus.cmd.ready)
val secondCycle = RegNext(firstCycle) val secondCycle = RegNext(firstCycle)
val resetIt = RegInit(False) val resetIt = RegInit(False)
@ -164,6 +156,9 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w
io.bus.rsp.data(4) := stepIt io.bus.rsp.data(4) := stepIt
} }
injectionPort.valid := False
injectionPort.payload := io.bus.cmd.data
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)) {
is(0) { is(0) {
@ -176,18 +171,14 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w
} }
is(1) { is(1) {
when(io.bus.cmd.wr) { when(io.bus.cmd.wr) {
insertDecodeInstruction := True injectionPort.valid := True
// decode.arbitration.isValid.getDrivingReg setWhen (firstCycle) io.bus.cmd.ready := injectionPort.ready
// decode.arbitration.haltItself setWhen (secondCycle)
// io.bus.cmd.ready := !firstCycle && !secondCycle && execute.arbitration.isValid
io.bus.cmd.ready := injectionPort.fire
} }
} }
} }
} }
injectionPort.valid := RegNext(insertDecodeInstruction) init(False) clearWhen(injectionPort.fire)
injectionPort.payload := RegNext(io.bus.cmd.data)
// Component.current.addPrePopTask(() => { // Component.current.addPrePopTask(() => {
@ -232,9 +223,17 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w
haltIt := True haltIt := True
} }
} }
when(stepIt && Cat(pipeline.stages.map(_.arbitration.redoIt)).asBits.orR) { when(stepIt && Cat(pipeline.stages.map(_.arbitration.redoIt)).asBits.orR) {
haltIt := False haltIt := False
} }
//Avoid having two C instruction executed in a single step
if(pipeline(RVC_GEN)){
val cleanStep = RegNext(stepIt && decode.arbitration.isFiring) init(False)
decode.arbitration.removeIt setWhen(cleanStep)
}
io.resetOut := RegNext(resetIt) io.resetOut := RegNext(resetIt)
if(serviceExist(classOf[InterruptionInhibitor])) { if(serviceExist(classOf[InterruptionInhibitor])) {
@ -248,8 +247,5 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w
} }
} }
}} }}
isInjectingOnDecode := RegNext(logic.insertDecodeInstruction) init(False)
} }
} }

View File

@ -171,7 +171,8 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
pcReg + 4 pcReg + 4
if (keepPcPlus4) KeepAttribute(pcPlus) if (keepPcPlus4) KeepAttribute(pcPlus)
when(decode.arbitration.isFiring) { val injectedDecode = False
when(decode.arbitration.isFiring && !injectedDecode) {
pcReg := pcPlus pcReg := pcPlus
} }
@ -250,31 +251,31 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3) incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3)
}) })
//TODO never colalpse buble of the last stage
def condApply[T](that : T, cond : Boolean)(func : (T) => T) = if(cond)func(that) else that def condApply[T](that : T, cond : Boolean)(func : (T) => T) = if(cond)func(that) else that
val injector = new Area { val injector = new Area {
val inputBeforeHalt = condApply(if(decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(flush)) val inputBeforeHalt = condApply(if (decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(flush))
if(injectorReadyCutGen) { if (injectorReadyCutGen) {
iBusRsp.readyForError.clearWhen(inputBeforeHalt.valid) iBusRsp.readyForError.clearWhen(inputBeforeHalt.valid)
incomingInstruction setWhen(inputBeforeHalt.valid) incomingInstruction setWhen (inputBeforeHalt.valid)
} }
val decodeInput = (if(injectorStage){ val decodeInput = (if (injectorStage) {
val decodeInput = inputBeforeHalt.m2sPipeWithFlush(killLastStage, collapsBubble = false) val decodeInput = inputBeforeHalt.m2sPipeWithFlush(killLastStage, collapsBubble = false)
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeHalt.rsp.inst) decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeHalt.rsp.inst)
iBusRsp.readyForError.clearWhen(decodeInput.valid) iBusRsp.readyForError.clearWhen(decodeInput.valid)
incomingInstruction setWhen(decodeInput.valid) incomingInstruction setWhen (decodeInput.valid)
decodeInput decodeInput
} else { } else {
inputBeforeHalt inputBeforeHalt
}) })
if(decodePcGen){ if (decodePcGen) {
decodeNextPcValid := True decodeNextPcValid := True
decodeNextPc := decodePc.pcReg decodeNextPc := decodePc.pcReg
}else { } else {
val lastStageStream = if(injectorStage) inputBeforeHalt val lastStageStream = if (injectorStage) inputBeforeHalt
else if(rspStageGen) iBusRsp.outputBeforeStage else if (rspStageGen) iBusRsp.outputBeforeStage
else if(cmdToRspStageCount > 1)iBusRsp.inputPipeline(cmdToRspStageCount-2) else if (cmdToRspStageCount > 1) iBusRsp.inputPipeline(cmdToRspStageCount - 2)
else throw new Exception("Fetch should at least have two stages") else throw new Exception("Fetch should at least have two stages")
// when(fetcherHalt){ // when(fetcherHalt){
@ -287,25 +288,72 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
decodeInput.ready := !decode.arbitration.isStuck decodeInput.ready := !decode.arbitration.isStuck
decode.arbitration.isValid := decodeInput.valid decode.arbitration.isValid := decodeInput.valid
decode.insert(PC) := (if(decodePcGen) decodePc.pcReg else decodeInput.pc) decode.insert(PC) := (if (decodePcGen) decodePc.pcReg else decodeInput.pc)
decode.insert(INSTRUCTION) := decodeInput.rsp.inst decode.insert(INSTRUCTION) := decodeInput.rsp.inst
decode.insert(INSTRUCTION_READY) := True decode.insert(INSTRUCTION_READY) := True
if(compressedGen) decode.insert(IS_RVC) := decodeInput.isRvc if (compressedGen) decode.insert(IS_RVC) := decodeInput.isRvc
// if(catchAccessFault){ // if(catchAccessFault){
// decodeExceptionPort.valid := decode.arbitration.isValid && decodeInput.rsp.error // decodeExceptionPort.valid := decode.arbitration.isValid && decodeInput.rsp.error
// decodeExceptionPort.code := 1 // decodeExceptionPort.code := 1
// decodeExceptionPort.badAddr := decode.input(PC) // decodeExceptionPort.badAddr := decode.input(PC)
// } // }
if(injectionPort != null){ if (injectionPort != null) {
val state = RegNext(injectionPort.valid) init(False) clearWhen(injectionPort.ready) Component.current.addPrePopTask(() => {
injectionPort.ready := !decode.arbitration.isStuck && state val state = RegInit(U"000")
when(injectionPort.valid) {
decode.arbitration.isValid := True injectionPort.ready := False
decode.arbitration.haltItself setWhen(!state) if(decodePcGen){
decode.insert(INSTRUCTION) := injectionPort.payload decodePc.injectedDecode setWhen(state =/= 0)
} }
switch(state) {
is(0) { //request pipelining
when(injectionPort.valid) {
state := 1
}
}
is(1) { //Give time to propagate the payload
state := 2
}
is(2){ //read regfile delay
decode.arbitration.isValid := True
decode.arbitration.haltItself := True
state := 3
}
is(3){ //Do instruction
decode.arbitration.isValid := True
when(!decode.arbitration.isStuck) {
state := 4
}
}
is(4){ //request pipelining
injectionPort.ready := True
state := 0
}
}
//Check if the decode instruction is driven by a register
val instructionDriver = try {
decode.input(INSTRUCTION).getDrivingReg
} catch {
case _: Throwable => null
}
if (instructionDriver != null) { //If yes =>
//Insert the instruction by writing the "fetch to decode instruction register",
// Work even if it need to cross some hierarchy (caches)
instructionDriver.component.rework {
when(state.pull() =/= 0) {
instructionDriver := injectionPort.payload.pull()
}
}
} else {
//Insert the instruction via a mux in the decode stage
when(state =/= 0) {
decode.input(INSTRUCTION) := RegNext(injectionPort.payload)
}
}
})
} }
} }

View File

@ -109,8 +109,8 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean,
catchAccessFault = catchAccessFault, catchAccessFault = catchAccessFault,
resetVector = BigInt(0x80000000l), resetVector = BigInt(0x80000000l),
keepPcPlus4 = false, keepPcPlus4 = false,
decodePcGen = false, decodePcGen = true,
compressedGen = false, compressedGen = true,
cmdToRspStageCount = 1, cmdToRspStageCount = 1,
rspStageGen = false, rspStageGen = false,
injectorReadyCutGen = false, injectorReadyCutGen = false,

1
src/test/python/tool/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/disasm.s

View File

@ -1 +1 @@
.word 0x8067 .word 0x812e23