Previously `extract` on a `SigSpec` would always unpack it. Since a
significant amount of `SigSpec`s have one or few chunks, it's worth
having a dedicated implementation.
This is especially true, since the RTLIL frontend calls into this for
every `wire [lhs:rhs]` slice, making this `extract` take up 40% when
profiling `read_rtlil` with one of the largest coarse grained RTLIL
designs I had on hand.
With this change the `read_rtlil` profile looks like I would expect it
to look like, but I noticed that a lot of the other core RTLIL methods
also are a bit too eager with unpacking or implementing
`SigChunk`/`Const` overloads that just convert to a single chunk
`SigSpec` and forward to the implementation for that, when a direct
implementation would avoid temporary std::vector allocations. While not
relevant for `read_rtlil`, to me it looks like there might be a few easy
overall performance gains to be had by addressing this more generally.
This PR speeds up by roughly 17% across a wide spectrum of designs
tested at Google. Particularly for the mux generation pass.
Co-authored-by: Rasmus Larsen <rmlarsen@google.com>
Signed-off-by: Ethan Mahintorabi <ethanmoon@google.com>
This does not correctly handle an `$overwrite_tag` on a module output,
but since we currently require the user to flatten the design for
cross-module dft, this cannot be observed from within the design, only
by manually inspecting the signals in the design.
The guard is optimised out on some compilers under certain conditions (eg: LTO on GCC) as constant under C++ lifetime rules.
This is because the guard type's member is invalid to access (UB) after the type has been destroyed, resulting in
`destruct_guard.ok` being unable to be `false` according to the optimiser, based on the lifetime rules.
This patch still invokes UB (all accesses to the destroyed IdString instance are), but at least the optimiser
can't reason that destruct_guard_ok cannot be false and therefore it's safe to optimise out from its guard role.
The new bitwise case equality (`$bweqx`) and bitwise mux (`$bwmux`)
cells enable compact encoding and decoding of 3-valued logic signals
using multiple 2-valued signals.
These can be used to protect undefined flip-flop initialization values
from optimizations that are not sound for formal verification and can
help mapping all solver-provided values in witness traces for flows that
use different backends simultaneously.
- Attempt to lookup a derived module if it potentially contains a port
connection with elaboration ambiguities
- Mark the cell if module has not yet been derived
- This can be extended to implement automatic hierarchical port
connections in a future change
This code now takes the AST nodes of type AST_BIND and generates a
representation in the RTLIL for them.
This is a little tricky, because a binding of the form:
bind baz foo_t foo_i (.arg (1 + bar));
means "make an instance of foo_t called foo_i, instantiate it inside
baz and connect the port arg to the result of the expression 1+bar".
Of course, 1+bar needs a cell for the addition. Where should that cell
live?
With this patch, the Binding structure that represents the construct
is itself an AST::AstModule module. This lets us put the adder cell
inside it. We'll pull the contents out and plonk them into 'baz' when
we actually do the binding operation as part of the hierarchy pass.
Of course, we don't want RTLIL::Binding to contain an
AST::AstModule (since kernel code shouldn't depend on a frontend), so
we define RTLIL::Binding as an abstract base class and put the
AST-specific code into an AST::Binding subclass. This is analogous to
the AST::AstModule class.
There will soon be more (versioned) memory cells, so handle passes that
only care if a cell is memory-related by a simple helper call instead of
a hardcoded list.
Among other problems, this also fixes equality comparisons between
SigSpec by enforcing a canonical form.
Also fix another minor issue with possible non-canonical SigSpec.
Fixes#2623.
The only difference between "RTLIL" and "ILANG" is that the latter is
the text representation of the former, as opposed to the in-memory
graph representation. This distinction serves no purpose but confuses
people: it is not obvious that the ILANG backend writes RTLIL graphs.
Passes `write_ilang` and `read_ilang` are provided as aliases to
`write_rtlil` and `read_rtlil` for compatibility.
The new types include:
- FFs with async reset and enable (`$adffe`, `$_DFFE_[NP][NP][01][NP]_`)
- FFs with sync reset (`$sdff`, `$_SDFF_[NP][NP][01]_`)
- FFs with sync reset and enable, reset priority (`$sdffs`, `$_SDFFE_[NP][NP][01][NP]_`)
- FFs with sync reset and enable, enable priority (`$sdffce`, `$_SDFFCE_[NP][NP][01][NP]_`)
- FFs with async reset, set, and enable (`$dffsre`, `$_DFFSRE_[NP][NP][NP][NP]_`)
- latches with reset or set (`$adlatch`, `$_DLATCH_[NP][NP][01]_`)
The new FF types are not actually used anywhere yet (this is left
for future commits).