diff --git a/scripts/debug_rom/debug_rom.S b/scripts/debug_rom/debug_rom.S index 73267976..8f7be006 100755 --- a/scripts/debug_rom/debug_rom.S +++ b/scripts/debug_rom/debug_rom.S @@ -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 diff --git a/src/main/scala/uncore/devices/debug/Debug.scala b/src/main/scala/uncore/devices/debug/Debug.scala index 3893b3ad..bd0c49f8 100644 --- a/src/main/scala/uncore/devices/debug/Debug.scala +++ b/src/main/scala/uncore/devices/debug/Debug.scala @@ -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 diff --git a/src/main/scala/uncore/devices/debug/DebugRomContents.scala b/src/main/scala/uncore/devices/debug/DebugRomContents.scala index 13438445..a56d83af 100644 --- a/src/main/scala/uncore/devices/debug/DebugRomContents.scala +++ b/src/main/scala/uncore/devices/debug/DebugRomContents.scala @@ -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) } }