diff --git a/src/main/scala/chisel3/iotesters/Driver.scala b/src/main/scala/chisel3/iotesters/Driver.scala index bd3db30f..f85d965b 100644 --- a/src/main/scala/chisel3/iotesters/Driver.scala +++ b/src/main/scala/chisel3/iotesters/Driver.scala @@ -29,7 +29,8 @@ object Driver { */ def execute[T <: MultiIOModule]( dutGenerator: () => T, - optionsManager: TesterOptionsManager + optionsManager: TesterOptionsManager, + firrtlSourceOverride: Option[String] = None ) ( testerGen: T => PeekPokeTester[T] @@ -48,11 +49,11 @@ object Driver { val (dut, backend) = testerOptions.backendName match { case "firrtl" => - setupFirrtlTerpBackend(dutGenerator, optionsManager) + setupFirrtlTerpBackend(dutGenerator, optionsManager, firrtlSourceOverride) case "treadle" => setupTreadleBackend(dutGenerator, optionsManager) case "verilator" => - setupVerilatorBackend(dutGenerator, optionsManager) + setupVerilatorBackend(dutGenerator, optionsManager, firrtlSourceOverride) case "ivl" => setupIVLBackend(dutGenerator, optionsManager) case "vcs" => diff --git a/src/main/scala/chisel3/iotesters/FirrtlTerpBackend.scala b/src/main/scala/chisel3/iotesters/FirrtlTerpBackend.scala index 1fc54da6..96e2c53f 100644 --- a/src/main/scala/chisel3/iotesters/FirrtlTerpBackend.scala +++ b/src/main/scala/chisel3/iotesters/FirrtlTerpBackend.scala @@ -118,7 +118,9 @@ private[iotesters] class FirrtlTerpBackend( private[iotesters] object setupFirrtlTerpBackend { def apply[T <: MultiIOModule]( dutGen: () => T, - optionsManager: TesterOptionsManager = new TesterOptionsManager): (T, Backend) = { + optionsManager: TesterOptionsManager = new TesterOptionsManager with HasInterpreterOptions, + firrtlSourceOverride: Option[String] = None + ): (T, Backend) = { // the backend must be firrtl if we are here, therefore we want the firrtl compiler optionsManager.firrtlOptions = optionsManager.firrtlOptions.copy(compilerName = "low") @@ -137,7 +139,8 @@ private[iotesters] object setupFirrtlTerpBackend { val dut = getTopModule(circuit).asInstanceOf[T] firrtlExecutionResult match { case FirrtlExecutionSuccess(_, compiledFirrtl) => - (dut, new FirrtlTerpBackend(dut, compiledFirrtl, optionsManager = optionsManager)) + val firrtlText = firrtlSourceOverride.getOrElse(compiledFirrtl) + (dut, new FirrtlTerpBackend(dut, firrtlText, optionsManager = optionsManager)) case FirrtlExecutionFailure(message) => throw new Exception(s"FirrtlBackend: failed firrlt compile message: $message") } diff --git a/src/main/scala/chisel3/iotesters/TreadleBackend.scala b/src/main/scala/chisel3/iotesters/TreadleBackend.scala index b779c95d..7aea7891 100644 --- a/src/main/scala/chisel3/iotesters/TreadleBackend.scala +++ b/src/main/scala/chisel3/iotesters/TreadleBackend.scala @@ -5,9 +5,10 @@ package chisel3.iotesters import chisel3.internal.InstanceId import chisel3.stage.{ChiselCircuitAnnotation, ChiselStage} import chisel3.{Element, MemBase, MultiIOModule, assert} -import firrtl.{AnnotationSeq, LowForm} +import firrtl.stage.CompilerAnnotation +import firrtl.{AnnotationSeq, annoSeqToSeq} import treadle.stage.TreadleTesterPhase -import treadle.{TreadleFirrtlFormHint, TreadleTester, TreadleTesterAnnotation} +import treadle.{TreadleTester, TreadleTesterAnnotation} private[iotesters] class TreadleBackend( dut: MultiIOModule, @@ -70,7 +71,8 @@ extends Backend(_seed = System.currentTimeMillis()) { val got = treadleTester.peek(name) val good = got == expected if (verbose || !good) logger info - s"""EXPECT AT $stepNumber $msg $name got ${bigIntToStr(got, base)} expected ${bigIntToStr(expected, base)}""" + + s"""EXPECT AT $stepNumber $msg $name got ${bigIntToStr(got, base)}""" + + s""" expected ${bigIntToStr(expected, base)}""" + s""" ${if (good) "PASS" else "FAIL"}""" if(good) treadleTester.expectationsMet += 1 good @@ -146,10 +148,11 @@ private[iotesters] object setupTreadleBackend { val dut = getTopModule(circuit).asInstanceOf[T] // This generates the firrtl circuit needed by the TreadleTesterPhase - annotationSeq = (new ChiselStage).run(annotationSeq) + // Uses low compiler to avoid padWidths changing Dshl to Dshlw which blows up CheckTypes + annotationSeq = (new ChiselStage).execute(Array("-X", "low"), annotationSeq) // This generates a TreadleTesterAnnotation with a treadle tester instance - annotationSeq = (new TreadleTesterPhase).transform(annotationSeq :+ TreadleFirrtlFormHint(LowForm)) + annotationSeq = (new TreadleTesterPhase).transform(annotationSeq) val treadleTester = annotationSeq.collectFirst { case TreadleTesterAnnotation(t) => t }.getOrElse( throw new Exception( @@ -161,4 +164,3 @@ private[iotesters] object setupTreadleBackend { (dut, new TreadleBackend(dut, treadleTester)) } } - diff --git a/src/main/scala/chisel3/iotesters/VerilatorBackend.scala b/src/main/scala/chisel3/iotesters/VerilatorBackend.scala index 1f472db1..2982b50f 100644 --- a/src/main/scala/chisel3/iotesters/VerilatorBackend.scala +++ b/src/main/scala/chisel3/iotesters/VerilatorBackend.scala @@ -205,7 +205,9 @@ int main(int argc, char **argv, char **env) { } private[iotesters] object setupVerilatorBackend { - def apply[T <: MultiIOModule](dutGen: () => T, optionsManager: TesterOptionsManager): (T, Backend) = { + def apply[T <: MultiIOModule](dutGen: () => T, + optionsManager: TesterOptionsManager, + firrtlSourceOverride: Option[String] = None): (T, Backend) = { import firrtl.{ChirrtlForm, CircuitState} optionsManager.makeTargetDir() @@ -220,7 +222,8 @@ private[iotesters] object setupVerilatorBackend { chisel3.Driver.execute(optionsManager, dutGen) match { case ChiselExecutionSuccess(Some(circuit), emitted, _) => - val chirrtl = firrtl.Parser.parse(emitted) + val chirrtlSource = firrtlSourceOverride.getOrElse(emitted) + val chirrtl = firrtl.Parser.parse(chirrtlSource) val dut = getTopModule(circuit).asInstanceOf[T] val suppressVerilatorVCD = optionsManager.testerOptions.generateVcdOutput == "off" diff --git a/src/test/scala/chisel3/iotesters/IntervalDshlTest.scala b/src/test/scala/chisel3/iotesters/IntervalDshlTest.scala new file mode 100644 index 00000000..46be60ae --- /dev/null +++ b/src/test/scala/chisel3/iotesters/IntervalDshlTest.scala @@ -0,0 +1,70 @@ +/* +Copyright 2020 The Regents of the University of California (Regents) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + */ + +package chisel3.iotesters + +import chisel3._ +import chisel3.experimental.Interval +import chisel3.internal.firrtl.IntervalRange +import org.scalatest.{FreeSpec, Matchers} + +class IntervalShifter(val bitWidth: Int, val binaryPoint: Int, val fixedShiftSize: Int) extends Module { + val dynamicShifterWidth = 3 + + val io = IO(new Bundle { + val inValue = Input(Interval(IntervalRange(bitWidth.W, binaryPoint.BP))) + val dynamicShiftValue = Input(UInt(dynamicShifterWidth.W)) + val shiftRightResult: Option[Interval] = if(fixedShiftSize < bitWidth) { + Some(Output(Interval(IntervalRange((bitWidth - fixedShiftSize).W, binaryPoint.BP)))) + } + else { + None + } + val shiftLeftResult = Output(Interval(IntervalRange((bitWidth + fixedShiftSize).W, binaryPoint.BP))) + val dynamicShiftRightResult = Output(Interval(IntervalRange(bitWidth.W, binaryPoint.BP))) + val dynamicShiftLeftResult = Output( + Interval(IntervalRange((bitWidth + (1 << dynamicShifterWidth) - 1).W, binaryPoint.BP)) + ) + }) + + io.shiftLeftResult := io.inValue << fixedShiftSize + io.shiftRightResult.foreach { out => + out := (io.inValue >> fixedShiftSize).asInstanceOf[Interval].squeeze(out) + } + io.dynamicShiftLeftResult := io.inValue << io.dynamicShiftValue + io.dynamicShiftRightResult := io.inValue >> io.dynamicShiftValue +} + +class IntervalShiftLeftSpec extends FreeSpec with Matchers { + "Shift left of interval used to create Dshlw problem in CheckTypes" in { + val backendName = "treadle" + val defaultWidth = 8 + val binaryPoint = 0 + val fixedShiftSize = 1 + Driver.execute( + Array( + "--backend-name", backendName, + "--target-dir", s"test_run_dir/interval-shift-test-$fixedShiftSize-$binaryPoint.BP" + ), + () => new IntervalShifter(bitWidth = 8, binaryPoint = binaryPoint, fixedShiftSize = fixedShiftSize) + + ) { c => + new PeekPokeTester(c) { + + } + } should be(true) + } +}