diff --git a/src/main/scala/firrtl/stage/FirrtlCli.scala b/src/main/scala/firrtl/stage/FirrtlCli.scala index 8be5fb74d4..9cfa6be9e5 100644 --- a/src/main/scala/firrtl/stage/FirrtlCli.scala +++ b/src/main/scala/firrtl/stage/FirrtlCli.scala @@ -22,7 +22,8 @@ trait FirrtlCli { this: Shell => NoCircuitDedupAnnotation, WarnNoScalaVersionDeprecation, PrettyNoExprInlining, - DisableFold + DisableFold, + OptimizeForFPGA ) .map(_.addOptions(parser)) diff --git a/src/main/scala/firrtl/stage/FirrtlCompilerTargets.scala b/src/main/scala/firrtl/stage/FirrtlCompilerTargets.scala new file mode 100644 index 0000000000..8029ea8731 --- /dev/null +++ b/src/main/scala/firrtl/stage/FirrtlCompilerTargets.scala @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 + +package firrtl.stage + +import firrtl.transforms._ +import firrtl.passes.memlib._ +import firrtl.options.{HasShellOptions, ShellOption} + +/** + * This flag enables a set of options that guide the FIRRTL compilation flow to ultimately + * generate Verilog that is more amenable to using for synthesized FPGA designs. Currently, this + * flag affects only memories, as the need to emit memories that support downstream inference of + * hardened RAM macros. These options are not intended to be specialized to any particular vendor; + * instead, they aim to emit simple Verilog that more closely reflects traditional human-written + * definitions of synchronous-read memories. + * + * 1) Allow some synchronous-read memories and readwrite ports to pass through VerilogMemDelays + * without introducing explicit pipeline registers or splitting ports. + * 2) Use the SimplifyMems transform to Lower aggregate-typed memories with always-high masks to + * packed memories without splitting. + * 3) Specify that memories with undefined read-under-write behavior should map to emitted + * microarchitectures characteristic of "read-first" ports by default. This eliminates the + * difficulty of inferring a RAM macro that matches the strict semantics of "write-first" ports. + * 4) Enable the InferReadWrite transform to reduce port count, where applicable. + */ +object OptimizeForFPGA extends HasShellOptions { + private val fpgaAnnos = Seq( + InferReadWriteAnnotation, + RunFirrtlTransformAnnotation(new InferReadWrite), + DefaultReadFirstAnnotation, + RunFirrtlTransformAnnotation(new SetDefaultReadUnderWrite), + RunFirrtlTransformAnnotation(new SimplifyMems), + PassthroughSimpleSyncReadMemsAnnotation + ) + val options = Seq( + new ShellOption[Unit]( + longOption = "target:fpga", + toAnnotationSeq = a => fpgaAnnos, + helpText = "Choose compilation strategies that generally favor FPGA targets" + ) + ) +}