1
0
Fork 0

debug: Use flags for resume instead of program buffer. Untested.

This commit is contained in:
Megan Wachs 2017-04-07 09:54:51 -07:00 committed by Andrew Waterman
parent d361e9e343
commit 22c6f728c3
3 changed files with 57 additions and 30 deletions

View File

@ -10,7 +10,9 @@
// Region of memory where each hart has 1
// byte to read.
#define OK_GO 0x400
#define FLAGS 0x400
#define FLAG_GO 0
#define FLAG_RESUME 1
.option norvc
.global entry
@ -18,7 +20,7 @@
// Entry location on ebreak, Halt, or Breakpoint
// It is the same for all harts. They branch when
// their specific OK_GO bit is set.
// their GO or RESUME bit is set.
entry:
jal zero, _entry
@ -36,12 +38,17 @@ _entry:
// We continue to let the hart know that we are halted in order that
// a DM which was reset is still made aware that a hart is halted.
// We keep checking both whether there is something the debugger wants
// us to do, or whether we should not be halted anymore.
// us to do, or whether we should resume.
entry_loop:
csrr s0, CSR_MHARTID
sw s0, HALTED(zero)
lb s0, OK_GO(s0) // 1 byte flag per hart. Only one hart advances here.
bne zero, s0, going
lbu s0, FLAGS(s0) // 1 byte flag per hart. Only one hart advances here.
andi s0, s0, (1 << FLAG_GO)
bnez s0, going
csrr s0, CSR_MHARTID
lbu s0, FLAGS(s0) // multiple harts can resume here
andi s0, s0, (1 << FLAG_RESUME)
bnez s0, resume
jal zero, entry_loop
_exception:
@ -50,16 +57,14 @@ _exception:
going:
csrr s0, CSR_DSCRATCH // Restore s0 here
sw zero, GOING(zero) // When debug module sees this write, the OK_GO flag is reset.
sw zero, GOING(zero) // When debug module sees this write, the GO flag is reset.
jalr zero, zero, %lo(whereto) // Rocket-Chip has a specific hack which is that jalr in
// Debug Mode will flush the I-Cache. We need that so that the
// remainder of the variable instructions will be what Debug Module
// intends.
_resume:
csrw CSR_DSCRATCH, s0 // Save s0 to allow signaling MHARTID
csrr s0, CSR_MHARTID
sw s0, RESUMING(zero) // Let the Debug Module know you're not halted anymore.
sw s0, RESUMING(zero) // When Debug Module sees this write, the RESUME flag is reset.
csrr s0, CSR_DSCRATCH // Restore s0
dret

View File

@ -52,7 +52,7 @@ object DsbRegAddrs{
def RESUMING = 0x108
def EXCEPTION = 0x10C
def GO = 0x400
def FLAGS = 0x400
def ROMBASE = 0x800
def RESUME = 0x804
@ -479,6 +479,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
//--------------------------------------------------------------
val haltedBitRegs = RegInit(Vec.fill(nComponents){false.B})
val resumeReqRegs = RegInit(Vec.fill(nComponents){false.B})
// --- regmapper outputs
@ -537,6 +538,9 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
DMSTATUSRdData.anyrunning := true.B
}
DMSTATUSRdData.allresumeack := ~resumeReqRegs(selectedHartReg)
DMSTATUSRdData.anyresumeack := ~resumeReqRegs(selectedHartReg)
//TODO
DMSTATUSRdData.cfgstrvalid := false.B
@ -685,7 +689,9 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
for (component <- 0 until nComponents) {
when (~io.dmactive) {
haltedBitRegs(component) := false.B
resumeReqRegs(component) := false.B
}.otherwise {
// Hart Halt Notification Logic
when (hartHaltedWrEn) {
when (cfg.hartIdToHartSel(hartHaltedId) === component.U) {
haltedBitRegs(component) := true.B
@ -695,6 +701,19 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
haltedBitRegs(component) := false.B
}
}
// Hart Resume Req Logic
// If you request a hart to resume at the same moment
// it actually does resume, then the request wins.
// So don't try to write resumereq more than once
when (hartResumingWrEn) {
when (cfg.hartIdToHartSel(hartResumingId) === component.U) {
resumeReqRegs(component) := false.B
}
}
when(io.innerCtrl.fire() && io.innerCtrl.bits.resumereq) {
resumeReqRegs(io.innerCtrl.bits.hartsel) := true.B
}
}
}
@ -723,7 +742,6 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
//--------------------------------------------------------------
val goProgramBuffer = Wire(init = false.B)
val goResume = Wire(init = false.B)
val goAbstract = Wire(init = false.B)
val whereToReg = Reg(UInt(32.W))
@ -736,17 +754,11 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
jalAbstract.setImm(ABSTRACT - WHERETO)
jalProgBuf.rd := 0.U
val jalResume = Wire(init = (new GeneratedUJ()).fromBits(rocket.Instructions.JAL.value.U))
jalResume.setImm(RESUME - WHERETO)
jalResume.rd := 0.U
when (~io.dmactive) {
whereToReg := 0.U
}.otherwise{
when (goProgramBuffer) {
whereToReg := jalProgBuf.asUInt()
}.elsewhen (goResume) {
whereToReg := jalResume.asUInt()
}.elsewhen (goAbstract) {
whereToReg := jalAbstract.asUInt()
}
@ -757,7 +769,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
when (~io.dmactive){
goReg := false.B
}.otherwise {
when (goProgramBuffer | goResume | goAbstract) {
when (goProgramBuffer | goAbstract) {
goReg := true.B
}.elsewhen (hartGoingWrEn){
assert(hartGoingId === 0.U, "Unexpected 'GOING' hart.")//Chisel3 #540 %x, expected %x", hartGoingId, 0.U)
@ -765,10 +777,20 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
}
}
val goBytes = Wire(init = Vec.fill(1024){0.U(8.W)})
class flagBundle extends Bundle {
val reserved = UInt(6.W)
val resume = Bool()
val go = Bool()
}
val flags = Wire(init = Vec.fill(1024){new flagBundle().fromBits(0.U)})
assert ((cfg.hartSelToHartId(selectedHartReg) < 1024.U),
"HartSel to HartId Mapping is illegal for this Debug Implementation, because HartID must be < 1024 for it to work.");
goBytes(cfg.hartSelToHartId(selectedHartReg)) := Cat(0.U(7.W), goReg)
flags(cfg.hartSelToHartId(selectedHartReg)).go := goReg
for (component <- 0 until nComponents) {
val componentSel = Wire(component.U)
flags(cfg.hartSelToHartId(componentSel)).resume := resumeReqRegs(component)
}
//----------------------------
// Abstract Command Decoding & Generation
@ -870,10 +892,10 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
// These sections are read-only.
ROMBASE -> DebugRomContents().map(x => RegField.r(8, (x & 0xFF).U(8.W))),
GO -> goBytes.map(x => RegField.r(8, x)),
FLAGS -> flags.map{x => RegField.r(8, x.asUInt())},
WHERETO -> Seq(RegField.r(32, whereToReg)),
ABSTRACT -> abstractGeneratedMem.map(x => RegField.r(32, x))
)
)
// Override System Bus accesses with dmactive reset.
when (~io.dmactive){
@ -940,9 +962,8 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
when (wrAccessRegisterCommand || regAccessRegisterCommand) {
ctrlStateNxt := CtrlState(CheckGenerate)
}.elsewhen(io.innerCtrl.fire() && io.innerCtrl.bits.resumereq) {
goResume := true.B
}
}.elsewhen (ctrlStateReg === CtrlState(CheckGenerate)){
// We use this state to ensure that the COMMAND has been

View File

@ -5,13 +5,14 @@ package uncore.devices
object DebugRomContents {
def apply() : Array[Byte] = { Array (
0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0x80, 0x03, 0x6f, 0x00, 0x00, 0x02,
0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0xc0, 0x04, 0x6f, 0x00, 0x40, 0x03,
0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x24, 0x40, 0xf1,
0x23, 0x20, 0x80, 0x10, 0x03, 0x04, 0x04, 0x40, 0x63, 0x18, 0x80, 0x00,
0x6f, 0xf0, 0x1f, 0xff, 0x23, 0x26, 0x00, 0x10, 0x73, 0x00, 0x10, 0x00,
0x73, 0x24, 0x20, 0x7b, 0x23, 0x22, 0x00, 0x10, 0x67, 0x00, 0x00, 0x30,
0x73, 0x10, 0x24, 0x7b, 0x73, 0x24, 0x40, 0xf1, 0x23, 0x24, 0x80, 0x10,
0x73, 0x24, 0x20, 0x7b, 0x73, 0x00, 0x20, 0x7b
0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, 0x13, 0x74, 0x14, 0x00,
0x63, 0x10, 0x04, 0x02, 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40,
0x13, 0x74, 0x24, 0x00, 0xe3, 0x18, 0x04, 0xfc, 0x6f, 0xf0, 0xdf, 0xfd,
0x23, 0x26, 0x00, 0x10, 0x73, 0x00, 0x10, 0x00, 0x73, 0x24, 0x20, 0x7b,
0x23, 0x22, 0x00, 0x10, 0x67, 0x00, 0x00, 0x30, 0x73, 0x24, 0x40, 0xf1,
0x23, 0x24, 0x80, 0x10, 0x73, 0x24, 0x20, 0x7b, 0x73, 0x00, 0x20, 0x7b
).map(_.toByte) }
}