aboutsummaryrefslogtreecommitdiff
path: root/fuzzer
diff options
context:
space:
mode:
authorAlbert Chen2020-08-25 16:54:25 -0700
committerGitHub2020-08-25 16:54:25 -0700
commit40cb49f9237e23608da454a194f5c55e33f19375 (patch)
treeef29fe2f44c9927f15fd1591285ffd008bd8d750 /fuzzer
parentd7a3741909edb72cda2b768e2f8fae4f3c2fd6e2 (diff)
Inline Boolean Expressions (#1817)
The following conditions must be satisfied to inline: 1. has type Utils.BoolType 2. is bound to a DefNode with name starting with '_' 3. is bound to a DefNode with a source locator that points at the same file and line number. If it is a MultiInfo source locator, the set of file and line number pairs must be the same. Source locators may point to different column numbers. 4. InlineBooleanExpressionsMax has not been exceeded 5. is not a Mux Also updates the Verilog emitter to break up lines greater than 120 characters
Diffstat (limited to 'fuzzer')
-rw-r--r--fuzzer/src/main/scala/firrtl/ExprGenParams.scala65
-rw-r--r--fuzzer/src/main/scala/firrtl/FirrtlCompileTests.scala54
-rw-r--r--fuzzer/src/main/scala/firrtl/FirrtlEquivalenceTest.scala59
3 files changed, 117 insertions, 61 deletions
diff --git a/fuzzer/src/main/scala/firrtl/ExprGenParams.scala b/fuzzer/src/main/scala/firrtl/ExprGenParams.scala
index ddaec00d..4c11b860 100644
--- a/fuzzer/src/main/scala/firrtl/ExprGenParams.scala
+++ b/fuzzer/src/main/scala/firrtl/ExprGenParams.scala
@@ -1,5 +1,8 @@
package firrtl.fuzzer
+import com.pholser.junit.quickcheck.generator.{Generator, GenerationStatus}
+import com.pholser.junit.quickcheck.random.SourceOfRandomness
+
import firrtl.{Namespace, Utils}
import firrtl.ir._
@@ -17,15 +20,15 @@ sealed trait ExprGenParams {
*/
def maxWidth: Int
- /** A list of frequency/expression generator pairs
+ /** A mapping of expression generator to frequency
*
* The frequency number determines the probability that the corresponding
- * generator will be chosen. i.e. for sequece Seq(1 -> A, 2 -> B, 3 -> C),
- * the probabilities for A, B, and C are 1/6, 2/6, and 3/6 respectively.
- * This sequency must be non-empty and all frequency numbers must be greater
- * than zero.
+ * generator will be chosen. i.g. for Map(A -> 1, B -> 2, C -> B), the
+ * probabilities for A, B, and C are 1/6, 2/6, and 3/6 respectively. This
+ * map must be non-empty and all frequency numbers must be greater than
+ * zero.
*/
- def generators: Seq[(Int, ExprGen[_ <: Expression])]
+ def generators: Map[ExprGen[_ <: Expression], Int]
/** The set of generated references that don't have a corresponding declaration
*/
@@ -102,10 +105,46 @@ sealed trait ExprGenParams {
object ExprGenParams {
+ val defaultGenerators: Map[ExprGen[_ <: Expression], Int] = {
+ import ExprGen._
+ Map(
+ AddDoPrimGen -> 1,
+ SubDoPrimGen -> 1,
+ MulDoPrimGen -> 1,
+ DivDoPrimGen -> 1,
+ LtDoPrimGen -> 1,
+ LeqDoPrimGen -> 1,
+ GtDoPrimGen -> 1,
+ GeqDoPrimGen -> 1,
+ EqDoPrimGen -> 1,
+ NeqDoPrimGen -> 1,
+ PadDoPrimGen -> 1,
+ ShlDoPrimGen -> 1,
+ ShrDoPrimGen -> 1,
+ DshlDoPrimGen -> 1,
+ CvtDoPrimGen -> 1,
+ NegDoPrimGen -> 1,
+ NotDoPrimGen -> 1,
+ AndDoPrimGen -> 1,
+ OrDoPrimGen -> 1,
+ XorDoPrimGen -> 1,
+ AndrDoPrimGen -> 1,
+ OrrDoPrimGen -> 1,
+ XorrDoPrimGen -> 1,
+ CatDoPrimGen -> 1,
+ BitsDoPrimGen -> 1,
+ HeadDoPrimGen -> 1,
+ TailDoPrimGen -> 1,
+ AsUIntDoPrimGen -> 1,
+ AsSIntDoPrimGen -> 1,
+ MuxGen -> 1
+ )
+ }
+
private case class ExprGenParamsImp(
maxDepth: Int,
maxWidth: Int,
- generators: Seq[(Int, ExprGen[_ <: Expression])],
+ generators: Map[ExprGen[_ <: Expression], Int],
protected val unboundRefs: Set[Reference],
protected val namespace: Namespace) extends ExprGenParams {
@@ -119,7 +158,7 @@ object ExprGenParams {
def apply(
maxDepth: Int,
maxWidth: Int,
- generators: Seq[(Int, ExprGen[_ <: Expression])]
+ generators: Map[ExprGen[_ <: Expression], Int]
): ExprGenParams = {
require(maxWidth > 0, "maxWidth must be greater than zero")
ExprGenParamsImp(
@@ -190,7 +229,8 @@ object ExprGenParams {
))(tpe).map(e => e.get) // should be safe because leaf generators are defined for all types
val branchGen: Type => StateGen[ExprGenParams, G, Expression] = (tpe: Type) => {
- combineExprGens(s.generators)(tpe).flatMap {
+ val gens = s.generators.toSeq.map { case (gen, freq) => (freq, gen) }
+ combineExprGens(gens)(tpe).flatMap {
case None => leafGen(tpe)
case Some(e) => StateGen.pure(e)
}
@@ -211,3 +251,10 @@ object ExprGenParams {
}
}
}
+
+abstract class SingleExpressionCircuitGenerator(val params: ExprGenParams) extends Generator[Circuit](classOf[Circuit]) {
+ override def generate(random: SourceOfRandomness, status: GenerationStatus): Circuit = {
+ implicit val r = random
+ params.generateSingleExprCircuit[SourceOfRandomnessGen]()
+ }
+}
diff --git a/fuzzer/src/main/scala/firrtl/FirrtlCompileTests.scala b/fuzzer/src/main/scala/firrtl/FirrtlCompileTests.scala
index 9ee8e52b..3091e4d6 100644
--- a/fuzzer/src/main/scala/firrtl/FirrtlCompileTests.scala
+++ b/fuzzer/src/main/scala/firrtl/FirrtlCompileTests.scala
@@ -53,50 +53,14 @@ object SourceOfRandomnessGen {
}
}
-
-class FirrtlSingleModuleGenerator extends Generator[Circuit](classOf[Circuit]) {
- override def generate(random: SourceOfRandomness, status: GenerationStatus): Circuit = {
- implicit val r = random
- import ExprGen._
-
- val params = ExprGenParams(
- maxDepth = 50,
- maxWidth = 31,
- generators = Seq(
- 1 -> AddDoPrimGen,
- 1 -> SubDoPrimGen,
- 1 -> MulDoPrimGen,
- 1 -> DivDoPrimGen,
- 1 -> LtDoPrimGen,
- 1 -> LeqDoPrimGen,
- 1 -> GtDoPrimGen,
- 1 -> GeqDoPrimGen,
- 1 -> EqDoPrimGen,
- 1 -> NeqDoPrimGen,
- 1 -> PadDoPrimGen,
- 1 -> ShlDoPrimGen,
- 1 -> ShrDoPrimGen,
- 1 -> DshlDoPrimGen,
- 1 -> CvtDoPrimGen,
- 1 -> NegDoPrimGen,
- 1 -> NotDoPrimGen,
- 1 -> AndDoPrimGen,
- 1 -> OrDoPrimGen,
- 1 -> XorDoPrimGen,
- 1 -> AndrDoPrimGen,
- 1 -> OrrDoPrimGen,
- 1 -> XorrDoPrimGen,
- 1 -> CatDoPrimGen,
- 1 -> BitsDoPrimGen,
- 1 -> HeadDoPrimGen,
- 1 -> TailDoPrimGen,
- 1 -> AsUIntDoPrimGen,
- 1 -> AsSIntDoPrimGen
- )
- )
- params.generateSingleExprCircuit[SourceOfRandomnessGen]()
- }
-}
+import ExprGen._
+class FirrtlCompileCircuitGenerator extends SingleExpressionCircuitGenerator (
+ ExprGenParams(
+ maxDepth = 50,
+ maxWidth = 31,
+ generators = ExprGenParams.defaultGenerators
+ )
+)
@RunWith(classOf[JQF])
class FirrtlCompileTests {
@@ -112,7 +76,7 @@ class FirrtlCompileTests {
}
@Fuzz
- def compileSingleModule(@From(value = classOf[FirrtlSingleModuleGenerator]) c: Circuit) = {
+ def compileSingleModule(@From(value = classOf[FirrtlCompileCircuitGenerator]) c: Circuit) = {
compile(CircuitState(c, ChirrtlForm, Seq()))
}
diff --git a/fuzzer/src/main/scala/firrtl/FirrtlEquivalenceTest.scala b/fuzzer/src/main/scala/firrtl/FirrtlEquivalenceTest.scala
index e0aa1707..822744c2 100644
--- a/fuzzer/src/main/scala/firrtl/FirrtlEquivalenceTest.scala
+++ b/fuzzer/src/main/scala/firrtl/FirrtlEquivalenceTest.scala
@@ -1,17 +1,19 @@
package firrtl.fuzzer
import com.pholser.junit.quickcheck.From
+import com.pholser.junit.quickcheck.generator.{Generator, GenerationStatus}
+import com.pholser.junit.quickcheck.random.SourceOfRandomness
-import edu.berkeley.cs.jqf.fuzz.Fuzz;
-import edu.berkeley.cs.jqf.fuzz.JQF;
+import edu.berkeley.cs.jqf.fuzz.{Fuzz, JQF};
import firrtl._
import firrtl.annotations.{Annotation, CircuitTarget, ModuleTarget, Target}
import firrtl.ir.Circuit
+import firrtl.options.Dependency
import firrtl.stage.{FirrtlCircuitAnnotation, InfoModeAnnotation, OutputFileAnnotation, TransformManager}
import firrtl.stage.Forms.{VerilogMinimumOptimized, VerilogOptimized}
import firrtl.stage.phases.WriteEmitted
-import firrtl.transforms.ManipulateNames
+import firrtl.transforms.{InlineBooleanExpressions, ManipulateNames}
import firrtl.util.BackendCompilationUtilities
import java.io.{File, FileWriter, PrintWriter, StringWriter}
@@ -89,6 +91,32 @@ object FirrtlEquivalenceTestUtils {
}
}
+import ExprGen._
+class InlineBooleanExprsCircuitGenerator extends SingleExpressionCircuitGenerator (
+ ExprGenParams(
+ maxDepth = 50,
+ maxWidth = 31,
+ generators = ExprGenParams.defaultGenerators ++ Map(
+ LtDoPrimGen -> 10,
+ LeqDoPrimGen -> 10,
+ GtDoPrimGen -> 10,
+ GeqDoPrimGen -> 10,
+ EqDoPrimGen -> 10,
+ NeqDoPrimGen -> 10,
+ AndDoPrimGen -> 10,
+ OrDoPrimGen -> 10,
+ XorDoPrimGen -> 10,
+ AndrDoPrimGen -> 10,
+ OrrDoPrimGen -> 10,
+ XorrDoPrimGen -> 10,
+ BitsDoPrimGen -> 10,
+ HeadDoPrimGen -> 10,
+ TailDoPrimGen -> 10,
+ MuxGen -> 10
+ )
+ )
+)
+
@RunWith(classOf[JQF])
class FirrtlEquivalenceTests {
private val lowFirrtlCompiler = new LowFirrtlCompiler()
@@ -103,8 +131,7 @@ class FirrtlEquivalenceTests {
}
private val baseTestDir = new File("fuzzer/test_run_dir")
- @Fuzz
- def compileSingleModule(@From(value = classOf[FirrtlSingleModuleGenerator]) c: Circuit) = {
+ private def runTest(c: Circuit, referenceCompiler: TransformManager, customCompiler: TransformManager) = {
val testDir = new File(baseTestDir, f"${c.hashCode}%08x")
testDir.mkdirs()
val fileWriter = new FileWriter(new File(testDir, s"${c.main}.fir"))
@@ -113,9 +140,9 @@ class FirrtlEquivalenceTests {
val passed = try {
FirrtlEquivalenceTestUtils.firrtlEquivalenceTestPass(
circuit = c,
- referenceCompiler = new TransformManager(VerilogMinimumOptimized),
+ referenceCompiler = referenceCompiler,
referenceAnnos = Seq(),
- customCompiler = new TransformManager(VerilogOptimized),
+ customCompiler = customCompiler,
customAnnos = Seq(),
testDir = testDir
)
@@ -131,4 +158,22 @@ class FirrtlEquivalenceTests {
s"not equivalent to reference compiler on input ${testDir}:\n${c.serialize}\n", false)
}
}
+
+ @Fuzz
+ def testOptimized(@From(value = classOf[FirrtlCompileCircuitGenerator]) c: Circuit) = {
+ runTest(
+ c = c,
+ referenceCompiler = new TransformManager(VerilogMinimumOptimized),
+ customCompiler = new TransformManager(VerilogOptimized)
+ )
+ }
+
+ @Fuzz
+ def testInlineBooleanExpressions(@From(value = classOf[InlineBooleanExprsCircuitGenerator]) c: Circuit) = {
+ runTest(
+ c = c,
+ referenceCompiler = new TransformManager(VerilogMinimumOptimized),
+ customCompiler = new TransformManager(VerilogMinimumOptimized :+ Dependency[InlineBooleanExpressions])
+ )
+ }
}