Skip to content

Commit

Permalink
Merge pull request #1004 from seldridge/issue-423
Browse files Browse the repository at this point in the history
Add "mverilog" Compiler Option, MinimumVerilogEmitter
  • Loading branch information
seldridge authored Feb 5, 2019
2 parents fa0a6e2 + 0a88492 commit d69c609
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 38 deletions.
10 changes: 10 additions & 0 deletions src/main/scala/firrtl/Emitter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

}
26 changes: 16 additions & 10 deletions src/main/scala/firrtl/ExecutionOptionsManager.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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}"
}
Expand Down Expand Up @@ -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(
Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/firrtl/LoweringCompilers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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]] */
Expand Down
30 changes: 17 additions & 13 deletions src/main/scala/firrtl/passes/Passes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
22 changes: 11 additions & 11 deletions src/main/scala/firrtl/transforms/ConstantPropagation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down
32 changes: 32 additions & 0 deletions src/test/scala/firrtlTests/CompilerTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import firrtl.{
Compiler,
HighFirrtlCompiler,
MiddleFirrtlCompiler,
MinimumVerilogCompiler,
LowFirrtlCompiler,
Parser,
VerilogCompiler
Expand Down Expand Up @@ -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)
}
}
8 changes: 6 additions & 2 deletions src/test/scala/firrtlTests/DriverSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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 {
Expand Down

0 comments on commit d69c609

Please sign in to comment.