Skip to content

Commit

Permalink
Use :<>= in VecInit methods instead of := or <> (backport #4248) (#4250)
Browse files Browse the repository at this point in the history
* Use :<>= in VecInit methods instead of := or <> (#4248)

Previously, VecInit would try to "intelligently" select := or <>
depending on if the type is bidirectional. :<>= has the desirable
behavior here for both passive and bidirectional types. It also has the
advantage over <> of handling internal wires.

(cherry picked from commit 255d3d4)

* Fix test for 6.x

---------

Co-authored-by: Jack Koenig <koenig@sifive.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
mergify[bot] and jackkoenig authored Jul 9, 2024
1 parent d4c0050 commit 2bc4859
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 29 deletions.
35 changes: 6 additions & 29 deletions core/src/main/scala/chisel3/Aggregate.scala
Original file line number Diff line number Diff line change
Expand Up @@ -633,26 +633,6 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) extend

object VecInit extends SourceInfoDoc {

/** Gets the correct connect operation (directed hardware assign or bulk connect) for element in Vec.
*/
private def getConnectOpFromDirectionality[T <: Data](
proto: T
)(
implicit sourceInfo: SourceInfo
): (T, T) => Unit = proto.direction match {
case ActualDirection.Input | ActualDirection.Output | ActualDirection.Unspecified =>
// When internal wires are involved, driver / sink must be specified explicitly, otherwise
// the system is unable to infer which is driver / sink
(x, y) => x := y
case ActualDirection.Bidirectional(_) =>
// For bidirectional, must issue a bulk connect so subelements are resolved correctly.
// Bulk connecting two wires may not succeed because Chisel frontend does not infer
// directions.
(x, y) => x <> y
case ActualDirection.Empty =>
(x, y) => x <> y
}

/** Creates a new [[Vec]] composed of elements of the input Seq of [[Data]]
* nodes.
*
Expand All @@ -678,10 +658,9 @@ object VecInit extends SourceInfoDoc {
elts.foreach(requireIsHardware(_, "vec element"))

val vec = Wire(Vec(elts.length, cloneSupertype(elts, "Vec")))
val op = getConnectOpFromDirectionality(vec.head)

(vec.zip(elts)).foreach { x =>
op(x._1, x._2)
for ((lhs, rhs) <- vec.zip(elts)) {
lhs :<>= rhs
}
vec
}
Expand Down Expand Up @@ -747,12 +726,11 @@ object VecInit extends SourceInfoDoc {

val tpe = cloneSupertype(flatElts, "Vec.tabulate")
val myVec = Wire(Vec(n, Vec(m, tpe)))
val op = getConnectOpFromDirectionality(myVec.head.head)
for {
(xs1D, ys1D) <- myVec.zip(elts)
(x, y) <- xs1D.zip(ys1D)
(lhs, rhs) <- xs1D.zip(ys1D)
} {
op(x, y)
lhs :<>= rhs
}
myVec
}
Expand Down Expand Up @@ -787,14 +765,13 @@ object VecInit extends SourceInfoDoc {

val tpe = cloneSupertype(flatElts, "Vec.tabulate")
val myVec = Wire(Vec(n, Vec(m, Vec(p, tpe))))
val op = getConnectOpFromDirectionality(myVec.head.head.head)

for {
(xs2D, ys2D) <- myVec.zip(elts)
(xs1D, ys1D) <- xs2D.zip(ys2D)
(x, y) <- xs1D.zip(ys1D)
(lhs, rhs) <- xs1D.zip(ys1D)
} {
op(x, y)
lhs :<>= rhs
}

myVec
Expand Down
21 changes: 21 additions & 0 deletions src/test/scala/chiselTests/Vec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,27 @@ class VecSpec extends ChiselPropSpec with Utils {
}
}

property("VecInit should work for Bundle that mixes Output and unspecified UInts") {
class MyBundle extends Bundle {
val a = Output(UInt(8.W))
val b = UInt(8.W)
}
val chirrtl = emitCHIRRTL(new RawModule {
val w = VecInit(Seq.fill(2)(0.U.asTypeOf(new MyBundle)))
})
chirrtl should include("wire _w_WIRE : { a : UInt<8>, b : UInt<8>}")
chirrtl should include("connect _w_WIRE.b, UInt<8>(0h0)")
chirrtl should include("connect _w_WIRE.a, UInt<8>(0h0)")
chirrtl should include("wire _w_WIRE_1 : { a : UInt<8>, b : UInt<8>}")
chirrtl should include("connect _w_WIRE_1.b, UInt<8>(0h0)")
chirrtl should include("connect _w_WIRE_1.a, UInt<8>(0h0)")
chirrtl should include("wire w : { a : UInt<8>, b : UInt<8>}[2]")
chirrtl should include("connect w[0].b, _w_WIRE.b")
chirrtl should include("connect w[0].a, _w_WIRE.a")
chirrtl should include("connect w[1].b, _w_WIRE_1.b")
chirrtl should include("connect w[1].a, _w_WIRE_1.a")
}

property("Infering widths on huge Vecs should not cause a stack overflow") {
ChiselStage.emitSystemVerilog(new HugeVecTester(10000))
}
Expand Down

0 comments on commit 2bc4859

Please sign in to comment.