summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/core/Data.scala
diff options
context:
space:
mode:
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/core/Data.scala')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala35
1 files changed, 35 insertions, 0 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
index cf6dabdd..bffd84df 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
@@ -87,10 +87,23 @@ object DataMirror {
target.direction
}
+ // Returns the top-level module ports
// TODO: maybe move to something like Driver or DriverUtils, since this is mainly for interacting
// with compiled artifacts (vs. elaboration-time reflection)?
def modulePorts(target: BaseModule): Seq[(String, Data)] = target.getChiselPorts
+ // Returns all module ports with underscore-qualified names
+ def fullModulePorts(target: BaseModule): Seq[(String, Data)] = {
+ def getPortNames(name: String, data: Data): Seq[(String, Data)] = Seq(name -> data) ++ (data match {
+ case _: Element => Seq()
+ case r: Record => r.elements.toSeq flatMap { case (eltName, elt) => getPortNames(s"${name}_${eltName}", elt) }
+ case v: Vec[_] => v.zipWithIndex flatMap { case (elt, index) => getPortNames(s"${name}_${index}", elt) }
+ })
+ modulePorts(target).flatMap { case (name, data) =>
+ getPortNames(name, data).toList
+ }
+ }
+
// Internal reflection-style APIs, subject to change and removal whenever.
object internal {
def isSynthesizable(target: Data) = target.topBindingOpt.isDefined
@@ -292,6 +305,26 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc {
_direction = Some(actualDirection)
}
+ // User-friendly representation of the binding as a helper function for toString.
+ // Provides a unhelpful fallback for literals, which should have custom rendering per
+ // Data-subtype.
+ protected def bindingToString: String = topBindingOpt match {
+ case None => ""
+ case Some(OpBinding(enclosure)) => s"(OpResult in ${enclosure.desiredName})"
+ case Some(MemoryPortBinding(enclosure)) => s"(MemPort in ${enclosure.desiredName})"
+ case Some(PortBinding(enclosure)) if !enclosure.isClosed => s"(IO in unelaborated ${enclosure.desiredName})"
+ case Some(PortBinding(enclosure)) if enclosure.isClosed =>
+ DataMirror.fullModulePorts(enclosure).find(_._2 == this) match {
+ case Some((name, _)) => s"(IO $name in ${enclosure.desiredName})"
+ case None => s"(IO (unknown) in ${enclosure.desiredName})"
+ }
+ case Some(RegBinding(enclosure)) => s"(Reg in ${enclosure.desiredName})"
+ case Some(WireBinding(enclosure)) => s"(Wire in ${enclosure.desiredName})"
+ case Some(DontCareBinding()) => s"(DontCare)"
+ case Some(ElementLitBinding(litArg)) => s"(unhandled literal)"
+ case Some(BundleLitBinding(litMap)) => s"(unhandled bundle literal)"
+ }
+
// Return ALL elements at root of this type.
// Contasts with flatten, which returns just Bits
// TODO: refactor away this, this is outside the scope of Data
@@ -646,6 +679,8 @@ object DontCare extends Element {
bind(DontCareBinding(), SpecifiedDirection.Output)
override def cloneType = DontCare
+ override def toString: String = "DontCare()"
+
override def litOption = None
def toPrintable: Printable = PString("DONTCARE")