https://llvm.discourse.group/t/rfc-representing-pipelined-loops/4171/1
for more discussion.
This defines the operation's syntax more or less as discussed,
including round-trip tests for the five running examples we've had.
In order to reduce test churn, the existing PipelineOp and the
StandardToStaticLogic pass are left untouched for now. Ultimately, the
new pipeline operation could replace the existing PipelineOp.
The verbatim op can be used for macro substitution with values. This PR adds
support for macro substitution with symbols.
For example,
```mlir
sv.verbatim "MACRO({{0}}, {{1}} reg={{4}}, {{3}})"
(%add, %xor) : i8,i8
{symbols= [@reg1, @module1, @instance1]}
```
In the above operation, `0` and `1` will be replaced by `%add` and `%xor` ,
`4` with the verilog name of the symbol `@instance1` and `3` with the
verilog name of the symbol `@module1`.
Changes in this commit:
1. Add the optional array of symbols as an attribute to the `VerbatimOp`
2. Add a type constraint for an array of `FlatSymbolRefAttr`, this can be pushed to `mlir`.
3. Update `ExportVerilog` to get the verilog name for any symbol. Most of the changes
in `ExportVerilog` is just to ensure the final symbol names can be tracked.
4. Update docs and test cases.
* [SCFToCalyx] Add partial lowering infrastructure [4/13]
This commit adds a partial lowering infrastructure to the SCFToCalyx pass. Similarly to `StandardToHandshake`, `SCFToCalyx` structures its conversion into multiple distinct stages. Some of these stages perform IR modifications instead of IR replacements. The partial lowering infrastructure allows for writing passes which are driven by the conversion infrastructure, but relaxes the requirement of "if a conversion pattern matches, the matched operation should be replaced or erased".
`FuncOpPartialLoweringPattern`s are patterns which intend to match on `FuncOp`s and then perform their own walking from these. These patterns are initialized with access to the `ComponentLoweringState` for corresponding component of the matched `FuncOp`.
The LowerToHW pass will emit an error for any unrecognized operation it
finds in the Circuit while lowering. We need to pass through
`sv.verbatim` operations which are created during metadata generation.
The `sv.interface` operation is already passed directly through when
lowering, and this change extends this to include `sv.verbatim`
operations. If we find that there are too many operations being
white-listed, we could modify it to pass-through anything by default.
The inliner removes any module which is left uninstantiated after all
inlining is complete. It was mistakenly deleting non-module operations
because there was no instance of them. For example, an `sv.verbatim`
operation would be deleted since it is not the sort of thing that could
be instantiated. This adds a check that the operation it is considering
for deletion is in fact a module operation before removing it.
This commit introduces the `ProgramLoweringState` and `ComponentLoweringState` classes. These are used as key-value stores for a variety of mappings used during lowering, which will be introduced in the following commits.
A `ProgramLoweringState` stores `calyx::ProgramOp`-level information, where `ComponentLoweringState` stores `calyx::ComponentOp`-level information.
* [SCFToCalyx] Add calyx::ProgramOp conversion [2/13]
This commit introduces logic for converting a top-level MLIR 'module' into a calyx::ProgramOp.
The implementation works around an issue/restriction of the current infrastructure, being that a top-level 'module' cannot be overwritten. see: https://llvm.discourse.group/t/de-privileging-moduleop-in-translation-apis/3733/26
Furthermore, an input program is legalized using a `ConversionTarget`.
This takes a similar approach to the FIRRTL structure. We define an entry-point component by
using its name in the ProgramOp. This is guaranteed to be unique since each ComponentOp
name is a `Symbol`.
Change the way that FIRRTL memories are lowered to HW memories to
propagate the write-under-write behavior. Modify HWMemSimImpl (which
generate a simulation model of a memory) to respect a new
write-under-write attribute.
This new write-under-write attribute can either be "undefined"
indicating that the resulting simulation memory should put each write
port in an independent always block, regardless of whether or not they
are on the same clock. If the write-under-write behavior is set to
"port order" then write ports that are trivially driven by the same
clock are put in the same always block and ordered sequentially by port
order. I.e., later ports will override earlier ports if they both write
to the same address.
This behavior is added because the Scala FIRRTL Compiler (SFC) will
lower write ports in this way and a deviation from it is a formal
equivalence mismatch.
Add tests of "port order" write-under-write behavior for simulation
memory generation.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
No functional change, but a major step in the debug-ability of the pass. Previously, there was a discrepancy between the # of args of the Handshake FuncOp and the inlined body of the source FuncOp. This meant that any attempt at dump'ing the IR during conversion would crash, due a mismatch between the type signature of the handshake funcop and its entry block arguments.
This commit postpones adding the control argument to (and modifying the type signature of) the handshake funcOp until end of conversion.
This makes it more efficient by storing it as a first-class attribute,
rather than as an interpreted dictionary. This exposes a bunch of
ways in which StructAttr is unnecessarily different than AttrDef,
which is filed as LLVM PR 51909
This also renames it to hw.verbatim.parameter.value, and gives it a
proper type. This makes it possible to do attribute checking without
the overhead of introducing an attribute interface.
This also switches the module build() methods to take an ArrayAttr for
parameters instead of an ArrayRef<ParameterAttr>. This is more consistent
with instances and is easier to work with.