circt
circt copied to clipboard
[FIRRTL] Feature Request: Provide a similar `--target:fpga` behavior for FPGA-suited targets
On FIRRTL, there is a command-line flag (currently --target:fpga) that applies some transformations better suited to FPGA targets. Details are in https://github.com/chipsalliance/firrtl/blob/master/src/main/scala/firrtl/stage/FirrtlCompilerTargets.scala
1) Enable the [[firrtl.passes.memlib.InferReadWrite]] transform to reduce port count, where applicable.
2) Use the [[firrtl.transforms.SimplifyMems]] transform to Lower aggregate-typed memories with always-high masks to
packed memories without splitting them into multiple independent ground-typed memories.
3) Use the [[firrtl.passes.memlib.SeparateWriteClocks]] transform to ensure that each write port of a
multiple-write, synchronous-read memory with 'undefined' collision behavior ultimately maps to a separate clocked
process in the emitted Verilog. This avoids the issue of implicitly constraining cross-port collision and write
ordering behavior and helps simplify inference of true dual-port RAM macros.
4) Use the [[firrtl.passes.memlib.SetDefaultReadUnderWrite]] to 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.
5) Add a [[firrtl.passes.memlib.PassthroughSimpleSyncReadMemsAnnotation]] to allow some synchronous-read memories
and readwrite ports to pass through [[firrtl.passes.memlib.VerilogMemDelays]] without introducing explicit
pipeline registers or splitting ports.
6) Add a [[firrtl.annotations.MemorySynthInit]] to enable memory initialization values to be synthesized.
Some transformations might be already implemented (or not required) on Circt while some like like memory initialization are still been worked on (https://github.com/llvm/circt/pull/4212).
I've been collecting some options that makes FPGA synthesis work fine as in:
ChiselStage.emitSystemVerilogFile(
new Toplevel(board, invreset, cpufreq),
chiselArgs.value.toArray,
Array(
"--strip-debug-info",
// Disables reg and memory randomization on initialization
"--disable-all-randomization",
// Creates memories with write masks in a single reg. Ref. https://github.com/llvm/circt/pull/4275
"--lower-memories",
// Avoids "unexpected TOK_AUTOMATIC" errors in Yosys. Ref. https://github.com/llvm/circt/issues/4751
"--lowering-options=disallowLocalVariables,disallowPackedArrays",
// Splits the generated Verilog into multiple files
"--split-verilog",
// Generates the Verilog files in the specified directory
"-o=./generated",
),
)
Maybe this could be a baseline for a "FPGA recipe"?
Also to have memory initialization on synthesis tool, passing a define in the synthesis is required (like -DENABLE_INITIAL_MEM_ in verilator or -Dname=ENABLE_INITIAL_MEM_ in Yosys.
Ref. https://github.com/llvm/circt/issues/4752#issuecomment-1696021770