The corresponding code snippet has a problem for checking whether the
pointer pointing to a module op is a nullptr. This commit rewrites its
code to fix the warning.
The ESI logging API is intended to be agnostic of the application's logging framework. In other words, it can be adapted to the application's logging method with ease -- users must only extend one class. It also comes with a simple text logger.
It is also designed to enable debug logging in Release builds with (very) minimal performance overhead if the user does not set the log level to debug.
This PR introduces the API, but doesn't use it much. More plumbing will be required to actually use it. In the interest of keeping this PR small, this is left for future work.
Don't convert the output op in the module pattern because the operands will be of the wrong type since the body has not been converted yet, so it need to apply the hw output pattern afterwards anyway. Instead of relying on that pattern we should have a separate one for moore.output to hw.output that is applied once the rest of the body was converted. The HW output pattern is unnecessary because in the IR before conversion, no hw.output operation should be present (at least none that has a moore typed operand), thus its presence is only the consequence of a bad conversion process (if a target operation is inserted of which the operands are still of the source type, conversion casts should be inserted).
This PR extends compreg's powerOnValue operand to be able to capture more complicated initialization such as firreg's randomized initialization or DPI calls. This change should make register initialization more modular and a step forward towards https://github.com/llvm/circt/issues/7213.
While ASICs might not have explicit initial values, they are crucial for simulation
and FPGA implementation. FPGA designs often require constant initial values, while
simulation allows for more complex initialization using expressions like function calls
`$random`, `$readmem`, and `$fopen`.
seq.compreg has a (optional) powerOn operand that is lowered into inlined assignment in SV which allows users to initialize registers with user-specified values. However this representation is not sufficient for initialization with function calls.
In order to represent various kinds of initialization, `seq.initial` op and `!seq.immutable` type
are introduced. The `seq.initial` operation produces values with types wrapped in `!seq.immutable`.
The `!seq.immutable` type wrapper prevents initial values from depending on time-variant values.
Stateful operations typically require corresponding initial values with the `!seq.immutable` type.
This ensures that the initial state of the operation is well-defined and independent of time-variant factors.
Example Input:
```mlir
%r_init, %u_init = seq.initial {
%rand = sv.macro.ref.se @RANDOM() : () -> i32
%c0_i32 = hw.constant 0 : i32
seq.yield %rand, %c0_i32 : i32, i32
} : !seq.immutable<i32>, !seq.immutable<i32>
%r = seq.compreg %i, %clk initial %r_init : i32
%u = seq.compreg %i, %clk initial %u_init : i32
```
Output Verilog:
```verilog
reg [31:0] r;
initial
r = `RANDOM;
reg [31:0] u = 32'h0;
```
Align CIRCT with the finalized layer ABI [[1]]. This changes the file
name of the bind file used to enable a layer. This specifically switches
from using underscore as a delimiter to a hyphen. This avoids a problem
where a circuit that contained modules or layers whose names contained
underscores could result in multiple layer enable files that had, by the
ABI, the exact same name.
[1]: https://github.com/chipsalliance/firrtl-spec/pull/233
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This adds a pass to check for illegal instantiation of a module with
layers underneath a layer. This is a situation that leads to
bind-unde-bind when emitted to Verilog, which is illegal. This does not
differentiate between inline layers and bind layers, although
theoretically this is only a problem for bind layers. This does not
create errors on extmodules, as we have no way of knowing whether they
contain a layer or not, and we don't want false positives.
Stop emitting external modules entirely in single file emission and drop
the creation of "extern_modules.sv" in split file emission. This is done
because it creates problems/confusion for Verilog generation flows which
are trying to hide the existence of some modules. E.g., the existence of
"extern_modules.sv" will leak what external modules were instantiated
under a FIRRTL layerblock.
Alternatively, this could be revived by creating these files by respecting
the output file attributes on external modules such that each significant
directory got such a file.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
`FreezePaths` pass may sometimes need to be invoked before `ExportVerilog`.
This change removes the dependency of the pass on the `hw.verilogName`
attribute, and adds an optional get operation name function, that can be
invoked if the verilog name is absent.
This enables any tool to invoke it earlier by providing an appropriate
name-getter function.
But as is expected, the names used to freeze the paths, may not match the
verilog names. This should be used with caution, only when the path will not
be used and its okay to be incorrect.
Currently, `AcceleratorConnection` implementations only have one "official" teardown entry point, being their destructors. However, this makes implementations susceptible to destructor race conditions, due to the various things that may be concurrently executing in implementation-owned resources.
To provide users with more control during teardown, mark `AcceleratorConnection::disconnect` as virtual, allowing implementations to tear things down before destruction.
Co-authored-by: Morten Borup Petersen <mpetersen@microsoft.com>
Fix a performance issue in the `LayerMerge` pass. Apparently, repeated
use of `inlineBlockBefore` with a forward walk can be a performance issue.
Fix this, by reversing the iteration order.
h/t @youngar for algorithmic suggestions.
Fixes#7551.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Remove vestigial code in BlackBoxReader related to tracking the "priority"
of different directories. This was made unused in an earlier commit that
switched to an LCA computation for where black box files should be placed.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Change how the output directory is computed for external modules with
black box annotations. Previously, this relied on a "precedence" of
predefined directories. Now, this trivially computes the LCA of the
directories for all output directories for a black box annotation with the
same name field.
This _does not_ replicate the old behavior. Instead, users are expected
to rework their output directory structure to align with this algorithm.
E.g., it is no longer possible to make the tesbench a sibling directory of
the main output directory and have blackboxes that are instantiated by
both the testbench and the design to be put in the design---instead a user
should nest the testbench directory _under_ the main output directory.
The omnibus test case has been necessarily updated to show how the above
nesting.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Add a utility, makeCommonPrefix, copied from AssignOutputDirs. This is
useful for computing the LCA of two directories.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Reorder the FIRRTL pass pipeline so that Chisel blackboxes (represented by
a `firrtl.extmodule` and one of two blackbox annotations) will be assigned
an output directory based on their instantiation location.
Fixes#7538.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Change the `AssignOutputDirs` pass to add `hw::output_file` attributes on
external modules in the same way that these attributes are added to normal
modules. While this has no effect on an external module which has no
implementation, this fixes a bug where the external module _does_ have an
implementation that the compiler will later resolve.
This is specifically done to make output directories compose correctly
with Chisel inline blackboxes where the body of the external module is in
an annotation and is supposed to be written to a file.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Add the standard debug header/footer to the `BlackBoxReader` pass. This
is entirely cosmetic.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Add some basic debugging information to the AssignOutputDirs pass. This
indicates that the pass is running and what modules are having their
output directories updated.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Skip values defined by `ConstantLike` ops when collecting the list of
values to observe in `llhd.wait` ops. Constants will never cause an
`llhd.wait` to resume execution since they never change value.
There is a canonicalization for `exract(c, shl(1, x))` to `x == c` but this
canonicalization introduces a bunch of comparision to constants. This harms
PPA when bitwidth is large (e.g. 16 bit shift introduce 2^16 icmp op). To prevent
such regressions this commit imposes restriction regarding the number of uses
for shift.
Start of static C++ header file generation. Just integer constants for now. Can work off of any manifest and will even connect to a live accelerator and read the manifest from there.
Generates a `types.h` file and one per module listed in the manifest. Inside the module header file, generates one class per module and adds the constants to that class. Puts _everything_ in a namespace specified by the user as `system_name`.
Combine two tests of LowerLayers end-to-end behavior into a single
`-split-input-file` test. This is done to add more tests to this file in
the future.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Greatly reduces IR size generated in presence of many repeat
constants as commonly occurs in practice due to the data-like
nature of classes / properties.
Same tricky as done for FIRRTL integer constants,
use single cache/code for both.
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>