NFC whitespace cleanup of tests and ODS files involving:
- Removal of trailing whitespace
- Addition of newlines to end of files if not already present
(I keep running into spurious whitespace changes due to save settings in
my editor. I'm then spending a fun amount of time doing interactive git
staging to work around this. This is attempting to do a one-shot
cleanup to make this better. We need a longer-term, automated solution
here, though.)
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This change makes the PrettifyVerilog pass duplicate constant ops into
the block where they are used. Sinking constants will allow the verilog
exporter to inline the expression instead of creating a `localparam`.
Add the force statement to SV dialect. force is a procedural continuous assignment statements.
A force can be applied to nets as well as to variables.
From the spec ::
A force statement to a variable shall override a procedural assignment or an assign procedural continuous
assignment to the variable until a release procedural statement is executed on the variable. When released,
then if the variable does not currently have an active assign procedural continuous assignment, the variable
shall not immediately change value. The variable shall maintain its current value until the next procedural
assignment or procedural continuous assignment to the variable. Releasing a variable that currently has an
active assign procedural continuous assignment shall immediately reestablish that assignment.
Constraints :
The left-hand side of the assignment can be a variable, a net, a constant bit-select of a vector net, a part-select of a vector net, or a concatenation. It cannot be a memory word (array reference)
or a bit-select or a part-select of a vector variable.
[ExportVerilog] Ensure stable names
Name legalization is happening twice, once via a dedicated pass, again in export verilog. This changes export verilog to not change the name of any port, wire, register, or instance durring emission, depending instead on legalize-names having done so already. This is done by pre-populating the name table durring the prepare phase with incoming names, so that subsequent temporary names will never displace input names.
sv.bind op for encoding system verilog bind statements. Bind is a syntax for an out-of-line instance declaration which happens logically at the end of the target module. This form refers to an instance in the IR to do the heavy lifting.
1. Randomly generate temporary output file name for the generator program. (Instead of taking a user specified input file name)
2. Use llvm::sys::path::filename and llvm::sys::path::parent_path to extract the executable name and program path.
3. Add emitError for cases when the genertor executable fails.
4. RTLGeneratorSchemaOp required attributes are stringAttrs, remove the dyn_cast
Attach symbols to instances, wires, and regs.
Wires, instances, and registers define externally visible names in verilog. Model this with optional symbols for those which are public.
Update the rational doc with notes on symbols and visibility.
This changes the generated modules to be at the same point in the MLIR module
as their generator nodes were, instead of forcing them to the bottom. This
just makes the IR more controllable from the frontend. This is the cause of
the testcase update.
We want ExportVerilog to be self contained and as simple as we can get
away with, which means we need a separate pass to handle elective
cleanups that don't effect correctness. This pass starts by addressing
a simple pet peeve of mine with unary operators.
When a mux feeds an assign to a register and one branch of the mux is the register's old value, we can turn that into a conditional assign. This results in much cleaner verilog output.
* [RTL] Generator Callout Pass
- This pass calls an external program for all the `rtl.module.generated` nodes.
- The corresponding `rtl.generator.schema` node is used for the port names.
- The value for each port name is parsed from the attribute on the `rtl.module.generated` nodes.
- The `rtl.module.generated` node is removed from the IR.
- The module is then declared as an external module, whose definition is present in a file with the module name.
- The file name in which the module definition exists is added as an attribute to the external module declaration.
Lower firrtl memory nodes into a simulation model. RW ports, which are underspecified in FIRRTL as implemented as a single port with latency = max(readLatency, writeLatency). This lowering uses 'x in some places were output is undefined.
This also improves the printing and parsing of ext modules and other
things to print with pretty syntax, and eliminates the rtl.name
attribute.
This new design is MUCH faster, uses less memory, and is simpler to
work with for passes. It eliminates a bunch of dictionary attr with a
single rtl.name key in it, and gets us out of making a bunch of arg1
attributes on the module itself.
This is the RTL half of Issue #872.
The -rtl-legalize-names was crashing on these ops that were lacking a name.
It isn't helpful to make these attributes optional when we can represent this
state as an empty string. Such a design defines away a class of bugs like this.
This fixes ISsue #855.
* Refactor the MLIR module level emission in ExportVerilog such that it
has a separate but symmetrical `UnifiedEmitter` and `SplitEmitter`.
These either emit Verilog into one large file, or one separate file
per module and interface. This will also provide a way to inject the
results of LegalNamesAnalysis into the emission process.
* Add `isNameValid` to SV dialect to check if a string contains only
characters that are legal for SV identifiers.
* Verify that module names contain only allowed characters when emitting
them in ExportVerilog. Do no longer sanitize the module names but rely
on a separate pass on the IR to do so.
* Run the RTLLegalizeNamesPass when emitting Verilog with firtool.
* Check for name consistency in split-verilog test case.
* Run `circt-opt --rtl-legalize-names` before `circt-translate
--export-verilog` to ensure names are legal for emission.
* Update the expected output in the rtl-dialect.mlir test, since the
separate renaming pass now ensures that the two `arrZero` ports do no
longer conflict in the output. Also the index on `reg_2` has shifted
by one due to an intentional conflict caused through `inout_0` to
check for proper renaming.
* Add explicit check for sanitization of an instance with unsavoury
name.
* Rename the `rtl.module.extern @reg` in the sv-interfaces.mlir test,
since the renaming pass cannot just go rename external modules. This
should probably become an error check at a later stage.
* Emit a diagnostic in the `RTLLegalizeNamesPass` if an extern module
has an invalid name.
* Add test cases that check for these diagnostics.
* Move `resolveKeywordConflict` and `sanitizeName` from ExportVerilog to
the SV dialect. This makes it easier to perform name sanitization at
an earlier stage already.
* Add name accessor convenience functions for the `rtl.instance` and
`sv.interface` operations.
* Add an analysis pass that establishes sanitized and uniquified names
for modules, interfaces, ports, wires, and registers in the SV and RTL
dialects. This pass will allow Verilog output to become more stable
and for it to have predictable names.
* Add a name legalization pass that applies the sanitized and uniquified
names determined by the LegalNamesAnalysis to the IR, transforming it.
* [SV] Canonicalize ifdef/always/initial op if they are empty
* temporal
* add test and fix logic for IfDef
* add for ifop
* Update SVOps.cpp
* address comment
* add not
* fix test
* Move comb.constant to rtl
* add missing
* fix
* fix ExportVerilog and example
* format
* format
* remove unnecessary header
* materialize constant
* format
* rebase
* fix
* clang-format
This refactors the code a bit to split between procedural and graph
regions (which are semantically very different). This also changes
the merging code to merge "down" instead of "up" which doesn't matter
for graph regions but is required for procedural regions.
Before we'd use "!FOO" as an identifier to get an inverted conditional.
Such a representation gives us two different ways to represent the same
thing and unnecessarily makes transformations on ifdefs (like merging
of them) more complicated.
Instead just put inverted logic into the else block, and have the verilog
exporter print a ifdef with no "then" as ifndef.
This patch also merges the code I duplicated in the verilog emitter for
the two ifdef cases.
This adds a pass to merge `sv.alwaysff` operations with identical
conditions. Due to the design of this operation it is trivial to check
if we meet the conditions for merging this operation. This pass is
structured to not depend on the RTL dialect, and does not assume that
the `sv.alwaysff` operations are in an RTL module. They do, however,
need to be in a graph region to work.
Although `sv.alwaysff` regions are not graph regions, they are limited
to having a single block. This pass takes advantage of this to quickly
splice blocks together when merging operations.
Always_ff support with explicit resets and reset style (sync/async). Reset blocks are tracked as part of this node to simplify merging always blocks with similar style resets. Keeping different always blocks for different reset styles of registers is driven from tool requirements and style guidelines.