debug: Make DMI NOPs really NOPs.
This simplifies SW design and CDC issues.
This commit is contained in:
parent
67404a665b
commit
0c013a56c0
@ -83,8 +83,11 @@ class DebugTransportModuleJTAG(debugAddrBits: Int, c: JtagDTMConfig)
|
|||||||
val busy = Wire(Bool())
|
val busy = Wire(Bool())
|
||||||
val nonzeroResp = Wire(Bool())
|
val nonzeroResp = Wire(Bool())
|
||||||
|
|
||||||
val busyResp = Wire(new DMIAccessCapture(debugAddrBits))
|
val busyResp = Wire(new DMIAccessCapture(debugAddrBits))
|
||||||
val nonbusyResp = Wire(new DMIAccessCapture(debugAddrBits))
|
val nonbusyResp = Wire(new DMIAccessCapture(debugAddrBits))
|
||||||
|
val dmiResp = Wire(new DMIAccessCapture(debugAddrBits))
|
||||||
|
val nopResp = Wire(new DMIAccessCapture(debugAddrBits))
|
||||||
|
|
||||||
|
|
||||||
val dmiReqReg = Reg(new DMIReq(debugAddrBits))
|
val dmiReqReg = Reg(new DMIReq(debugAddrBits))
|
||||||
val dmiReqValidReg = Reg(init = Bool(false));
|
val dmiReqValidReg = Reg(init = Bool(false));
|
||||||
@ -156,20 +159,29 @@ class DebugTransportModuleJTAG(debugAddrBits: Int, c: JtagDTMConfig)
|
|||||||
// Especially for the first request, we must consider dtmResp.valid,
|
// Especially for the first request, we must consider dtmResp.valid,
|
||||||
// so that we don't consider junk in the FIFO to be an error response.
|
// so that we don't consider junk in the FIFO to be an error response.
|
||||||
// The current specification says that any non-zero response is an error.
|
// The current specification says that any non-zero response is an error.
|
||||||
|
// But there is actually no case in the current design where you SHOULD get an error,
|
||||||
|
// as we haven't implemented Bus Masters or Serial Ports, which are the only cases errors
|
||||||
|
// can occur.
|
||||||
nonzeroResp := stickyNonzeroRespReg | (io.dmi.resp.valid & (io.dmi.resp.bits.resp != UInt(0)))
|
nonzeroResp := stickyNonzeroRespReg | (io.dmi.resp.valid & (io.dmi.resp.bits.resp != UInt(0)))
|
||||||
|
assert(!nonzeroResp, "There is no reason to get a non zero response in the current system.");
|
||||||
|
assert(!stickyNonzeroRespReg, "There is no reason to have a sticky non zero response in the current system.");
|
||||||
|
|
||||||
busyResp.addr := UInt(0)
|
busyResp.addr := UInt(0)
|
||||||
busyResp.resp := -1.S(DMIConsts.dmiRespSize.W).asUInt // Generalizing busy to 'all-F'
|
busyResp.resp := Fill(DMIConsts.dmiRespSize, 1.U) // Generalizing busy to 'all-F'
|
||||||
busyResp.data := UInt(0)
|
busyResp.data := UInt(0)
|
||||||
|
|
||||||
nonbusyResp.addr := dmiReqReg.addr
|
dmiResp.addr := dmiReqReg.addr
|
||||||
nonbusyResp.resp := io.dmi.resp.bits.resp
|
dmiResp.resp := io.dmi.resp.bits.resp
|
||||||
nonbusyResp.data := io.dmi.resp.bits.data
|
dmiResp.data := io.dmi.resp.bits.data
|
||||||
|
|
||||||
|
nopResp.addr := UInt(0)
|
||||||
|
nopResp.resp := UInt(0)
|
||||||
|
nopResp.data := UInt(0)
|
||||||
|
|
||||||
//--------------------------------------------------------
|
//--------------------------------------------------------
|
||||||
// Debug Access Chain Implementation
|
// Debug Access Chain Implementation
|
||||||
|
|
||||||
dmiAccessChain.io.capture.bits := Mux(busy, busyResp, nonbusyResp)
|
dmiAccessChain.io.capture.bits := Mux(busy, busyResp, Mux(io.dmi.resp.valid, dmiResp, nopResp))
|
||||||
when (dmiAccessChain.io.update.valid) {
|
when (dmiAccessChain.io.update.valid) {
|
||||||
skipOpReg := Bool(false)
|
skipOpReg := Bool(false)
|
||||||
downgradeOpReg := Bool(false)
|
downgradeOpReg := Bool(false)
|
||||||
@ -177,24 +189,25 @@ class DebugTransportModuleJTAG(debugAddrBits: Int, c: JtagDTMConfig)
|
|||||||
when (dmiAccessChain.io.capture.capture) {
|
when (dmiAccessChain.io.capture.capture) {
|
||||||
skipOpReg := busy
|
skipOpReg := busy
|
||||||
downgradeOpReg := (!busy & nonzeroResp)
|
downgradeOpReg := (!busy & nonzeroResp)
|
||||||
stickyBusyReg := busy
|
stickyBusyReg := busy
|
||||||
stickyNonzeroRespReg := nonzeroResp
|
stickyNonzeroRespReg := nonzeroResp
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------
|
//--------------------------------------------------------
|
||||||
// Drive Ready Valid Interface
|
// Drive Ready Valid Interface
|
||||||
|
|
||||||
|
assert(!(dmiAccessChain.io.update.valid && io.dmi.req.ready), "Conflicting updates for dmiReqValid, should not happen.");
|
||||||
|
|
||||||
when (dmiAccessChain.io.update.valid) {
|
when (dmiAccessChain.io.update.valid) {
|
||||||
when (skipOpReg) {
|
when (skipOpReg) {
|
||||||
// Do Nothing
|
// Do Nothing
|
||||||
|
}.elsewhen(downgradeOpReg || (dmiAccessChain.io.update.bits.op === DMIConsts.dmi_OP_NONE)) {
|
||||||
|
// Do Nothing
|
||||||
|
dmiReqReg.addr := UInt(0)
|
||||||
|
dmiReqReg.data := UInt(0)
|
||||||
|
dmiReqReg.op := UInt(0)
|
||||||
}.otherwise {
|
}.otherwise {
|
||||||
when (downgradeOpReg) {
|
dmiReqReg := dmiAccessChain.io.update.bits
|
||||||
dmiReqReg.addr := UInt(0)
|
|
||||||
dmiReqReg.data := UInt(0)
|
|
||||||
dmiReqReg.op := UInt(0)
|
|
||||||
}.otherwise {
|
|
||||||
dmiReqReg := dmiAccessChain.io.update.bits
|
|
||||||
}
|
|
||||||
dmiReqValidReg := Bool(true)
|
dmiReqValidReg := Bool(true)
|
||||||
}
|
}
|
||||||
}.otherwise {
|
}.otherwise {
|
||||||
|
@ -1097,19 +1097,13 @@ class DMIToTL(implicit p: Parameters) extends LazyModule {
|
|||||||
val (_, gbits) = edge.Get(src, addr, size)
|
val (_, gbits) = edge.Get(src, addr, size)
|
||||||
val (_, pfbits) = edge.Put(src, addr, size, io.dmi.req.bits.data)
|
val (_, pfbits) = edge.Put(src, addr, size, io.dmi.req.bits.data)
|
||||||
|
|
||||||
// Note we force DMI NOPs to go to CONTROL register because
|
when (io.dmi.req.fire()) {
|
||||||
// Inner may be in reset / not have a clock,
|
assert (io.dmi.req.bits.op === DMIConsts.dmi_OP_WRITE || io.dmi.req.bits.op === DMIConsts.dmi_OP_READ,
|
||||||
// so we force address to be the one that goes to Outer.
|
"Invalid DMI Request Type.");
|
||||||
// Besides, for a NOP we don't really need to pay the penalty to go
|
|
||||||
// across the CDC.
|
|
||||||
|
|
||||||
val (_, nbits) = edge.Put(src, toAddress = (DMI_RegAddrs.DMI_DMCONTROL << 2).U, size, data=0.U, mask = 0.U)
|
|
||||||
|
|
||||||
when (io.dmi.req.bits.op === DMIConsts.dmi_OP_WRITE) { tl.a.bits := pfbits
|
|
||||||
}.elsewhen (io.dmi.req.bits.op === DMIConsts.dmi_OP_READ) { tl.a.bits := gbits
|
|
||||||
}.otherwise { tl.a.bits := nbits
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tl.a.bits := Mux(io.dmi.req.bits.op === DMIConsts.dmi_OP_WRITE, pfbits, gbits);
|
||||||
|
|
||||||
tl.a.valid := io.dmi.req.valid
|
tl.a.valid := io.dmi.req.valid
|
||||||
io.dmi.req.ready := tl.a.ready
|
io.dmi.req.ready := tl.a.ready
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user