CIRCT

Circuit IR Compilers and Tools

Passes

This document describes the available CIRCT passes and their contracts.

Conversion Passes 

-calyx-native 

Callout to the Calyx native compiler and run a pass pipeline

This pass calls out to the native, Rust-based Calyx compiler to run passes with it and generate a new, valid, calyx dialect program.

Options 

-pass-pipeline : Passes to run with the native compiler

-calyx-remove-groups-fsm 

Perform FSM outlining and group removal

This pass will outline the FSM into module scope and replace any SSA value references from within the FSM body with additional inputs. Given this, the FSM is instantiated as a fsm.hw_module operation within the Calyx component. Using the FSM I/O (which is the group go/done signals), the calyx.group operations are removed from the component, with the group go and done signals being wired up to the FSM instance. Example:

calyx.component {
    %reg, ... = calyx.register ... : i1
    calyx.wires {
        // Groups have explicit done signals, and assignments are not guarded
        // by a group go signal.
        calyx.group @A {
            ...
            calyx.assign %reg = ...
            ...
            calyx.group_done %foo ? %bar
        }
    }
    calyx.control {
        // Machine is defined inside the `calyx.control` operation and references
        // SSA values defined outside the machine.
        fsm.machine @control(%A_done : i1) -> (%A_go : i1) {
            ...
            %0 = comb.not %reg // reference some SSA value defined outside the machine
            ...
        }
    }
}

into

// The machine has been outlined into module scope, and no longer references
// any SSA values defined outside the machine. It is now fully independent
// from any notion of Calyx.
fsm.machine @control(%A_done : i1, %reg : i1) -> (%A_go : i1) {
    ...
    %0 = comb.not %reg // reference some SSA value defined outside the machine
    ...
}

calyx.component {
    %reg, ... = calyx.register ...
    // Done signals are now wires
    %A_done_in, %A_done_out = calyx.wire : i1
    // The FSM is now instantiated as an `fsm.hwinstance` module
    %A_go = fsm.hwinstance @control(%A_done_out, %reg) : ...
    calyx.wires {
        // Groups have been inlined, the group go signal is now a guard for
        // all assignments, and `calyx.group_done` operations have been
        // replaced by wire assignments.
        ...
        calyx.assign %reg = %A_go ? ...
        ...
        calyx.assign %A_done_in = %foo ? %bar
    }
    calyx.control {
    }
}

-convert-affine-to-loopschedule 

Convert Affine dialect to LoopSchedule scheduled loops

This pass analyzes Affine loops and control flow, creates a Scheduling problem using the Calyx operator library, solves the problem, and lowers the loops to a LoopSchedule.

-convert-aig-to-comb 

Lower AIG ops to Comb ops

This pass converts AIG operations to Comb operations. This is mostly used for verifying post-synthesis results.

-convert-comb-to-aig 

Lower Comb ops to AIG ops.

Options 

-additional-legal-ops : Specify additional legal ops for testing

-convert-comb-to-arith 

Convert combinational ops and constants into arith ops

-convert-comb-to-smt 

Convert combinational ops and constants to SMT ops

-convert-fsm-to-sv 

Convert FSM to SV and HW

-convert-hw-to-btor2 

Convert HW to BTOR2

This pass converts a HW module into a state transition system that is then directly used to emit btor2. The output of this pass is thus a btor2 string.

-convert-hw-to-llvm 

Convert HW to LLVM

This pass translates HW to LLVM.

-convert-hw-to-smt 

Convert HW ops and constants to SMT ops

-convert-hw-to-systemc 

Convert HW to SystemC

This pass translates a HW design into an equivalent SystemC design.

-convert-moore-to-core 

Convert Moore to Core

This pass translates Moore to the core dialects.

-convert-to-arcs 

Outline logic between registers into state transfer arcs

This pass outlines combinational logic between registers into state transfer arc definitions. The the original combinational logic and register is replaced with an arc invocation, where the register is now represented as a latency.

Options 

-tap-registers : Make registers observable

-convert-verif-to-smt 

Convert Verif ops to SMT ops

-export-chisel-interface 

Emit a Chisel interface to a FIRRTL circuit

This pass generates a Scala Chisel interface for the top level module of a FIRRTL circuit.

-export-split-chisel-interface 

Emit a Chisel interface to a FIRRTL circuit to a directory of files

This pass generates a Scala Chisel interface for the top level module of a FIRRTL circuit.

Options 

-dir-name : Directory to emit into

-export-split-verilog 

Emit the IR to a (System)Verilog directory of files

This pass generates (System)Verilog for the current design, mutating it where necessary to be valid Verilog.

Options 

-dir-name : Directory to emit into

-export-verilog 

Emit the IR to a (System)Verilog file

This pass creates empty module bodies for external modules. This is useful for linting to eliminate missing file errors.

-handshake-remove-block-structure 

Remove block structure in Handshake IR

-hw-lower-instance-choices 

Prepare the collateral for instance choice emission

This pass runs as part of verilog emission. It introduces the macros & file lists to which instance choices lower to.

-legalize-anon-enums 

Prepare anonymous enumeration types for ExportVerilog

This pass transforms all anonymous enumeration types into typedecls to work around difference in how anonymous enumerations work in SystemVerilog.

-lower-arc-to-llvm 

Lower state transfer arc representation to LLVM

-lower-calyx-to-fsm 

Lower Calyx to FSM

This pass lowers a Calyx control schedule to an FSM representation. An fsm.machine operation is nested within the control region of the Calyx component. This machine is itself in an intermediate format wherein it has no I/O ports and solely contains output statements with calyx.enables referencing calyx.group and transition logic guarded by the SSA values specified in the source control schedule. This intermediate state facilitates transformation of the FSM, given that top-level I/O has yet to be materialized (one input and output per activated group) as well as guard transition logic (every transition must be guarded on all groups active within the state having finished). As such, calyx.enable operations can easily be moved between states without worrying about updating transition guards while doing so.

Eventually, the FSM must be materialized (materialize I/O ports, remove calyx.enable operations in favor of asserting output ports, guarding transitions by input done ports) and outlined to a separate module.

-lower-calyx-to-hw 

Lower Calyx to HW

This pass lowers Calyx to HW.

-lower-cf-to-handshake 

Lower func and CF into Handshake IR

Options 

-source-constants        : If true, will connect constants to source operations instead of to the control network. May reduce the size of the final circuit.
-disable-task-pipelining : If true, will disable support for task pipelining. This relaxes the restrictions put on the structure of the input CDFG. Disabling task pipelining may severely reduce kernel II.

-lower-dc-to-hw 

Lower DC to HW

Lower DC to ESI/hw/comb/seq operations. In case the IR contains DC operations that need to be clocked (fork, buffer), there must exist a clock and reset signal in the parent FunctionLike operation. These arguments are to be marked with a dc.clock and dc.reset attribute, respectively.

-lower-firrtl-to-hw 

Lower FIRRTL to HW

Lower a module of FIRRTL dialect to the HW dialect family.

Options 

-warn-on-unprocessed-annotations : Emit warnings on unprocessed annotations during lower-to-hw pass
-verification-flavor             : Specify a verification flavor used in the lowering

-lower-handshake-to-dc 

Lower Handshake to DC

Lower Handshake to DC operations. Currently, a handshake.func will be converted into a hw.module. This is principally an incorrect jump of abstraction - DC does not imply any RTL/hardware semantics. However, DC does not define a container operation, and there does not exist an e.g. func.graph_func which would be a generic function with graph region behaviour. Thus, for now, we just use hw.module as a container operation.

Options 

-clk-name : Name of the clock signal to use in the generated DC module
-rst-name : Name of the reset signal to use in the generated DC module

-lower-handshake-to-hw 

Lower Handshake to ESI/HW/Comb/Seq

Lower Handshake to ESI/HW/Comb/Seq.

-lower-hw-to-sv 

Convert HW to SV

This pass converts various HW contructs to SV.

-lower-hwarith-to-hw 

Lower HWArith to HW/Comb

This pass lowers HWArith to HW/Comb.

-lower-loopschedule-to-calyx 

Lower LoopSchedule to Calyx

This pass lowers LoopSchedule to Calyx.

Options 

-top-level-function             : Identifier of top-level function to be the entry-point component of the Calyx program.
-cider-source-location-metadata : Whether to track source location for the Cider debugger.

-lower-ltl-to-core 

Convert LTL and Verif to Core

This pass converts ltl and verif operations to core ones. This can be done directly without going through FSM if we’re only working with overlapping properties (no delays).

-lower-pipeline-to-hw 

Lower Pipeline to HW

This pass lowers pipeline.rtp operations to HW.

Options 

-clock-gate-regs       : Clock gate each register instead of (default) input muxing  (ASIC optimization).
-enable-poweron-values : Add power-on values to the pipeline control registers

-lower-scf-to-calyx 

Lower SCF/Standard to Calyx

This pass lowers SCF / standard to Calyx.

Options 

-top-level-function             : Identifier of top-level function to be the entry-point component of the Calyx program.
-cider-source-location-metadata : Whether to track source location for the Cider debugger.
-write-json                     : Whether to write memory contents to the json file.

-lower-seq-firmem 

Lower seq.firmem ops to instances of hw.module.generated ops

-lower-seq-to-sv 

Lower sequential firrtl ops to SV.

Options 

-disable-reg-randomization   : Disable emission of register randomization code
-disable-mem-randomization   : Disable emission of memory randomization code
-emit-separate-always-blocks : Emit assigments to registers in separate always blocks
-lower-to-always-ff          : Place assignments to registers into `always_ff` blocks if possible

Statistics 

num-subaccess-restored : Number of lhs subaccess operations restored 

-lower-sim-to-sv 

Lower simulator-specific sim ops to SV.

-lower-smt-to-z3-llvm 

Lower the SMT dialect to LLVM IR calling the Z3 API

Options 

-debug : Insert additional printf calls printing the solver's state to stdout (e.g. at check-sat operations) for debugging purposes

-lower-verif-to-sv 

Convert Verif to SV

This pass converts various Verif contructs to SV.

-materialize-calyx-to-fsm 

Materializes an FSM embedded inside the control of this Calyx component.

Materializes the FSM in the control of the component. This materializes the top-level I/O of the FSM to receive group_done signals as input and group_go signals as output, based on the calyx.enable operations used within the states of the FSM. Each transition of the FSM is predicated on the enabled groups within a state being done, or, for static groups, a separate sub-FSM is instantiated to await the group finishing.

Given an FSM that enables N unique groups, the top-level FSM will have N+1 in- and output ports, wherein:

  • Input # 0 to N-1 are group_done signals
  • Input N is the top-level go port
  • Output 0 to N-1 are group_go signals
  • Output N is the top-level done port

-prepare-for-emission 

Prepare IR for ExportVerilog

This pass runs only PrepareForEmission. It is not necessary for users to run this pass explicitly since ExportVerilog internally runs PrepareForEmission.

-test-apply-lowering-options 

Apply lowering options

This pass allows overriding lowering options. It is intended for test construction.

Options 

-options : Lowering Options

Arc Dialect Passes 

-arc-add-taps 

Add taps to ports and wires such that they remain observable

Options 

-ports        : Make module ports observable
-wires        : Make wires observable
-named-values : Make values with `sv.namehint` observable

-arc-allocate-state 

Allocate and layout the global simulation state

-arc-canonicalizer 

Simulation centric canonicalizations

Statistics 

num-arc-args-removed : Number of arguments removed from DefineOps

-arc-dedup 

Deduplicate identical arc definitions

This pass deduplicates identical arc definitions. If two arcs differ only by constants, the constants are outlined such that the arc can be deduplicated.

Statistics 

dedupPassNumArcsDeduped : Number of arcs deduped
dedupPassTotalOps       : Total number of ops deduped

-arc-find-initial-vectors 

Find initial groups of vectorizable ops

Statistics 

vectorizedOps       : Total number of ops that were vectorized
numOfSavedOps       : Total number of ops saved after FindInitialVectors pass
biggestSeedVector   : Size of the biggest seed vector
numOfVectorsCreated : Total number of VectorizeOps the pass inserted

-arc-infer-memories 

Convert FIRRTL_Memory instances to dedicated memory ops

Options 

-tap-ports    : Make memory ports observable
-tap-memories : Make memory contents observable

-arc-infer-state-properties 

Add resets and enables explicitly to the state operations

Options 

-enables : Infer enable signals
-resets  : Infer reset signals

Statistics 

added-enables  : Enables added explicitly to a StateOp
added-resets   : Resets added explicitly to a StateOp
missed-enables : Detected enables that could not be added explicitly to a StateOp
missed-resets  : Detected resets that could not be added explicitly to a StateOp

-arc-inline 

Inline very small arcs

Options 

-into-arcs-only : Call operations to inline
-max-body-ops   : Max number of non-trivial ops in the region to be inlined

Statistics 

inlined-arcs    : Arcs inlined at a use site
removed-arcs    : Arcs removed after full inlining
trivial-arcs    : Arcs with very few ops
single-use-arcs : Arcs with a single use

-arc-isolate-clocks 

Group clocked operations into clock domains

-arc-latency-retiming 

Push latencies through the design

Statistics 

num-ops-removed     : Number of zero-latency passthrough states removed
latency-units-saved : Number of latency units saved by merging them in a successor state

-arc-lower-arcs-to-funcs 

Lower arc definitions into functions

-arc-lower-clocks-to-funcs 

Lower clock trees into functions

-arc-lower-lut 

Lowers arc.lut into a comb and hw only representation.

-arc-lower-state 

Split state into read and write ops grouped by clock tree

-arc-lower-vectorizations 

Lower arc.vectorize operations

This pass lowers arc.vectorize operations. By default, the operation will be fully lowered (i.e., the op disappears in the IR). Alternatively, it can be partially lowered.

The “mode” pass option allows to only lower the boundary, only the body, or only inline the body given that both the boundary and the body are already lowered.

The pass supports vectorization within scalar registers and SIMD vectorization and prioritizes vectorization by packing the vector elements into a scalar value if it can fit into 64 bits.

Example:

hw.module @example(%in0: i8, %in1: i8, %in2: i8) -> (out0: i8, out1: i8) {
  %0:2 = arc.vectorize (%in0, %in1), (%in2, %in2) :
    (i8, i8, i8, i8) -> (i8, i8) {
  ^bb0(%arg0: i8, %arg1: i8):
    %1 = comb.and %arg0, %arg1 : i8
    arc.vectorize.return %1 : i8
  }
  hw.output %0#0, %0#1 : i8, i8
}

This piece of IR is lowered to the following fully vectorized IR:

hw.module @example(%in0: i8, %in1: i8, %in2: i8) -> (out0: i8, out1: i8) {
  %0 = comb.concat %in0, %in1 : i8, i8
  %1 = comb.concat %in2, %in2 : i8, i8
  %2 = comb.and %0, %1 : i16
  %3 = comb.extract %2 from 0 : (i16) -> i8
  %4 = comb.extract %2 from 8 : (i16) -> i8
  hw.output %3, %4 : i8, i8
}

Options 

-mode : Select what should be lowered.

-arc-make-tables 

Transform appropriate arc logic into lookup tables

-arc-merge-ifs 

Merge control flow structures

This pass optimizes control flow in a few ways. It moves operations closer to their earliest user, if possible sinking them into blocks if all uses are nested in the same block. It merges adjacent scf.if operations with the same condition. And it moves operations in between two scf.if operations ahead of the first if op to allow them to be merged. The pass runs on any SSACFG regions nested under the operation it is applied to.

Note that this pass assumes that !arc.state and !arc.memory values can never alias. That is, different values are assumed to never point to the same storage location in simulation memory.

Statistics 

sunk                   : Ops sunk into blocks
moved-to-user          : Ops moved to first user
ifs-merged             : Adjacent scf.if ops merged
moved-from-between-ifs : Ops moved from between ifs to enable merging
iterations             : Number of iterations until no more ops were sunk/merged

-arc-mux-to-control-flow 

Convert muxes with large independent fan-ins to if-statements

-arc-print-cost-model 

A dummy pass to test analysis passes

Statistics 

Operation(s)           : Number of operations in the module
Pack operations(s)     : Number of scalar to vector packking in the module
Shuffle operation(s)   : Number of shuffles done to set up the VectorizeOps
VectorizeOps Body Cost : Number of operations inside the body of the VectorizeOps
All VectorizeOps Cost  : Total Cost of all VectorizeOps in the module

-arc-simplify-variadic-ops 

Convert variadic ops into distributed binary ops

Statistics 

skipped-multiple-blocks : Ops skipped due to operands in different blocks
simplified              : Ops simplified into binary ops
created                 : Ops created as part of simplification
reordered               : Ops where simplification reordered operands

-arc-split-funcs 

Split large funcs into multiple smaller funcs

Options 

-split-bound : Size threshold (in ops) above which to split funcs

Statistics 

funcs-created : Number of new functions created

-arc-split-loops 

Split arcs to break zero latency loops

Statistics 

created : Arcs created during the splitting
removed : Arcs removed during the splitting

-arc-strip-sv 

Remove SV wire, reg, and assigns

Calyx Dialect Passes 

-calyx-clk-insertion 

Inserts assignments from component clock to sub-component clock.

-calyx-compile-control 

Generates latency-insensitive finite state machines to realize control.

This pass performs a bottom-up traversal of the control program and does the following:

  1. For each control statement such as “calyx.seq”, create a new GroupOp to contain all the structure to realize the schedule.
  2. Implement the schedule by setting the constituent groups’ GoOp and DoneOp.
  3. Replace the control statement in the control program with the corresponding compilation group.

-calyx-gicm 

Lift group-invariant operations to wire-scope.

This pass performs GICM (group-invariant code motion) of operations which are deemed to be invariant of the group in which they are placed. In practice, this amounts to anything which is not a calyx.group_done/assign/group_go operation. GICM’d operations are lifted to wire-scope.

After GICM, a Calyx component has the following properties:

  • No values are being defined within groups (excluding calyx.group_go). As such, groups will only contain group-level assignments (calyx.assign/group_done).
  • Any value referenced by operations within the group may safely be referenced by other groups, or operations in wire scope.
  • A group does not define anything structural; it exclusively describes wiring between existing structures.

-calyx-go-insertion 

Insert go signals into the guards of a group’s non-hole assignments

This pass inserts the operation “calyx.group_go” into the guards of all assignments housed in the group, with the exception of the “calyx.group_done” terminator. For example,

Before:

calyx.group @Group1 {
  calyx.assign %in = %out1, %guard ? : i8
  %done = calyx.group_done %out2 : i1
}

After:

// The `go` assignment takes on an undefined
// value until the Compile Control pass.
%undef = calyx.undef : i1
...
calyx.group @Group1 {
  %go = calyx.group_go %undef : i1

  %and = comb.and %guard, %go : i1
  calyx.assign %in = %out1, %and ? : i8

  %done = calyx.group_done %out2 : i1
}

-calyx-remove-comb-groups 

Removes combinational groups from a Calyx component.

Transforms combinational groups, which have a constant done condition, into proper groups by registering the values read from the ports of cells used within the combinational group.

It also transforms (invoke,if,while)-with into semantically equivalent control programs that first enable a group that calculates and registers the ports defined by the combinational group execute the respective cond group and then execute the control operator.

Example 

group comb_cond<"static"=0> {
    lt.right = 32'd10;
    lt.left = 32'd1;
    eq.right = r.out;
    eq.left = x.out;
    comb_cond[done] = 1'd1;
}
control {
    invoke comp(left = lt.out, ..)(..) with comb_cond;
    if lt.out with comb_cond {
        ...
    }
    while eq.out with comb_cond {
        ...
    }
}

into:

group comb_cond<"static"=1> {
    lt.right = 32'd10;
    lt.left = 32'd1;
    eq.right = r.out;
    eq.left = x.out;
    lt_reg.in = lt.out
    lt_reg.write_en = 1'd1;
    eq_reg.in = eq.out;
    eq_reg.write_en = 1'd1;
    comb_cond[done] = lt_reg.done & eq_reg.done ? 1'd1;
}
control {
    seq {
      comb_cond;
      invoke comp(left = lt_reg.out, ..)(..);
    }
    seq {
      comb_cond;
      if lt_reg.out {
          ...
      }
    }
    seq {
      comb_cond;
      while eq_reg.out {
          ...
          comb_cond;
      }
    }
}

-calyx-remove-groups 

Inlines the groups in a Calyx component.

This pass removes the Group interface from the Calyx program, and inlines all assignments. This is done in the following manner:

  1. Assign values to the ‘done’ signal of the component, corresponding with the top-level control group’s DoneOp. Add the ‘go’ signal of the component to all assignments.
  2. TODO(Calyx): If there are multiple writes to a signal, replace the reads with the disjunction.
  3. Remove all groups.

-calyx-reset-insertion 

Connect component reset to sub-component reset for applicable components.

Comb Dialect Passes 

-lower-comb 

Lowers the some of the comb ops

Some operations in the comb dialect (e.g. comb.truth_table) are not directly supported by ExportVerilog. They need to be lowered into ops which are supported. There are many ways to lower these ops so we do this in a separate pass. This also allows the lowered form to participate in optimizations like the comb canonicalizers.

DC Dialect Passes 

-dc-dematerialize-forks-sinks 

Dematerialize fork and sink operations.

This pass analyses a function-like operation and removes all fork and sink operations.

-dc-materialize-forks-sinks 

Materialize fork and sink operations.

This pass analyses a function-like operation and inserts fork and sink operations ensuring that all values have exactly one use.

-dc-print-dot 

Print .dot graph of a DC function.

This pass analyses a dc modulen and prints a .dot graph of the structure. If multiple functions are present in the IR, the top level function will be printed, and called functions will be subgraphs within the main graph.

ESI Dialect Passes 

-esi-appid-hier 

Build an AppID based hierarchy rooted at top module ’top’

Options 

-top : Root module of the instance hierarchy

-esi-build-manifest 

Build a manifest of an ESI system

Options 

-top : Root module of the instance hierarchy

-esi-clean-metadata 

Clean up ESI service metadata

-esi-connect-services 

Connect up ESI service requests to service providers

-lower-esi-bundles 

Lower ESI bundles to channels.

-lower-esi-ports 

Lower ESI input and/or output ports.

-lower-esi-to-hw 

Lower ESI to HW where possible and SV elsewhere.

Options 

-platform : Target this platform

-lower-esi-to-physical 

Lower ESI abstract Ops to ESI physical ops.

-lower-esi-types 

Lower ESI high level types.

-verify-esi-connections 

Verify that channels and bundles are only used once

FIRRTL Dialect Passes 

-firrtl-add-seqmem-ports 

Add extra ports to memory modules

This pass looks for AddSeqMemPortAnnotation annotations and adds extra ports to memories. It will emit metadata based if the AddSeqMemPortsFileAnnotation annotation is specified.

This pass requires that FIRRTL MemOps have been lowered to modules to add the extra ports.

Statistics 

num-added-ports : Number of extra ports added

-firrtl-advanced-layer-sink 

Sink operations into layer blocks

This pass sinks ops into layers, whenever possible, to minimize unused hardware in the design.

-firrtl-assign-output-dirs 

Assign output directories to modules.

While some modules are assigned output directories by the user, many modules “don’t care” what output directory they are placed into. This pass uses the instance graph to assign these modules to the “deepest” output directory possible.

Options 

-output-dir : The default output directory.

-firrtl-blackbox-reader 

Load source files for black boxes into the IR

This pass reads the Verilog source files for black boxes and adds them as sv.verbatim.file operations into the IR. Later passes can then write these files back to disk to ensure that they can be accessed by other tools down the line in a well-known location. Supports inline and path annotations for black box source files.

The supported firrtl.circuit annotations are:

  • {class = "firrtl.transforms.BlackBoxTargetDirAnno", targetDir = "..."} Overrides the target directory into which black box source files are emitted.
  • {class = "firrtl.transforms.BlackBoxResourceFileNameAnno", resourceFileName = "xyz.f"} Specifies the output file name for the list of black box source files that is generated as a collateral of the pass.

The supported firrtl.extmodule annotations are:

  • {
      class = "firrtl.transforms.BlackBoxInlineAnno",
      name = "myfile.v",
      text = "..."
    }
    
    Specifies the black box source code (text) inline. Generates a file with the given name in the target directory.
  • {
      class = "firrtl.transforms.BlackBoxPathAnno",
      path = "myfile.v"
    }
    
    Specifies the file path as source code for the module. Copies the file to the target directory.

Options 

-input-prefix : Prefix for input paths in black box annotations. This should be the directory where the input file was located, to allow for annotations relative to the input file.

-firrtl-check-comb-loops 

Check combinational cycles and emit errors

This pass checks combinational cycles in the IR and emit errors.

-firrtl-check-layers 

Check for illegal layers instantiated under layers

This pass checks for illegal instantiation of a module with a layer underneath another layer.

-firrtl-check-recursive-instantiation 

Check for illegal recursive instantiation

This pass checks for illegal recursive module instantion. Recursive instantiation is when a module instantiates itself, either directly or indirectly through other modules it instantiates. Recursive module instantiation is illegal because it would require infinite hardware to synthesize. Recursive class instantiation is illegal as it would create an infinite loop.

-firrtl-create-companion-assume 

Create companion assume statements for assertions

This pass generates companion assume statements gated by macros to assertions. If the assertion is UNR only one, a special form of assume (AssumeEdgedPredicateIntrinsicOp) is used. Otherwise a concurrent assume is used

-firrtl-dedup 

Deduplicate modules which are structurally equivalent

This pass detects modules which are structurally equivalent and removes the duplicate module by replacing all instances of one with the other. Structural equivalence ignores the naming of operations and fields in bundles, and any annotations. Deduplicating a module may cause the result type of instances to change if the field names of a bundle type change. To handle this, the pass will update any bulk-connections so that the correct fields are legally connected. Deduplicated modules will have their annotations merged, which tends to create many non-local annotations.

Statistics 

num-erased-modules : Number of modules which were erased by deduplication

-firrtl-drop-const 

Drop ‘const’ modifier from types

This pass drops the ‘const’ modifier from all types and removes all const-cast ops.

This simplifies downstream passes and folds so that they do not need to take ‘const’ into account.

-firrtl-drop-names 

Drop interesting names

This pass changes names of namable ops to droppable so that we can disable full name preservation. For example, before:

%a = firrtl.node interesting_name %input

after:

%a = firrtl.node droppable_name %input

Options 

-preserve-values : specify the values which can be optimized away

Statistics 

num-names-dropped   : Number of names dropped
num-names-converted : Number of interesting names made droppable

-firrtl-eliminate-wires 

Eliminate Unneeded Wires

This pass eliminates wires for which the write dominates the reads and for which there are no other preservation reasons.

Statistics 

num-erased-wires         : Number of wires erased
num-complex-wires        : Number of wires not erased due to complex writes
num-not-dominating-wires : Number of wires not erased due to dominance issues
num-not-passive-wires    : Number of wires not erased due to type issues

-firrtl-emit-metadata 

Emit metadata of the FIRRTL modules

This pass handles the emission of several different kinds of metadata.

Options 

-repl-seq-mem      : Lower the seq mem for macro replacement and emit relevant metadata
-repl-seq-mem-file : File to which emit seq meme metadata

-firrtl-expand-whens 

Remove all when conditional blocks.

This pass will:

  1. Resolve last connect semantics.
  2. Remove all when operations.

When a wire has multiple connections, only the final connection is used, all previous connections are overwritten. When there is a conditional connect, the previous connect is only overwritten when the condition holds:

w <= a
when c :
  w <= b

; Equivalent to:
w <= mux(c, b, a)

This pass requires that all connects are expanded.

-firrtl-extract-instances 

Move annotated instances upwards in the module hierarchy

This pass takes instances in the design annotated with one out of a particular set of annotations and pulls them upwards to a location further up in the module hierarchy.

The annotations that control the behaviour of this pass are:

  • MarkDUTAnnotation
  • ExtractBlackBoxAnnotation
  • ExtractClockGatesFileAnnotation

-firrtl-finalize-ir 

Perform final IR mutations after ExportVerilog

This pass finalizes the IR after it has been exported with ExportVerilog, and before firtool emits the final IR. This includes mutations like dropping verbatim ops that represent sideband files and are not required in the IR.

-firrtl-flatten-memory 

Flatten aggregate memory data to a UInt

This pass flattens the aggregate data of memory into a UInt, and inserts appropriate bitcasts to access the data.

Statistics 

num-flatten-mems : Number of memories flattened

-firrtl-grand-central 

Remove Grand Central Annotations

Processes annotations associated with SiFive’s Grand Central utility.

Options 

-companion-mode : specify the handling of companion modules

Statistics 

num-views-created       : Number of top-level SystemVerilog interfaces that were created
num-interfaces-created  : Number of SystemVerilog interfaces that were created
num-xmrs-created        : Number of SystemVerilog XMRs added
num-annotations-removed : Number of annotations removed

-firrtl-imconstprop 

Intermodule constant propagation and dead code elimination

Use optimistic constant propagation to delete ports and unreachable IR.

Statistics 

num-folded-op : Number of operations folded
num-erased-op : Number of operations erased

-firrtl-imdeadcodeelim 

Intermodule dead code elimination

This pass performs inter-module liveness analysis and deletes dead code aggressively. A value is considered as alive if it is connected to a port of public modules or a value with a symbol. We first populate alive values into a set, and then propagate the liveness by looking at their dataflow.

Statistics 

num-erased-ops     : Number of operations erased
num-erased-modules : Number of modules erased
num-removed-ports  : Number of ports erased

-firrtl-infer-resets 

Infer reset synchronicity and add implicit resets

This pass infers whether resets are synchronous or asynchronous, and extends reset-less registers with a reset based on the following annotations:

  • circt.FullResetAnnotation
  • circt.ExcludeFromFullResetAnnotation
  • sifive.enterprise.firrtl.FullAsyncResetAnnotation (deprecated)
  • sifive.enterprise.firrtl.IgnoreFullAsyncResetAnnotation (deprecated)

-firrtl-infer-rw 

Infer the read-write memory port

This pass merges the read and write ports of a memory, using a simple module-scoped heuristic. The heuristic checks if the read and write enable conditions are mutually exclusive. The heuristic tries to break up the read enable and write enable logic into an AND expression tree. It then compares the read and write AND terms, looking for a situation where the read/write is the complement of the write/read.

Statistics 

num-rw-port-mems-inferred : Number of memories inferred to use RW port

-firrtl-infer-widths 

Infer the width of types

This pass infers the widths of all types throughout a FIRRTL module, and emits diagnostics for types that could not be inferred.

-firrtl-inject-dut-hier 

Add a level of hierarchy outside the DUT

This pass takes the DUT (as indicated by the presence of a MarkDUTAnnotation) and moves all the contents of it into a new module insided the DUT named by an InjectDUTHierarchyAnnotation. This pass is intended to be used in conjunction with passes that pull things out of the DUT, e.g., SRAM extraction, to give the extracted modules a new home that is still inside the original DUT.

-firrtl-inliner 

Performs inlining, flattening, and dead module elimination

This inliner pass will inline any instance of module marked as inline, and recursively inline all instances inside of a module marked with flatten. This pass performs renaming of every entity with a name that is inlined by prefixing it with the instance name. This pass also will remove any module which is not reachable from the top level module.

The inline and flatten annotation attributes are attached to module definitions, and they are:

  {class = "firrtl.passes.InlineAnnotation"}
  {class = "firrtl.transforms.FlattenAnnotation"}

-firrtl-inner-symbol-dce 

Eliminate dead inner symbols

This pass deletes all inner symbols which have no uses. This is necessary to unblock optimizations and removal of the operations which have these unused inner symbols.

Statistics 

num-inner-refs-found  : Number of inner-refs found
num-inner-sym-found   : Number of inner symbols found
num-inner-sym-removed : Number of inner symbols removed

-firrtl-layer-merge 

Merge layer blocks

Combine all layer blocks in a module which reference the same layer definition.

Statistics 

num-merged : Number of layers merged

-firrtl-layer-sink 

Sink operations into layer blocks

Statistics 

num-sunk : Number of operations sunk

-firrtl-lint 

An analysis pass to detect static simulation failures.

This pass detects operations that will trivially fail any simulation. Currently it detects assertions whose predicate condition can be statically inferred to be false. The pass emits error on such failing ops.

-firrtl-lower-annotations 

Lower FIRRTL annotations to usable entities

Lower FIRRTL annotations to usable forms. FIRRTL annotations are a big bag of semi-structured, irregular JSON. This pass normalizes all supported annotations and annotation paths.

Options 

-disable-annotation-classless         : Ignore classless annotations.
-disable-annotation-unknown           : Ignore unknown annotations.
-no-ref-type-ports                    : Create normal ports, not ref type ports.
-allow-adding-ports-on-public-modules : Allow public modules to gain additional ports as a result of wiring.

Statistics 

num-raw-annos          : Number of raw annotations on circuit
num-added-annos        : Number of additional annotations
num-annos              : Total number of annotations processed
num-unhandled-annos    : Number of unhandled annotations
num-reused-hierpath    : Number of reused HierPathOp's
num-public-ports-wired : Number of ports on public modules added due to wiring

-firrtl-lower-chirrtl 

Infer the memory ports of SeqMem and CombMem

This pass finds the CHIRRTL behavioral memories and their ports, and transforms them into standard FIRRTL memory operations. For each seqmem or combmem, a new memory is created. For every memoryport operation using a CHIRRTL memory, a memory port is defined on the new standard memory.

The direction or kind of the port is inferred from how each of the memory ports is used in the IR. If a memory port is only written to, it becomes a Write port. If a memory port is only read from, it become a Read port. If it is used both ways, it becomes a ReadWrite port.

Write, ReadWrite and combinational Read ports are disabled by default, but then enabled when the CHIRRTL memory port is declared. Sequential Read ports have more complicated enable inference:

  1. If a wire or register is used as the index of the memory port, then the memory is enabled whenever a non-invalid value is driven to the address.
  2. If a node is used as the index of the memory port, then the memory is enabled at the declaration of the node.
  3. In all other cases, the memory is never enabled.

In the first two cases, they can easily produce a situation where we try to enable the memory before it is even declared. This produces a compilation error.

Statistics 

num-created-mems  : Number of memories created
num-lowered-mems  : Number of memories lowered
num-portless-mems : Number of memories dropped as having no valid ports

-firrtl-lower-classes 

Lower FIRRTL classes and objects to OM classes and objects

This pass walks all FIRRTL classes and creates OM classes. It also lowers FIRRTL objects to OM objects. OM classes are created with parameters corresponding to FIRRTL input properties, and OM class fields corresponding to FIRRTL output properties. FIRRTL operations are converted to OM operations.

-firrtl-lower-dpi 

Lower DPI intrinsic into Sim DPI operations

-firrtl-lower-intmodules 

Lower instances instances of intrinsic modules to ops.

This pass replaces instances of intrinsic modules (intmodule) with firrtl.int.generic operations, and removes the intmodule’s from the circuit.

Use this before running LowerIntrinsics.

Options 

-fixup-eicg-wrapper : Lower `EICG_wrapper` modules into clock gate intrinsics

Statistics 

num-instances  : Number of intmodules instances lowered
num-intmodules : Number of intmodules lowered

-firrtl-lower-intrinsics 

Lower intrinsics

This pass lowers generic intrinsic ops to their implementation or op.

Statistics 

num-converted : Number of intrinsic operations lowered

-firrtl-lower-layers 

Lower layers and layer blocks to instances

This pass lowers FIRRTL layers as defined by their convention. After this pass, all layer blocks and layers are removed.

-firrtl-lower-matches 

Remove all matchs conditional blocks

Lowers FIRRTL match statements in to when statements, which can later be lowered with ExpandWhens.

-firrtl-lower-memory 

Lower memories to generated modules

This pass lowers FIRRTL memory operations to generated modules.

Statistics 

num-created-mem-modules : Number of modules created
num-lowered-mems        : Number of memories lowered

-firrtl-lower-open-aggs 

Lower ‘Open’ aggregates by splitting out non-hardware elements

This pass lowers aggregates of the more open varieties into their equivalents using only hardware types, by pulling out non-hardware to other locations.

-firrtl-lower-signatures 

Lower FIRRTL module signatures

Lower aggregate FIRRTL types in Modules as indicated by the calling convention.

-firrtl-lower-types 

Lower FIRRTL types to ground types

Lower aggregate FIRRTL types to ground types. Memories, ports, wires, etc are split apart by elements of aggregate types. The only aggregate types which exist after this pass are memory ports, though memory data types are split.

Connect and expansion and canonicalization happen in this pass.

Options 

-flatten-mem        : Concat all elements of the aggregate data into a single element.
-preserve-aggregate : Specify aggregate preservation mode
-preserve-memories  : Specify memory preservation mode

-firrtl-lower-xmr 

Lower ref ports to XMR

This pass lowers RefType ops and ports to verbatim encoded XMRs.

-firrtl-materialize-debug-info 

Generate debug ops to track FIRRTL values

This pass creates debug ops to track FIRRTL-level ports, nodes, wires, registers, and instances throughout the pipeline. The DebugInfo analysis can then be used at a later point in the pipeline to obtain a source language view into the lowered IR.

-firrtl-mem-to-reg-of-vec 

Convert combinational memories to a vector of registers

This pass generates the logic to implement a memory using Registers.

Options 

-repl-seq-mem           : Prepare seq mems for macro replacement
-ignore-read-enable-mem : ignore the read enable signal, instead of assigning X on read disable

Statistics 

num-converted-mems : Number of memories converted to registers

-firrtl-module-summary 

Print a summary of modules.

The pass produces a summary of modules.

-firrtl-passive-wires 

Make FIRRTL wires have passive type

Eliminate flips from aggregate types on wires.

-firrtl-print-field-source 

Print field source information.

-firrtl-print-instance-graph 

Print a DOT graph of the module hierarchy.

-firrtl-print-nla-table 

Print the NLA Table.

-firrtl-probes-to-signals 

Convert probes to signals.

This pass transforms the design to replace probes with non-probe signals that are explicitly routed through the design instead of remote access. The result will not be ABI-compatible but provide similar behavior without the use of potentially unsynthesizable cross-module references.

The pass will do a complete conversion or produce an error.

Not all FIRRTL designs with probes can be equivalently represented with non-probes.

Run after LowerOpenAggs, ExpandWhens (so ref.define can always be replaced), and any colored probes are removed through specialization.

Due to differences in width and reset inference, it is suggested to run those first as well but not required.

RWProbes and related operations are not supported.

-firrtl-randomize-register-init 

Randomize register initialization.

This pass eagerly creates large vectors of randomized bits for initializing registers, and marks each register with attributes indicating which bits to read. If the registers survive until LowerToHW, their initialization logic will pick up the correct bits.

This ensures a stable initialization, so registers should always see the same initial value for the same seed, regardless of optimization levels.

-firrtl-register-optimizer 

Optimizer Registers

This pass applies classic FIRRTL register optimizations. These optimizations are isolated to this pass as they can change the visible behavior of the register, especially before reset.

-firrtl-remove-unused-ports 

Remove unused ports

This pass removes unused ports without annotations or symbols. Implementation wise, this pass iterates over the instance graph in a topological order from leaves to the top so that we can remove unused ports optimally.

Statistics 

num-removed-ports : Number of ports erased

-firrtl-resolve-paths 

Lowers UnresolvedPathOps to PathOps

FIRRTL path operations are initially create as unresolved path operations, which encode their target as a string. This pass parses and resolves those target strings to actual path operations. Path operations refer to their targets using annotations with a unique identifier.

-firrtl-resolve-traces 

Write out TraceAnnotations to an output annotation file

This pass implements Chisel’s Trace API. It collects all TraceAnnotations that exist in the circuit, updates them with information about the final target in a design, and writes these to an output annotation file. This exists for Chisel users to build tooling around them that needs to query the final output name/path of some component in a Chisel circuit.

Note: this pass and API are expected to be eventually replaced via APIs and language bindings that enable users to directly query the MLIR.

Options 

-file : Output file for the JSON-serialized Trace Annotations

-firrtl-sfc-compat 

Perform SFC Compatibility fixes

-firrtl-specialize-layers 

Specialize a configurable design for a given layer

This pass performs specialization of layers, layerblocks, and probe operations by permanantly enabling or disabling layers. The layers are specified by attributes on the firrtl.circuit operation in the enable_layers and disable_layers attributes which are both lists of SymbolRefAttrs. When a layer is specialized, it will be removed from the circuit and all references to it should be cleaned up. If a layer is disabled, all layerblock are referencing that layer will be deleted, and all probe colored by that layer will be removed. When a layer is enabled, all contents of the layer will be inlined in to the outer context, and probes colored by that layer will no longer be colored.

-firrtl-specialize-option 

Specialize a configurable design for a given option.

If the design has option groups, instead of preserving the information up to the emitted SystemVerilog, this pass specializes it early on for a given choice.

Options 

-select-default-for-unspecified-instance-choice : Specialize instance choice to default, if no option selected.

Statistics 

num-instances : Number of instances specialized

-firrtl-vb-to-bv 

Transform vector-of-bundles to bundle-of-vectors

This pass converts vectors containing bundles, into bundles containing vectors.

-merge-connections 

Merge field-level connections into full bundle connections

Options 

-aggressive-merging : Merge connections even when source values won't be simplified.

-vectorization 

Transform firrtl primitive operations into vector operations

FSM Dialect Passes 

-fsm-print-graph 

Print a DOT graph of an FSM’s structure.

Handshake Dialect Passes 

-handshake-add-ids 

Add an ID to each operation in a handshake function.

This pass adds an ID to each operation in a handshake function. This id can be used in lowerings facilitate mapping lowered IR back to the handshake code which it originated from. An ID is unique with respect to other operations of the same type in the function. The tuple of the operation name and the operation ID denotes a unique identifier for the operation within the handshake.func operation.

-handshake-dematerialize-forks-sinks 

Dematerialize fork and sink operations.

This pass analyses a handshake.func operation and removes all fork and sink operations.

-handshake-insert-buffers 

Insert buffers to break graph cycles

Options 

-strategy    : Strategy to apply. Possible values are: cycles, allFIFO, all (default)
-buffer-size : Number of slots in each buffer

-handshake-legalize-memrefs 

Memref legalization and lowering pass.

Lowers various memref operations to a state suitable for passing to the CFToHandshake lowering.

-handshake-lock-functions 

Lock each function to only allow single invocations.

This pass adds a locking mechanism to each handshake function. This mechanism ensures that only one control token can be active in a function at each point in time.

-handshake-lower-extmem-to-hw 

Lowers handshake.extmem and memref inputs to ports.

Lowers handshake.extmem and memref inputs to a hardware-targeting memory accessing scheme (explicit load- and store ports on the top level interface).

Options 

-wrap-esi : Create an ESI wrapper for the module. Any extmem will be served by an esi.mem.ram service

-handshake-materialize-forks-sinks 

Materialize fork and sink operations.

This pass analyses a handshake.func operation and inserts fork and sink operations ensuring that all values have exactly one use.

-handshake-op-count 

Count the number of operations (resources) in a handshake function.

This pass analyses a handshake.func operation and prints the number of operations (resources) used the function.

-handshake-print-dot 

Print .dot graph of a handshake function.

This pass analyses a handshake.func operation and prints a .dot graph of the structure. If multiple functions are present in the IR, the top level function will be printed, and called functions will be subgraphs within the main graph.

-handshake-remove-buffers 

Remove buffers from handshake functions.

This pass analyses a handshake.func operation and removes any buffers from the function.

-handshake-split-merges 

Deconstruct >2 input merge operations into 2-input merges

This pass deconstructs the (rather complex) semantics of a >2 input merge and control merge operation into a series of 2-input merge operations + supporting logic.

HW Dialect Passes 

-hw-flatten-io 

Flattens hw::Structure typed in- and output ports.

Options 

-recursive      : Recursively flatten nested structs.
-flatten-extern : Flatten the extern modules also.
-join-char      : Use a custom character to construct the flattened names.

-hw-flatten-modules 

Eagerly inline private modules

This pass eagerly inlines private HW modules into their instantiation sites. This is necessary for verification purposes, as model checking backends do not require or support the use of module hierarchy. For simulation, module hierarchies degenerate into a purely cosmetic construct, at which point it is beneficial to fully flatten the module hierarchy to simplify further analysis and optimization of state transfer arcs.

-hw-foo-wires 

Change all wires’ name to foo._

Very basic pass that numbers all of the wires in a given module. The wires’ names are then all converte to foo_.

-hw-print-instance-graph 

Print a DOT graph of the module hierarchy.

-hw-print-module-graph 

Print a DOT graph of the HWModule’s within a top-level module.

Options 

-verbose-edges : Print information on SSA edges (types, operand #, ...)

-hw-specialize 

Specializes instances of parametric hw.modules

Any hw.instance operation instantiating a parametric hw.module will trigger a specialization procedure which resolves all parametric types and values within the module based on the set of provided parameters to the hw.instance operation. This specialized module is created as a new hw.module and the referring hw.instance operation is rewritten to instantiate the newly specialized module.

-hw-verify-irn 

Verify InnerRefNamespaceLike operations, if not self-verifying.

Kanagawa Dialect Passes 

-kanagawa-add-operator-library 

Injects the Kanagawa operator library into the IR

Injects the Kanagawa operator library into the IR, which contains the definitions of the Kanagawa operators.

-kanagawa-argify-blocks 

Add arguments to kanagawa blocks

Analyses kanagawa.sblock operations and converts any SSA value defined outside the kanagawa.sblock to a block argument. As a result, kanagawa.sblock.isolated are produced.

-kanagawa-call-prep 

Convert kanagawa method calls to use dc.value

-kanagawa-clean-selfdrivers 

Kanagawa clean selfdrivers pass

  • Removes kanagawa.port.inputs which are driven by operations within the same container.
  • Removes reads of instance ports which are also written to within the same container.

-kanagawa-containerize 

Kanagawa containerization pass

Convert Kanagawa classes to containers, and outlines containers inside classes.

-kanagawa-convert-cf-to-handshake 

Converts an kanagawa.method to kanagawa.method.df

Converts an kanagawa.method from using cf operations and MLIR blocks to an kanagawa.method.df operation, using the handshake dialect to represent control flow through the handshake fine grained dataflow operations.

-kanagawa-convert-containers-to-hw 

Kanagawa containers to hw conversion pass

Converts kanagawa.container ops to hw.module ops.

-kanagawa-convert-handshake-to-dc 

Converts an kanagawa.method.df to use DC

Converts an kanagawa.method.df from using handshake operations to dc operations.

-kanagawa-convert-methods-to-containers 

Converts kanagawa.method.df to kanagawa.containers

-kanagawa-inline-sblocks 

Inlines kanagawa.sblock operations as MLIR blocks

Inlines kanagawa.sblock operations, by creating MLIR blocks and cf operations, while adding attributes to the parent operation about sblock-specific attributes.

The parent attributes are located under the kanagawa.blockinfo identifier as a dictionary attribute. Each entry in the dictionary consists of:

  • Key: an ID (numerical) string identifying the block.
  • Value: a dictionary of attributes. As a minimum this will contain a loc-keyed attribute specifying the location of the block.

-kanagawa-lower-portrefs 

Kanagawa portref lowering pass

Lower kanagawa.portref<portref <T>> to T (i.e. portref resolution).

We do this by analyzing how a portref is used inside a container, and then creating an in- or output port based on that. That is:

  • write to portref<in portref<in, T>> becomes out T i.e this container wants to write to an input of another container, hence it will produce an output value that will drive that input port.
  • read from portref<in portref<out, T>> becomes in T i.e. this container wants to read from an output of another container, hence it will have an input port that will be driven by that output port.
  • write to portref<out portref<out, T>> becomes out T i.e. a port reference inside the module will be driven by a value from the outside.
  • read from portref<out portref<in, T>> becomes in T i.e. a port reference inside the module will be driven by a value from the outside.

A benefit of having portref lowering separate from portref tunneling is that portref lowering can be done on an kanagawa.container granularity, allowing for a bit of parallelism in the flow.

-kanagawa-prepare-scheduling 

Prepare kanagawa.sblock operations for scheduling

Prepares kanagawa.sblock operations for scheduling by:

  • creating an kanagawa.pipleine.header operation
  • moving operations of an kanagawa.sblock into a pipeline.unscheduled operation, which is connected to the pipeline header.

-kanagawa-reblock 

Recreates kanagawa.sblock operations from a CFG

Recreates kanagawa.sblock operations from a CFG. Any kanagawa.block.attributes operations at the parent operation will be added to the resulting blocks.

The IR is expected to be in maximal SSA form prior to this pass, given that the pass will only inspect the terminator operation of a block for any values that are generated within the block. Maximum SSA form thus ensures that any value defined within the block is never used outside of the block.

It is expected that kanagawa.call operations have been isolated into their own basic blocks before this pass is run. This implies that all operations within a block (except for the terminator operation) can be statically scheduled with each other.

e.g.

^bb_foo(%arg0 : i32, %arg1 : i32):
  %res = arith.addi %arg0, %arg1 : i32
  %v = ...
  cf.br ^bb_bar(%v : i32)

becomes

^bb_foo(%arg0 : i32, %arg1 : i32):
  %v_outer = kanagawa.sblock(%a0 : i32 = %arg0, %a1 : i32 = %arg1) -> (i32) {
    %res = arith.addi %arg0, %arg1 : i32
    %v = ...
    kanagawa.sblock.return %v : i32
  }
  cf.br ^bb_bar(%v_outer : i32)

-kanagawa-tunneling 

Kanagawa tunneling pass

Tunnels relative get_port ops through the module hierarchy, based on kanagawa.path ops. The result of this pass is that various new in- and output ports of !kanagawa.portref<...> type are created. After this pass, get_port ops should only exist at the same scope of container instantiations.

The user may provide options for readSuffix and writeSuffix, respectively, which is to be used to generate the name of the ports that are tunneled through the hierarchy, with respect to how the port was requested to be accessed. Suffixes must be provided in cases where a port is tunneled for both read and write accesses, and the suffixes must be different (in this case, the suffixes will be appended to the target port name, and thus de-alias the resulting ports).

Options 

-read-suffix  : Suffix to be used for the port when a port is tunneled for read access
-write-suffix : Suffix to be used for the port when a port is tunneled for write access

LLHD Dialect Passes 

-llhd-desequentialize 

Convert sequential processes to registers

Analyzes the drive conditions of all drives in sequential processes and tries to convert them to registers. This is not always possible because a process might consist of more than two temporal regions, or the drive condition might depend on values sampled in the past that are not a clock, or the condition depends on the conjunction of two clocks which is not supported by regular registers, etc. If all drives in a process were successfully lowered to registers, the process is inlined into the surrounding module.

Options 

-max-primitives : The maximum number of primitives to analyze.

-llhd-early-code-motion 

Move side-effect-free instructions and llhd.prb up in the CFG

Moves side-effect-free instructions as far up in the CFG as possible. That means to the earliest block where all operands are defined. Special care has to be given to the llhd.prb instruction (which is the only side-effect instruction moved by this pass) as it must stay in the same temporal region, because otherwise it might sample an older or newer state of the signal. This pass is designed as a preparatory pass for the Temporal Code Motion pass to be able to move the llhd.drv operations in a single TR exiting block without having to move operations defining the operands used by the llhd.drv. It also enables total control flow elimination as the llhd.prb instructions would not be moved by other canonicalization passes.

-llhd-function-elimination 

Deletes all functions.

Deletes all functions in the module. In case there is still a function call in an entity or process, it fails. This pass is intended as a post-inlining pass to check if all functions could be successfully inlined and remove the inlined functions. This is necessary because Structural LLHD does not allow functions. Fails in the case that there is still a function call left in a llhd.process or hw.module.

-llhd-memory-to-block-argument 

Promote memory to block arguments.

Promotes memory locations allocated with llhd.var to block arguments. This enables other optimizations and is required to be able to lower behavioral LLHD to structural LLHD. This is because there are no memory model and control flow in structural LLHD. After executing this pass, the “-llhd-block-argument-to-mux” pass can be used to convert the block arguments to multiplexers to enable more control-flow elimination.

Example:

llhd.process {
  %c5 = hw.constant 5 : i32
  %cond = llhd.prb %condsig : !hw.inout<i1>
  %ptr = llhd.var %c5 : i32
  cond_br %cond, ^bb1, ^bb2
^bb1:
  %c6 = hw.constant 6 : i32
  llhd.store %ptr, %c6 : !llhd.ptr<i32>
  br ^bb2
^bb2:
  %ld = llhd.load %ptr : !llhd.ptr<i32>
  %c-1_i32 = hw.constant -1 : i32
  %res = comb.xor %ld, %c-1_i32 : i32
  llhd.halt
}

is transformed to

llhd.process {
  %c5 = hw.constant 5 : i32
  %cond = llhd.prb %condsig : !hw.inout<i1>
  cond_br %cond, ^bb1, ^bb2(%c5 : i32)
^bb1:
  %c6 = hw.constant 6 : i32
  br ^bb2(%c6 : i32)
^bb2(%arg : i32):
  %c-1_i32 = hw.constant -1 : i32
  %res = comb.xor %arg, %c-1_i32 : i32
  llhd.halt
}

-llhd-process-lowering 

Lowers LLHD Processes to Entities.

TODO

-llhd-sig2reg 

Promote LLHD signals to SSA values

-llhd-temporal-code-motion 

Move drive operations to the exit basic block in processes

This pass uses the temporal region analysis to transform the IR such that every temporal region has a unique exit block and moves all ’llhd.drv’ operations in a temporal region into its exit block by adjusting the enable operand. Furthermore, it combines ’llhd.drv’ operations driving the same signal with the same delay by multiplexing the driven value according to their enable operands. This pass assumes that the early code motion pass has been run beforehand. Otherwise, dominance errors are to be expected.

MSFT Dialect Passes 

-msft-export-tcl 

Create tcl ops

Options 

-tops     : List of top modules to export Tcl for
-tcl-file : File to output Tcl into

-msft-lower-constructs 

Lower high-level constructs

-msft-lower-instances 

Lower dynamic instances

OM Dialect Passes 

-om-freeze-paths 

Hard code all path information

Replaces paths to hardware with hard-coded string paths. This pass should only run once the hierarchy will no longer change, and the final names for objects have been decided.

Link separated OM modules into a single module

Flatten nested modules and resolve external classes.

-om-verify-object-fields 

Verify fields of ObjectOp are valid

Verify object fields are valid.

Pipeline Dialect Passes 

-pipeline-explicit-regs 

Makes stage registers explicit.

Makes all stage-crossing def-use chains into explicit registers.

-pipeline-schedule-linear 

Schedules pipeline.unscheduled operations.

Schedules pipeline.unscheduled operations based on operator latencies.

Seq Dialect Passes 

-externalize-clock-gate 

Convert seq.clock_gate ops into hw.module.extern instances

Options 

-name          : Name of the external clock gate module
-input         : Name of the clock input
-output        : Name of the gated clock output
-enable        : Name of the enable input
-test-enable   : Name of the optional test enable input
-instance-name : Name of the generated instances

Statistics 

num-clock-gates-converted : Number of clock gates converted to external module instances

-hw-memory-sim 

Implement FIRRTMMem memories nodes with simulation model

This pass replaces generated module nodes of type FIRRTLMem with a model suitable for simulation.

Options 

-disable-mem-randomization                                : Disable emission of memory randomization code
-disable-reg-randomization                                : Disable emission of register randomization code
-repl-seq-mem                                             : Prepare seq mems for macro replacement
-read-enable-mode                                         : specify the behaviour of the read enable signal
-add-mux-pragmas                                          : Add mux pragmas to memory reads
-add-vivado-ram-address-conflict-synthesis-bug-workaround : Add a vivado attribute to specify a ram style of an array register

-lower-seq-fifo 

Lower seq.fifo ops

-lower-seq-hlmem 

Lowers seq.hlmem operations.

-lower-seq-shiftreg 

Lower seq.shiftreg ops

Default pass for lowering shift register operations. This will lower into a chain of seq.compreg.ce operations. Note that this is not guaranteed to be a performant implementation, but instead a default, fallback lowering path which is guaranteed to provide a semantically valid path to verilog emissions. Users are expected to provide a custom lowering pass to maps seq.shiftreg operations to target-specific primitives.

SSP Dialect Passes 

-ssp-print 

Prints all SSP instances as DOT graphs.

-ssp-roundtrip 

Roundtrips all SSP instances via the scheduling infrastructure

Options 

-check  : Check the problem's input constraints.
-verify : Verify the problem's solution constraints.

-ssp-schedule 

Schedules all SSP instances.

Options 

-scheduler : Scheduling algorithm to use.
-options   : Scheduler-specific options.

SV Dialect Passes 

-hw-cleanup 

Cleanup transformations for operations in hw.module bodies

This pass merges sv.alwaysff operations with the same condition, sv.ifdef nodes with the same condition, and perform other cleanups for the IR. This is a good thing to run early in the HW/SV pass pipeline to expose opportunities for other simpler passes (like canonicalize).

Options 

-merge-always-blocks : Allow always and always_ff blocks to be merged

-hw-eliminate-inout-ports 

Raises usages of inout ports into explicit input and output ports

This pass raises usages of inout ports into explicit in- and output ports. This is done by analyzing the usage of the inout ports and creating new input and output ports at the using module, and subsequently moving the inout read- and writes to the instantiation site.

Options 

-read-suffix  : Suffix to be used for the port when the inout port has readers
-write-suffix : Suffix to be used for the port when the inout port has writers

-hw-export-module-hierarchy 

Export module and instance hierarchy information

This pass exports the module and instance hierarchy tree for each module with the firrtl.moduleHierarchyFile attribute. These are lowered to sv.verbatim ops with the output_file attribute.

-hw-generator-callout 

Lower Generator Schema to external module

This pass calls an external program for all the hw.module.generated nodes, following the description in the hw.generator.schema node.

Options 

-schema-name                    : Name of the schema to process
-generator-executable           : Generator program executable with optional full path
-generator-executable-arguments : Generator program arguments separated by ;

-hw-legalize-modules 

Eliminate features marked unsupported in LoweringOptions

This pass lowers away features in the SV/Comb/HW dialects that are unsupported by some tools, e.g. multidimensional arrays. This pass is run relatively late in the pipeline in preparation for emission. Any passes run after this must be aware they cannot introduce new invalid constructs.

-hw-stub-external-modules 

Transform external hw modules to empty hw modules

This pass creates empty module bodies for external modules. This is useful for linting to eliminate missing file errors.

-prettify-verilog 

Transformations to improve quality of ExportVerilog output

This pass contains elective transformations that improve the quality of SystemVerilog generated by the ExportVerilog library. This pass is not compulsory: things that are required for ExportVerilog to be correct should be included as part of the ExportVerilog pass itself to make sure it is self contained.

-sv-extract-test-code 

Extract simulation only constructs to modules and bind

This pass extracts cover, assume, assert operations to a module, along with any ops feeding them only, to modules which are instantiated with a bind statement.

Options 

-disable-instance-extraction : Disable extracting instances only that feed test code
-disable-register-extraction : Disable extracting registers only that feed test code
-disable-module-inlining     : Disable inlining modules that only feed test code

Statistics 

num-ops-extracted : Number of ops extracted
num-ops-erased    : Number of ops erased

-sv-trace-iverilog 

Add tracing to an iverilog simulated module

This pass adds the necessary instrumentation to a HWModule to trigger tracing in an iverilog simulation.

Options 

-top-only : If true, will only add tracing to the top-level module.
-module   : Module to trace. If not provided, will trace all modules
-dir-name : Directory to emit into

SystemC Dialect Passes 

-systemc-lower-instance-interop 

Lower all SystemC instance interop operations.