Making this an inherent attribute means that it will be stored in the
properties of the operation. Some module-like classes already had
declared it as an input, but our older modules kinds did not.
Make ExpandWhen's folding of the when condition into LTL properties work
for more inputs. This used to be very brittle and the condition would
be mapped to a new implication around the entire property:
when (a):
assert(@(posedge clock) b |-> c)
used to become
assert(a |-> @(posedge clock) b |-> c)
This commit improves on this by always pushing implications behind
clocks, and by merging implications like `a |-> b |-> c` into a single
`(a & b) |-> c`. As a result, ExpandWhens now produces the following
output, which is more in line with what users expect:
assert(@(posedge clock) a & b |-> c)
Also add a FIR-to-Verilog test to nail this behavior down and ensure we
don't regress on user expectations.
Extend `ltl.and`, `ltl.or`, and `ltl.intersect` to infer their return
type as `i1` if all operands are `i1`. Also add a canonicalization
method that replaces these ops with `comb.and` and `comb.or` if they
operate entirely on `i1`.
Add the `TestSuite` and `Test` classes to represent the discovered
tests. Instead of directly printing ops to the output, first traverse
the provided MLIR module and populate a test suite object with the
discovered tests. Then print the list of tests in the test suite.
A separate test discovery step will later allow us to discover tests via
other means, for example, by scanning an entire Verilog directory for
marker comments.
* create register based on type
* support calyx constant op and the corresponding emitter
Co-authored-by: Chris Gyurgyik <Gyurgyikcp@gmail.com>
---------
Co-authored-by: Chris Gyurgyik <Gyurgyikcp@gmail.com>
This enables properties in the FIRRTL dialect. Some op parsers which
called `inferReturnTypes` had to be updated to store inherent attributes
as properties on the OperationState, as the call to `inferReturnTypes`
expects properties to have already been populated. This is a change
that we should make for all operation parsers and builders, to make
things faster, but is not strictly necessary at this time.
This is a big change to clean up our implementation of
`inferReturnTypes` in an effort to get ourselves ready to enable
properties in the FIRRTL dialect. We had structured our API so that
`inferReturnType` would call out to a simpler version of itself with
some of the useless arguments removed. This prevented us from using op
adaptors to abstract over whether or not an inherent attribute was
contained inside the attr-dict or the properties.
This change keeps the old structure of a two level API, but with
different boundaries: The large API takes all arguments, creates an
adapter, pulls out the necessary attributes and then calls in to the
simpler interface. FIRParser uses the simpler API when inferring return
types. The simpler interface is now specific to each operation and not
common with other operations.
This last change caused a problem for `parsePrimExp`, which relied on a
generic interface to create all expressions. This function is now
templated over exactly how many arguments the specific prim op takes,
parses exactly that many, and splats them out when calling
`inferReturnType`. As an upside to this, we can also call a more
specific builder for each operation, which should speed up building
operations when we move to properties.
Ensure the ordering of the fields of a bundle, when its cast to a UInt.
This commit ensures that the left-to-right order of fields is the high-to-low-order.
This adds a conversion pass from AIG dialect to Comb dialect. AndInverterOp can be easily converted into comb.and + comb.xor + hw.constant.
This enables us to utilize core dialects tools for synthesis results without any addition. Primarly use case is running LEC on IR before and after synthesis.
Slightly tweak the `verif.contract`, `verif.require`, and `verif.ensure`
ops to match the usage outlined in the Verif dialect documentation. This
also adjusts the operands and constraints slightly.
This is a complete rewrite of the `LowerState` pass that makes the
`LegalizeStateUpdate` pass obsolete.
The old implementation of `LowerState` produces `arc.model`s that still
contain read-after-write conflicts. This primarily happens because the
pass simply emits `arc.state_write` operations that write updated values
to simulation memory for each `arc.state`, and any user of `arc.state`
would use an `arc.state_read` operation to retrieve the original value
of the state before any writes occurred. Memories are similar. The Arc
dialect considers `arc.state_write` and `arc.memory_write` operations to
be _deferred_ writes until the `LegalizeStateUpdate` pass runs, at which
point they become _immediate_ since the legalization inserts the
necessary temporaries to resolve the read-after-write conflicts.
The previous implementation would also not handle state-to-output and
state-to-side-effecting-op propagation paths correctly. When a model's
eval function is called, registers are updated to their new value, and
any outputs that combinatorially depend on those new values should also
immediately update. Similarly, operations such as asserts or debug
trackers should observe new values for states immediately after they
have been written. However, since all writes are considered deferred,
there is no way for `LowerState` to produce a mixture of operations that
depend on a register's _old_ state (because they are used to compute a
register's new state), and on a _new_ state because they are
combinatorially derived values.
This new implementation of `LowerState` completely avoids
read-after-write conflicts. It does this by changing the way modules are
lowered in two ways:
**Phases:** The pass tracks in which _phase_ of the simulation lifecycle
a value is needed and allows for operations to have different lowerings
in different phases. An `arc.state` operation for example requires its
inputs, enable, and reset to be computed based on the _old_ value they
had, i.e. the value the end of the previous call to the model's eval
function. The clock however has to be computed based on the _new_ value
it has in the current call to eval. Therefore, the ops defining the
inputs, enable, and reset are lowered in the _old_ phase, while the ops
defining the clock are lowered in the _new_ phase. The `arc.state` op
lowering will then write its _new_ value to simulation storage.
This phase tracking allows registers to be used as the clock for other
registers: since the clocks require _new_ values, registers serving as
clock to others are lowered first, such that the dependent registers can
immediately react to the updated clock. It also allows for module
outputs and side-effecting ops based on `arc.state`s to be scheduled
after the states have been updated, since they depend on the state's
_new_ value.
The pass also covers the situation where an operation depends on a
module input and a state, and feeds into a module output as well as
another state. In this situation that operation has to be lowered twice:
once for the _old_ phase to serve as input to the subsequent state, and
once for the _new_ phase to compute the new module output.
In addition to the _old_ and _new_ phases representing the previous and
current call to eval, the pass also models an _initial_ and _final_
phase. These are used for `seq.initial` and `llhd.final` ops, and in
order to compute the initial values for states. If an `arc.state` op has
an initial value operand it is lowered in the _initial_ phase. Similarly
for the ops in `llhd.final`. The pass places all ops lowered in the
initial and final phases into corresponding `arc.initial` and
`arc.final` ops. At a later point we may want to generate the
`*_initial`, `*_eval`, and `*_final` functions directly.
**No more clock trees:** The new implementation also no longer generates
`arc.clock_tree` and `arc.passthrough` operations. These were a holdover
from the early days of the Arc dialect, where no eval function would be
generated. Instead, the user was required to directly call clock
functions. This was never able to model clocks changing at the exact
same moment, or having clocks derived from registers and other
combinatorial operations. Since Arc has since switched to generating an
eval function that can accurately interleave the effects of different
clocks, grouping ops by clock tree is no longer needed. In fact,
removing the clock tree ops allows for the pass to more efficiently
interleave the operations from different clock domains.
The Rocket core in the circt/arc-tests repository still works with this
new implementation of LowerState. In combination with the MergeIfs pass
the performance stays the same.
I have renamed the implementation and test files to make the git diffs
easier to read. The names will be changed back in a follow-up commit.
Fixes#6390.
Add a region verifier to OM dialect's Class Op. This verifies that the
terminator returns the right number of fields with the correct types that
match the declared type of the Class Op.
Fixes#7736.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
The `aig.cut` operation represents a cut in the And-Inverter-Graph.
This operation is variadic and can take multiple inputs and outputs,
which corresponds to the input and output edges in AIG conceptually.
This adds a conversion pass from Comb to AIG. Currently conversion patterns for variadic `comb.or/and`
and binary xor are supported. There will be a follow up to implement conversion patterns for arithmetic ops.
This commit adds AIG LowerVariadic pass to lower variadic AndInverter
op to have at most two operands. This makes IR closer to traditinal
AIG representation combined with LowerWordToBits pass
This commit adds `aig.and_inv` op that represents an And-Inverter in AIG.
DenseBoolArray `inverted` field specifies if each operand is inverted.
This commit also adds a basic canonicalizer for it.
Add support for invalidation syntax that invalidates an instance or a
memory. This was never technically supported before, though it should
have been. Previously, this was only supported through the "is invalid"
path which is has been deprecated for FIRRTL versions >=3.
Fixes#7730.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Get rid of usages of the deprecated '<=' connect syntax that is not
supported in FIRRTL versions >=3.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Convert tests to use "invalidate" and not "is invalid". The latter is
supposed to be illegal in FIRRTL >=3.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Reject parsing registers that use the "reg with" syntax if the FIRRTL
version is 3 or higher.
Towards #7731.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
FIRRTL spec 3.0.0 dropped support for the "reg with" syntax for specifying
a register with a reset in favor of the simpler "regreset" syntax. Update
all tests to use this new syntax.
This is preparing to start rejecting this syntax if the reported FIRRTL
version is 3.0.0+.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Migrate all FIRRTL tests to FIRRTL spec version 3.0+. Many tests were
still using "a <= b" and "c is invalid" syntax which was deprecated in
FIRRTL 3.0. This was _not_ deprecated in CIRCT's FIRRTL parser, though.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Expand the API of the InstanceInfo analysis to include queries for if
something is in the "effective" design. This is equivalent to querying if
something is not under a layer.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Extend the existing InstanceInfo analysis to track information about if a
module is in the "design". The design is defined is everything that is or
is under the design-under-test, but is not in a layer. I.e., this
excludes things that are in layers.
This is added because it is not possible to compute this using the
existing information about something being under the DUT or under a layer.
A module could have mixed instantiation under the DUT and mixed
instantiation under a layer, yet not be in the design.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Manually format the MLIR in the emit-metadata.mlir test as the current
state is difficult for me to read. This doesn't cleanup the FileCheck
lines.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This fixes https://github.com/llvm/circt/issues/7716. Aggregate constant verifier rejects unknown attributes hence hw.aggregate_constant cannot be used for attributes defined by other dialects (in this case seq.const_clock) was rejected even when hw.aggregate_create allows users to create clock type arrays. This PR loosen the restriction by allowing TypedAttribute.
This commits also adds TypedAttrInterface to seq.const_clock and support its lowering.
Fix a bug where the internal `underDut` member was not correctly asserted
if the top module is the DUT.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Move annotations used only for a lit test into the test as inline
annotations. This annotaiton file is only used for that test and is never
optionally included, e.g., there are multiple RUN lines and only some of
them use the annotation file.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This changes the OM dialect Class/ExternClass to use a return style
field name/type specifier syntax and, for non-extern class, a terminator
op in the style of hw.output.
Previously, cosim store its ESI channel to cosim channel name in the
`implDetails`. DMA engines to make channel communication work in real
hardware need this information as well.
We're already doing a best-effort preservation of discardable attributes through `narrowOperationWidth`. I cannot think of a reason why the inherent two-state attribute should not be carried over.