summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala17
-rw-r--r--coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala3
-rw-r--r--src/test/scala/chiselTests/Vec.scala106
3 files changed, 116 insertions, 10 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
index efb30326..5f64b079 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
@@ -43,12 +43,19 @@ object Vec {
*
* @note elements are NOT assigned by default and have no value
*/
- def apply[T <: Data](n: Int, gen: T)(implicit compileOptions: CompileOptions): Vec[T] =
- new Vec(gen.chiselCloneType, n)
+ def apply[T <: Data](n: Int, gen: T): Vec[T] = macro VecTransform.apply_ngen;
+
+ def do_apply[T <: Data](n: Int, gen: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = {
+ if ( gen.isLit ) {
+ Vec(Seq.fill(n)(gen))
+ } else {
+ new Vec(gen.chiselCloneType, n)
+ }
+ }
@deprecated("Vec argument order should be size, t; this will be removed by the official release", "chisel3")
- def apply[T <: Data](gen: T, n: Int)(implicit compileOptions: CompileOptions): Vec[T] =
- apply(n, gen)
+ def apply[T <: Data](gen: T, n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] =
+ do_apply(n, gen)
/** Creates a new [[Vec]] composed of elements of the input Seq of [[Data]]
* nodes.
@@ -233,7 +240,7 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int)
}
override def cloneType: this.type = {
- new Vec(gen, length).asInstanceOf[this.type]
+ new Vec(gen.cloneType, length).asInstanceOf[this.type]
}
private[chisel3] def toType: String = s"${sample_element.toType}[$length]"
diff --git a/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala b/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala
index 7930138b..ab4cf8fb 100644
--- a/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala
+++ b/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala
@@ -75,6 +75,9 @@ class MuxTransform(val c: Context) extends SourceInfoTransformMacro {
class VecTransform(val c: Context) extends SourceInfoTransformMacro {
import c.universe._
+ def apply_ngen(n: c.Tree, gen: c.Tree): c.Tree = {
+ q"$thisObj.do_apply($n,$gen)($implicitSourceInfo, $implicitCompileOptions)"
+ }
def apply_elts(elts: c.Tree): c.Tree = {
q"$thisObj.do_apply($elts)($implicitSourceInfo, $implicitCompileOptions)"
}
diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala
index 4822d892..132bfcdc 100644
--- a/src/test/scala/chiselTests/Vec.scala
+++ b/src/test/scala/chiselTests/Vec.scala
@@ -2,16 +2,81 @@
package chiselTests
-import org.scalatest._
-import org.scalatest.prop._
-
import chisel3._
+import chisel3.core.Binding.BindingException
import chisel3.testers.BasicTester
import chisel3.util._
-//import chisel3.core.ExplicitCompileOptions.Strict
+import org.scalacheck.Shrink
+
+class LitTesterMod(vecSize: Int) extends Module {
+ val io = IO(new Bundle {
+ val out = Output(Vec(vecSize, UInt()))
+ })
+ io.out := Vec(vecSize, 0.U)
+}
+
+class RegTesterMod(vecSize: Int) extends Module {
+ val io = IO(new Bundle {
+ val in = Input(Vec(vecSize, UInt()))
+ val out = Output(Vec(vecSize, UInt()))
+ })
+ val vecReg = Reg(init = Vec(vecSize, 0.U), next = io.in)
+ io.out := vecReg
+}
+
+class IOTesterMod(vecSize: Int) extends Module {
+ val io = IO(new Bundle {
+ val in = Input(Vec(vecSize, UInt()))
+ val out = Output(Vec(vecSize, UInt()))
+ })
+ io.out := io.in
+}
+
+class LitTester(w: Int, values: List[Int]) extends BasicTester {
+ val dut = Module(new LitTesterMod(values.length))
+ for (a <- dut.io.out)
+ assert(a === 0.U)
+ stop()
+}
+
+class RegTester(w: Int, values: List[Int]) extends BasicTester {
+ val v = Vec(values.map(_.U(w.W)))
+ val dut = Module(new RegTesterMod(values.length))
+ val doneReg = RegInit(false.B)
+ dut.io.in := v
+ when (doneReg) {
+ for ((a,b) <- dut.io.out.zip(values))
+ assert(a === b.U)
+ stop()
+ } .otherwise {
+ doneReg := true.B
+ for (a <- dut.io.out)
+ assert(a === 0.U)
+ }
+}
+
+class IOTester(w: Int, values: List[Int]) extends BasicTester {
+ val v = Vec(values.map(_.U(w.W))) // Does this need a Wire? No. It's a Vec of Lits and hence synthesizeable.
+ val dut = Module(new IOTesterMod(values.length))
+ dut.io.in := v
+ for ((a,b) <- dut.io.out.zip(values)) {
+ assert(a === b.U)
+ }
+ stop()
+}
+
+class IOTesterModFill(vecSize: Int) extends Module {
+ // This should generate a BindingException when we attempt to wire up the Vec.fill elements
+ // since they're pure types and hence unsynthesizeable.
+ val io = IO(new Bundle {
+ val in = Input(Vec.fill(vecSize) {UInt()})
+ val out = Output(Vec.fill(vecSize) {UInt()})
+ })
+ io.out := io.in
+}
class ValueTester(w: Int, values: List[Int]) extends BasicTester {
- val v = Vec(values.map(_.asUInt(w.W))) // TODO: does this need a Wire? Why no error?
+ val v = Vec(values.map(_.asUInt(w.W)))
for ((a,b) <- v.zip(values)) {
assert(a === b.asUInt)
}
@@ -45,12 +110,43 @@ class ShiftRegisterTester(n: Int) extends BasicTester {
}
class VecSpec extends ChiselPropSpec {
+ // Disable shrinking on error.
+ implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty)
+ implicit val noShrinkInt = Shrink[Int](_ => Stream.empty)
+
property("Vecs should be assignable") {
forAll(safeUIntN(8)) { case(w: Int, v: List[Int]) =>
assertTesterPasses{ new ValueTester(w, v) }
}
}
+ property("Vecs should be passed through vec IO") {
+ forAll(safeUIntN(8)) { case(w: Int, v: List[Int]) =>
+ assertTesterPasses{ new IOTester(w, v) }
+ }
+ }
+
+ property("Vec.fill with a pure type should generate an exception") {
+ // We don't really need a sequence of random widths here, since any should throw an exception.
+ forAll(safeUIntWidth) { case(w: Int) =>
+ an[BindingException] should be thrownBy {
+ elaborate(new IOTesterModFill(w))
+ }
+ }
+ }
+
+ property("A Reg of a Vec should operate correctly") {
+ forAll(safeUIntN(8)) { case(w: Int, v: List[Int]) =>
+ assertTesterPasses{ new RegTester(w, v) }
+ }
+ }
+
+ property("A Vec of lit should operate correctly") {
+ forAll(safeUIntN(8)) { case(w: Int, v: List[Int]) =>
+ assertTesterPasses{ new LitTester(w, v) }
+ }
+ }
+
property("Vecs should tabulate correctly") {
forAll(smallPosInts) { (n: Int) => assertTesterPasses{ new TabulateTester(n) } }
}