From 334c9bbe5061a3bcb72df971ec555de7df0ba36c Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Fri, 25 Jan 2019 14:04:16 -0500 Subject: Add "mverilog" Compiler Option, Compiler Fixes This adds "mverilog" to the "--compiler" command line option. This will run the MinimumVerilogCompiler. This additionally fixes the MinimumVerilogCompiler such that DeadCodeElimination will not be run (it's not supposed to be). This is done by adding a MinimumVerilogEmitter, subclassing VerilogVerilog, that strips the DeadCodeElimination step from its parent. Additionally, BlackBoxSourceHelper is removed from the MinimumVerilogCompiler since this will be run by the VerilogEmitter already. Signed-off-by: Schuyler Eldridge --- src/main/scala/firrtl/Emitter.scala | 10 ++++++++ .../scala/firrtl/ExecutionOptionsManager.scala | 26 +++++++++++-------- src/main/scala/firrtl/LoweringCompilers.scala | 4 +-- src/test/scala/firrtlTests/CompilerTests.scala | 29 ++++++++++++++++++++++ 4 files changed, 57 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala index 67bd1583..8049e33c 100644 --- a/src/main/scala/firrtl/Emitter.scala +++ b/src/main/scala/firrtl/Emitter.scala @@ -882,3 +882,13 @@ class VerilogEmitter extends SeqTransform with Emitter { state.copy(annotations = newAnnos ++ state.annotations) } } + +class MinimumVerilogEmitter extends VerilogEmitter with Emitter { + + + override def transforms = super.transforms.filter{ + case _: DeadCodeElimination => false + case _ => true + } + +} diff --git a/src/main/scala/firrtl/ExecutionOptionsManager.scala b/src/main/scala/firrtl/ExecutionOptionsManager.scala index 16e30f3a..47083cb4 100644 --- a/src/main/scala/firrtl/ExecutionOptionsManager.scala +++ b/src/main/scala/firrtl/ExecutionOptionsManager.scala @@ -207,18 +207,19 @@ extends ComposableOptions { case "low" => new LowFirrtlCompiler() case "middle" => new MiddleFirrtlCompiler() case "verilog" => new VerilogCompiler() + case "mverilog" => new MinimumVerilogCompiler() case "sverilog" => new SystemVerilogCompiler() } } def outputSuffix: String = { compilerName match { - case "verilog" => "v" - case "sverilog" => "sv" - case "low" => "lo.fir" - case "middle" => "mid.fir" - case "high" => "hi.fir" - case "none" => "fir" + case "verilog" | "mverilog" => "v" + case "sverilog" => "sv" + case "low" => "lo.fir" + case "middle" => "mid.fir" + case "high" => "hi.fir" + case "none" => "fir" case _ => throw new Exception(s"Illegal compiler name $compilerName") } @@ -267,6 +268,7 @@ extends ComposableOptions { case "middle" => classOf[MiddleFirrtlEmitter] case "low" => classOf[LowFirrtlEmitter] case "verilog" => classOf[VerilogEmitter] + case "mverilog" => classOf[MinimumVerilogEmitter] case "sverilog" => classOf[VerilogEmitter] } getOutputConfig(optionsManager) match { @@ -344,13 +346,16 @@ trait HasFirrtlOptions { parser.opt[String]("compiler") .abbr("X") - .valueName ("") + .valueName ("") .foreach { x => firrtlOptions = firrtlOptions.copy(compilerName = x) } .validate { x => - if (Array("high", "middle", "low", "verilog", "sverilog", "none").contains(x.toLowerCase)) parser.success - else parser.failure(s"$x not a legal compiler") + if (Array("high", "middle", "low", "verilog", "mverilog", "sverilog", "none").contains(x.toLowerCase)) { + parser.success + } else { + parser.failure(s"$x not a legal compiler") + } }.text { s"compiler to use, default is ${firrtlOptions.compilerName}" } @@ -492,7 +497,8 @@ object FirrtlExecutionSuccess { * Indicates a successful execution of the firrtl compiler, returning the compiled result and * the type of compile * - * @param emitType The name of the compiler used, currently "high", "middle", "low", "verilog", or "sverilog" + * @param emitType The name of the compiler used, currently "high", "middle", "low", "verilog", "mverilog", or + * "sverilog" * @param emitted The emitted result of compilation */ class FirrtlExecutionSuccess( diff --git a/src/main/scala/firrtl/LoweringCompilers.scala b/src/main/scala/firrtl/LoweringCompilers.scala index eab928c2..7499d6d1 100644 --- a/src/main/scala/firrtl/LoweringCompilers.scala +++ b/src/main/scala/firrtl/LoweringCompilers.scala @@ -166,9 +166,9 @@ class VerilogCompiler extends Compiler { /** Emits Verilog without optimizations */ class MinimumVerilogCompiler extends Compiler { - def emitter = new VerilogEmitter + def emitter = new MinimumVerilogEmitter def transforms: Seq[Transform] = getLoweringTransforms(ChirrtlForm, LowForm) ++ - Seq(new MinimumLowFirrtlOptimization, new BlackBoxSourceHelper) + Seq(new MinimumLowFirrtlOptimization) } /** Currently just an alias for the [[VerilogCompiler]] */ diff --git a/src/test/scala/firrtlTests/CompilerTests.scala b/src/test/scala/firrtlTests/CompilerTests.scala index 348ed300..ff7d2cb8 100644 --- a/src/test/scala/firrtlTests/CompilerTests.scala +++ b/src/test/scala/firrtlTests/CompilerTests.scala @@ -13,6 +13,7 @@ import firrtl.{ Compiler, HighFirrtlCompiler, MiddleFirrtlCompiler, + MinimumVerilogCompiler, LowFirrtlCompiler, Parser, VerilogCompiler @@ -153,3 +154,31 @@ class VerilogCompilerSpec extends CompilerSpec with Matchers { getOutput should be (check) } } + +class MinimumVerilogCompilerSpec extends CompilerSpec with Matchers { + val input = """|circuit Top: + | module Top: + | output b: UInt<1>[2] + | node c = UInt<1>("h0") + | node d = UInt<1>("h0") + | b[0] <= UInt<1>("h0") + | b[1] <= c + |""".stripMargin + val check = """|module Top( + | output b_0, + | output b_1 + |); + | wire c; + | wire d; + | assign c = 1'h0; + | assign d = 1'h0; + | assign b_0 = 1'h0; + | assign b_1 = c; + |endmodule + |""".stripMargin + def compiler = new MinimumVerilogCompiler() + + "A circuit's minimum Verilog output" should "not have constants propagated or dead code eliminated" in { + getOutput should be (check) + } +} -- cgit v1.2.3 From 6ef7ad148ff491c06d417d417e2134da7ff49ef7 Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Fri, 25 Jan 2019 14:53:13 -0500 Subject: Add "mverilog" and "sverilog" DriverSpec tests This adds runs of the minimum Verilog compiler and SystemVerilog compiler in DriverSpec. Signed-off-by: Schuyler Eldridge --- src/test/scala/firrtlTests/DriverSpec.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/test/scala/firrtlTests/DriverSpec.scala b/src/test/scala/firrtlTests/DriverSpec.scala index 545bf09a..ae1e08e7 100644 --- a/src/test/scala/firrtlTests/DriverSpec.scala +++ b/src/test/scala/firrtlTests/DriverSpec.scala @@ -371,7 +371,9 @@ class DriverSpec extends FreeSpec with Matchers with BackendCompilationUtilities "low" -> "./Top.lo.fir", "high" -> "./Top.hi.fir", "middle" -> "./Top.mid.fir", - "verilog" -> "./Top.v" + "verilog" -> "./Top.v", + "mverilog" -> "./Top.v", + "sverilog" -> "./Top.sv" ).foreach { case (compilerName, expectedOutputFileName) => val manager = new ExecutionOptionsManager("test") with HasFirrtlOptions { commonOptions = CommonOptions(topName = "Top") @@ -391,7 +393,9 @@ class DriverSpec extends FreeSpec with Matchers with BackendCompilationUtilities "low" -> Seq("./Top.lo.fir", "./Child.lo.fir"), "high" -> Seq("./Top.hi.fir", "./Child.hi.fir"), "middle" -> Seq("./Top.mid.fir", "./Child.mid.fir"), - "verilog" -> Seq("./Top.v", "./Child.v") + "verilog" -> Seq("./Top.v", "./Child.v"), + "mverilog" -> Seq("./Top.v", "./Child.v"), + "sverilog" -> Seq("./Top.sv", "./Child.sv") ).foreach { case (compilerName, expectedOutputFileNames) => println(s"$compilerName -> $expectedOutputFileNames") val manager = new ExecutionOptionsManager("test") with HasFirrtlOptions { -- cgit v1.2.3 From a77122b4bb8756636c169473af3dc367b14698ef Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Tue, 5 Feb 2019 11:23:19 -0500 Subject: Add RemoveValidIf to -X mverilog This adds the RemoveValidIf Pass to the MinimumLowFirrtlOptimization Transform. A test case is included to verify that `is invalid` is properly converted to a connection to zero. Signed-off-by: Schuyler Eldridge --- src/main/scala/firrtl/LoweringCompilers.scala | 1 + src/test/scala/firrtlTests/CompilerTests.scala | 15 ++++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/main/scala/firrtl/LoweringCompilers.scala b/src/main/scala/firrtl/LoweringCompilers.scala index 7499d6d1..9969150d 100644 --- a/src/main/scala/firrtl/LoweringCompilers.scala +++ b/src/main/scala/firrtl/LoweringCompilers.scala @@ -119,6 +119,7 @@ class MinimumLowFirrtlOptimization extends CoreTransform { def inputForm = LowForm def outputForm = LowForm def transforms = Seq( + passes.RemoveValidIf, passes.Legalize, passes.memlib.VerilogMemDelays, // TODO move to Verilog emitter passes.SplitExpressions) diff --git a/src/test/scala/firrtlTests/CompilerTests.scala b/src/test/scala/firrtlTests/CompilerTests.scala index ff7d2cb8..df83dd38 100644 --- a/src/test/scala/firrtlTests/CompilerTests.scala +++ b/src/test/scala/firrtlTests/CompilerTests.scala @@ -159,21 +159,18 @@ class MinimumVerilogCompilerSpec extends CompilerSpec with Matchers { val input = """|circuit Top: | module Top: | output b: UInt<1>[2] - | node c = UInt<1>("h0") - | node d = UInt<1>("h0") - | b[0] <= UInt<1>("h0") - | b[1] <= c + | node c = UInt<1>("h1") + | b[0] <= c + | b[1] is invalid |""".stripMargin val check = """|module Top( | output b_0, | output b_1 |); | wire c; - | wire d; - | assign c = 1'h0; - | assign d = 1'h0; - | assign b_0 = 1'h0; - | assign b_1 = c; + | assign c = 1'h1; + | assign b_0 = c; + | assign b_1 = 1'h0; |endmodule |""".stripMargin def compiler = new MinimumVerilogCompiler() -- cgit v1.2.3 From 0a88492bfbbfe7e446b74776ec59cab69e73585b Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Tue, 5 Feb 2019 14:03:08 -0500 Subject: Do Shr constant propagation in Legalize This uses the foldShiftRight method of the ConstantPropagation Transform when legalizing Shr PrimOps. This has the effect of removing literals with bit extracts from the MinimumVerilogCompiler. This makes the formerly private foldShiftRight method of a public method of the ConstantPropagation companion object. Tests in the MimimumVerilogCompilerSpec are updated to check that Shr is handled as intended. Signed-off-by: Schuyler Eldridge --- src/main/scala/firrtl/passes/Passes.scala | 30 ++++++++++++---------- .../firrtl/transforms/ConstantPropagation.scala | 22 ++++++++-------- src/test/scala/firrtlTests/CompilerTests.scala | 20 ++++++++++----- 3 files changed, 41 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/main/scala/firrtl/passes/Passes.scala b/src/main/scala/firrtl/passes/Passes.scala index bb65201b..04bfb19c 100644 --- a/src/main/scala/firrtl/passes/Passes.scala +++ b/src/main/scala/firrtl/passes/Passes.scala @@ -183,19 +183,23 @@ object ExpandConnects extends Pass { object Legalize extends Pass { private def legalizeShiftRight(e: DoPrim): Expression = { require(e.op == Shr) - val amount = e.consts.head.toInt - val width = bitWidth(e.args.head.tpe) - lazy val msb = width - 1 - if (amount >= width) { - e.tpe match { - case UIntType(_) => zero - case SIntType(_) => - val bits = DoPrim(Bits, e.args, Seq(msb, msb), BoolType) - DoPrim(AsSInt, Seq(bits), Seq.empty, SIntType(IntWidth(1))) - case t => error(s"Unsupported type $t for Primop Shift Right") - } - } else { - e + e.args.head match { + case _: UIntLiteral | _: SIntLiteral => ConstantPropagation.foldShiftRight(e) + case _ => + val amount = e.consts.head.toInt + val width = bitWidth(e.args.head.tpe) + lazy val msb = width - 1 + if (amount >= width) { + e.tpe match { + case UIntType(_) => zero + case SIntType(_) => + val bits = DoPrim(Bits, e.args, Seq(msb, msb), BoolType) + DoPrim(AsSInt, Seq(bits), Seq.empty, SIntType(IntWidth(1))) + case t => error(s"Unsupported type $t for Primop Shift Right") + } + } else { + e + } } } private def legalizeBitExtract(expr: DoPrim): Expression = { diff --git a/src/main/scala/firrtl/transforms/ConstantPropagation.scala b/src/main/scala/firrtl/transforms/ConstantPropagation.scala index 54338719..6618312a 100644 --- a/src/main/scala/firrtl/transforms/ConstantPropagation.scala +++ b/src/main/scala/firrtl/transforms/ConstantPropagation.scala @@ -45,6 +45,17 @@ object ConstantPropagation { case _ => e } } + + def foldShiftRight(e: DoPrim) = e.consts.head.toInt match { + case 0 => e.args.head + case x => e.args.head match { + // TODO when amount >= x.width, return a zero-width wire + case UIntLiteral(v, IntWidth(w)) => UIntLiteral(v >> x, IntWidth((w - x) max 1)) + // take sign bit if shift amount is larger than arg width + case SIntLiteral(v, IntWidth(w)) => SIntLiteral(v >> x, IntWidth((w - x) max 1)) + case _ => e + } + } } class ConstantPropagation extends Transform with ResolvedAnnotationPaths { @@ -144,17 +155,6 @@ class ConstantPropagation extends Transform with ResolvedAnnotationPaths { case _ => e } - private def foldShiftRight(e: DoPrim) = e.consts.head.toInt match { - case 0 => e.args.head - case x => e.args.head match { - // TODO when amount >= x.width, return a zero-width wire - case UIntLiteral(v, IntWidth(w)) => UIntLiteral(v >> x, IntWidth((w - x) max 1)) - // take sign bit if shift amount is larger than arg width - case SIntLiteral(v, IntWidth(w)) => SIntLiteral(v >> x, IntWidth((w - x) max 1)) - case _ => e - } - } - private def foldDynamicShiftRight(e: DoPrim) = e.args.last match { case UIntLiteral(v, IntWidth(w)) => val shr = DoPrim(Shr, Seq(e.args.head), Seq(v), UnknownType) diff --git a/src/test/scala/firrtlTests/CompilerTests.scala b/src/test/scala/firrtlTests/CompilerTests.scala index df83dd38..dc70847a 100644 --- a/src/test/scala/firrtlTests/CompilerTests.scala +++ b/src/test/scala/firrtlTests/CompilerTests.scala @@ -158,19 +158,25 @@ class VerilogCompilerSpec extends CompilerSpec with Matchers { class MinimumVerilogCompilerSpec extends CompilerSpec with Matchers { val input = """|circuit Top: | module Top: - | output b: UInt<1>[2] - | node c = UInt<1>("h1") - | b[0] <= c - | b[1] is invalid + | output b: UInt<1>[3] + | node c = bits(UInt<3>("h7"), 2, 2) + | node d = shr(UInt<3>("h7"), 2) + | b[0] is invalid + | b[1] <= c + | b[2] <= d |""".stripMargin val check = """|module Top( | output b_0, - | output b_1 + | output b_1, + | output b_2 |); | wire c; + | wire d; | assign c = 1'h1; - | assign b_0 = c; - | assign b_1 = 1'h0; + | assign d = 1'h1; + | assign b_0 = 1'h0; + | assign b_1 = c; + | assign b_2 = d; |endmodule |""".stripMargin def compiler = new MinimumVerilogCompiler() -- cgit v1.2.3