diff options
| author | Jim Lawson | 2017-02-03 13:56:32 -0800 |
|---|---|---|
| committer | GitHub | 2017-02-03 13:56:32 -0800 |
| commit | 8974f749eea1a452ba732dd833376ef4283173a8 (patch) | |
| tree | 038e0e673b5b212622c46d2afb359faf3b2cdb89 | |
| parent | 41ed27574cf871f48d4c4ddfed5285b9853b41d3 (diff) | |
Added vec IO tests for #104 (#480)
* Added vec IO tests for #104
* Added Vec test case for Reg of vecs
* Change Vec creation to check if gen is lit (and hence needs to be declared)
Fixes #104
* Fix tests (add IO())), Vec.fill()
* Fix deprecated usage.
* Add Binding IO() NPE fix so tests pass.
* Fix style - use space consistently.
* Fix style - use space consistently.
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) } } } |
