diff options
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/core/Data.scala')
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Data.scala | 35 |
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") |
