Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion core/src/main/scala/chisel3/Data.scala
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,17 @@ abstract class Data extends HasId with NamedComponent with DataIntf {
// Trace views to give better error messages
// Reifying involves checking against ViewParent which requires being in a Builder context
// Since we're just printing a String, suppress such errors and use this object
val thiz = Try(reifySingleTarget(this)).toOption.flatten.getOrElse(this)
// Use a guard to prevent infinite recursion when reifySingleTarget triggers toString
val thiz = if (Data.avoidReifyingViews.get()) {
this
} else {
Data.avoidReifyingViews.set(true)
try {
Try(reifySingleTarget(this)).toOption.flatten.getOrElse(this)
} finally {
Data.avoidReifyingViews.set(false)
}
}
thiz.topBindingOpt match {
case None => chiselTypeWithModifier
// Handle DontCares specially as they are "literal-like" but not actually literals
Expand Down Expand Up @@ -896,6 +906,9 @@ object Data {
// Needed for the `implicit def toConnectableDefault`
import scala.language.implicitConversions

// ThreadLocal to prevent infinite recursion in stringAccessor when reifySingleTarget triggers toString
private[chisel3] val avoidReifyingViews: ThreadLocal[Boolean] = ThreadLocal.withInitial(() => false)

private[chisel3] case class ProbeInfo(val writable: Boolean, color: Option[layer.Layer])

/** Provides :<=, :>=, :<>=, and :#= between consumer and producer of the same T <: Data */
Expand Down
26 changes: 26 additions & 0 deletions src/test/scala-2/chiselTests/ProbeSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -771,4 +771,30 @@ class ProbeSpec extends AnyFlatSpec with Matchers with FileCheck with ChiselSim
}
ChiselStage.emitCHIRRTL(new TestMod)
}

"FlatIO probe" should "not stack overflow" in {
class ProbeIO extends Bundle {
val a = UInt(32.W)
}
class WithProbeIO extends Bundle {
val probe = Output(Probe(new ProbeIO))
}
class FlatIOModule extends RawModule {
val io = FlatIO(new WithProbeIO)
val w = Wire(new ProbeIO)
define(io.probe, ProbeValue(w))
w.a := 0.U
dontTouch(io)
dontTouch(w)
}
class TestTop extends RawModule {
val testMod = Module(new FlatIOModule)
val r: Bool = testMod.io.probe.a === 0.U
dontTouch(r)
}
val exc = intercept[Throwable] {
ChiselStage.emitSystemVerilog(new TestTop)
}
exc should not be a[StackOverflowError]
}
}
Loading