From b28c1c7ad73c5a1a2150af83da60cd7710b26abe Mon Sep 17 00:00:00 2001 From: Yinan Xu Date: Sat, 20 Jan 2024 11:39:59 +0800 Subject: [PATCH] Support checking isVisible with reflect.DataMirror Users are now able to check whether a Data is visible from the current context via `chisel.reflect.DataMirror.isVisible`. --- core/src/main/scala/chisel3/Data.scala | 22 ++++++++++++------- .../scala/chisel3/reflect/DataMirror.scala | 6 +++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/core/src/main/scala/chisel3/Data.scala b/core/src/main/scala/chisel3/Data.scala index c65635182cf..ef39647cc99 100644 --- a/core/src/main/scala/chisel3/Data.scala +++ b/core/src/main/scala/chisel3/Data.scala @@ -582,18 +582,24 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { rec(leftType, rightType) } - private[chisel3] def requireVisible(): Unit = { + private[chisel3] def isVisible: Boolean = isVisibleFromModule && isVisibleFromWhen + private[chisel3] def isVisibleFromModule: Boolean = { val mod = topBindingOpt.flatMap(_.location) topBindingOpt match { - case Some(tb: TopBinding) if (mod == Builder.currentModule) => + case Some(tb: TopBinding) if (mod == Builder.currentModule) => true case Some(pb: PortBinding) - if (mod.flatMap(Builder.retrieveParent(_, Builder.currentModule.get)) == Builder.currentModule) => - case Some(pb: SecretPortBinding) => // Ignore secret to not require visibility - case Some(_: UnconstrainedBinding) => - case _ => - throwException(s"operand '$this' is not visible from the current module ${Builder.currentModule.get.name}") + if mod.flatMap(Builder.retrieveParent(_, Builder.currentModule.get)) == Builder.currentModule => true + case Some(pb: SecretPortBinding) => true // Ignore secret to not require visibility + case Some(_: UnconstrainedBinding) => true + case _ => false + } + } + private[chisel3] def isVisibleFromWhen: Boolean = MonoConnect.checkWhenVisibility(this) + private[chisel3] def requireVisible(): Unit = { + if (!isVisibleFromModule) { + throwException(s"operand '$this' is not visible from the current module ${Builder.currentModule.get.name}") } - if (!MonoConnect.checkWhenVisibility(this)) { + if (!isVisibleFromWhen) { throwException(s"operand has escaped the scope of the when in which it was constructed") } } diff --git a/core/src/main/scala/chisel3/reflect/DataMirror.scala b/core/src/main/scala/chisel3/reflect/DataMirror.scala index b7509b5a665..17a903f5179 100644 --- a/core/src/main/scala/chisel3/reflect/DataMirror.scala +++ b/core/src/main/scala/chisel3/reflect/DataMirror.scala @@ -475,4 +475,10 @@ object DataMirror { (modulePath(left, Some(lca)) ++ Seq(lca), modulePath(right, Some(lca)) ++ Seq(lca)) } } + + /** Check if a given `Data` is visible from the current context + * @param x the `Data` to check + * @return `true` if x is visible, `false` otherwise + */ + def isVisible(target: Data): Boolean = target.isVisible }