summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/test/scala/chiselTests/ChiselSpec.scala81
-rw-r--r--src/test/scala/chiselTests/WidthSpec.scala171
2 files changed, 251 insertions, 1 deletions
diff --git a/src/test/scala/chiselTests/ChiselSpec.scala b/src/test/scala/chiselTests/ChiselSpec.scala
index 661cf00e..ff75c1a3 100644
--- a/src/test/scala/chiselTests/ChiselSpec.scala
+++ b/src/test/scala/chiselTests/ChiselSpec.scala
@@ -31,6 +31,33 @@ trait ChiselRunners extends Assertions with BackendCompilationUtilities {
}
def elaborate(t: => RawModule): Unit = Driver.elaborate(() => t)
+ def assertKnownWidth(expected: Int)(gen: => Data): Unit = {
+ assertTesterPasses(new BasicTester {
+ val x = gen
+ assert(x.getWidth === expected)
+ // Sanity check that firrtl doesn't change the width
+ x := 0.U.asTypeOf(chiselTypeOf(x))
+ val (_, done) = chisel3.util.Counter(true.B, 2)
+ when (done) {
+ chisel3.assert(~(x.asUInt) === -1.S(expected.W).asUInt)
+ stop()
+ }
+ })
+ }
+
+ def assertInferredWidth(expected: Int)(gen: => Data): Unit = {
+ assertTesterPasses(new BasicTester {
+ val x = gen
+ assert(!x.isWidthKnown, s"Asserting that width should be inferred yet width is known to Chisel!")
+ x := 0.U.asTypeOf(chiselTypeOf(x))
+ val (_, done) = chisel3.util.Counter(true.B, 2)
+ when (done) {
+ chisel3.assert(~(x.asUInt) === -1.S(expected.W).asUInt)
+ stop()
+ }
+ })
+ }
+
/** Given a generator, return the Firrtl that it generates.
*
* @param t Module generator
@@ -63,7 +90,59 @@ trait ChiselRunners extends Assertions with BackendCompilationUtilities {
}
/** Spec base class for BDD-style testers. */
-class ChiselFlatSpec extends FlatSpec with ChiselRunners with Matchers
+abstract class ChiselFlatSpec extends FlatSpec with ChiselRunners with Matchers
+
+class ChiselTestUtilitiesSpec extends ChiselFlatSpec {
+ import org.scalatest.exceptions.TestFailedException
+ // Who tests the testers?
+ "assertKnownWidth" should "error when the expected width is wrong" in {
+ a [TestFailedException] shouldBe thrownBy {
+ assertKnownWidth(7) {
+ Wire(UInt(8.W))
+ }
+ }
+ }
+
+ it should "error when the width is unknown" in {
+ a [ChiselException] shouldBe thrownBy {
+ assertKnownWidth(7) {
+ Wire(UInt())
+ }
+ }
+ }
+
+ it should "work if the width is correct" in {
+ assertKnownWidth(8) {
+ Wire(UInt(8.W))
+ }
+ }
+
+ "assertInferredWidth" should "error if the width is known" in {
+ a [TestFailedException] shouldBe thrownBy {
+ assertInferredWidth(8) {
+ Wire(UInt(8.W))
+ }
+ }
+ }
+
+ it should "error if the expected width is wrong" in {
+ a [TestFailedException] shouldBe thrownBy {
+ assertInferredWidth(8) {
+ val w = Wire(UInt())
+ w := 2.U(2.W)
+ w
+ }
+ }
+ }
+
+ it should "pass if the width is correct" in {
+ assertInferredWidth(4) {
+ val w = Wire(UInt())
+ w := 2.U(4.W)
+ w
+ }
+ }
+}
/** Spec base class for property-based testers. */
class ChiselPropSpec extends PropSpec with ChiselRunners with PropertyChecks with Matchers {
diff --git a/src/test/scala/chiselTests/WidthSpec.scala b/src/test/scala/chiselTests/WidthSpec.scala
index 9a5b1860..0011c532 100644
--- a/src/test/scala/chiselTests/WidthSpec.scala
+++ b/src/test/scala/chiselTests/WidthSpec.scala
@@ -4,6 +4,19 @@ package chiselTests
import chisel3._
+class SimpleBundle extends Bundle {
+ val x = UInt(4.W)
+ val y = UInt()
+}
+object SimpleBundle {
+ def intoWire(): SimpleBundle = {
+ val w = Wire(new SimpleBundle)
+ w.x := 0.U(4.W)
+ w.y := 0.U(4.W)
+ w
+ }
+}
+
class WidthSpec extends ChiselFlatSpec {
"Literals without specified widths" should "get the minimum legal width" in {
"hdeadbeef".U.getWidth should be (32)
@@ -15,3 +28,161 @@ class WidthSpec extends ChiselFlatSpec {
1.S.getWidth should be (2)
}
}
+
+abstract class WireRegWidthSpecImpl extends ChiselFlatSpec {
+ def name: String
+ def builder[T <: Data](x: T): T
+
+ behavior of name
+
+ it should "set the width if the template type has a set width" in {
+ assertKnownWidth(4) {
+ builder(UInt(4.W))
+ }
+ assertKnownWidth(4) {
+ val w = builder(new SimpleBundle)
+ w := SimpleBundle.intoWire()
+ w.x
+ }
+ assertKnownWidth(4) {
+ val x = builder(Vec(1, UInt(4.W)))
+ x(0)
+ }
+ }
+
+ it should "infer the width if the template type has no width" in {
+ assertInferredWidth(4) {
+ val w = builder(UInt())
+ w := 0.U(4.W)
+ w
+ }
+ assertInferredWidth(4) {
+ val w = builder(new SimpleBundle)
+ w := SimpleBundle.intoWire()
+ w.y
+ }
+ assertInferredWidth(4) {
+ val w = builder(Vec(1, UInt()))
+ w(0) := 0.U(4.W)
+ w(0)
+ }
+ }
+}
+
+class WireWidthSpec extends WireRegWidthSpecImpl {
+ def name = "Wire"
+ def builder[T <: Data](x: T): T = Wire(x)
+}
+class RegWidthSpec extends WireRegWidthSpecImpl {
+ def name = "Reg"
+ def builder[T <: Data](x: T): T = Reg(x)
+}
+
+abstract class WireInitRegInitSpecImpl extends ChiselFlatSpec {
+ def name: String
+ def builder1[T <: Data](x: T): T
+ def builder2[T <: Data](x: T, y: T): T
+
+ behavior of s"$name (Single Argument)"
+
+ it should "set width if passed a literal with forced width" in {
+ assertKnownWidth(4) {
+ builder1(3.U(4.W))
+ }
+ }
+
+ it should "NOT set width if passed a literal without a forced width" in {
+ assertInferredWidth(4) {
+ val w = builder1(3.U)
+ w := 3.U(4.W)
+ w
+ }
+ }
+
+ it should "NOT set width if passed a non-literal" in {
+ assertInferredWidth(4) {
+ val w = WireInit(3.U(4.W))
+ builder1(w)
+ }
+ }
+
+ it should "copy the widths of aggregates" in {
+ assertInferredWidth(4) {
+ val w = builder1(SimpleBundle.intoWire())
+ w.y
+ }
+ assertKnownWidth(4) {
+ val w = builder1(SimpleBundle.intoWire())
+ w.x
+ }
+ assertInferredWidth(4) {
+ val x = Wire(Vec(1, UInt()))
+ x(0) := 0.U(4.W)
+ val w = builder1(x)
+ w(0)
+ }
+ assertKnownWidth(4) {
+ val x = Wire(Vec(1, UInt(4.W)))
+ x(0) := 0.U(4.W)
+ val w = builder1(x)
+ w(0)
+ }
+ }
+
+ behavior of s"$name (Double Argument)"
+
+ it should "set the width if the template type has a set width" in {
+ assertKnownWidth(4) {
+ WireInit(UInt(4.W), 0.U)
+ }
+ assertKnownWidth(4) {
+ WireInit(UInt(4.W), 0.U(2.W))
+ }
+ assertKnownWidth(4) {
+ val w = WireInit(new SimpleBundle, SimpleBundle.intoWire())
+ w.x
+ }
+ assertKnownWidth(4) {
+ val x = Wire(Vec(1, UInt()))
+ x(0) := 0.U(4.W)
+ val w = WireInit(Vec(1, UInt(4.W)), x)
+ w(0)
+ }
+ }
+
+ it should "infer the width if the template type has no width" in {
+ val templates = Seq(
+ () => 0.U, () => 0.U(2.W), () => WireInit(0.U), () => WireInit(0.U(2.W))
+ )
+ for (gen <- templates) {
+ assertInferredWidth(4) {
+ val w = WireInit(UInt(), gen())
+ w := 0.U(4.W)
+ w
+ }
+ }
+ assertInferredWidth(4) {
+ val w = WireInit(new SimpleBundle, SimpleBundle.intoWire())
+ w.y
+ }
+ assertInferredWidth(4) {
+ val x = Wire(Vec(1, UInt()))
+ x(0) := 0.U(4.W)
+ val w = WireInit(Vec(1, UInt()), x)
+ w(0)
+ }
+ }
+}
+
+class WireInitWidthSpec extends WireInitRegInitSpecImpl {
+ def name = "WireInit"
+ def builder1[T <: Data](x: T): T = WireInit(x)
+ def builder2[T <: Data](x: T, y: T): T = WireInit(x, y)
+}
+
+class RegInitWidthSpec extends WireInitRegInitSpecImpl {
+ def name = "RegInit"
+ def builder1[T <: Data](x: T): T = RegInit(x)
+ def builder2[T <: Data](x: T, y: T): T = RegInit(x, y)
+}
+