circt icon indicating copy to clipboard operation
circt copied to clipboard

[FIRRTL] Feature Request: Provide a similar `--target:fpga` behavior for FPGA-suited targets

Open carlosedp opened this issue 3 years ago • 2 comments

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).

carlosedp avatar Nov 02 '22 17:11 carlosedp

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"?

carlosedp avatar Jan 08 '24 17:01 carlosedp

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

carlosedp avatar Jan 08 '24 17:01 carlosedp