@@ -114,25 +114,52 @@ sealed abstract class Aggregate extends Data {
114
114
}
115
115
}
116
116
117
- private [chisel3] override def connectFromBits (
118
- that : Bits
119
- )(
120
- implicit sourceInfo : SourceInfo
121
- ): Unit = {
122
- var i = 0
123
- val bits = if (that.isLit) that else WireDefault (UInt (this .width), that) // handles width padding
124
- for (x <- flatten) {
125
- val fieldWidth = x.getWidth
126
- if (fieldWidth > 0 ) {
127
- x.connectFromBits(bits(i + fieldWidth - 1 , i))
128
- i += fieldWidth
129
- } else {
130
- // There's a zero-width field in this bundle.
131
- // Zero-width fields can't really be assigned to, but the frontend complains if there are uninitialized fields,
132
- // so we assign it to DontCare. We can't use connectFromBits() on DontCare, so use := instead.
133
- x := DontCare
117
+ // Return a literal of the same type from a Seq of literals for each leaf
118
+ private [chisel3] final def _makeLitFromLeaves (elems : Seq [Element ])(implicit sourceInfo : SourceInfo ): Data = {
119
+ // We could use virtual methods instead of matching on concrete subtypes,
120
+ // but the difference for Record vs Vec is so small, it doesn't seem worth it
121
+ val clone : Aggregate = this .cloneTypeFull
122
+ val mapping = clone.flatten.view
123
+ .zip(elems)
124
+ .map {
125
+ case (thisElt, litElt) =>
126
+ val litArg = litElt.topBindingOpt match {
127
+ case Some (ElementLitBinding (value)) => value
128
+ case _ => throwException(s " Internal Error! For field $thisElt, given non-literal $litElt! " )
129
+ }
130
+ thisElt -> litArg
131
+ }
132
+ val binding = clone match {
133
+ case r : Record => BundleLitBinding (mapping.to(Map ))
134
+ case v : Vec [_] => VecLitBinding (mapping.to(VectorMap ))
135
+ }
136
+ clone.bind(binding)
137
+ clone
138
+ }
139
+
140
+ override private [chisel3] def _fromUInt (that : UInt )(implicit sourceInfo : SourceInfo ): Data = {
141
+ val _asUInt = _resizeToWidth(that, this .widthOption)(identity)
142
+ // If that is a literal and all constituent Elements can be represented as literals, return a literal
143
+ val ((_, allLit), rvalues) = {
144
+ this .flatten.toList.mapAccumulate((0 , _asUInt.isLit)) {
145
+ case ((lo, literal), elt) =>
146
+ val hi = lo + elt.getWidth
147
+ // Chisel only supports zero width extraction if hi = -1 and lo = 0, so do it manually
148
+ val _extracted = if (elt.getWidth == 0 ) 0 .U (0 .W ) else _asUInt(hi - 1 , lo)
149
+ // _fromUInt returns Data but we know that it is an Element
150
+ val rhs = elt._fromUInt(_extracted).asInstanceOf [Element ]
151
+ ((hi, literal && rhs.isLit), rhs)
134
152
}
135
153
}
154
+ if (allLit) {
155
+ this ._makeLitFromLeaves(rvalues)
156
+ } else {
157
+ val _wire = Wire (this .cloneTypeFull)
158
+ for ((l, r) <- _wire.flatten.zip(rvalues)) {
159
+ l := r
160
+ }
161
+ _wire
162
+ }
136
163
}
137
164
}
138
165
@@ -215,8 +242,10 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) extend
215
242
216
243
val resolvedDirection = SpecifiedDirection .fromParent(parentDirection, specifiedDirection)
217
244
sample_element.bind(SampleElementBinding (this ), resolvedDirection)
245
+ // Share same object for binding of all children.
246
+ val childBinding = ChildBinding (this )
218
247
for (child <- elementsIterator) { // assume that all children are the same
219
- child.bind(ChildBinding ( this ) , resolvedDirection)
248
+ child.bind(childBinding , resolvedDirection)
220
249
}
221
250
222
251
// Since all children are the same, we can just use the sample_element rather than all children
@@ -512,7 +541,7 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) extend
512
541
if (m < n) Some (index -> lit) else None
513
542
case (KnownWidth (_), _) =>
514
543
None
515
- case (UnknownWidth () , _) =>
544
+ case (UnknownWidth , _) =>
516
545
None
517
546
case _ =>
518
547
Some (index -> lit)
@@ -632,26 +661,6 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) extend
632
661
633
662
object VecInit extends SourceInfoDoc {
634
663
635
- /** Gets the correct connect operation (directed hardware assign or bulk connect) for element in Vec.
636
- */
637
- private def getConnectOpFromDirectionality [T <: Data ](
638
- proto : T
639
- )(
640
- implicit sourceInfo : SourceInfo
641
- ): (T , T ) => Unit = proto.direction match {
642
- case ActualDirection .Input | ActualDirection .Output | ActualDirection .Unspecified =>
643
- // When internal wires are involved, driver / sink must be specified explicitly, otherwise
644
- // the system is unable to infer which is driver / sink
645
- (x, y) => x := y
646
- case ActualDirection .Bidirectional (_) =>
647
- // For bidirectional, must issue a bulk connect so subelements are resolved correctly.
648
- // Bulk connecting two wires may not succeed because Chisel frontend does not infer
649
- // directions.
650
- (x, y) => x <> y
651
- case ActualDirection .Empty =>
652
- (x, y) => x <> y
653
- }
654
-
655
664
/** Creates a new [[Vec ]] composed of elements of the input Seq of [[Data ]]
656
665
* nodes.
657
666
*
@@ -677,10 +686,9 @@ object VecInit extends SourceInfoDoc {
677
686
elts.foreach(requireIsHardware(_, " vec element" ))
678
687
679
688
val vec = Wire (Vec (elts.length, cloneSupertype(elts, " Vec" )))
680
- val op = getConnectOpFromDirectionality(vec.head)
681
689
682
- ( vec.zip(elts)).foreach { x =>
683
- op(x._1, x._2)
690
+ for ((lhs, rhs) <- vec.zip(elts)) {
691
+ lhs :<>= rhs
684
692
}
685
693
vec
686
694
}
@@ -746,12 +754,11 @@ object VecInit extends SourceInfoDoc {
746
754
747
755
val tpe = cloneSupertype(flatElts, " Vec.tabulate" )
748
756
val myVec = Wire (Vec (n, Vec (m, tpe)))
749
- val op = getConnectOpFromDirectionality(myVec.head.head)
750
757
for {
751
758
(xs1D, ys1D) <- myVec.zip(elts)
752
- (x, y ) <- xs1D.zip(ys1D)
759
+ (lhs, rhs ) <- xs1D.zip(ys1D)
753
760
} {
754
- op(x, y)
761
+ lhs :<>= rhs
755
762
}
756
763
myVec
757
764
}
@@ -786,14 +793,13 @@ object VecInit extends SourceInfoDoc {
786
793
787
794
val tpe = cloneSupertype(flatElts, " Vec.tabulate" )
788
795
val myVec = Wire (Vec (n, Vec (m, Vec (p, tpe))))
789
- val op = getConnectOpFromDirectionality(myVec.head.head.head)
790
796
791
797
for {
792
798
(xs2D, ys2D) <- myVec.zip(elts)
793
799
(xs1D, ys1D) <- xs2D.zip(ys2D)
794
- (x, y ) <- xs1D.zip(ys1D)
800
+ (lhs, rhs ) <- xs1D.zip(ys1D)
795
801
} {
796
- op(x, y)
802
+ lhs :<>= rhs
797
803
}
798
804
799
805
myVec
@@ -1066,18 +1072,20 @@ abstract class Record extends Aggregate {
1066
1072
1067
1073
checkForAndReportDuplicates()
1068
1074
1069
- // This check is for making sure that elements always returns the
1070
- // same object, which will not be the case if the user makes it a
1071
- // def inside the Record. Checking elementsIterator against itself
1072
- // is not useful for this check because it's a lazy val which will
1073
- // always return the same thing.
1075
+ // Share same object for binding of all children.
1076
+ val childBinding = ChildBinding (this )
1074
1077
for (((_, child), sameChild) <- this .elements.iterator.zip(this .elementsIterator)) {
1078
+ // This check is for making sure that elements always returns the
1079
+ // same object, which will not be the case if the user makes it a
1080
+ // def inside the Record. Checking elementsIterator against itself
1081
+ // is not useful for this check because it's a lazy val which will
1082
+ // always return the same thing.
1075
1083
if (child != sameChild) {
1076
1084
throwException(
1077
1085
s " ${this .className} does not return the same objects when calling .elements multiple times. Did you make it a def by mistake? "
1078
1086
)
1079
1087
}
1080
- child.bind(ChildBinding ( this ) , resolvedDirection)
1088
+ child.bind(childBinding , resolvedDirection)
1081
1089
1082
1090
// Update the flipped tracker based on the flipped-ness of this specific child element
1083
1091
_containsAFlipped |= child.containsAFlipped
@@ -1222,7 +1230,7 @@ abstract class Record extends Aggregate {
1222
1230
case (field, value) =>
1223
1231
field.width match {
1224
1232
// If width is unknown, then it is set by the literal value.
1225
- case UnknownWidth () => field -> value
1233
+ case UnknownWidth => field -> value
1226
1234
case width @ KnownWidth (widthValue) =>
1227
1235
val valuex = if (widthValue < value.width.get) {
1228
1236
// For legacy reasons, 0.U is 1-bit, don't warn when it comes up as a literal value for 0-bit Bundle lit field.
0 commit comments