diff --git a/src/main/scala/chisel3/util/experimental/BoringUtils.scala b/src/main/scala/chisel3/util/experimental/BoringUtils.scala index a916b341644..eee7fbb0e52 100644 --- a/src/main/scala/chisel3/util/experimental/BoringUtils.scala +++ b/src/main/scala/chisel3/util/experimental/BoringUtils.scala @@ -282,6 +282,12 @@ object BoringUtils { } if (parent(source) == thisModule) { // No boring to do + if (createProbe.nonEmpty && !DataMirror.isFullyAligned(source)) { + // Create aligned wire if source isn't aligned. This ensures result has same type regardless of origin. + val bore = Wire(purePortTypeBase) + bore :#= source + return bore + } return source } diff --git a/src/test/scala/chiselTests/BoringUtilsTapSpec.scala b/src/test/scala/chiselTests/BoringUtilsTapSpec.scala index cc0c52ac632..f1919a34bfd 100644 --- a/src/test/scala/chiselTests/BoringUtilsTapSpec.scala +++ b/src/test/scala/chiselTests/BoringUtilsTapSpec.scala @@ -495,6 +495,29 @@ class BoringUtilsTapSpec extends ChiselFlatSpec with ChiselRunners with Utils wi val verilog = circt.stage.ChiselStage.emitSystemVerilog(new Foo) } + it should "work with DecoupledIO locally" in { + import chisel3.util.{Decoupled, DecoupledIO} + class Foo extends RawModule { + val a = WireInit(DecoupledIO(Bool()), DontCare) + val b = BoringUtils.tapAndRead(a) + assert(chisel3.reflect.DataMirror.isFullyAligned(b), "tapAndRead should always return passive data") + } + + val chirrtl = circt.stage.ChiselStage.emitCHIRRTL(new Foo, Array("--full-stacktrace")) + + matchesAndOmits(chirrtl)( + "module Foo :", + "wire a : { flip ready : UInt<1>, valid : UInt<1>, bits : UInt<1>}", + "wire b : { ready : UInt<1>, valid : UInt<1>, bits : UInt<1>}", + "connect b.bits, a.bits", + "connect b.valid, a.valid", + "connect b.ready, a.ready" + )() + + // Check that firtool also passes + val verilog = circt.stage.ChiselStage.emitSystemVerilog(new Foo) + } + it should "allow tapping a probe" in { class Bar extends RawModule { val a = IO(probe.Probe(Bool()))