diff options
Diffstat (limited to 'src/test/scala/chiselTests/IntervalSpec.scala')
| -rw-r--r-- | src/test/scala/chiselTests/IntervalSpec.scala | 962 |
1 files changed, 0 insertions, 962 deletions
diff --git a/src/test/scala/chiselTests/IntervalSpec.scala b/src/test/scala/chiselTests/IntervalSpec.scala deleted file mode 100644 index a2d36579..00000000 --- a/src/test/scala/chiselTests/IntervalSpec.scala +++ /dev/null @@ -1,962 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import scala.language.reflectiveCalls -import _root_.firrtl.ir.{Closed, Open} -import chisel3._ -import chisel3.internal.firrtl.{IntervalRange, KnownBinaryPoint} -import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.testers.BasicTester -import cookbook.CookbookTester -import firrtl.options.TargetDirAnnotation -import firrtl.passes.CheckTypes.InvalidConnect -import firrtl.passes.CheckWidths.{DisjointSqueeze, InvalidRange} -import firrtl.passes.{PassExceptions, WrapWithRemainder} -import firrtl.stage.{CompilerAnnotation, FirrtlCircuitAnnotation} -import firrtl.{ - HighFirrtlCompiler, - LowFirrtlCompiler, - MiddleFirrtlCompiler, - MinimumVerilogCompiler, - NoneCompiler, - SystemVerilogCompiler, - VerilogCompiler -} -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -//noinspection TypeAnnotation - -object IntervalTestHelper { - - /** Compiles a Chisel Module to Verilog - * NOTE: This uses the "test_run_dir" as the default directory for generated code. - * @param compilerName the generator for the module - * @param gen the generator for the module - * @return the Verilog code as a string. - */ - def makeFirrtl[T <: RawModule](compilerName: String)(gen: () => T): String = { - (new ChiselStage) - .execute( - Array("--compiler", compilerName, "--target-dir", "test_run_dir/IntervalSpec"), - Seq(ChiselGeneratorAnnotation(gen)) - ) - .collectFirst { case FirrtlCircuitAnnotation(source) => source } match { - case Some(circuit) => circuit.serialize - case _ => - throw new Exception( - s"makeFirrtl($compilerName) failed to generate firrtl circuit" - ) - } - - } -} - -import chiselTests.IntervalTestHelper.makeFirrtl -import chisel3.experimental._ -import chisel3.experimental.Interval - -class IntervalTest1 extends Module { - val io = IO(new Bundle { - val in1 = Input(Interval(range"[0,4]")) - val in2 = Input(Interval(range"[0,4].3")) - val out = Output(Interval(range"[0,8].3")) - }) - - io.out := io.in1 + io.in2 -} - -class IntervalTester extends CookbookTester(10) { - - val dut = Module(new IntervalTest1) - - dut.io.in1 := BigInt(4).I - dut.io.in2 := 4.I - assert(dut.io.out === 8.I) - - val i = Interval(range"[0,10)") - stop() -} - -class IntervalTest2 extends Module { - val io = IO(new Bundle { - val p = Input(Bool()) - val in1 = Input(Interval(range"[0,4]")) - val in2 = Input(Interval(range"[0,6]")) - val out = Output(Interval()) - }) - - io.out := Mux(io.p, io.in1, io.in2) -} - -class IntervalTester2 extends CookbookTester(10) { - - val dut = Module(new IntervalTest2) - - dut.io.p := 1.U - dut.io.in1 := 4.I - dut.io.in2 := 5.I - assert(dut.io.out === 4.I) - - stop() -} - -class IntervalAddTester extends BasicTester { - - val in1 = Wire(Interval(range"[0,4]")) - val in2 = Wire(Interval(range"[0,4]")) - - in1 := 2.I - in2 := 2.I - - 5.U - - val result = in1 +& in2 - - assert(result === 4.I) - - stop() - -} - -class IntervalSetBinaryPointTester extends BasicTester { - implicit val sourceinfo: SourceInfo = UnlocatableSourceInfo - val in1 = Wire(Interval(range"[0,4].4")) - val in2 = in1.setPrecision(2) - - assert(in2.binaryPoint == KnownBinaryPoint(2)) - - in1 := 2.I - - val shiftedLeft = in1.increasePrecision(2) - - assert( - shiftedLeft.binaryPoint == KnownBinaryPoint(6), - s"Error: increasePrecision result ${shiftedLeft.range} expected bt = 2" - ) - - val shiftedRight = in1.decreasePrecision(2) - - assert( - shiftedRight.binaryPoint == KnownBinaryPoint(2), - s"Error: increasePrecision result ${shiftedRight.range} expected bt = 2" - ) - - stop() -} - -class MoreIntervalShiftTester extends BasicTester { - implicit val sourceinfo: SourceInfo = UnlocatableSourceInfo - - val in1 = Wire(Interval(range"[0,4].4")) - val in2 = in1.setPrecision(2) - - assert(in2.binaryPoint == KnownBinaryPoint(2)) - - val toShiftLeft = Wire(Interval(range"[0,4].4")) - val shiftedLeft = in1.increasePrecision(2) - - assert( - shiftedLeft.binaryPoint == KnownBinaryPoint(2), - s"Error: decreasePrecision result ${shiftedLeft.range} expected bt = 2" - ) - - val toShiftRight = Wire(Interval(range"[0,4].4")) - val shiftedRight = in1.decreasePrecision(2) - - assert( - shiftedRight.binaryPoint == KnownBinaryPoint(6), - s"Error: decreasePrecision result ${shiftedRight.range} expected bt = 2" - ) - - stop() -} - -/** - * This is a reality check not a test. Makes it easier to figure out - * what is going on in other places - * @param range a range for inputs - * @param targetRange a range for outputs - * @param startNum start here - * @param endNum end here - * @param incNum increment by this - */ -class ClipSqueezeWrapDemo( - range: IntervalRange, - targetRange: IntervalRange, - startNum: Double, - endNum: Double, - incNum: Double) - extends BasicTester { - - val binaryPointAsInt = range.binaryPoint.asInstanceOf[KnownBinaryPoint].value -// val startValue = Interval.fromDouble(startNum, binaryPoint = binaryPointAsInt) -// val increment = Interval.fromDouble(incNum, binaryPoint = binaryPointAsInt) -// val endValue = Interval.fromDouble(endNum, binaryPoint = binaryPointAsInt) - val startValue = startNum.I(range.binaryPoint) - val increment = incNum.I(range.binaryPoint) - val endValue = endNum.I(range.binaryPoint) - - val counter = RegInit(Interval(range), startValue) - - counter := (counter + increment).squeeze(counter) - when(counter > endValue) { - stop() - } - - val clipped = counter.clip(0.U.asInterval(targetRange)) - val squeezed = counter.squeeze(0.U.asInterval(targetRange)) - val wrapped = counter.wrap(0.U.asInterval(targetRange)) - - when(counter === startValue) { - printf(cf"Target range is $range\n") - printf("value clip squeeze wrap\n") - } - - printf( - " %d %d %d %d\n", - counter.asSInt(), - clipped.asSInt(), - squeezed.asSInt(), - wrapped.asSInt() - ) -} - -class SqueezeFunctionalityTester(range: IntervalRange, startNum: BigDecimal, endNum: BigDecimal, increment: BigDecimal) - extends BasicTester { - - val counter = RegInit(0.U(10.W)) - counter := counter + 1.U - when(counter > 10.U) { - stop() - } - - val squeezeInterval = Wire(Interval(range)) - squeezeInterval := 0.I - - val squeezeTemplate = Wire(Interval(range)) - - val ss = WireInit(Interval(range), (-10).S.asInterval(range)) - - val toSqueeze = counter.asInterval(range) - ss - - squeezeTemplate := toSqueeze.squeeze(squeezeInterval) - - printf( - cf"SqueezeTest $counter%d ${toSqueeze.asSInt()}%d.squeeze($range) => ${squeezeTemplate.asSInt()}%d\n" - ) -} - -/** - * Demonstrate a simple counter register with an Interval type - */ -class IntervalRegisterTester extends BasicTester { - - val range = range"[-2,5]" - val counter = RegInit(Interval(range), (-1).I) - counter := (counter + 1.I) - .squeeze(counter) // this works with other types, why not Interval - when(counter > 4.I) { - stop() - } -} - -//noinspection ScalaStyle -class IntervalWrapTester extends BasicTester { - - val t1 = Wire(Interval(range"[-2, 12]")) - t1 := (-2).I - val u1 = 0.U(3.W) - val r1 = RegInit(u1) - r1 := u1 - val t2 = t1.wrap(u1) - val t3 = t1.wrap(r1) - - assert( - t2.range.upper == Closed(7), - s"t1 upper ${t2.range.upper} expected ${Closed(7)}" - ) - assert( - t3.range.upper == Closed(7), - s"t1 upper ${t3.range.upper} expected ${Closed(7)}" - ) - - val in1 = WireInit(Interval(range"[0,9].6"), 0.I) - val in2 = WireInit(Interval(range"[1,6).4"), 2.I) - val in3 = in1.wrap(in2) - - assert( - in3.range.lower == Closed(1), - s"in3 lower ${in3.range.lower} expected ${Closed(1)}" - ) - assert( - in3.range.upper == Open(6), - s"in3 upper ${in3.range.upper} expected ${Open(6)}" - ) - assert( - in3.binaryPoint == KnownBinaryPoint(6), - s"in3 binaryPoint ${in3.binaryPoint} expected ${KnownBinaryPoint(2)}" - ) - - val enclosedRange = range"[-2, 5]" - val base = Wire(Interval(range"[-4, 6]")) - val enclosed = WireInit(Interval(enclosedRange), 0.I) - val enclosing = WireInit(Interval(range"[-6, 8]"), 0.I) - val overlapLeft = WireInit(Interval(range"[-10,-2]"), (-3).I) - val overlapRight = WireInit(Interval(range"[-1,10]"), 0.I) - - val w1 = base.wrap(enclosed) - val w2 = base.wrap(enclosing) - val w3 = base.wrap(overlapLeft) - val w4 = base.wrap(overlapRight) - val w7 = base.wrap(enclosedRange) - - base := 6.I - - assert(w1 === (-2).I) - assert(w2 === 6.I) - assert(w3 === (-3).I) - assert(w4 === 6.I) - assert(w7 === (-2).I) - - stop() -} - -class IntervalClipTester extends BasicTester { - - val enclosedRange = range"[-2, 5]" - val base = Wire(Interval(range"[-4, 6]")) - val enclosed = Wire(Interval(enclosedRange)) - val enclosing = Wire(Interval(range"[-6, 8]")) - val overlapLeft = Wire(Interval(range"[-10,-2]")) - val overlapRight = Wire(Interval(range"[-1,10]")) - val disjointLeft = Wire(Interval(range"[-14,-7]")) - val disjointRight = Wire(Interval(range"[7,11]")) - - enclosed := DontCare - enclosing := DontCare - overlapLeft := DontCare - overlapRight := DontCare - disjointLeft := DontCare - disjointRight := DontCare - - val enclosedResult = base.clip(enclosed) - val enclosingResult = base.clip(enclosing) - val overlapLeftResult = base.clip(overlapLeft) - val overlapRightResult = base.clip(overlapRight) - val disjointLeftResult = base.clip(disjointLeft) - val disjointRightResult = base.clip(disjointRight) - val enclosedViaRangeString = base.clip(enclosedRange) - - base := 6.I - - assert(enclosedResult === 5.I) - assert(enclosingResult === 6.I) - assert(overlapLeftResult === (-2).I) - assert(overlapRightResult === 6.I) - assert(disjointLeftResult === (-7).I) - assert(disjointRightResult === 7.I) - - assert(enclosedViaRangeString === 5.I) - - stop() -} - -class IntervalChainedAddTester extends BasicTester { - - val intervalResult = Wire(Interval()) - val uintResult = Wire(UInt()) - - intervalResult := 1.I + 1.I + 1.I + 1.I + 1.I + 1.I + 1.I - uintResult := 1.U +& 1.U +& 1.U +& 1.U +& 1.U +& 1.U +& 1.U - - assert(intervalResult === 7.I) - assert(uintResult === 7.U) - stop() -} - -class IntervalChainedMulTester extends BasicTester { - - val intervalResult = Wire(Interval()) - val uintResult = Wire(UInt()) - - intervalResult := 2.I * 2.I * 2.I * 2.I * 2.I * 2.I * 2.I - uintResult := 2.U * 2.U * 2.U * 2.U * 2.U * 2.U * 2.U - - assert(intervalResult === 128.I) - assert(uintResult === 128.U) - stop() -} - -class IntervalChainedSubTester extends BasicTester { - val intervalResult1 = Wire(Interval()) - val intervalResult2 = Wire(Interval()) - val uIntResult = Wire(UInt()) - val sIntResult = Wire(SInt()) - val fixedResult = Wire(FixedPoint()) - - intervalResult1 := 17.I - 2.I - 2.I - 2.I - 2.I - 2.I - 2.I // gives same result as -& operand version below - intervalResult2 := 17.I -& 2.I -& 2.I -& 2.I -& 2.I -& 2.I -& 2.I - uIntResult := 17.U -& 2.U -& 2.U -& 2.U -& 2.U -& 2.U -& 2.U - fixedResult := 17.0.F(0.BP) -& 2.0.F(0.BP) -& 2.0.F(0.BP) -& 2.0.F(0.BP) -& 2.0 - .F(0.BP) -& 2.0.F(0.BP) -& 2.0.F(0.BP) - sIntResult := 17.S -& 2.S -& 2.S -& 2.S -& 2.S -& 2.S -& 2.S - - assert(uIntResult === 5.U) - assert(sIntResult === 5.S) - assert(fixedResult.asUInt === 5.U) - assert(intervalResult1 === 5.I) - assert(intervalResult2 === 5.I) - - val negativeInterval = (-3.5).I(4.BP) - val positiveInterval = 3.5.I(4.BP) - - assert(negativeInterval =/= positiveInterval) - assert(-negativeInterval === positiveInterval) - assert(negativeInterval === -positiveInterval) - - stop() -} - -//TODO: need tests for dynamic shifts on intervals -class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { - - type TempFirrtlException = Exception - - "Test a simple interval add" in { - assertTesterPasses { new IntervalAddTester } - } - "Intervals can be created" in { - assertTesterPasses { new IntervalTester } - } - "Test a simple interval mux" in { - assertTesterPasses { new IntervalTester2 } - } - "Intervals can have binary points set" in { - assertTesterPasses { new IntervalSetBinaryPointTester } - } - "Interval literals that don't fit in explicit ranges are caught by chisel" - { - "case 1: does not fit in specified width" in { - intercept[ChiselException] { - ChiselGeneratorAnnotation(() => - new BasicTester { - val x = 5.I(3.W, 0.BP) - } - ).elaborate - } - } - "case 2: doesn't fit in specified range" in { - intercept[ChiselException] { - ChiselGeneratorAnnotation(() => - new BasicTester { - val x = 5.I(range"[0,4]") - } - ).elaborate - } - } - } - - "Interval literals support to double and to BigDecimal" in { - val d = -7.125 - val lit1 = d.I(3.BP) - lit1.litToDouble should be(d) - - val d2 = BigDecimal("1232123213131123.125") - val lit2 = d2.I(3.BP) - lit2.litToBigDecimal should be(d2) - - // Numbers that are too big will throw exception - intercept[ChiselException] { - lit2.litToDouble - } - } - - "Interval literals creation handles edge cases" - { - "value at closed boundaries works" in { - val inputRange = range"[-6, 6].2" - val in1 = (-6.0).I(inputRange) - val in2 = 6.0.I(inputRange) - BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be(-6) - BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be(6) - intercept[ChiselException] { - (-6.25).I(inputRange) - } - intercept[ChiselException] { - (6.25).I(inputRange) - } - } - "value at open boundaries works" in { - val inputRange = range"(-6, 6).2" - val in1 = (-5.75).I(inputRange) - val in2 = 5.75.I(inputRange) - BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be(-5.75) - BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be(5.75) - intercept[ChiselException] { - (-6.0).I(inputRange) - } - intercept[ChiselException] { - (6.0).I(inputRange) - } - } - "values not precisely at open boundaries works but are converted to nearest match" in { - val inputRange = range"(-6, 6).2" - val in1 = (-5.95).I(inputRange) - val in2 = 5.95.I(inputRange) - BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be(-5.75) - BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be(5.75) - intercept[ChiselException] { - (-6.1).I(inputRange) - } - intercept[ChiselException] { - (6.1).I(inputRange) - } - } - } - - "Let's take a look at the results of squeeze over small range" in { - assertTesterPasses { - new ClipSqueezeWrapDemo( - range = range"[-10,33].0", - targetRange = range"[-4,17].0", - startNum = -4.0, - endNum = 30.0, - incNum = 1.0 - ) - } - assertTesterPasses { - new ClipSqueezeWrapDemo( - range = range"[-2,5].1", - targetRange = range"[-1,3].1", - startNum = -2.0, - endNum = 5.0, - incNum = 0.5 - ) - } - } - "Intervals can be squeezed into another intervals range" in { - assertTesterPasses { - new SqueezeFunctionalityTester( - range"[-2,5]", - BigDecimal(-10), - BigDecimal(10), - BigDecimal(1.0) - ) - } - } - "Intervals can be wrapped with wrap operator" in { - assertTesterPasses { new IntervalWrapTester } - } - - "Interval compile pathologies: clip, wrap, and squeeze have different behavior" - { - "wrap target range is completely left of source" in { - intercept[TempFirrtlException] { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[-7,-5]"), (-6).I) - val w5 = base.wrap(disjointLeft) - stop() - }) - } - } - "wrap target range is completely right of source" in { - intercept[TempFirrtlException] { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.wrap(disjointLeft) - stop() - }) - } - } - "clip target range is completely left of source" in { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[-7,-5]"), (-6).I) - val w5 = base.clip(disjointLeft) - chisel3.assert(w5 === (-5).I) - stop() - }) - } - "clip target range is completely right of source" in { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.clip(disjointLeft) - chisel3.assert(w5.asSInt === 7.S) - stop() - }) - } - "squeeze target range is completely right of source" in { - intercept[TempFirrtlException] { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - chisel3.assert(w5.asSInt === 6.S) - stop() - }) - } - } - "squeeze target range is completely left of source" in { - intercept[TempFirrtlException] { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[-7, -5]"), 8.I) - val w5 = base.squeeze(disjointLeft) - stop() - }) - } - } - - def makeCircuit(operation: String, sourceRange: IntervalRange, targetRange: IntervalRange): () => RawModule = { - () => - new Module { - val io = IO(new Bundle { val out = Output(Interval()) }) - val base = Wire(Interval(sourceRange)) - base := 6.I - - val disjointLeft = WireInit(Interval(targetRange), 8.I) - val w5 = operation match { - case "clip" => base.clip(disjointLeft) - case "wrap" => base.wrap(disjointLeft) - case "squeeze" => base.squeeze(disjointLeft) - } - io.out := w5 - } - } - - "disjoint ranges should error when used with clip, wrap and squeeze" - { - - def mustGetException(disjointLeft: Boolean, operation: String): Boolean = { - val (rangeA, rangeB) = if (disjointLeft) { - (range"[-4, 6]", range"[7,10]") - } else { - (range"[7,10]", range"[-4, 6]") - } - try { - makeFirrtl("low")(makeCircuit(operation, rangeA, rangeB)) - false - } catch { - case _: InvalidConnect | _: PassExceptions | _: InvalidRange | _: WrapWithRemainder | _: DisjointSqueeze => - true - case _: Throwable => - false - } - } - - "Range A disjoint left, operation clip should generate useful error" in { - mustGetException(disjointLeft = true, "clip") should be(false) - } - "Range A largely out of bounds left, operation wrap should generate useful error" in { - mustGetException(disjointLeft = true, "wrap") should be(true) - } - "Range A disjoint left, operation squeeze should generate useful error" in { - mustGetException(disjointLeft = true, "squeeze") should be(true) - } - "Range A disjoint right, operation clip should generate useful error" in { - mustGetException(disjointLeft = false, "clip") should be(true) - } - "Range A disjoint right, operation wrap should generate useful error" in { - mustGetException(disjointLeft = false, "wrap") should be(true) - } - "Range A disjoint right, operation squeeze should generate useful error" in { - mustGetException(disjointLeft = false, "squeeze") should be(true) - } - } - - "Errors are sometimes inconsistent or incorrectly labelled as Firrtl Internal Error" - { - "squeeze disjoint is not internal error when defined in BasicTester" in { - intercept[DisjointSqueeze] { - makeFirrtl("low")(() => - new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - val base2 = Wire(Interval(range"[-4, 6]")) - base := 6.I - base2 := 5.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - stop() - } - ) - } - } - "wrap disjoint is not internal error when defined in BasicTester" in { - intercept[DisjointSqueeze] { - makeFirrtl("low")(() => - new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - val base2 = Wire(Interval(range"[-4, 6]")) - base := 6.I - base2 := 5.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - stop() - } - ) - } - } - "squeeze disjoint from Module gives exception" in { - intercept[DisjointSqueeze] { - makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { - val out = Output(Interval()) - }) - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - io.out := w5 - } - ) - } - } - "clip disjoint from Module gives no error" in { - makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { - val out = Output(Interval()) - }) - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.clip(disjointLeft) - io.out := w5 - } - ) - } - "wrap disjoint from Module wrap with remainder" in { - intercept[WrapWithRemainder] { - makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { - val out = Output(Interval()) - }) - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.wrap(disjointLeft) - io.out := w5 - } - ) - } - } - } - - "assign literal out of range of interval" in { - intercept[firrtl.passes.CheckTypes.InvalidConnect] { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := (-8).I - }) - } - } - } - - "Intervals should catch assignment of literals outside of range" - { - "when literal is too small" in { - intercept[InvalidConnect] { - makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { val out = Output(Interval()) }) - val base = Wire(Interval(range"[-4, 6]")) - base := (-7).I - io.out := base - } - ) - } - } - "when literal is too big" in { - intercept[InvalidConnect] { - makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { val out = Output(Interval()) }) - val base = Wire(Interval(range"[-4, 6]")) - base := 9.I - io.out := base - } - ) - } - } - } - - "Intervals can be shifted left" in { - assertTesterPasses(new BasicTester { - val i1 = 3.0.I(range"[0,4]") - val shifted1 = i1 << 2 - val shiftUInt = WireInit(1.U(8.W)) - val shifted2 = i1 << shiftUInt - - chisel3.assert(shifted1 === 12.I, "shifted 1 should be 12, it wasn't") - chisel3.assert(shifted2 === 6.I, "shifted 2 should be 6 it wasn't") - stop() - }) - } - - "Intervals can be shifted right" in { - assertTesterPasses(new BasicTester { - val i1 = 12.0.I(range"[0,15]") - val shifted1 = i1 >> 2 - val shiftUInt = 1.U - val shifted2 = i1 >> shiftUInt - - chisel3.assert(shifted1 === 3.I) - chisel3.assert(shifted2 === 6.I) - stop() - }) - } - - "Intervals can be used to construct registers" in { - assertTesterPasses { new IntervalRegisterTester } - } - "Intervals can be clipped with clip (saturate) operator" in { - assertTesterPasses { new IntervalClipTester } - } - "Intervals adds same answer as UInt" in { - assertTesterPasses { new IntervalChainedAddTester } - } - "Intervals should produce canonically smaller ranges via inference" in { - val loFirrtl = makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { - val in = Input(Interval(range"[0,1]")) - val out = Output(Interval()) - }) - - val intervalResult = Wire(Interval()) - - intervalResult := 1.I + 1.I + 1.I + 1.I + 1.I + 1.I + 1.I - io.out := intervalResult - } - ) - loFirrtl.contains("output io_out : SInt<4>") should be(true) - - } - "Intervals multiplication same answer as UInt" in { - assertTesterPasses { new IntervalChainedMulTester } - } - "Intervals subs same answer as UInt" in { - assertTesterPasses { new IntervalChainedSubTester } - } - "Test clip, wrap and a variety of ranges" - { - """range"[0.0,10.0].2" => range"[2,6].2"""" in { - assertTesterPasses(new BasicTester { - - val sourceRange = range"[0.0,10.0].2" - val targetRange = range"[2,6].2" - - val sourceSimulator = ScalaIntervalSimulator(sourceRange) - val targetSimulator = ScalaIntervalSimulator(targetRange) - - for (sourceValue <- sourceSimulator.allValues) { - val clippedValue = Wire(Interval(targetRange)) - clippedValue := sourceSimulator - .makeLit(sourceValue) - .clip(clippedValue) - - val goldClippedValue = - targetSimulator.makeLit(targetSimulator.clip(sourceValue)) - - // Useful for debugging - // printf(s"source value $sourceValue clipped gold value %d compare to clipped value %d\n", - // goldClippedValue.asSInt(), clippedValue.asSInt()) - - chisel3.assert(goldClippedValue === clippedValue) - - val wrappedValue = Wire(Interval(targetRange)) - wrappedValue := sourceSimulator - .makeLit(sourceValue) - .wrap(wrappedValue) - - val goldWrappedValue = - targetSimulator.makeLit(targetSimulator.wrap(sourceValue)) - - // Useful for debugging - // printf(s"source value $sourceValue wrapped gold value %d compare to wrapped value %d\n", - // goldWrappedValue.asSInt(), wrappedValue.asSInt()) - - chisel3.assert(goldWrappedValue === wrappedValue) - } - - stop() - }) - } - } - - "Test squeeze over a variety of ranges" - { - """range"[2,6].2""" in { - assertTesterPasses(new BasicTester { - - val sourceRange = range"[0.0,10.0].2" - val targetRange = range"[2,6].3" - - val sourceSimulator = ScalaIntervalSimulator(sourceRange) - val targetSimulator = ScalaIntervalSimulator(targetRange) - - for (sourceValue <- sourceSimulator.allValues) { - val squeezedValue = Wire(Interval(targetRange)) - squeezedValue := sourceSimulator - .makeLit(sourceValue) - .clip(squeezedValue) - - val goldSqueezedValue = - targetSimulator.makeLit(targetSimulator.clip(sourceValue)) - - // Useful for debugging - // printf(s"source value $sourceValue squeezed gold value %d compare to squeezed value %d\n", - // goldSqueezedValue.asSInt(), squeezedValue.asSInt()) - - chisel3.assert(goldSqueezedValue === squeezedValue) - } - - stop() - }) - } - } - - "test asInterval" - { - "use with UInt" in { - assertTesterPasses(new BasicTester { - val u1 = Wire(UInt(5.W)) - u1 := 7.U - val i1 = u1.asInterval(range"[0,15]") - val i2 = u1.asInterval(range"[0,15].2") - printf("i1 %d\n", i1.asUInt) - chisel3.assert(i1 === 7.I, "i1") - stop() - }) - } - "use with SInt" in { - assertTesterPasses(new BasicTester { - val s1 = Wire(SInt(5.W)) - s1 := 7.S - val s2 = Wire(SInt(5.W)) - s2 := 7.S - val i1 = s1.asInterval(range"[-16,15]") - val i2 = s1.asInterval(range"[-16,15].1") - printf("i1 %d\n", i1.asSInt) - printf("i2 %d\n", i2.asSInt) - chisel3.assert(i1 === 7.I, "i1 is wrong") - chisel3.assert(i2 === (3.5).I(binaryPoint = 1.BP), "i2 is wrong") - stop() - }) - } - "more SInt tests" in { - assertTesterPasses(new BasicTester { - chisel3.assert(7.S.asInterval(range"[-16,15].1") === 3.5.I(binaryPoint = 1.BP), "adding binary point") - stop() - }) - } - } -} |
