summaryrefslogtreecommitdiff
path: root/core/src/main/scala/chisel3/internal
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/scala/chisel3/internal')
-rw-r--r--core/src/main/scala/chisel3/internal/BiConnect.scala6
-rw-r--r--core/src/main/scala/chisel3/internal/Binding.scala9
-rw-r--r--core/src/main/scala/chisel3/internal/Builder.scala66
-rw-r--r--core/src/main/scala/chisel3/internal/MonoConnect.scala6
-rw-r--r--core/src/main/scala/chisel3/internal/firrtl/IR.scala7
5 files changed, 83 insertions, 11 deletions
diff --git a/core/src/main/scala/chisel3/internal/BiConnect.scala b/core/src/main/scala/chisel3/internal/BiConnect.scala
index aa7d7ac3..4a9bb4f5 100644
--- a/core/src/main/scala/chisel3/internal/BiConnect.scala
+++ b/core/src/main/scala/chisel3/internal/BiConnect.scala
@@ -3,9 +3,11 @@
package chisel3.internal
import chisel3._
+import chisel3.experimental.dataview.reify
import chisel3.experimental.{Analog, BaseModule, attach}
import chisel3.internal.Builder.pushCommand
import chisel3.internal.firrtl.{Connect, DefInvalid}
+
import scala.language.experimental.macros
import chisel3.internal.sourceinfo._
@@ -225,8 +227,10 @@ private[chisel3] object BiConnect {
// This function checks if element-level connection operation allowed.
// Then it either issues it or throws the appropriate exception.
- def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, left: Element, right: Element, context_mod: RawModule): Unit = {
+ def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, _left: Element, _right: Element, context_mod: RawModule): Unit = {
import BindingDirection.{Internal, Input, Output} // Using extensively so import these
+ val left = reify(_left)
+ val right = reify(_right)
// If left or right have no location, assume in context module
// This can occur if one of them is a literal, unbound will error previously
val left_mod: BaseModule = left.topBinding.location.getOrElse(context_mod)
diff --git a/core/src/main/scala/chisel3/internal/Binding.scala b/core/src/main/scala/chisel3/internal/Binding.scala
index 300803ce..6f4ab4b0 100644
--- a/core/src/main/scala/chisel3/internal/Binding.scala
+++ b/core/src/main/scala/chisel3/internal/Binding.scala
@@ -120,6 +120,15 @@ case class MemTypeBinding[T <: Data](parent: MemBase[T]) extends Binding {
// It is a source (RHS). It may only be connected/applied to sinks.
case class DontCareBinding() extends UnconstrainedBinding
+// Views currently only support 1:1 Element-level mappings
+private[chisel3] case class ViewBinding(target: Element) extends UnconstrainedBinding
+/** Binding for Aggregate Views
+ * @param childMap Mapping from children of this view to each child's target
+ * @param target Optional Data this Aggregate views if the view is total and the target is a Data
+ */
+private[chisel3] case class AggregateViewBinding(childMap: Map[Data, Element], target: Option[Data]) extends UnconstrainedBinding
+
+
sealed trait LitBinding extends UnconstrainedBinding with ReadOnlyBinding
// Literal binding attached to a element that is not part of a Bundle.
case class ElementLitBinding(litArg: LitArg) extends LitBinding
diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala
index fef12093..ddaedd2e 100644
--- a/core/src/main/scala/chisel3/internal/Builder.scala
+++ b/core/src/main/scala/chisel3/internal/Builder.scala
@@ -10,7 +10,8 @@ import chisel3.internal.firrtl._
import chisel3.internal.naming._
import _root_.firrtl.annotations.{CircuitName, ComponentName, IsMember, ModuleName, Named, ReferenceTarget}
import _root_.firrtl.annotations.AnnotationUtils.validComponentName
-import _root_.firrtl.AnnotationSeq
+import _root_.firrtl.{AnnotationSeq, RenameMap}
+import chisel3.experimental.dataview.{reify, reifySingleData}
import chisel3.internal.Builder.Prefix
import logger.LazyLogging
@@ -215,32 +216,48 @@ private[chisel3] trait HasId extends InstanceId {
private[chisel3] def getRef: Arg = _ref.get
private[chisel3] def getOptionRef: Option[Arg] = _ref
+ private def localName(c: Component): String = _ref match {
+ case Some(arg) => arg fullName c
+ case None => computeName(None, None).get
+ }
+
+ // Helper for reifying views if they map to a single Target
+ private[chisel3] def reifyTarget: Option[Data] = this match {
+ case d: Data => reifySingleData(d) // Only Data can be views
+ case bad => throwException(s"This shouldn't be possible - got $bad with ${_parent}")
+ }
+
+ // Helper for reifying the parent of a view if the view maps to a single Target
+ private[chisel3] def reifyParent: BaseModule = reifyTarget.flatMap(_._parent).getOrElse(ViewParent)
+
// Implementation of public methods.
def instanceName: String = _parent match {
+ case Some(ViewParent) => reifyTarget.map(_.instanceName).getOrElse(this.localName(ViewParent.fakeComponent))
case Some(p) => p._component match {
- case Some(c) => _ref match {
- case Some(arg) => arg fullName c
- case None => computeName(None, None).get
- }
+ case Some(c) => localName(c)
case None => throwException("signalName/pathName should be called after circuit elaboration")
}
case None => throwException("this cannot happen")
}
def pathName: String = _parent match {
case None => instanceName
+ case Some(ViewParent) => s"${reifyParent.pathName}.$instanceName"
case Some(p) => s"${p.pathName}.$instanceName"
}
def parentPathName: String = _parent match {
+ case Some(ViewParent) => reifyParent.pathName
case Some(p) => p.pathName
case None => throwException(s"$instanceName doesn't have a parent")
}
def parentModName: String = _parent match {
+ case Some(ViewParent) => reifyParent.name
case Some(p) => p.name
case None => throwException(s"$instanceName doesn't have a parent")
}
// TODO Should this be public?
protected def circuitName: String = _parent match {
case None => instanceName
+ case Some(ViewParent) => reifyParent.circuitName
case Some(p) => p.circuitName
}
@@ -288,8 +305,10 @@ private[chisel3] trait NamedComponent extends HasId {
final def toAbsoluteTarget: ReferenceTarget = {
val localTarget = toTarget
+ def makeTarget(p: BaseModule) = p.toAbsoluteTarget.ref(localTarget.ref).copy(component = localTarget.component)
_parent match {
- case Some(parent) => parent.toAbsoluteTarget.ref(localTarget.ref).copy(component = localTarget.component)
+ case Some(ViewParent) => makeTarget(reifyParent)
+ case Some(parent) => makeTarget(parent)
case None => localTarget
}
}
@@ -304,6 +323,11 @@ private[chisel3] class ChiselContext() {
// Records the different prefixes which have been scoped at this point in time
var prefixStack: Prefix = Nil
+
+ // Views belong to a separate namespace (for renaming)
+ // The namespace outside of Builder context is useless, but it ensures that views can still be created
+ // and the resulting .toTarget is very clearly useless (_$$View$$_...)
+ val viewNamespace = Namespace.empty
}
private[chisel3] class DynamicContext(val annotationSeq: AnnotationSeq) {
@@ -319,6 +343,9 @@ private[chisel3] class DynamicContext(val annotationSeq: AnnotationSeq) {
*/
val aspectModule: mutable.HashMap[BaseModule, BaseModule] = mutable.HashMap.empty[BaseModule, BaseModule]
+ // Views that do not correspond to a single ReferenceTarget and thus require renaming
+ val unnamedViews: ArrayBuffer[Data] = ArrayBuffer.empty
+
// Set by object Module.apply before calling class Module constructor
// Used to distinguish between no Module() wrapping, multiple wrappings, and rewrapping
var readyForModuleConstr: Boolean = false
@@ -370,6 +397,9 @@ private[chisel3] object Builder extends LazyLogging {
def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq
def namingStack: NamingStack = dynamicContext.namingStack
+ def unnamedViews: ArrayBuffer[Data] = dynamicContext.unnamedViews
+ def viewNamespace: Namespace = chiselContext.get.viewNamespace
+
// Puts a prefix string onto the prefix stack
def pushPrefix(d: String): Unit = {
val context = chiselContext.get()
@@ -403,6 +433,7 @@ private[chisel3] object Builder extends LazyLogging {
case PortBinding(mod) if Builder.currentModule.contains(mod) => data.seedOpt
case PortBinding(mod) => map2(mod.seedOpt, data.seedOpt)(_ + "_" + _)
case (_: LitBinding | _: DontCareBinding) => None
+ case _ => Some("view_") // TODO implement
}
id match {
case d: Data => recData(d)
@@ -646,8 +677,29 @@ private[chisel3] object Builder extends LazyLogging {
}
}
+ // Builds a RenameMap for all Views that do not correspond to a single Data
+ // These Data give a fake ReferenceTarget for .toTarget and .toReferenceTarget that the returned
+ // RenameMap can split into the constituent parts
+ private[chisel3] def makeViewRenameMap: RenameMap = {
+ val renames = RenameMap()
+ for (view <- unnamedViews) {
+ val localTarget = view.toTarget
+ val absTarget = view.toAbsoluteTarget
+ val elts = getRecursiveFields.lazily(view, "")
+ .collect { case (elt: Element, _) => elt }
+ for (elt <- elts) {
+ val targetOfView = reify(elt)
+ renames.record(localTarget, targetOfView.toTarget)
+ renames.record(absTarget, targetOfView.toAbsoluteTarget)
+ }
+ }
+ renames
+ }
+
private [chisel3] def build[T <: RawModule](f: => T, dynamicContext: DynamicContext): (Circuit, T) = {
dynamicContextVar.withValue(Some(dynamicContext)) {
+ ViewParent // Must initialize the singleton in a Builder context or weird things can happen
+ // in tiny designs/testcases that never access anything in chisel3.internal
checkScalaVersion()
logger.warn("Elaborating design...")
val mod = f
@@ -655,7 +707,7 @@ private[chisel3] object Builder extends LazyLogging {
errors.checkpoint(logger)
logger.warn("Done elaborating.")
- (Circuit(components.last.name, components.toSeq, annotations.toSeq), mod)
+ (Circuit(components.last.name, components.toSeq, annotations.toSeq, makeViewRenameMap), mod)
}
}
initializeSingletons()
diff --git a/core/src/main/scala/chisel3/internal/MonoConnect.scala b/core/src/main/scala/chisel3/internal/MonoConnect.scala
index b979ebae..5cbab329 100644
--- a/core/src/main/scala/chisel3/internal/MonoConnect.scala
+++ b/core/src/main/scala/chisel3/internal/MonoConnect.scala
@@ -5,7 +5,9 @@ package chisel3.internal
import chisel3._
import chisel3.experimental.{Analog, BaseModule, EnumType, FixedPoint, Interval, UnsafeEnum}
import chisel3.internal.Builder.pushCommand
+import chisel3.experimental.dataview.reify
import chisel3.internal.firrtl.{Connect, DefInvalid}
+
import scala.language.experimental.macros
import chisel3.internal.sourceinfo.SourceInfo
@@ -188,8 +190,10 @@ private[chisel3] object MonoConnect {
// This function checks if element-level connection operation allowed.
// Then it either issues it or throws the appropriate exception.
- def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, sink: Element, source: Element, context_mod: RawModule): Unit = {
+ def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, _sink: Element, _source: Element, context_mod: RawModule): Unit = {
import BindingDirection.{Internal, Input, Output} // Using extensively so import these
+ val sink = reify(_sink)
+ val source = reify(_source)
// If source has no location, assume in context module
// This can occur if is a literal, unbound will error previously
val sink_mod: BaseModule = sink.topBinding.location.getOrElse(throw UnwritableSinkException)
diff --git a/core/src/main/scala/chisel3/internal/firrtl/IR.scala b/core/src/main/scala/chisel3/internal/firrtl/IR.scala
index 5796522c..f8a3cf7f 100644
--- a/core/src/main/scala/chisel3/internal/firrtl/IR.scala
+++ b/core/src/main/scala/chisel3/internal/firrtl/IR.scala
@@ -8,7 +8,8 @@ import chisel3.internal._
import chisel3.internal.sourceinfo.SourceInfo
import chisel3.experimental._
import _root_.firrtl.{ir => firrtlir}
-import _root_.firrtl.PrimOps
+import _root_.firrtl.{PrimOps, RenameMap}
+import _root_.firrtl.annotations.Annotation
import scala.collection.immutable.NumericRange
import scala.math.BigDecimal.RoundingMode
@@ -789,4 +790,6 @@ abstract class Component extends Arg {
case class DefModule(id: RawModule, name: String, ports: Seq[Port], commands: Seq[Command]) extends Component
case class DefBlackBox(id: BaseBlackBox, name: String, ports: Seq[Port], topDir: SpecifiedDirection, params: Map[String, Param]) extends Component
-case class Circuit(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation] = Seq.empty)
+case class Circuit(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation], renames: RenameMap) {
+ def firrtlAnnotations: Iterable[Annotation] = annotations.flatMap(_.toFirrtl.update(renames))
+}