From fc1f5be316025de1e3cb7cddc3d6b02880a8a882 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 30 Nov 2017 16:36:45 -0800 Subject: [PATCH 1/2] Debug: fix a latent combinational loop (d_ready => d_bits) When passed a Wire, WNotify outputs that wire on reads wire => d_bits. Furthermore, it updates the Wire when a write occures d_ready => wire. These registers should be returning undefined value on read, anyway. --- src/main/scala/devices/debug/Debug.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/scala/devices/debug/Debug.scala b/src/main/scala/devices/debug/Debug.scala index 12dc7a4d..a0da5a04 100644 --- a/src/main/scala/devices/debug/Debug.scala +++ b/src/main/scala/devices/debug/Debug.scala @@ -249,11 +249,11 @@ class DebugCtrlBundle (nComponents: Int)(implicit val p: Parameters) extends Par */ // Local reg mapper function : Notify when written, but give the value as well. -object WNotify { +object WNotifyWire { def apply(n: Int, value: UInt, set: Bool) : RegField = { - RegField(n, value, RegWriteFn((valid, data) => { + RegField(n, UInt(0), RegWriteFn((valid, data) => { set := valid - when(valid) {value := data} + value := data Bool(true) })) } @@ -881,10 +881,10 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p: tlNode.regmap( // This memory is writable. - HALTED -> Seq(WNotify(sbIdWidth, hartHaltedId, hartHaltedWrEn)), - GOING -> Seq(WNotify(sbIdWidth, hartGoingId, hartGoingWrEn)), - RESUMING -> Seq(WNotify(sbIdWidth, hartResumingId, hartResumingWrEn)), - EXCEPTION -> Seq(WNotify(sbIdWidth, hartExceptionId, hartExceptionWrEn)), + HALTED -> Seq(WNotifyWire(sbIdWidth, hartHaltedId, hartHaltedWrEn)), + GOING -> Seq(WNotifyWire(sbIdWidth, hartGoingId, hartGoingWrEn)), + RESUMING -> Seq(WNotifyWire(sbIdWidth, hartResumingId, hartResumingWrEn)), + EXCEPTION -> Seq(WNotifyWire(sbIdWidth, hartExceptionId, hartExceptionWrEn)), DATA -> abstractDataMem.map(x => RegField(8, x)), PROGBUF(cfg)-> programBufferMem.map(x => RegField(8, x)), From 35506279af7bd3b8377180eb9db8c3dd641dbb58 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 30 Nov 2017 16:38:45 -0800 Subject: [PATCH 2/2] regmapper: fix d_ready => d_bits loop in RegField.bytes RegField.bytes updates only those bytes which are written every cycle. However, there was a bug that it would try to return the updated value on reads. This led to another TL-spec violating combinational path, just like the Debug module. --- src/main/scala/regmapper/RegField.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/scala/regmapper/RegField.scala b/src/main/scala/regmapper/RegField.scala index 3cf0caa8..16212c24 100644 --- a/src/main/scala/regmapper/RegField.scala +++ b/src/main/scala/regmapper/RegField.scala @@ -113,13 +113,15 @@ object RegField // than the intended bus width of the device (atomic updates are impossible). def bytes(reg: UInt, numBytes: Int): Seq[RegField] = { val pad = reg | UInt(0, width = 8*numBytes) - val bytes = Wire(init = Vec.tabulate(numBytes) { i => pad(8*(i+1)-1, 8*i) }) + val oldBytes = Vec.tabulate(numBytes) { i => pad(8*(i+1)-1, 8*i) } + val newBytes = Wire(init = oldBytes) val valids = Wire(init = Vec.fill(numBytes) { Bool(false) }) - when (valids.reduce(_ || _)) { reg := bytes.asUInt } - bytes.zipWithIndex.map { case (b, i) => RegField(8, b, - RegWriteFn((valid, data) => { + when (valids.reduce(_ || _)) { reg := newBytes.asUInt } + Seq.tabulate(numBytes) { i => + RegField(8, oldBytes(i), + RegWriteFn((valid, data) => { valids(i) := valid - when (valid) { bytes(i) := data } + when (valid) { newBytes(i) := data } Bool(true) }))}}