summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/src/main/scala/chisel3/Module.scala34
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala7
2 files changed, 32 insertions, 9 deletions
diff --git a/core/src/main/scala/chisel3/Module.scala b/core/src/main/scala/chisel3/Module.scala
index ed323504..84139630 100644
--- a/core/src/main/scala/chisel3/Module.scala
+++ b/core/src/main/scala/chisel3/Module.scala
@@ -248,8 +248,14 @@ package internal {
}
// Maps proto ports to module clone's ports
private[chisel3] lazy val ioMap: Map[Data, Data] = {
- val name2Port = getPorts.elements
- getProto.getChiselPorts.map { case (name, data) => data -> name2Port(name) }.toMap
+ getProto match {
+ // BlackBox needs special handling for its pseduo-io Bundle
+ case protoBB: BlackBox =>
+ Map(protoBB._io.get -> getPorts.elements("io"))
+ case _ =>
+ val name2Port = getPorts.elements
+ getProto.getChiselPorts.map { case (name, data) => data -> name2Port(name) }.toMap
+ }
}
// This module doesn't actually exist in the FIRRTL so no initialization to do
private[chisel3] def initializeInParent(parentCompileOptions: CompileOptions): Unit = ()
@@ -267,7 +273,17 @@ package internal {
case bad => throwException(s"Internal Error! Cloned-module Record $record has unexpected ref $bad")
}
// Set both the record and the module to have the same instance name
- record.setRef(ModuleCloneIO(getProto, instName), force = true) // force because we did .forceName first
+ val ref = ModuleCloneIO(getProto, instName)
+ record.setRef(ref, force = true) // force because we did .forceName first
+ getProto match {
+ // BlackBox needs special handling for its pseduo-io Bundle
+ case _: BlackBox =>
+ // Override the io Bundle's ref so that it thinks it is the top for purposes of
+ // generating FIRRTL
+ record.elements("io").setRef(ref, force = true)
+ case _ => // Do nothing
+ }
+
this.setRef(Ref(instName))
}
}
@@ -329,8 +345,8 @@ package internal {
* @note These are not true Data (the Record doesn't correspond to anything in the emitted
* FIRRTL yet its elements *do*) so have some very specialized behavior.
*/
- private[chisel3] class ClonePorts(elts: Data*)(implicit compileOptions: CompileOptions) extends Record {
- val elements = ListMap(elts.map(d => d.instanceName -> d.cloneTypeFull): _*)
+ private[chisel3] class ClonePorts(elts: (String, Data)*)(implicit compileOptions: CompileOptions) extends Record {
+ val elements = ListMap(elts.map { case (name, d) => name -> d.cloneTypeFull }: _*)
def apply(field: String) = elements(field)
override def cloneType = (new ClonePorts(elts: _*)).asInstanceOf[this.type]
}
@@ -351,12 +367,18 @@ package internal {
// Fake Module to serve as the _parent of the cloned ports
// We don't create this inside the ModuleClone because we need the ref to be set by the
// currentModule (and not clonePorts)
- val clonePorts = new ClonePorts(proto.getModulePorts: _*)
+ val clonePorts = proto match {
+ // BlackBox needs special handling for its pseduo-io Bundle
+ case b: BlackBox =>
+ new ClonePorts(proto.getChiselPorts :+ ("io" -> b._io.get): _*)
+ case _ => new ClonePorts(proto.getChiselPorts: _*)
+ }
clonePorts.bind(PortBinding(cloneParent))
clonePorts.setAllParents(Some(cloneParent))
cloneParent._portsRecord = clonePorts
// Normally handled during Module construction but ClonePorts really lives in its parent's parent
if (!compileOptions.explicitInvalidate) {
+ // FIXME This almost certainly doesn't work since clonePorts is not a real thing...
pushCommand(DefInvalid(sourceInfo, clonePorts.ref))
}
if (proto.isInstanceOf[Module]) {
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala
index bc94f95d..60290f83 100644
--- a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala
@@ -10,7 +10,7 @@ import scala.annotation.implicitNotFound
import scala.collection.mutable.HashMap
import chisel3._
import chisel3.experimental.dataview.{isView, reify, reifySingleData}
-import chisel3.internal.firrtl.{Arg, ILit, Index, Slot, ULit}
+import chisel3.internal.firrtl.{Arg, ILit, Index, ModuleIO, Slot, ULit}
import chisel3.internal.{throwException, AggregateViewBinding, Builder, ChildBinding, ViewBinding, ViewParent}
/** Represents lookup typeclass to determine how a value accessed from an original IsInstantiable
@@ -123,8 +123,8 @@ object Lookupable {
def unrollCoordinates(res: List[Arg], d: Data): (List[Arg], Data) = d.binding.get match {
case ChildBinding(parent) =>
d.getRef match {
- case arg @ (_: Slot | _: Index) => unrollCoordinates(arg :: res, parent)
- case other => err(s"Unroll coordinates failed for '$arg'! Unexpected arg '$other'")
+ case arg @ (_: Slot | _: Index | _: ModuleIO) => unrollCoordinates(arg :: res, parent)
+ case other => err(s"unrollCoordinates failed for '$arg'! Unexpected arg '$other'")
}
case _ => (res, d)
}
@@ -135,6 +135,7 @@ object Lookupable {
val next = (coor.head, d) match {
case (Slot(_, name), rec: Record) => rec.elements(name)
case (Index(_, ILit(n)), vec: Vec[_]) => vec.apply(n.toInt)
+ case (ModuleIO(_, name), rec: Record) => rec.elements(name)
case (arg, _) => err(s"Unexpected Arg '$arg' applied to '$d'! Root was '$start'.")
}
applyCoordinates(coor.tail, next)