This is necessary to lower the moore dialect's always_comb and always_latch without introducing helper signals. It also allows for more mem2reg at the LLHD level.
This changes emission style for unpacked array declaration. Verilator doesn't support initialization assignments for unpacked arrays, e.g:
```verilog
wire w[1:0] = '{0, 0};
```
This PR checks the value type and prevents inlining. Ideally it is more desirable to improve verilator but for now I want to avoid inlining unpacked arrays to declaration since it's just a tiny readability optimization.
Fix https://github.com/llvm/circt/issues/6363.
Fix a bug in the `SpecializeLayers` pass where sibling layers would not be
enabled/disabled correctly if an earlier sibling layer was also
enabled/disabled.
Fixes#7525.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Rework the `moore.wait_event` op to be able to accurately model the
semantics of SystemVerilog's `@...` event control statements. The op now
has a body region which is executed to detect a relevant change in one
or more interesting values. A new `moore.detect_event` op serves as the
mechanism to encode whether a posedge, negedge, both, or any change at
all on a value should be detected as an event.
Based on this new `moore.wait_event` op we can properly convert most of
the event control statements in `ImportVerilog` to a corresponding MLIR
op. Delay control like `#1ns` is not handled yet.
In the MooreToCore conversion this new op allows us to properly generate
`llhd.wait` operations at the right place that suspend process execution
until an interesting event has occurred. This now also allows us to
support almost all SystemVerilog processes in the lowering. The only
missing ones are `always_comb` and `always_latch` which require an
implicit `llhd.wait` to be inserted. @maerhart has a version of that
lowering almost ready though.
This commit also adds an `llhd.final` op in order to be able to lower
`final` procedures.
Fixes#7482.
Co-authored-by: Martin Erhart <maerhart@outlook.com>
Make the `llhd.sig` op use the same naming pattern as HW wires, Moore
variables, Seq registers, and a handful of other operations in CIRCT.
These all use the `custom<ImplicitSSAName>` parser to provide uniform
handling of optional names.
Make the signal name optional to align with other ops.
Rename the class to `SignalOp` for clarity.
PathInfo stores a pointer to an Operation, which was problematic
because that Operation may be deleted in updateInstanceInModule. The
test case added in this patch would lead to a use-after-free.
This pointer was only really used for a few things, which can be
handled differently to avoid needing to consider Operation lifetimes.
One use was the operator bool implementation, to check if a PathInfo is
empty. In the one place this was used, an equivalent check is to query
the PathInfoTable, and check if the key was not in the table.
Another use was adding the Operation's location in error messages and
notes. We can safely store a Location directly for these messages.
The final use was to do an isa check while determining the target
kind. This is where the use in the use-after-free would manifest. For
this, we do the isa check early, and store the result in a bool.
In summary, we are able to simplify the data in PathInfo in order to
avoid hanging on to an Operation pointer and needing to worry about
its lifetime.
This removes a verifier that checks that modules do not instantiate
themsselves. This will be covered by a new diagnostic pass which can
handle indirect recursion as well. This instance verifier goes a bit
beyond what we normally check in verifiers, as it must reach upward to
find the owning module to compare against its target module, and we
normally try to check only local operation properties in verifiers.
This changes how nested layers are specified when using --enable-layers
or --disable-layers. Previously a nested layer was specified with
`A::B`, and now it follows the syntax in the FIRRTL spec for layers,
which is `A.B`.
The goal of this PR is to add a new set of inline formal test ops to FIRRTL:
```firrtl
FIRRTL version 4.0.0
circuit Foo:
public module Foo:
input data : UInt<32>
input c : UInt<1>
output out : UInt<32>
;; Foo body
module FooTest:
;; example test
inst foo of Foo
;; symbolic input -- maps to input in btor2
input s_foo_c : UInt<1>
input s_foo_data : UInt<32>
;; feed the symbolic inputs to the instance
connect foo.c, s_foo_c
connect foo.data, s_foo_data
;; example assertion that uses the symbolic inputs and outputs
intrinsic(circt_verif_assert, intrinsic(
circt_ltl_implication : UInt<1>, s_foo_c, eq(foo.out, s_foo_data))
)
formal testFormal of FooTest, bound = 20
```
These new ops will then be lowered to the existing `verif.formal` op in a future PR.
For each layer, we emit a bindfile. Each bindfile has a header consisting of an
include guard, and an `include for each parent layer's bindfile. To emit the
bindfile's headers, we walk the layer declarations, and keep track of a stack
of parent layers, which we use to emit the `includes.
Unfortunately, a bug in the stack management code means that we forget to
unwind the stack of parent layers, when the curent layer has no parents. This
caused us to emit an include from one layer to the previous layer, when the
previous layer had any children.
This PR fixes the stack unwind loop to correctly clear the stack, when the
current layer has no parents.
List concatenation is implemented by first ensuring all the sub-lists
are evaluated, and then appending the elements of each sub-list into
the final ListValue that represents the concatenation of the lists.
* Fix n^2 behavior with canonicalizeIdempotentInputs.
Add arbitrary "depth" check to bound the search.
* Don't allow flattening or idempotent to search into operations
defined in other blocks.
* Support removing duplicates even when operands come from other
blocks. (or(x, y, x) -> or(x, x) regardless of their origin).
* Don't walk into operations with different two-state-ness in the
idempotent operand canonicalizer.
* When creating new operation in idempotent canonicalizer,
create it with matching two-state-ness.
Add tests for functional changes above.
Only attempt to promote variables with packed types during mem2reg. Also
run the `basic.sv` test of ImportVerilog through `circt-verilog` as a
sanity check of the transformations done by the tool.
This parses `list_concat(exp+)` into the ListConcatOp. The type of the
list is inferred during parsing, and all expressions must be the
same. It is a parser error to not concatenate at least one list.
The `CreateSifiveMetadata` pass was creating hierarchy paths to the memory
module pre-extraction. The `om.path` was being updated as the memory was
extracted in the following passes. But recently we realized this was a bug,
as the downstream tools consuming the metadata files, were actually expecting
the pre-extraction hierarchy paths to the memory.
This PR fixes the path, to terminate at the parent of the module that
instantiates the memory and encodes the pre-extraction memory instance as a
string. The tool that will parse the final `mlir` must now construct the
actual pre-extraction path from the two lists, by appending the pre-extraction
instance name to the path.
Users want to know what constants were used in a design. Plumb them through using the manifest. No runtime support, no pycde support.
Cleanups to the manifest as well. Update the runtime to support the schema changes to the manifest.
LLHD's `reg` operation dates back to when the `seq` dialect was not a thing yet. It has the disadvantage that
* it only works with `inout` values
* while it can model all kinds of registers and latches you can think of, more than is actually used/necessary in practice, it is very complicated to work with
Instead of having this operation, we can
* use the seq registers
* if we need to work with inout values, we can continuously drive the seq register output to the signal with an additional `llhd.drv` operation
* If some state element occurs frequently for which we don't have an operation in the seq dialect, we can add one there specifically for that kind of element (e.g., a latch?)
* the `lllhd.reg` operation can specify triggers with different clocks. The most common case are async resets which we also support in the seq dialect. Other, more weird constructs could also just be left in the `llhd.process` based representation. We need to support them in simulation and verilog export anyway. Alternatively, we could also decompose it to the bare logic gates with feedback loops directly, don't know why that would be necessary though.
Add a conversion for `moore.casez_eq` and `moore.casexz_eq` operations.
These only really make sense if the operands are four-valued integers,
since the X and Z bits indicate which bits to ignore during the equality
check. We don't have support for four-valued integers in the core
dialects yet. However, the vast majority of uses of this op are
comparing an SSA value against a `moore.constant`. This case we can
handle properly by looking at the constant, identifying the unknown
bits, and then masking them before performing a regular two-valued
comparison between the two operands.
Add a lowering pattern from `moore.conditional` to `scf.if`. This
currently relies on the condition being a two-valued integer after
lowering. Once we support four-valued integers at the core dialect
level, the lowering of `moore.conditional` will become a lot more
complicated.
Initialize `VariableOp`s of a four-valued type with a zero. This is in
line with the rest of `MooreToCore` which maps all X/Z to zero at the
moment, either implicitly by mapping to `comb.*` ops, or explicitly by
conjuring up zero constants.
Fix a few issues in the mem2reg interface implementations of VariableOp,
ReadOp, and BlockingAssignOp. Add tests reduced from the Snitch core
that used to fail before this fix.
Bump LLVM [1] to include an upstream verifier performance fix [2].
This required two minor fixes to CIRCT:
* [HW] Qualify types for safer use in other dialects.
* [ImportVerilog] Fix ternary with diff types, both become Value.
[1]: 5689cccead...c69b8c445a
[2]: 7a98071da2
Fix a bug where the LowerLayers pass could create output ports on a module
lowered from a bind convention layer. Avoid this _almost_ entirely by moving
all subfield, subindex, and subaccess operations (sub-* ops) out of layerblocks
before modules are created (when this is possible).
LowerLayers works by converting "captured" values into ports. However,
the sub-* ops may capture non-passive types allowably, but then never
drive them. E.g., consider the following:
%0 = firrtl.wire : !firrtl.bundle<a : uint<1>, b flip: uint<1>>
firrtl.layerblock @A {
%1 = firrtl.subfield %0[a] : !firrtl.bundle<a : uint<1>, b flip: uint<1>>
%2 = firrtl.node %1 : !firrtl.uint<1>
}
Naively, this "captures" the non-passive %0. However, this is really only
capturing the _passive portion_ of %0 through a subfield. Without this
commit, LowerLayers will try to create a port with the same type as %0
when it should be creating a port with the same type of %1. In order to
determine what the port is, LowerLayers needs to know what is actually
captured and not blindly assume that anything captured needs to be a port.
Because this analysis may be tricky, instead solve this by moving the
sub-* ops outside the layerblock before computing captures. The captures
can then _continue_ to be naively computed by seeing if a value is defined
outside the layerblock.
This approach always works for subfield and subindex. However, this approach
does not work if the subaccess index is defined inside the layerblock. If this
happens, error. This can be revisited later with a complete solution.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Implement the `materializeConstant` function for the Moore dialect and
mark the `ConstantOp` as a `ConstantLike` operation. This now allows us
to write constant folders for various operations. As a first example,
add a constant folder for `ConversionOp` that directly applies domain
conversions (e.g., `i42` to `l42` or vice versa) to constants.
Change the `AssignedVariableOp` to directly return type `T` instead of
the `ref<T>`. This removes the implied allocation and assignment, and
makes this op behave essentially like `hw.wire`.
The canonicalizers for `VariableOp` and `NetOp` can now replace all
reads from the old variable or net with the value of
`AssignedVariableOp` directly, since there is no more `ref<T>` type
involved. This also allows us to fully eliminate unnamed variables and
nets that have a unique continuous assignment.
Also add canonicalizers that remove `AssignedVariableOp` if they shadow
an input or output port of the same name, or if there are multiple such
variables with the same name in a chain.
At a later stage we may want to replace `AssignedVariableOp` entirely
with `dbg.variable`.
Fix issues with verification of subfield, subindex, and subaccess
operations which appear in a layer block. These operations are allowed to
occur in a layer block even if they capture non-passive operands.
This requires reworking layer block verification to no longer check for
operations using non-passive operands. The spec requires that no
operation in a layer block _drives_ a value declared outside the layer
block. However, this is exceedingly difficult to verify due to the fact
that non-passive destinations in ConnectLike operations can be
source-to-destination, destination-to-source, or bi-directional. If the
verifier sees this, just allow it. The FIRRTL pass pipeline will later
canonicalize away flips (i.e., make all types passive) which will then
allow the verifier to check these. This should be revisited in the
future.
Fixes#7451.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Don't check non-passive connects.