diff options
| author | albertchen-sifive | 2018-07-20 14:36:30 -0700 |
|---|---|---|
| committer | Adam Izraelevitz | 2018-07-20 14:36:30 -0700 |
| commit | 7dff927840a30893facae957595a8e88ea62509a (patch) | |
| tree | 08210d9b2936fc4606ae8a0fe1c9f12a8c7c673e /src/test | |
| parent | 897dad039a12a49b3c4ae833fbf0d02087b26ed5 (diff) | |
Constant prop add (#849)
* add FoldADD to const prop, add yosys miter tests
* add option for verilog compiler without optimizations
* rename FoldLogicalOp to FoldCommutativeOp
* add GetNamespace and RenameModules, GetNamespace stores namespace as a ModuleNamespaceAnnotation
* add constant propagation for Tail DoPrims
* add scaladocs for MinimumLowFirrtlOptimization and yosysExpectFalure/Success, add constant propagation for Head DoPrim
* add legalize pass to MinimumLowFirrtlOptimizations, use constPropBitExtract in legalize pass
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/scala/firrtlTests/ConstantPropagationTests.scala | 136 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/FirrtlSpec.scala | 65 |
2 files changed, 196 insertions, 5 deletions
diff --git a/src/test/scala/firrtlTests/ConstantPropagationTests.scala b/src/test/scala/firrtlTests/ConstantPropagationTests.scala index 6fc685a8..603ddc25 100644 --- a/src/test/scala/firrtlTests/ConstantPropagationTests.scala +++ b/src/test/scala/firrtlTests/ConstantPropagationTests.scala @@ -694,6 +694,46 @@ class ConstantPropagationSingleModule extends ConstantPropagationSpec { """ (parse(exec(input))) should be (parse(check)) } + + "ConstProp" should "propagate constant addition" in { + val input = + """circuit Top : + | module Top : + | input x : UInt<5> + | output z : UInt<5> + | node _T_1 = add(UInt<5>("h0"), UInt<5>("h1")) + | node _T_2 = add(_T_1, UInt<5>("h2")) + | z <= add(x, _T_2) + """.stripMargin + val check = + """circuit Top : + | module Top : + | input x : UInt<5> + | output z : UInt<5> + | node _T_1 = UInt<6>("h1") + | node _T_2 = UInt<7>("h3") + | z <= add(x, UInt<7>("h3")) + """.stripMargin + (parse(exec(input))) should be(parse(check)) + } + + "ConstProp" should "propagate addition with zero" in { + val input = + """circuit Top : + | module Top : + | input x : UInt<5> + | output z : UInt<5> + | z <= add(x, UInt<5>("h0")) + """.stripMargin + val check = + """circuit Top : + | module Top : + | input x : UInt<5> + | output z : UInt<5> + | z <= pad(x, 6) + """.stripMargin + (parse(exec(input))) should be(parse(check)) + } } // More sophisticated tests of the full compiler @@ -1065,3 +1105,99 @@ class ConstantPropagationIntegrationSpec extends LowTransformSpec { execute(input, check, Seq.empty) } } + + +class ConstantPropagationEquivalenceSpec extends FirrtlFlatSpec { + private val srcDir = "/constant_propagation_tests" + private val transforms = Seq(new ConstantPropagation) + + "anything added to zero" should "be equal to itself" in { + val input = + s"""circuit AddZero : + | module AddZero : + | input in : UInt<5> + | output out1 : UInt<6> + | output out2 : UInt<6> + | out1 <= add(in, UInt<5>("h0")) + | out2 <= add(UInt<5>("h0"), in)""".stripMargin + firrtlEquivalenceTest(input, transforms) + } + + "constants added together" should "be propagated" in { + val input = + s"""circuit AddLiterals : + | module AddLiterals : + | input uin : UInt<5> + | input sin : SInt<5> + | output uout : UInt<6> + | output sout : SInt<6> + | node uconst = add(UInt<5>("h1"), UInt<5>("h2")) + | uout <= add(uconst, uin) + | node sconst = add(SInt<5>("h1"), SInt<5>("h-1")) + | sout <= add(sconst, sin)""".stripMargin + firrtlEquivalenceTest(input, transforms) + } + + "UInt addition" should "have the correct widths" in { + val input = + s"""circuit WidthsAddUInt : + | module WidthsAddUInt : + | input in : UInt<3> + | output out1 : UInt<10> + | output out2 : UInt<10> + | wire temp : UInt<5> + | temp <= add(in, UInt<1>("h0")) + | out1 <= cat(temp, temp) + | node const = add(UInt<4>("h1"), UInt<3>("h2")) + | out2 <= cat(const, const)""".stripMargin + firrtlEquivalenceTest(input, transforms) + } + + "SInt addition" should "have the correct widths" in { + val input = + s"""circuit WidthsAddSInt : + | module WidthsAddSInt : + | input in : SInt<3> + | output out1 : UInt<10> + | output out2 : UInt<10> + | wire temp : SInt<5> + | temp <= add(in, SInt<7>("h0")) + | out1 <= cat(temp, temp) + | node const = add(SInt<4>("h1"), SInt<3>("h-2")) + | out2 <= cat(const, const)""".stripMargin + firrtlEquivalenceTest(input, transforms) + } + + "addition by zero width wires" should "have the correct widths" in { + val input = + s"""circuit ZeroWidthAdd: + | module ZeroWidthAdd: + | input x: UInt<0> + | output y: UInt<7> + | node temp = add(x, UInt<9>("h0")) + | y <= cat(temp, temp)""".stripMargin + firrtlEquivalenceTest(input, transforms) + } + + "tail of constants" should "be propagated" in { + val input = + s"""circuit TailTester : + | module TailTester : + | output out : UInt<1> + | node temp = add(UInt<1>("h00"), UInt<5>("h017")) + | node tail_temp = tail(temp, 1) + | out <= tail_temp""".stripMargin + firrtlEquivalenceTest(input, transforms) + } + + "head of constants" should "be propagated" in { + val input = + s"""circuit TailTester : + | module TailTester : + | output out : UInt<1> + | node temp = add(UInt<1>("h00"), UInt<5>("h017")) + | node head_temp = head(temp, 3) + | out <= head_temp""".stripMargin + firrtlEquivalenceTest(input, transforms) + } +} diff --git a/src/test/scala/firrtlTests/FirrtlSpec.scala b/src/test/scala/firrtlTests/FirrtlSpec.scala index 01ae0431..95b09d93 100644 --- a/src/test/scala/firrtlTests/FirrtlSpec.scala +++ b/src/test/scala/firrtlTests/FirrtlSpec.scala @@ -5,22 +5,79 @@ package firrtlTests import java.io._ import com.typesafe.scalalogging.LazyLogging + import scala.sys.process._ import org.scalatest._ import org.scalatest.prop._ -import scala.io.Source +import scala.io.Source import firrtl._ import firrtl.ir._ -import firrtl.Parser.UseInfo +import firrtl.Parser.{IgnoreInfo, UseInfo} +import firrtl.analyses.{GetNamespace, InstanceGraph, ModuleNamespaceAnnotation} import firrtl.annotations._ -import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation} +import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation, RenameModules} import firrtl.util.BackendCompilationUtilities +import scala.collection.mutable + trait FirrtlRunners extends BackendCompilationUtilities { val cppHarnessResourceName: String = "/firrtl/testTop.cpp" + private class RenameTop(newTopPrefix: String) extends Transform { + def inputForm: LowForm.type = LowForm + def outputForm: LowForm.type = LowForm + + def execute(state: CircuitState): CircuitState = { + val namespace = state.annotations.collectFirst { + case m: ModuleNamespaceAnnotation => m + }.get.namespace + + val newTopName = namespace.newName(newTopPrefix) + val modulesx = state.circuit.modules.map { + case mod: Module if mod.name == state.circuit.main => mod.mapString(_ => newTopName) + case other => other + } + + state.copy(circuit = state.circuit.copy(main = newTopName, modules = modulesx)) + } + } + + /** Check equivalence of Firrtl transforms using yosys + * + * @param input string containing Firrtl source + * @param customTransforms Firrtl transforms to test for equivalence + * @param customAnnotations Optional Firrtl annotations + * @param resets tell yosys which signals to set for SAT, format is (timestep, signal, value) + */ + def firrtlEquivalenceTest(input: String, + customTransforms: Seq[Transform] = Seq.empty, + customAnnotations: AnnotationSeq = Seq.empty, + resets: Seq[(Int, String, Int)] = Seq.empty): Unit = { + val circuit = Parser.parse(input.split("\n").toIterator) + val compiler = new MinimumVerilogCompiler + val prefix = circuit.main + val testDir = createTestDirectory(prefix + "_equivalence_test") + + val customVerilog = compiler.compileAndEmit(CircuitState(circuit, HighForm, customAnnotations), + new GetNamespace +: new RenameTop(s"${prefix}_custom") +: customTransforms) + val namespaceAnnotation = customVerilog.annotations.collectFirst { case m: ModuleNamespaceAnnotation => m }.get + val customTop = customVerilog.circuit.main + val customFile = new PrintWriter(s"${testDir.getAbsolutePath}/$customTop.v") + customFile.write(customVerilog.getEmittedCircuit.value) + customFile.close() + + val referenceVerilog = compiler.compileAndEmit(CircuitState(circuit, HighForm, Seq(namespaceAnnotation)), + Seq(new RenameModules, new RenameTop(s"${prefix}_reference"))) + val referenceTop = referenceVerilog.circuit.main + val referenceFile = new PrintWriter(s"${testDir.getAbsolutePath}/$referenceTop.v") + referenceFile.write(referenceVerilog.getEmittedCircuit.value) + referenceFile.close() + + assert(yosysExpectSuccess(customTop, referenceTop, testDir, resets)) + } + /** Compiles input Firrtl to Verilog */ def compileToVerilog(input: String, annotations: AnnotationSeq = Seq.empty): String = { val circuit = Parser.parse(input.split("\n").toIterator) @@ -248,5 +305,3 @@ abstract class CompilationTest(name: String, dir: String) extends FirrtlPropSpec compileFirrtlTest(name, dir) } } - - |
