diff options
| author | Jack Koenig | 2018-12-19 11:04:00 -0800 |
|---|---|---|
| committer | GitHub | 2018-12-19 11:04:00 -0800 |
| commit | 416b9d9d8f4363b4e0071526d99882bc01b8cda8 (patch) | |
| tree | f660a222bb97400fd562f7dca0773e910c77a962 /src/test/scala/chiselTests/WidthSpec.scala | |
| parent | 9ce6d7de1510a9d73c718acc475f1000a9979e56 (diff) | |
Fix width inferencing issue (#952)
* Fix width propagation of non-literals in WireInit and RegInit
* Change .getWidth to throw an exception instead of calling .get
* Add utilities for checking inferred vs. known widths
* Add tests for Wire, WireInit, Reg, and RegInit width inference
* Add ScalaDoc for Reg, Wire, RegInit, and WireInit
Diffstat (limited to 'src/test/scala/chiselTests/WidthSpec.scala')
| -rw-r--r-- | src/test/scala/chiselTests/WidthSpec.scala | 171 |
1 files changed, 171 insertions, 0 deletions
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) +} + |
