BlackBoxMemory creates modules with bundles types to replace memory
operations. If this runs after LowerTypes, then we hit the LowerToHW
pass with a bunch of bundle types around. This pass is not often used,
and this must have regressed at some point.
This also adds an integration test to ensure that CHIRRTL memories are being
properly lowered to verilog.
This pass provides a structured way to handle IR features that are not
supported by all tools, and this lowering option reflects a specific
limitation of the Yosys tool.
Right now the pass isn't super helpful: it just rejects unsupported operations
with an error. This is progress towards Issue #1592.
This adds an implementation of the RemoveCHIRRTL pass called
LowerCHIRRTL. This pass takes the CHIRRTL memory operations, `seqmem`
and `combmem`, and transforms them into standard FIRRTL `mem`
operations.
Add an explicit attribute for port annotations to FModule and FExtModule. Adding a common name for port annotations, similar to instance, mem, etc, makes manipulating annotations simpler. Although this could be folded into argattr, having it in the same format as used in other ops makes annotation scatting able to be operation type invariant, thus simplifying it.
* [Calyx] Add IR support for calyx::WhileOp
This commit adds support for the Calyx While control operation. The operation takes two arguments; a boolean port and a group name. The op has a single body region representing the groups to execute when the condition evaluates to true.
This is solely for IR support and does not include:
- CalyxEmitter support (unsupported for all control ops as of now)
- CompileControl control FSM generation
Co-authored-by: Andrew Lenharth <andrew@lenharth.org>
Co-authored-by: Fabian Schuiki <fabian@schuiki.ch>
Co-authored-by: Andrew Young <youngar17@gmail.com>
This improves verilog emission quality because it allows expressions
to be inlined into input ports of the module. This eliminates some
extranous wires, shrinking `wc -l` on a big testcase by 3%. This
fixes Issue #1568
This generalizes the previous patch to sink expressions with multiple
users to the deepest common region between all the users. In the case
of FIRRTL, this sinks a shocking amount of test-only code into
"ifndef SYNTHESIS" blocks, eliminating wires at the top level.
However, because these expressions have multiple uses, they don't get
emitted inline - they get temporaries declared at their local scope,
usually as `automatic logic` values. These never get their initializer
emitted inline (see Issue #1567), but sinking these is still the right
thing to do IMO.
This allows the verilog printer to print them inline, for example we'd
turn the example from Issue #1601 into:
```
module test(
input clock, a, a2, a3);
wire _T = a2 | a3;
always @(posedge clock) begin
`ifndef SYNTHESIS
if (`PRINTF_COND_ & a)
$fwrite(32'h80000002, "thing");
if (`STOP_COND_ & _T)
$fatal;
`endif
end // always @(posedge)
endmodule
```
We now produce: `if (`STOP_COND_ & (a2 | a3))` with no temporary
wire. This is a pretty huge improvement to lots of things.
There is a more general version of this as well, but it seems best
to split into two patches.
Different build configurations were previously trampling on the same
cache directory on the build host. The cache directory wasn't
configurable, so just use the cache action directly.
This allows it to compose with the binary expression tree lowering
work that is already there, allowing us to handle multi-operand
additions that end with a constant.
This pass is duplicating unary ops in order to make verilog prettier,
but can result in the op being in a different block than the constant.
This causes the constant to get emitted as a weird local param, which
can even be unused in the generated verilog. Fix this to duplicate
the constant operands as well.
* [Calyx] Add IR support for calyx::IfOp
This commit adds support for the Calyx If control operation. The operation takes two arguments; a b boolean SSA value and a group name. The op has two regions, a mandatory 'then' and optional 'else' region.
This is solely for IR support and does not include:
- CalyxEmitter support (unsupported for all control ops as of now)
- CompileControl control FSM generation
When emitting two always/initial/... blocks with the same conditions, leave the
resultant block at the location of the last use, instead of at the location of
the first use. This ensures that the values used by that block are defined above
it.
This isn't necessary by the semantics of our IR, since hw.module is a graph region,
but leads to better generated verilog and puts less pressure on the cleanup passes.
Add a `--parse-only` option to `firtool` which causes the program to
stop after the FIR/MLIR and annotation input files have been parsed and
processed, and writes the resulting MLIR module to the output. This is
interesting and useful since `firtool` performs a unique combination of
input translation and annotation scattering that is not trivially
reproduced with `circt-translate` and `circt-opt`. Useful for test case
reduction.
- Update/rewrite the `circt-reduce` tool with a custom proof-of-concept
reducer for the FIRRTL dialect. This is supposed to be a pathfinding
exercise and just uses FIRRTL as an example. The intent is for other
dialects to be able to produce sets of their own reducers that will
then be combined by the tool to operate on some input IR.
At this point, `circt-reduce` can be used to reduce FIRRTL test cases by
converting as many `firrtl.module` ops into `firrtl.extmodule` ops as
possible while still maintaining some interesting characteristic.
- Extend `circt-reduce` to support exploratively applying passes to the
input in an effort to reduce its size. Also add the ability to specify
an entire list of potential reduction strategies/patterns which are
tried in order. This allows for reductions with big effect, like
removing entire modules, to be tried first, before taking a closer
look at individual instructions.
- Add reduction strategies to `circt-reduce` that try to replace the
right hand side of FIRRTL connects with `invalidvalue`, and generally
try to remove operations if they have no results or no users of their
results.
- Add a reduction pattern to `circt-reduce` that replaces instances of
`firrtl.extmodule` with a `firrtl.wire` for each port. This can
significantly reduce the complexity of test cases by pruning the
module hierarchy of unused modules.
- Move the `Reduction` class and sample implementations into a separate
header and implementation file. These currently live in
`tools/circt-reduce`, but should later move into a dedicated reduction
framework, maybe in `include/circt/Reduce`, where dialects can easily
access them and provide their own reduction implementations.
When a node is used as the address (aka index) of a CHIRRTL synchronous
read-only memory port, the memory port is enabled at the declaration
location of the node op. Nodes are being removed by the parser if they
don't carry any annotations. When the node op is removed by the parser,
the enable conditions of the memory change, and sometimes the memory
port is never enabled.
This change removes the small optimization from the FIRParser so that
the memory port enable can be properly inferred. These node operations
will still be removed later on during canonicalization.
The two CHIRRTL memory operations have been renamed from `smem` to
`seqmem` and `cmem` to `combmem`. In addition, instead of returning
`!firrtl.vector<>` types, they return a new type `!firrtl.cmemory`.
This new type can only be used with CHIRRTL memories and ports, and
prevents some shenanigans where it could be used like a normal vector.
Memory ports in SFC are allowed to be used outside of the scope which they are
defined in. To work around this issue, the memory port declaration was split
into two operations:
1. `firrtl.memoryport`: This operation is the declaration of the memory port,
and it should be emitted into the body of the module.
2. `firrtl.memoryport.acccess`: This operations is emitted to the location of
the original memory port declaration, and is used for enable inference.
For more information about these new operations, and why we added them, see the
changes to FIRRTLRational.md.
This include changes to the FIR parser to emit these new operations.
Schuyler points out in Issue #1600 that it isn't correctly implemented,
and there is only one place in the compiler that forms it ... in a
theoretical case. I added this a long time ago on a theoretical basis.
It is best to remove this until there is a real need for it.
This fixes Issue #1600.
This enables LowerToHW's auto-cse of always blocks to kick in in more
cases, e.g. in the example from Issue #1594. Thanks to Schuyler for
tracking down the root issue here.
The Cell trait is used to annotate each sub-component within a component.
This consists of primitives (e.g. RegisterOp) and component instances. This will
be useful for future passes that want to work on Cells, such as resource-sharing.
I've also renamed the CellOp to InstanceOp.
Modify sv-dialect.mlir to generate legal Verilog, with properly defined
`defines so that the output can be directly checked with a linter.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Fix a bug where a spilled localparam could result in invalid Verilog (a
two-statement always block without a begin/end).
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Change sv-dialect test to emit legal Verilog (a comment) from an
sv.verbatim op as opposed to raw strings that are illegal Verilog.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>