aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authoralbertchen-sifive2018-07-20 14:36:30 -0700
committerAdam Izraelevitz2018-07-20 14:36:30 -0700
commit7dff927840a30893facae957595a8e88ea62509a (patch)
tree08210d9b2936fc4606ae8a0fe1c9f12a8c7c673e /src/test
parent897dad039a12a49b3c4ae833fbf0d02087b26ed5 (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.scala136
-rw-r--r--src/test/scala/firrtlTests/FirrtlSpec.scala65
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)
}
}
-
-