diff options
| author | Schuyler Eldridge | 2019-02-05 14:57:53 -0500 |
|---|---|---|
| committer | GitHub | 2019-02-05 14:57:53 -0500 |
| commit | d69c609fd41c2b6ca2993085bcd2923daa563bde (patch) | |
| tree | 3d7a3bacd8debc917cd5525d6fdecdee6a50e31c /src | |
| parent | fa0a6e2cbe2a78fc231f47b5b73d870669b54ade (diff) | |
| parent | 0a88492bfbbfe7e446b74776ec59cab69e73585b (diff) | |
Merge pull request #1004 from seldridge/issue-423
Add "mverilog" Compiler Option, MinimumVerilogEmitter
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 10 | ||||
| -rw-r--r-- | src/main/scala/firrtl/ExecutionOptionsManager.scala | 26 | ||||
| -rw-r--r-- | src/main/scala/firrtl/LoweringCompilers.scala | 5 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/Passes.scala | 30 | ||||
| -rw-r--r-- | src/main/scala/firrtl/transforms/ConstantPropagation.scala | 22 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/CompilerTests.scala | 32 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/DriverSpec.scala | 8 |
7 files changed, 95 insertions, 38 deletions
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 ("<high|middle|low|verilog|sverilog|none>") + .valueName ("<high|middle|low|verilog|mverilog|sverilog|none>") .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..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) @@ -166,9 +167,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/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 348ed300..dc70847a 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,34 @@ 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>[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_2 + |); + | wire c; + | wire d; + | assign c = 1'h1; + | assign d = 1'h1; + | assign b_0 = 1'h0; + | assign b_1 = c; + | assign b_2 = d; + |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) + } +} 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 { |
