This PR adds an op `sv.func.dpi.import` for "emitting" DPI import statement. `sv.func.dpi.import` doesn't declare function but it takes a function symbol to emit import statement. This design is similar to what `sv.macro.ref/def` does and it enables us to decouple function declaration and emission.
```
// CHECK-LABEL: import "DPI-C" linkage_name = function void function_declare1(
// CHECK-NEXT: input [1:0] in_0,
// CHECK-NEXT: out_0,
// CHECK-NEXT: in_1,
// CHECK-NEXT: output out_1
// CHECK-NEXT: );
sv.func.dpi.import linkage "linkage_name" @function_declare1
```
This PR adds function call constructs (sv.func, sv.return and sv.func.call) to SV dialect.
* `sv.func` -- this op is between hw.module and func.func. This op implement interfaces `PortList`, `HWModuleLike` and `FunctionOpInterface`. Similar to hw.module, we can preserve argument names and mix the order of input and output arguments. Following func.func empty body indicates that the op is a declaration. Currently sv/func is defined as "automatic" function in SV.
* `sv.return` -- terminator for sv.func. We cannot reuse neither hw.output nor func.func since they have constraints on parent op(and I think it's not reasonable to loose them).
* `sv.func.call` and `sv.func.call.procedural`. Two operations are added because output arguments cannot be used non-procedural regions.
Fix a bug where SVExtractTestCode was not extracting asserts, assumes, and
covers from the verif dialect. This resulted in unexpected end-to-end
"failures" from Chisel where Chisel asserts, assumes, and covers were not
extracted and left in the design.
Fixes#6864.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Macro identifiers now use a proper symbol to handle references.
The verifiers are not yet enabled as more intrusive pipeline changes are required, to be done in follow-ups.
Modules generated by ETC are currently marked as public but it should be private. This change allows the compiler to freely rename and reorder ports or names on them.
The pass relies on `seq` items, creating a circular dependency between SV and Seq.
It better belongs to the seq dialect, alongside options and ops it related to.
Moving forward, this should be merged into FIR memory lowerings.
This PR refactors HWLegalizeModules to something more like existing lower types passes in order to support more complex patterns such as array concatenations. Several new tests are also added.
Fix https://github.com/llvm/circt/issues/5355.
Treat blockargs like other values and let the asm name hint interface compute names for them. If the port name is a legal ssa name, it will be used, otherwise the legalization will compute a new name based on the port name. This has stable round-tripping after the first round, which is consistent with other ops which provide ssa name hints.
Previously Namespace::newName could return empty string for empty string.
This is a problematic behaivor since primary use cases of Namespace is
symbol generation but empty string cannot be used a symbol.
For example HWExportModuleHierarchy crashed with an instance with an
empty name.
This commit fixes the issue by pre-registering empty string in a constructor of
Namespace.
This is quite invasive. This converts from the functiontype printer to the moduletype printer.
---------
Co-authored-by: Mike Urbach <mikeurbach@gmail.com>
Change the BFS of operations used to compute backwards slices in
SVExtractTestCode to, instead, use a DFS of operands. This ensures that
any intermediary operations which may show up do not cause the ports of
extracted modules to change.
This was triggered by addition of the `seq.from_clock` operation to cause
the BFS discovery order of roots to change.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Fixes a bug where an inout input was being eliminated which resulted in the block argument list shifting, but input->output replacements were not being updated correctly.
Fixed by keeping to-be-output values as temporary operations instead of an in-memory array of values. By doing so, any value replacements performed by other patterns will also affect the temporary output operations.
... that pattern should maybe be factored out and given a name - seems like a generic thing where we want to store a value for later use, but that value may be replaced at any point in time.
This bumps llvm. There is an upstream bug which affects DC.join. Some folders and tests are disabled due to this.
---------
Co-authored-by: Andrew Young <youngar17@gmail.com>
Co-authored-by: Andrew Lenharth <andrew@lenharth.org>
Currently we only inline input only modulse when op is extracted.
However if a module only contains input only modules there might
be no extraction and hence we might end up having input only modules.
Fix an inconsistency between the handling of read ports and read-write
ports when running HWMemSimImpl with the "ignore-read-enable"
option (firtool option "-ignore-read-enable-mem"). After #5700, this
would cause the enable line of a read-write read port to have no effect.
I.e., the memory would always read even if not enabled. Change this to
align with the behavior of read ports where the memory always returns the
last read address.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Close https://github.com/llvm/circt/issues/5665. This commit fixes a bug that
bound instances are accidentally erased. When inlining input only modules it's necessary
to clone bind statements for bound instances in the module. Previously single bind op is shared by multiple instances, as a result ExportVerilog only emits a bind statement for one of them.
Adds a pass which analyses the module hierarchy to eliminate `inout` ports in favor of:
1. poking holes through the module hierarchy (explicit in/output ports)
2. raising `sv.assign`/`sv.read_inout` operations to the definition point of the `hw.inout` value.
This is unarbited, and only allows for multiple-readers, single-writer scenarios. Currently only supports `sv.assign`, as well as `hw.inout` input ports.
Cleanup the `HWExportModuleHierarchyPass` pass in the following ways:
1. Do not emit JSON directly, but rely use `sv.verbatim` operations with
substitutions.
2. Move `HWExportModuleHierarchyPass` before `ExportVerilog` (again).
Given that (1) is happening, this must happen. Both (1) and (2)
effectively undo the work in #1931.
3. Use a `hw::ModuleNamespace` to ensure unique symbols are created for
substitutions. This motivated some refactoring of the
`HWExportModuleHierarchyPass` from a `struct` to a `class` since it now
has private members. (This aligns with LLVM coding guidelines.)
4. Update existing tests to expect the new `sv.verbatim` JSON.
5. Add a new `firtool` end-to-end test baed on #5478.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Change HWExportModuleHierarchy to use the optional "hw.verilogName" of an
instance as opposed to blindly using the instance name. The latter may be
wrong if the former is set.
Fixes#5478.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Fix#5459. Use namehints and name attributes on module boundary as port names of extracted modules. Also improve instance op logic a bit to avoid unnecessary linear search.
Fix#5356. There is an edge case that ETC wrongly erase an extracted operation which is still used by (dead) module instances. This issue can be fixed by appropriately updating opsToErase based on opsAiive. inlineInputOnly is reordered since it depends on opsToErase.
This commit extends ETC to extract registers.
In order to enable the same generic logic to extract registers, the
pass has been moved earlier in the firtool pipeline, so it can work at
the seq.firreg level of abstraction, which behaves just like an
instance. As firreg registers introduce cycles in dataflow by nature, this commit
changes extraction mechanism so that we can find and extract maximum subset
of testcode. Previously we were tracking dataflow until it reaches least fixedpoint
of verification parts, but instead we can first compute least fixedpoint of design
parts and subtract it from entire modules.
---------
Co-authored-by: Mike Urbach <mikeurbach@gmail.com>
Added a separate macro to bypass synthesis and enable initial blocks setting memories lowered through `HWMemSimImpl`.
Co-authored-by: Nandor Licker <nandorl@sifive.com>
This adds a macro.decl to declare the existance and arguments of a macro.
This adds a macro.def to define a macro body.
Since macros can be defined multiple times, I separate the declaration of a macro from the definitions.
Update firrtl to use the new ops instead of verbatim.
By their nature macros cannot always know the type of the result of their use, so we leave it to each call site to declare what this is, which is not a change from the exisiting code.
These don't actually belong in the testbench directory; they are still
part of the design. So for now, simply leave them in the directory
they were initially declared.
The HW dialect currently defines a `WUWAttr` to capture the
write-under-write behavior of memories. FIRRTL memories also specify a
read-under-write behavior, which suggests that we also need a `RUWAttr`.
Since these attributes talk specifically about the behavior of
sequential circuit elements, it seems sensible to move them into the Seq
dialect.
This commit adds a `RUWAttr` and a `WUWAttr` enum to the Seq dialect and
updates the FIRRTL dialect and `HWMemSimImpl` lowering to work with
these new attributes. The `WUWAttr` in HW is removed.
This change is a preparation step for later adding a `seq.firmem`
operation to capture the semantics of FIRRTL memories more precisely at
the HW dialect level in Seq.
Changes to tests are related to teh new `RUWAttr` being encoded as `i32`
instead of the manual cast to `ui32` we had before.
This introduces SV for operation e.g.:
```mlir
sv.for %i = %c0_i2 to %c-1_i2 step %c1_i2 : i2 {
%RANDOM = sv.macro.ref.se< "RANDOM"> : i32
%index = sv.array_index_inout %_RANDOM[%i] : !hw.inout<uarray<3xi32>>, i2
sv.bpassign %index, %RANDOM : i32
}
```
which corresponds to:
```verilog
for (logic [1:0] i = 2'h0; i < 2'h3; i = i + 2'h1) begin
_RANDOM[i] = `RANDOM;
end
```
The `sv.for` operation in System Verilog defines a for statement that requires
three SSA operands: `lowerBounds`, `upperBound`, and `step`. It functions
similarly to `scf.for`, where the loop iterates the induction variable from
`lowerBound` to `upperBound` with a step size of `step`, i.e:
```
for (logic ... indVar = lowerBound; indVar < upperBound; indVar += step) begin
end
```
It's important to note that since we are using a bit precise type instead of a Verilog
`integer` type, users must be cautious about potential overflow. For example, if
you wish to iterate over all 2-bit values, you must use a 3-bit value as the
induction variable type.
We previously extracted instances that only feed the test code. This
change enhances that logic to also extract instances that may feed
other instances, which transitively only feed the test code. This also
works for instances that potentially feed each other, cyclicly, and
otherwise only feed the test code.
If the read latency is 1, Vivado issues a warning since the behaviour under a collision
is undefined. This change forces write_first behaviour by adding the appropriate annotation.
Co-authored-by: Nandor Licker <nandorl@sifive.com>
Move the `{parse,print}ImplicitSSAName` directive currently used by the
SystemC dialect into the support library and make the SV dialect use it
as well. This directive works on a `StringAttr` instead of the entire
attribute dictionary of the operation, which has a few advantages:
- Name is an explicit ODS attribute on the operation
- Name gets automatically elided in attr-dict printing (TableGen elides
all ODS-defined attributes)
- The fact that the "name" attribute has a specific meaning is exposed
in ODS more explicitly, and the assembly format makes this more
apparent by having a dedicated `name <ATTR>` portion.
NFC besides the change in assembly format.
* [SV] Move emitAsComment to SVAttributeAttr; remove SVAttributesAttr
Move the `emitAsComments` flag from `SVAttributesAttr` (plural) to
`SVAttributeAttr` (singular). Then remove `SVAttributesAttr` (plural)
since it only contains a single array field after `emitAsComments` is
gone.
Add add, remove, and read-modify-write functions to deal with SV
attributes on operations more conveniently. Also enforce deduplicated
SV attributes where easily possible. The new functions now allow for
easy addition and removal of individual SV attributes.
Adapt ExportVerilog to handle the fact that emission as comments is now
a per-attribute option. The emission code now can emit multiple
`/*...*/` and `(*...*)` groups if needed, but tries to pack as many
consecutive attributes with the same `emitAsComment` flag into one
group.
* [ExportVerilog] PP-ify SV attribute emission.
* Test pretty-printing of SV attributes on statements.
* Tweak whitespaces between SV attributes
---------
Co-authored-by: Will Dietz <will.dietz@sifive.com>
This PR extends HWLegalizeModules to support aggregate constants.
Also `signalPassFailure` is called when we fail to legalize expressions.
Fix https://github.com/llvm/circt/issues/4623.
Add support to HWMemSimImpl for doing file-based memory initialization.
This comes in two flavors:
1. Inline initialization
2. Bind-based initialization
In (1), a ReadMemOp is used to initialize the memory from a file.
In (2), a separate module is created that initializes the memory via
ReadMemOp using an XMRRefOp. This new module is then instantiated in
the memory module via a bind.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Change the existing ReadMemOp to use an SSA Value for its destination
memory as opposed to a symbol. This more closely models how the
operation actually works and enables the operation to be used to be used
with XMRRefOp to initialize memories that are not in the current module.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Don't add values to the input set if they are the result of an op we
are already going to clone. In the case of cycles, such values might
get erased as part of an instance's forward dataflow. Regardless, they
are unnecessary ports into the test code module.