[Pipeline] Add pipeline stage register materialization pass
This commit adds an intermediate transformation to the Pipeline dialect
which is responsible for converting `pipeline.stage` to `pipeline.stage.register`
operations. The purpose of this transformation is to 'fix' where
registers needs to be placed in the pipeline, after all stages have been
defined and placed.
In short, the transformation will scan through the pipeline (in order,
top to bottom) and insert `pipeline.stage.register` operations in place
of `pipeline.stage` operations. Any operand used in any operation will
be analyzed to determine if it originates in between the last seen stage
and the operation itself. If not, this means that the operand crossed
a pipeline stage, and as such, the value will be routed through the
predecessor stage (`routeThroughStage`).
* [Calyx][FIRRTL] Put explicit type hints for TypedValue where necessary.
With the introduction of TypedValue in upstream llvm commit
688c51a5acc53b456014e53663051476d825e896, there are now a few cases
where we need to explicitly write the types. In some cases, we need to
explicitly upcast to Value to be consistent with other Values in the
expression, and in other cases, we need to upcast the type parameter of
TypedValue when there are ambiguous implicit conversions.
* [FIRRTL] Replace llvm::GreatestCommonDivisor64 with std::gcd.
GreatestCommonDivisor64 was removed in upstream LLVM in
87c38323a2cff5b26023b24c36a7c01741aba834, and the recommended migration
path is to use std::gcd. This performs an explicit cast to uint64_t for
the same reasons described in 4a2377afd69bcf014492cb665ee955eab3121c4c,
which is that std::gcd may have different and unexpected semantics when
its arguments are of different types and signedness.
* [NFC] Explicitly set dialect accessor prefix to kEmitAccessorPrefix_Raw.
Upstream recently changed the default value of emitAccessorPrefix to
kEmitAccessorPrefix_Prefixed. This patch explicitly sets
emitAccessorPrefix to the previous default value of
kEmitAccessorPrefix_Raw, which will allow us to the new accessor prefix
style more gradually and at our own pace. Upstream will completely
remove the _Raw style in the next couple of months, so we will need to
make the migration soon, though.
See [1] for more information.
[1]: https://discourse.llvm.org/t/psa-ods-generated-accessors-will-change-to-have-a-get-prefix-update-you-apis/4476
* [firtool] Pass config object to new writeBytecodeToFile API.
The third argument to writeBytecodeToFile() now takes a
BytecodeWriterConfig object instead of just the producer string.
* Bump llvm to 13f1bc41888e7d6555c532ba5fa925b9fe3e6b2f.
This is a fairly straight-forward transformation since the brunt of the
work of detecting which values will be registered in a given pipeline
stage has already been performed by a prior pass.
This pass simply elaborates the `pipeline.stage.register` operations
into `seq.compreg` operations and stitches up the circuit.
... the long awaited.
This intends to be a mostly boilerplate-y commit for introducing an `hlstool` to circt. The goal is fairly clear - provide a tool which composes the various passes and abstractions in CIRCT which care about high-level design/synthesis.
By doing so, the tool intends to take out the guesswork in terms of how these abstractions are to be composed, as well as when and where to run a pass.
Benefits should be fairly immediate - both in terms of reducing the verbosity of integration tests (many of which currently have to manually describe a fairly long pass pipeline) as well as for newcomers to CIRCT, which can be pointed to a tool/pass pipeline that shows a verified phase ordering of lowering/transformation passes.
As for tests, this commit includes modifications to most of the Handshake integration tests using the 'all' driver.
To replace all tests, a follow-up commit should define how to handle flow-specific arguments to `hlstool`.
These new options support expanded ESI/PyCDE integration tests.
'interactive' runs the python script in the foreground to enable
interactive debugging. 'tmpdir' is generally used for finding the
generated ESI runtime API.
* [FIRRTL] Use BitVector over ArrayRef/SmallVector for eraseArguments.
Upstream MLIR removed an overload of `eraseArguments()` in
27e8ee208cb2142514ee2e3ab342dafaf6374f9e, stating that the overload
isn't useful because we should probably be using BitVector in most
cases.
This mostly affected code in the FIRRTL dialect that used SmallVector
for holding the list of port indices to delete, which indeed can be
replaced with a BitVector.
One thing to be careful about is that while `push_back()` is still
defined on BitVector, it has different behavior than
`SmallVector<unsigned>::push_back()`, in that the former only allows you
to push back a boolean 0 or 1 to the end of the bit vector, while the
latter pushes back an integer index. `BitVector::set()` matches the
previous behavior.
Co-authored-by: Will Dietz <will.dietz@sifive.com>
Endpoint IDs differ by simulator by prefix, wherein the prefix is based
on the top module. Instead of specializing tests to the simulator,
automatically prepend the endpoint ID prefix to endpoint IDs on open
requests.
We have many flags which control whether or not we run a specific pass,
such as `--lower-types`. Most of these flags should never be used by
regular firtool users; they are only really useful for circumventing a
crash in a pass and can often lead to other crashes. This moves most of
the pass options to be of the form `--disable-mypass`, and makes them
hidden by default. The descriptions of these options were made
uniform, at the cost of a less detailed description.
The `GrandCentral` pass was enabled by default. Since its behavior is
controlled by annotations, it should always run.
This also did a small sweep to make sure that all our option
descriptions begin with a capital letter.
This commit adds the `LowerXMR` pass to the firtool pipeline and enables it
by default. This is required since the `LowerToHW` pass cannot handle `RefType`,
so all ops and ports of `RefType` must be removed.
Towards aggregate preservation, this PR disables CheckCombCycles for now
when aggregate preservation is enabled. This should be reverted once CheckCombCycles
pass support aggregate.
Support emitting bytecode via new `-emit-bytecode` flag.
Use the `-f` flag to force printing to terminal.
Also, auto-detect and parse bytecode when passed to stdin.
Bump LLVM and the required updates:
1. Rename getEnclosingAffineForAndIfOps to getEnclosingAffineOps: The utility was extended to also support affine.parallel ops) The commit: llvm/llvm-project@26fedf9
2. Update lit tests to make DefaultValueAttr, not optional! llvm/llvm-project@af3ed4a
3. Move hasValue to has_value
If they happen to call APIs which need some of the shared libraries,
it's important they use the same Python version against which we
compiled those libraries.
* [ExportChiselInterface] Basic infrastructure for Chisel Interface file emission
This commit adds a pass for FIRRTL that generates a Scala file with a module
class that represents the interface for the top module of the FIRRTL circuit.
This is to support the development of separable compilation of FIRRTL circuits.
The details about linking circuits together are to be determined. The generated
Scala module extends ExtModule, although a new module class may be introduced
in the future.
This now tracks when randomized registers exceed a threshold, and
splits them up into multiple registers. This is intended to work
around register size limits in simulators that may be exceeded by
using a single large register to hold all of the random bits for each
module.
This adds a pass that collects all registers in each module, computes
how many bits of random data should be used to initialize them, and
saves this information for each module and register. In FirRegLower,
this is used to create one large random register per module, and
select out the appropriate bits for each register in the initial
block. This ensures the same large random register is created, and the
same bits are always selected for the same register, regardless of
optimizations that may remove registers.
FIRRTLType is still base for all FIRRTL types,
but all current types are now under a new FIRRTLBaseType.
This makes it possible to add new (non-base) types to FIRRTL in the future.
This representation and conversion aren't being used, and never
connected to Verilog output. The newer PipelineWhileOp could subsume
this use-case, and further evolution is coming to this dialect, so it
seems like a good time to clean out the older parts that aren't used.
Motivation:
1. This file is nearing 2000 LOC. I personally find that having a single file per pass helps in quickly navigating to/between implementations of different passes. Bunching everything into one file makes locating things just a bit harder.
2. This is the style used in the remainder of CIRCT.
3. Uses canonical CMake structure for declaring passes.
It is probably fair to conclude that naming this dialect `StaticLogic` has been a pain point for a while. This commit proposes a dialect renaming to `Pipeline`, for a couple of reaons:
1. So far, we've only been working with pipeline abstractions within this dialect.
2. Pipeline representations aren't necessarily statically scheduled - we plan on adding switches to select between latency sensitive and latency insensitive lowerings of pipelines.
This name change does not preclude renamings in the future if we want to fit more stuff into this dialect. Personally, i think it is prudent to maintain a dialect name which reflects what's actually being done within the dialect, as well as the (near/mid/"someone actually intends to work on this"-term) future plans for the dialect.
Primarily:
getValue -> value
hasValue -> has_value
Value accesses not dominated by a presence check use 'value'.
(only use 'operator *' when clearly dominated by check)
"operator bool" and "operator *" used only when meaning was clear
(if variable looks like an integer, like getBitWidth(),
don't use operator bool unless the code already does so;
if returning result of a presence check prefer has_value, etc.)
Few places are slightly simplified, such as: using value_or,
avoiding calling same method for presence check and for the value,
and X.getValue().y -> X->y.
Fixes#3552.
(LLVM will be deprecating the old method names)
Moves Comb to LLVM and HW to LLVM conversions out of the LLHDToLLVM pass and into their own dedicated lowering passes, as proposed in #3539.
The methods convertToLLVMEndianess and llvmIndexOfStructField are also encapsulated here within a HWToLLVMEndianessConverter class, in order to allow easier re-use between different passes.
Apparently using an interface like FModuleLike as the source
for a isa/dyn_cast causes these errors.
Workaround by grabbing the actual operation and checking that.
This commit represents a lowering pass for converting a Calyx control schedule (seq/if/while/enable) into an FSM representation. The FSM is embedded within the Calyx component, and references both the group symbols and cell SSA values.
The lowering method is a fairly straight forward conversion, which leaves plenty of canonicalization opportunities to remove redundant states in the generated FSM. However, doing it as presented in this PR lends itself to some very clean code (which I prefer, rather than prematurely optimizing during lowering) as well as meaningful naming of states (which i think is fairly important).
Cull unnecessary dependences. Reduces the number of files which need to
be compiled for check-circt by ~20%. Compiles and links fine on my machine,
but we've had linking issues in the past, so this may be bumpy.
This adds an option to `firtool` to specify the optimizations at a large
granularity, with two `release` and `debug`. Right now, this just
customizes the value preservation flag. The use of a hook allows these
options to compose sensibly with the finer grained options, s the last
command line option specified overrides previous settings.
This PR modifies LowerTypes to specify types preserved by aggregate preservation, i.e. `-preserve-aggregate={none, 1d-vec, vec, all}`.
Implementation wise, `peelType` takes the enum and selectively lower types.
This commit adds an option `emit-chisel-asserts-as-sva` to emit chisel
asserts as SVA assertions at LowerToHW. Users sometimes want to emit
only SVA for verification purpose and therefore, this commit provides a
command line option to emit "ifElseFatal" style assertion as SVA.
Ensure the passes we use are registered before parsing the command line
options, so that options such as `--mlir-print-ir-before=` work.
Add test.
It would be better if we didn't have to worry about this,
("did we remember to register all the passes" / early loading)
but in the meantime these options are very helpful for debugging
large designs.
Improve the `InstanceStubber` reduction to properly remove modules that
become unused after an instance has been dropped. This now eagerly gets
rid of stubbed-out modules instead of relying on some later
canonicalization and operation pruning to do this.
Add options to set a lower and upper bound on the granularity at which
reductions are applied to operations. The limit can be set based on the
number of operations processed at once, or the number of chunks into
which the input is subdivided. This allows the user to perform coarse
passes over an input before advancing to more fine-grained reductions.
Also properly hides the MLIR/LLVM options from the default help page.
Add a reduction that eagerly inlines modules. This should ideally be run
after the instance stubber and module externalization patterns, to avoid
a huge blow-up of the IR in case modules are multiply instantiated. But
as @darthscsi observed, removing hierarchy usually has a very beneficial
effect on reduceability.
Add a reduction pattern which replaces wires with the connected value.
This tends to be more aggressive than the canonicalizer and happily
nukes wires that may be marked as to be preserved for user inspection.
Improve the progress summary printed by `circt-reduce` by making it
actually end in a newline, adding additional information, and properly
overwriting the previous summary if no other output has been printed in
the meantime.
This implements `-strip-fir-debug-info` option (enabled by default) to drop source locators of fir files
just before ExportVerilog emission. The pass StripDebugInfoWithPred is similar to StripDebugInfo
pass, but StripDebugInfoWithPred selectively strips locations using given predicate.
This change moves more logic related to name preservation into the
DropNames pass. The parser no longer determines if names should be
droppable at parse time, it always creates wires and registers with
`interesting_name`s.
The drop names pass used to unconditionally mark all operation as
"droppable_name"s when run. The `DropNames` pass now takes a parameter
if it should preserve everything, nothing, or only things with meaningful
names.
I think that there is a problem with our current naming of "name
preservation": it is not about whether the "name" is preserved or
dropped, it describes whether a wire or register should be preserved or
dropped. For this reason I think it makes more sense to refer to it as
"value preservation". As the first step toward moving the focus , I
changed the command line option of `firtool` from `-drop-names` to
`--preserve-values=[none | named | all]`. Alternatives suggestions
welcome!
In the future, I think it would make sense to change the enum attributes
`interesting_name` to `preserved` and `droppable_name` to `droppable`.
This also changes firtool to mark all values droppable by default.
Remove all logic related to handling SubAnnotationAttr inside FIRRTL
Dialect passes, utilities, and tools. This is work towards fully
removing SubAnnotationAttr.
Remove the (now unused) SubAnnotationAttr. This has been, in prior
commits, fully replaced with a "circt.fieldID" field that is added to
annotations which apply only to part of an aggregate. This was done
because "circt.fieldID" is viewed as a lighter weight solution that
avoids the need for constant special casing of different "types" of
annotations, i.e., is this a dictionary or is this a SubAnnotationAttr.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This commit creates a new Attribute `InnerSymAttr` for inner_sym and replaces
the `SymbolNameAttr` with `InnerSymAttr`.
The `InnerSymAttr` contains a single field `StringAttr` for the inner_sym name.
The plan is to extend the `InnerSymAttr` to specify symbols per field of an
aggregate type, and also specify public/private visibility for each symbol.
Every `FIRRTLOp` that has the `InnerSym` trait, now has the `InnerSymAttr`
attribute. Also update the builders to either take the new attribute or
convert a `StringAttr` to `InnerSymAttr`
Majority of the changes in this commit is to create an `InnerSymAttr`
from a `StringAttr`.
This pass performs inter-module liveness anaysis and deletes dead code
aggressively. A value is considered as alive if it is connected to a port
of public modules or a value with a symbol. We first populate alive values
into a set, and then propagate the liveness by looking at their dataflow.
The framework is almost same as IMCP except that lattice has two states
(knownAlive, assumedDead) and direction of propagation is opposite.
Writing failing tests for PyCDE code gets cumbersome, quickly, without --split-input-file behaviour like we're used to in opt tools.
This commit adds a small python script which splits an input file based on a split token (# -----) and executes each split separately, catching any exceptions which might be thrown.
Middle-end passes might introduce operations with interesting names so this
commit adds another instance of DropNamesPass so that we can clean up them.
This commit adds a pass `DropNamesPass` to change names to droppable
in order to disable name preservation. The pass walks `FNamableOp` and
drop their names. This pass should be executed in the very early pipeline
so that other passes can get more freedom about their names.
This PR adds NameKindAttr to explicitly represent name preservations of node, wire and register ops. Previously, `name` is directly used to represent the preservation kind (useless or interesting name) but it would be nicer to have the information explicitly, considering that name attributes are used as SSA names too. NameKindEnum has two elements, `InterestingName` and `DroppableName`. `InterestingName` must be preserved.
Example:
```scala
circuit Foo:
module Foo:
input a: UInt<1>
node b = a
node _c = a
```
Parse only output:
```mlir
firrtl.module @Foo(in %a: !firrtl.uint<1>) {
%b = firrtl.node %a : !firrtl.uint<1>
// same as %b = firrtl.node interesting_name %a: !firrtl.uint<1>
%_c = firrtl.node droppable_name %a : !firrtl.uint<1>
}
```
This adds the `firrtl-` prefix to the beginning of the command line
option for this pass, so that we keep our dialect passes namespaced.
I found the use of capital letters in the command line option to be a
unconventional, so I spread it out to the significantly longer
`firrtl-mem-to-reg-of-vec`. In the future maybe we can think about
renaming this pass.
The `BlackBoxMemory` pass was an earlier implementation of SFC's
`ReplaceMemMacros` and has since been totally superseded by the newer
`LowerMemory` pass.
Due some hasty changes when we realized that `MemToRegOfVec` transform
should not lower all memories, we started blackboxing seq mems which
we shouldn't be. We need to make sure that the `LowerMemory` pass is
gated on the `repl-seq-mem` flag in firtool, which will allow SRAMs to
be lowered to generated memory modules instead of blackboxes.
* [FIRRTL] basic support for subcircuit signal driving flows
This is handled with a two-step flow:
* main.fir + subCircuit.json --(firtool)--> (normal output) + sigdrive.json (new)
* subcircuit.fir + sigdrive.json --(firtool)--> (normal output)
The new test in 'subcircuit-flow' demonstrates this in action.
There are many limitations, this is meant to just be enough to
support some specific existing use cases only.
See PR for more details.
Change firtool to always run LowerAnnotations. Remove the "--new-anno"
option to conditionally run LowerAnnotations.
Move all logic related to Grand Central (GCT) view annotation scattering
from FIRAnnotations into the LowerAnnotations pass. In this commit
there are difficult to spot changes to parseAugmentedType and
applyGCTView functions (where the latter is extracted from the body of a
method inside FIRAnnotations):
1. Functions now use ApplyState instead of parameters passed to the
functions.
2. Any scattered annotations are handled by using ApplyState's ability
to add annotations to the worklist. E.g., parseAugmentedType will add a
new annotation to the worklist for every ground type leaf.
Co-authored-by: Will Dietz <will.dietz@sifive.com>
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This PR adds a functionality to include build information in output files.
The format of the version string is `<releases tag name>-
<how many commits since the tag>-g(means git)<current commit hash>[-dirty]`
Two cmake flags are added to control version strings,
`CIRCT_RELEASE_TAG_ENABLED` (default is On) and
`CIRCT_RELEASE_TAG` (default is `circtorg`).
If `CIRCT_RELEASE_TAG_ENABLED` is false, the version string becomes
"unknown" and cmake script is ran only at the first cmake configuration. Example,
```
$ cmake .. -DCIRCT_RELEASE_TAG=pycde
// Generated by CIRCT pycde-0.0.5-28-ge846cf26e
module Bar(
$ cmake .. -DCIRCT_RELEASE_TAG=sifive
// Generated by CIRCT sifive/0/9/0-31-ge846cf26e
module Bar(
$ cmake .. -DCIRCT_RELEASE_TAG_ENABLED=Off
// Generated by CIRCT unknown git version
```
Co-authored-by: Hideto Ueno <uenoku.tokotoko@gmail.com>
Moved the definiton of `Seq` passes to a separate `SeqPasses.h`, similarly to other dialects.
Exposed the `createSeqLowerToSV` function to be used by other clients.
* [FIRRTL] Remove all-or-nothing LowerAnnos
Change the behavior of the LowerAnnos pass to work with existing
annotation scattering. Previously, use of the `--new-anno` firtool
flag (and backing FIRParser option) would cause ONLY the LowerAnnos pass
to be used. This changes that to use normal scattering and then apply
LowerAnnos. This is done to enable piecemeal migration of scattering
work into LowerAnnos.
* [FIRRTL] Make LowerAnnos search non-standard attr
Change the LowerAnnotations pass to only process annotations from a
non-standard attribute on the circuit with key
"annotationsForLowerAnnotations". This is done to enable the
LowerAnnotations pass to be run _after_ normal annotation processing
inside FIRAnnotations and FIRParser. This then enables us to migrate
annotations one-by-one from FIRAnnotation/FIRParser handling (by moving
the annotation into "annotationsForLowerAnnotations"). This commit does
not put any annotations into this area for processing. That will be
handled by subsequent commits.
* [FIRRTL] Add LowerAnnos passthrough in Parser
Modify the FIRRTL parser to let annotations that come in with the key
"annotationsForLowerAnnotations" to be placed in an attribute on the
circuit with this key. This is currently unused infrastructure that
lets annotations inside FIRAnnotations be put behind this key to let
them be handled by the LowerAnnos pass.
* [FIRRTL] Add isAnnoClassLowered util, NFC
Add a utility, isAnnoClassLowered, that returns true if an annotation
class name is known to be handled by the LowerAnnotations pass. This
effectively leaks internal information from the LowerAnnotations-defined
table of known annotations to let parsing/scattering logic know that
these annotations will be handled later.
* [FIRRTL] Skip LowerAnnos Annos During Parsing
Modify the Annotation parser to NOT handle annotations that are known to
LowerAnnotations. This is done to enable seamless migration from
annotation handling in the parser to annotation handling in
LowerAnnotations.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
The metadata for seq_mems.json needs to be created before extract
instances runs, since it needs the original paths to the memory
operations.
This PR reverts the recent improvement to metadata emission, which used
symbols to ensure that the metadata reflected changes in the hierarchy.
It also modified the CreateSiFiveMetadata to pass to be able to run
before BlackBoxMemory. This just involved adding one extra annotation
to the list of known BlackBoxReader annotations.
Eventually, we will be getting rid of this particular piece of metadata, and
replacing it with OM.
Run the MemToRegofVec transformation only on DUT memories and ignore any
modules in the testbench. Also retain MemOps marked with
`ExcludeMemFromMemToRegOfVec` annotation.
LowerMemory pass should not error out on CombMems, but just retain them to be
lowered by HWMemSimImpl to registers.
This changes the memory-related metadata emitted by this pass to be
created from FMemModules instead of MemOps. The memories will have
already been lowered into modules. The pass can be simplified because
it no longer has to worry about deduplicating the memories itself.
Initial implementation of LLVM graph traits for an FSM machine operation. This will most likely be a useful piece of code for building further transformations, visualizations, ... upon.
This commit adds the MemToRegOfVec transformation to the FIRRTL pipeline.
This transformation converts all comb memories, to registers.
The mem tap and Async reset transformation are also updated to align
with this transformation.
(More details in the updated FIRRTL doc)
This transformation is enabled by default.
This adds a new FIRRTL transformation which looks for
`AddSeqMemPortsAnnotation` and attaches the extra port specified to all
SRAMs under the DUT. The extra ports are always of type UInt<> with a
user specified width. The extra ports are wired up through the top of
the DUT and tied off to 0 in the testharness.
This pass requires that memories have been lowered to modules, and will
emit an error if it finds a regular mem op in the module. This is
because it is not possible to add arbitrary ports to a `mem` op that don't
match the schema of a memory `r`/`w`/`rw` port.
This commit introduces tuple types to the handshake runner. Tuple values
are represented as vectors of values.
Tuples can be feed to the handshake runner by using the `"(val1, ...,
valN)"` syntax.
This works similarly to output-omir: if specified, the final MLIR is
written into this file. This is useful to get the final MLIR output
alongside some other output, especially split-verilog.
This would close https://github.com/llvm/circt/issues/2946.
This does a simple wire preservation. This means:
nodes and wires become wires if they have names
names that don't start with '_' are preserved
names don't block constant propgation, but do block deleting wires.
This commit moves the ExtractInstances pass before the GCT passes.
GCT passes can embed the instance paths into Verbatim ops, which can later be
updated by the ExtractInstances pass, causing incorrect instance paths being
generated into the verilog.
This commit should fix that bug with invalid instance paths.
Add a `ExtractInstances` pass which implements a combined version of the
Scala `ExtractBlackBoxes`, `ExtractClockGates`, and `ExtractSeqMems`
passes. The pass is split into two phases:
As a first step it traverses modules and instances in the design and
marks the ones appropriately annotated for extraction.
In a second step it repeatedly pushes the marked instances up one level
of the hierarchy until they reach the desired parent module (usually
indicated with a `MarkDUTAnnotation`). The extracted instances are then
optionally grouped into a submodule at their extracted location. Finally
the pass also emits a text file indicating where the extracted instances
were originally located in the design.
Remove a check that asynchronous reset registers are only reset to
constant values from the LowerToHW conversion. This check has been
moved into the SFCCompat test.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Change RemoveInvalid pass (yet again) to be called SFCCompat. This
better reflects that this pass is currently and will be later changed to
be where SFC compatible modifications or checks live.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
* circt-reduce: cleanup --help output, put options in category
Hides unrelated options from LLVM+co, and makes it easier
to find the most relevant options at glance.
When building CIRCT against LLVM built as shared libraries
(as preferred by many Linux distributions) this greatly
reduces the number of options printed.
* firtool: cleanup --help output, put options in category
Hides unrelated options from LLVM+co, and makes it easier
to find the most relevant options at glance.
When building CIRCT against LLVM built as shared libraries
(as preferred by many Linux distributions) this greatly
reduces the number of options printed.
* llhd-sim: group llhd-sim options in --help output
Hides unrelated options from LLVM+co, and makes it easier
to find the most relevant options at glance.
When building CIRCT against LLVM built as shared libraries
(as preferred by many Linux distributions) this greatly
reduces the number of options printed.
Even for the statically linked version more commonly used
with CIRCT, the help output is significantly reduced.
* llhd-sim: touchup optimizationLevel cl::opt to be static (NFCI)
* test/llhd-sim: Add commandline test
* circt-reduce: check categories in help test
* firtool: check categories in help test
* firtool: add new option to mainCategory too
Add a pass that adds a level of hierarchy (indicated by an
InjectDUTHierarchyAnnotation) above the DUT (as indicated by a
MarkDUTAnnotation).
Add an option to enable the InjectDUTHierarchy pass from a command-line
option in firtool.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
The `LowerMemory` pass currently just flatten aggregate datatypes into a
single uint. I want to separate the logic which lowers memories into
`hw.generatorModule`s out into a different pass, and I want to use the
name `LowerMemory` for that.
Create a new pass to flatten the aggregate memory instead of doing it in LowerTypes.
This commit removes the logic from LowerTypes and moves it into a new pass that
should run before LowerTypes.
Cmdline flags to deal with subcircuit. subcircuits need to print xmrs relative to the DUT, which they don't know due to their separate compilation. The toplevel module might also have been prefixed. This is all less than ideal, but the mechanism is expected to be removed from Chisel soon, so this is a stopgap.
Add an output file option to the GCT Signal Mappings pass. This pass
needs to know this information as it must generate a JSON configuration
which includes output file information.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
* Func argument source locators are no longer needed 31c8abc3f1
* Some rearranging means we need to make our dialect dependencies explicit eda6f907d2
* Max iterations on GreedyPatternRewriteDriver is changed to post-increment: 673e9828be
This commit adds a new reduction named NodeSymbolRemover to
remove symbols on node operations. This reduction is intended to
clean up symbols created by name preservation.
Change the Grand Central (GCT) Signal Mappings pass to be a pass that
operates on the whole FIRRTL circuit instead of on a module. Continue
to keep its parallel execution behavior. This is done in preparation
for modifications to the pass to support emission of a JSON structure
necessary for SiFive tooling which requires full-circuit information.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This commit adds CSE after hw canonicalization to clean up values
created by canonicalization. Even though it will increase compile time slightly,
I believe it is very beneficial to run CSE again in terms of verilog qualify.
I have seen 20% simulation speed up for large designs.
This also closes#2449
Added a separate flag to dump the IR with `sv` ops, replacing `--ir-hw`.
From this point onwards, `--ir-hw` will dump IR in HW form, while `--ir-sv`
will include constructs (such as registers) expanded into SytemVerilog form.
Change the name of FIRRTL Dialect's RemoveResets pass to RemoveInvalid.
This is done in preparation to add functionality to RemoveResets to
remove all invalid values after it removes resets. In effect, this pass
is now an "invalid removal" pass.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This commit adds a few timing scope for FIPParser so that
we can profile elapsed times more precisely.
FIRParser is the most expensive pass in firtool which spends 30%
of whole time. This commit puts 3 nested timing scopes such as
"annotation parsing", "module parsing" and "circuit verification".
Change two usages of create_directory to create_directories as the
former will error if parent directories do not exist while the latter
will create parent directories.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
In a recent refactoring, firtool was split into two pass managers, so
we could stop before the "export" passes if any of the "lower" passes
failed. However, this neglected to include adding the
FirtoolPassInstrumentation to the "export" pass manager. This closes
https://github.com/llvm/circt/issues/2854.
This commit makes firtool print emit logs about parsing if
verbose-pass-executions option is enabled. Currently I just hard-coded
the logging messages to keep the implementation simple.
Example:
```
[firtool] Running fir parser
[firtool] -- Done in 0.056 sec
[firtool] ...
```
If questa or vivado are not found, `iverilog` is used to run supported tests. Tests which cannot be executed using this simulator can be disabled by adding `// DISABLED: ieee-sim-iverilog` or `// DISABLED: iverilog`.
Icarus verilog tests can be disabled altogether by passing `-DIVERILOG_DISABLE=ON` to cmake, similarly to other simulators.
resolvesllvm/circt#879
Remove all support for BlackBoxResourceAnno. This annotation was
deprecated in FIRRTL 1.5.0 and is no longer emitted by any Chisel APIs
as of Chisel 3.5.0.
Fixes#2785.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Change Grand Central Views to modify existing black boxes which are
instantiated in a companion so that they will be written to the Grand
Central extraction directory. This is done to match SFC behavior around
where black boxes are written.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Fix a bug when running `firtool --mlir-timing` where the timing
information of the second pass manager (which handles Verilog emission)
was being elided from the output.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This adds early returns with signalPassFailure when failure bubbles up
in the LowerToHW pass. In order to catch such failures and exit before
the ExportVerilog passes, the firtool pass manager is split into two
pipelines. The first pipeline handles the main lowering passes, and
only if those succeed, the second pipeline handles ExportVerilog.
The `ModuleExternalizer`, `InstanceStubber`, and `MemoryStubber`
reductions are pretty aggressive and usually do a good job at pruning
the non-interesting hierarchies of the design. Move these up such that
they run very early on, making subsequent fine-grained reductions able
to iterate a lot faster.
Add the `detach-subaccesses` reduction which replaces subaccesses on a
wire or register with a new wire of the subaccess' type. The reduction
is done on entire wires, if the only uses of those wires are
subaccesses. The original wire and all its subaccesses are deleted, such
that only the newly-created, detached wires are left. This has the
ability to dissolve large aggregate wires that are invalidate through
subaccesses, which the reducer cannot otherwise remove efficiently if
the wire type is non-passive.
This reduction greatly improves `circt-reduce`'s ability to deal with
inputs that have not seen type lowering.
Run inter-module constant propagation as part of the reduction process.
This can help remove a lot of unused and unnecessary code across module
boundaries.
Extend those parts of `circt-reduce` that interact with connect
operations and check for `ConnectOp` and `PartialConnectOp`, and make
them also check for `StrictConnectOp`.
Extend `circt-reducer` with some additional mechanism to appropriately
remove `firrtl.nla` ops when instances, modules, or ports are modified
or removed. Currently this is very FIRRTL-specific, but I hope to make
this more general-purpose in the future. With this fix the reducer
becomes more useful on FIRRTL inputs that make heavy use of non-local
annotations and non-local anchors, which is very likely if they use some
form of deduplication or proper multiple instantiation.
This initial commit handles building of the top-level hw.module when converting a handshake.func operation. All handshake modules are created as external hw modules. By doing so, follow-up commits may gradually implement each of the handshake operations using RTL dialect logic.
To transition from FIRRTL bundles with explicit ready/valid/data bundles, this commit relies on ESI channels for handshake module I/O as well as the top-level I/O.
Some changes to the flow are that:
- We're no longer inlining the handshake operations into the hw module. Instead, we maintain a value mapping from SSA values in the handshake.func to those in the hw.module, and maintain this using BackedgeBuilder operations. In general, an approach is taken of maintaining state outside the IR instead of inside the IR.
This is just the first commit in the process of transitioning away from FIRRTL for lowering Handshake operations; transitioning to be ESI based should hopefully also create a good basis for composing Handshake circuits with other parts of future HLS and CIRCT infrastructure.
Change end-to-end FIRRTL compilation behavior to preserve (via tapping) all
nodes and wires which are "named". A "named" node or wire is one whose name
does not begin with an underscore. Tapping is done by creating a "shadow node"
that is assigned the value of the actual wire and marked "don't touch".
This is done to enable better debug-ability of Chisel designs by enabling users
to always have references to named things they define in Chisel. More
specifically, anytime a Chisel user defines a `val foo = <expression>`, CIRCT
will now produce a wire called "foo" in the output Verilog.
Add a parser option for controlling whether or not "named" wires and
nodes will be preserved from FIRRTL to Verilog.
Add a firtool command-line option for disabling name preservation during
FIRRTL parsing.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This commit implements MergeConnectionPass to merge expanded connections into one connection.
LowerTypes fully expands aggregate connections even when semantically
we don't have to expand because it is necessary for ExpandWhen.
More specifically this pass folds the following patterns:
```
%dest(0) <= subfield %a(0)
%dest(1) <= subfield %a(1)
...
%dest(n) <= subfield %a(n)
```
into
```
%dest <= %a
```
This pass also merge connections if their source values are known to be
constant. If `aggressive-merging` flag is true, we will merge all connections
even when source values are not simplified.
This commit adds RemoveUnusedPortsPass to reduction passes and replaces
PortPruner with RemoveUnusedPortsPass. RemoveUnusedPortsPass would be
more powerfull since it prunus ports interprocedurally.
This commit adds RemoveUnusedPortsPass to prune unused ports.
RemoveUnusedPortsPass removes unused ports from the bottom of the
instance graph so that we can remove ports optimally. Ports are
not removed if they have annotations or inner sym.
This adds a pass to wire the "test_en" port of all modules named
EICG_Wrapper to a signal marked by the "DFTEnable" annotation. This is
used to support the Design For Testing clock gating.
* mlir::Identifier deprecated
* StringAttr::get(string, context) deprecated
* Many api changes in std dialect e.g. op.res() ==> op.getRes()
* getAsmBlockArgumentNames is moved to interface (https://reviews.llvm.org/D116018)
* populateFuncOpTypeConversionPattern =>
populateFunctionLikeOpTypeConversionPattern
* SmallVector::set_size() becomes private (https://reviews.llvm.org/D115380) replaced with resize()
* #dialect.mnemonic is elided by default https://reviews.llvm.org/D113873. For now, migrate by marking every type directive in asmFormat as qualified(https://reviews.llvm.org/D116905).
* Indices of LLVM::GEPOp are now required to be constant (https://reviews.llvm.org/D116759)
This commit adds preservePublicTypes option to preserve port types of
top-level and exeternal modules.
In chisel, external modules and top-level modules are implicitly assumed to have
lowered types. Therefore even in the aggregate presevartion mode, we
can't preserve them.
Add a FIRRTL pass to merge the read and write ports of a memory, if their
enable condition is mutually exclusive.
This is an implementation of the Scala InferReadWrite pass,
`passes/memlib/InferReadWrite.scala`.
The heuristic used to infer mutually exclusive conditions,
1. First constructs the And expression tree for both the read and write
enable conditions.
2. The conditions are mutually exclusive if any of the product terms is a
complement of each other.
3. Also check if both the ports are connected to the same clock.
This pass only looks for Seq memories, that is memory with read and write
latency of 1, and exactly two ports.
Some canonicalizers create new sv.if ops. As a result,
we get redundant if statement in output verilog.
This commit fixes the issue by moving HWCleanup to the later.
* [reduce] Add `ConnectSourceOperandForwarder` reduction
This commit adds a new reducion called `ConnectSourceOperandForwarder`.
If a wire is used only once as a destination of a connect, we can
forward the wire to one of operands of the source value.
For example, consider the following IR.
```mlir
%a = firrtl.wire : !firrtl.uint<1>
%src0 = firrtl.wire : !firrtl.uint<2>
%src1 = firrtl.bits %src0 0 to 0 : (!firrtl.uint<2>) -> !firrtl.uint<1>
firrtl.connect %a, %src1
```
ConnectSourceOperandForwarder reduces the IR above into
```mlir
%a = firrtl.wire : !firrtl.uint<2>
%src0 = firrtl.wire : !firrtl.uint<2>
firrtl.connect %a, %src0
```
This reduction is potentially useful for cleaning up chains of bits/pad
op inserted by the reducer.
Co-authored-by: Fabian Schuiki <fabian@schuiki.ch>
This commit adds `preserve-aggregate` flag to enable experimental
feature to preserve passive aggregate wires/register/connection.
Currently, if preserve-aggregate flag is enabled, we change the
behavior of `peelTypes` function. We don't preserve aggregate if any
of the following condition holds:
1. They are ports of MemOp (Ports of MemOp must be ground types)
2. They are non-passive types
3. They contain an analog type
4. They are types with zero width.
This dialect is going to contain the CHIRRTL operations and types
currently in the FIRRTL dialect. This will provide better structuring
in the MLIR types as we don't want CHIRRTL types to be FIRRTL types.
For more information see this issue here:
https://github.com/llvm/circt/pull/2134
Add a new pass, RemoveResets, that replaces RegResetOps that have
invalidated initialization values with RegOps. This is part of a series
of patches that are intended to align CIRCT with the Scala FIRRTL
Compiler (SFC) interpretation of invalid. Previously, CIRCT relies on
canonicalization/folding of invalid values to do this optimization.
This pass enables future canonicalization/folding of invalid values to
zero (as the SFC does) without having to worry about performing this
optimization.
Run the RemoveResets pass as part of firtool after ExpandWhens and
before the first canonicalization. This enables conversion of
invalidated RegResetOps to RegOps before canonicalization (eventually)
interprets invalid values as zero.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This change adds an option to ignore the memory read enable signal during
memory lowering to register banks.
According to the FIRRTL spec, the read output is undefined if the read
enable signal is disabled.
But the `firrtl` implementation ignores the read enable signal on latency 0.
This change ensures that, in `HWMemSimImpl` by default the read output is set
to `X` if read enable is disabled, but if `ignore-read-enable-mem` option
is passed, then the read output is set with the data at the read address,
irrespective of the enable signal.
This provides an option to match the Scala FIRRTL compiler behavior.
Currently, the Moore frontend-compiler parses SystemVerilog, lowers the AST to Moore MIR, and then generates HW/Comb/LLHD code which it forwards to CIRCT.
This new Moore dialect aims to move the MIR into CIRCT to benefit from the CIRCT/MLIR infrastructure. In the long-run also the parser and AST can be implemented to have a complete SystemVerilog frontend natively in CIRCT.
The purpose of Moore MIR in the lowering chain is to make all the implicit things (e.g., type casts) in SystemVerilog explicit to ease further lowering to HW/Comb/LLHD.
Attributes on handshake func's may arrive all the way from i.e. Polygeist, which will set some LLVM-dialect attributes on the operations. To support running functions having such attributes, we allow unregistered dialects in handshake-runner.
This is a pass which flattens statically sized memories and indexing into them by elaborating multi-dimensional indexing into a tree of multipliers and adders. The motivation of this is currently to be able to lower programs having multi-dimensional memories through the handshake flow, which currently only supports single-dimensional memories when lowering to FIRRTL.
Co-authored-by: Mike Urbach <mikeurbach@gmail.com>
Add a new reduction that tries to remove ports from FIRRTL modules. If
an input port is never used or an output port is only ever invalidated,
this will remove those ports from the module and replace the ports on
any instances with a wire.
Add a reduction pattern that simply removes FIRRTL annotations from IR
operations. This allows the reducer to clean out annotations that are
not vital for the test case to be interesting.
Instead of entirely refraining from removing operations with a
`sym_name`, add a check to `OperationPruner` that only removes these
operations if there are no references to the symbol.
Add a `SymbolCache` utility which wraps MLIR's symbol table facilities
and provides access to lazily constructed tables. These allow reductions
such as `InstanceStubber` to speed up resolving an `InstanceOp` to the
corresponding `FModuleOp`, but also quick checks to see if a module is
no longer in use.
Add a `beforeReduction` and `afterReduction` callback to `Reduction`,
which get called by the reducer before and after it walks a `ModuleOp`
and applies reductions. This allows reductions to clear and initialize
caches before walking the module, and to peform post-processing and
cleanup before the output is tried for interestingness.
Fix an issue in the instance and memory stubber reductions where the
code to invalidate and reduce wires erroneously uses `SubfieldOp` to
index into a vector.
* Revert "Revert "[StaticLogic] Add conversion pass for Affine loop nests. (#2157)""
This reverts commit 0ce0e99b7c.
The new pass wassing missing a CMake dependency on generated files.
This is just the start of a pass, but this is enough to use the
scheduling tools and build a pipeline. At the moment, this doesn't
make use of the schedule, it just sets up a loop template. This is
just enough to lower a single loop and generate the appropriate
induction variable increments. Checkpointing here before moving any
further.
After this, I plan to add a helper class to this pass to answer the
questions we will need to flesh out createStaticLogicPipeline.
My goal is to take something as simple as this and start threading it
through the Calyx lowering to get a very thin path working before
adding support for more cases.
Co-authored-by: Julian Oppermann <oppermann@esa.tu-darmstadt.de>
The dot printing and resource usage printing passes have nothing to do with StandardToHandshake. Passes are moved to a separate file, defining a new Handshake transformation library. Furthermore, dot printing and resource count are split to two separate passes.
Add an option to decide whether `LowerToHW` should treat non-constant
async reset values as warning or error. Have firtool keep these as
errors unless IMConstProp is disabled, in which case it is highlgy
likely that the user does not care about a full stop of the compilation
and his downstream tools will possibly break for a lot of other reasons.
Accept increases in module size in the `ConnectInvalidator` pattern,
which often needs to create a `firrtl.invalidvalue` operation. The
reduction in complexity of the module is worth the increase though.
Run the connect invalidation before constant replacement of operations,
and constant replacement before any operand forwarding. This ensures
that the reductions that are likely to have the highest payoff run
first.
The `OperandForwarder` reduction pattern can generate `bits` and `pad`
operations to adjust the operand it forwards. As a result, it should not
try to re-adjust these kinds of operations. Furthermore, prevent operand
forwarding from toying with declarations and operations that can have
flow (like wires or regs), where simply forwarding an operand can
thoroughly throw things off.
Add a reduction pattern that forwards one of an operation's operands if
possible. This can help pruning large parts of the expression tree
rapidly early on in the reduction process.
When generating new operations as part of reduction patterns, use the
`createOrFold` functions to give the pattern an additional opportunity
to make the reduction more attractive.
Add a reduction pattern that substitutes operations with a constant zero
of their result type. This can be extremely potent at quickly pruning
large expression trees in the input IR.
Add dedicated reduction patterns that replace `firrtl.instance` and
`firrtl.mem` ops in the IR with invalidated wires directly. This
provides a very handy shortcut where the design hierarchy would be
pruned very quickly as one of the first steps of reduction, speeding up
the subsequent search for a detailed test case.
Currently the reducer will apply one-shot patterns way too often. The
canonicalizer for example applies to every operation. As a first try,
the reducer would apply it to the entire IR, accepting the result. Now
the canonicalizer is done, but the reducer would then half the size of
the application domain and try each half in turn, and so on until it
reaches a granularity of 1 operation.
This change adds a check to see if a one-shot pattern applied to the
entire IR (which is common), and then simply moves on to the next
pattern instead.
Add the following options to `circt-reduce`:
- `--list` to print the list of available reduction patterns
- `--include` to restrict to a subset of reductions
- `--exclude` to prevent some reductions from being tried
This makes it easier to work with the reducer, especially if an input
triggers a bug in a pass that would otherwise be tried as a reduction
pattern.
Setup a CIRCT-specific runner for reduction test cases. This
implementation is more elaborate than what's in MLIR at the moment, and
allows for test cases to be carefully validated, written to disk and
checked for their size, and then run through the tester, in distinct
steps. The MLIR version does all of these things at the same time, which
can be prohibitively expensive if the test case is a two-hour formal
equivalence check -- just to find out that the module size increased and
we have to throw away the reduction regardless.
Eventually we'll want to upstream this back to MLIR.
* [reduce] Add a root port pruning reduction pattern
Add a pattern to circt-reduce which removes unused ports from the root
module, which can significantly reduce the size of the test case.
* [reduce] Keep current pattern chunk size after successful reduction
The circt-reduce tool iteratively tries to apply a rewrite pattern on
large subsets of the operations. If the pattern doesn't apply on the
current subset, the number of operations is halved and application is
retried, forming a sort of binary search for reductions.
In the current implementation, when circt-reduce applies a pattern that
improves the output, it will immediately reset the subset to its maximum
size and restart trying pattern application from the top. This can be
very cumbersome in the case where the rewrite pattern applies only when
a fine granularity of operations is chosen. However, it takes a while to
arrive at that granularity, with circt-reduce having to try through all
the larger operation subsets first. But having arrived at a small subset
size suggests that subsequent successful rewrites will occur at the same
subset size, or even smaller. So it makes much more sense to continue
trying rewriting at the current level of granularity, even after a
pattern has applied successfully.
This commit changes circt-reduce such that it does not restart pattern
application at the top with largest granularity, but keeps going at the
current setting. If that runs through, the reduction will rerun from the
top anyway due to the pattern having successfully applied.
* [reduce] Add one-shot reductions, enable FIRRTL passes
Add the ability for reductions to declared themselves as "one-shot",
which indicates to circt-reduce that it should not try to reapply the
same reduction at the same location again. This is useful for reductions
that always apply, like lowerings and optimization passes, as they are
likely to be marked as accepting increases in module size for the sake
of reduced complexity elsewhere. This can get them stuck in a loop where
circt-reduce would accept their reduction, and then immediately try to
reapply them at the exact same spot. Marking a reduction as "one-shot"
will cause circt-reduce to skip this reapplication, and also to not
restart pattern application at the top after a successful reduction.
This now allows this kind of lowering pass to be used as a reduction
pattern in circt-reduce, and this commit enables a whole bunch of passes
from the FIRRTL dialect as one-shot reduction patterns.
* [reduce] Add progress reporting
Add a `-v` flag to the circt-reduce tool, on by default, and move most
of the LLVM_DEBUG prints over to emit to stderr if the flag is present.
Since the reducer usually runs for extended periods of time, it's useful
to produce some progress indication by default. Having an on-by-default
verbosity flag covers the common case where a user just runs the tool
and expects some output, without the user having to pass the obscure
`--debug-only=circt-reduce` option.
Also, make the `--keep-best` option on-by-default. This causes the
reducer to continuously update the best reduction on disk. Doing so is
important since the reducer can run for hours, and if it aborts at any
point (due to a bug or user interrupt), there would not be *any* output.
Since in the majority of use cases the user wants to pass this flag, it
makes sense to be on-by-default to reduce frustration.
Fix an issue in `circt-reduce` where the `pruneUnusedOps` function would
cause a double-free if an operation had the same SSA value as an operand
multiple times, like `firrtl.and %0, %0`.
Add a pass to the FIRRTL dialect that consumes `OMIRAnnotation`s on the
circuit, gathers the tracker nodes back up, and serializes the data back
into a JSON blob.
FIRRTL lowers a memory with an aggregate type into a new memory for every leaf
element in the memory's data type. This commit adds a flag `--repl-seq-mem`
to instead lower the memory to a single new memory with flattened data type.
The data and mask bits need to be mapped to the new memory accordingly.
We use BitCastOp to cast the aggregate types to the flattened UInt type.
Mask bits might not have a 1:1 mapping, for example with
`!firrtl.bundle<a: uint<8>, b: uint<16>`, the flattened data has 24 bits,
and the 3 bit mask bitwidth. In that case, the mask granularity is 8 and
the mask bits for element b is repeated once.
The `repl-seq-mem` flag will be enabled by default in a followup PR.
Add the `--repl-seq-mem` option to enable memory lowering for macro
substitution and metadata emission.
Changes in this commit:
1. Enable metadata emission by default, except memory metadata
2. Add an option `repl-seq-mem` to enable memory metadata emission
3. Add an option `repl-seq-mem` to generate external module
for certain FIRRTL memories, that are candidates for macro substitution.
4. The requirements for macro replacement:
1. read latency and write latency of one.
2. only one readwrite port or write port.
3. zero or one read port.
4. undefined read-under-write behavior.
This a subset of changes from the approved PR https://github.com/llvm/circt/pull/1957
<prithayan@gmail.com>
Operations that implement `InferTypeOpInterface` can now omit their result
types in their `assemblyFormat` without needing custom parse and print functions.
`comb.concat` has been updated to take advantage of this.
Delay the `firrtl::createCreateSiFiveMetadataPass` to just before `LowerToHW`.
This is required to ensure the `LowerTypes` has run and all the memory lowering
has been done, for correct memory metadata generation.
This keeps the structure largely the same, but pulls the implementation
logic over. This needs to be integrated better with the existing logic
in ExportVerilog which does a similar but different thing on the fly.
* [Support] Factor appendPossiblyAbsolutePath() into lib/Support.
This was duplicated between ExportVerilog.cpp and BlackBoxReader.cpp,
but it is a generally useful utility function.
* [HWExportModuleHierarchy] Directly emit JSON to a file instead of an sv.verbatim op.
Previously this pass created an sv.verbatim op with the entirety of the
module hierarchy JSON file embedded into it, with the expectation that
the --split-verilog mode of firtool would actually be the one to create
it. This is now problematic because we'd like to move name legalization,
into the ExportVerilog pass, which means module names could change after
ExportVerilog runs.
Moving the HWExportModuleHierarchy pass after ExportVerilog guarantees
that names match the final verilog, but that means that
HWExportModuleHierarchy may no longer rely on the sv.verbatim op
output_file method to actually emit the file.
This commit changes HWExportModuleHierarchy to directly write the module
hierarchy JSON files. Note that firtool will now only run the
HWExportModuleHierarchy pass when --split-verilog mode is enabled, since
we now only want to run it when we have an output directory to dump
files to.
I misunderstood how this worked and accidentally broke it: it isn't printing
anything itself, it is mutating the IR and having verilog emission print its
output.
Move singleton headers like circt/Conversion/LLHDToLLVM/LLHDToLLVM.h
up to circt/Conversion/LLHDToLLVM.h since that is the only thing in that
directory.
This also moves HWLegalize*Names next to it, in preparation for it being
slurped in. This, in turn, allows us to run it before
HWExportModuleHierarchy pass.
ExportVerilog was initially conceived as a translation that read the
IR and printed out verilog text. However, it evolved to being a pass
that mutates the IR (e.g. its prepare pass). As such, it makes more
sense to model it in CIRCT as a transformation: we want to be able to
run passes after it in the pass pipeline, e.g. to generate metadata.
This takes one step towards that, adding new entrypoints that make it
available in circt-opt.
Add a new option to firtool, "--omir-file <file>", which will parse an
Object Model 2.0 JSON file into an OMIRAnnotation. This only handles
parsing. No scattering is performed.
Add one test that the "--omir-file <file>" option used to ingest an
Object Mdoel 2.0 JSON file works for firtool. Check that the
information in the OMIR is preserved and is wrapped in an
OMIRAnnotation on the circuit.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Add a first implementation of Grand Central's `EmitSignalMappings` pass,
which populates a module in a circuit with `force` statements and
cross-module references that access things in a second circuit. This
requires a lot of polishing and ironing out of kinks and the design in
general later, but this is a first bare-bones implementation in the
spirit of the other Grand Central passes (use verbatim SV to get
something going, even if it's brittle and needs some cleaning up later).
To avoid having to deal with the issue that `EmitSignalMappings`
actually operates on two circuits in parallel, the current
implementation only operates on the circuit where the `force` statements
are to be inserted, and uses some text manipulation to guess what name
the forced/probed things in the remote circuit will end up having in the
output Verilog. This will need proper XMRs in the future, but works as a
first shot.
Co-authored-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This commit refactors the handshake-runner to be based on a visitor pattern rather than manually checking for the type of each possible operation. The commit takes a step towards reducing the code duplication between executing a mlir::FuncOp and handshake::FuncOp. Many more opportunities for cleanup and refactoring exists, however, I decided to focus on wrapping the existing code into a visitor for this commit.
Since this is creating verbatim operations instead of emitting files
directly, `create` makes more sense as a verb.
Since the metadata emitted is specific to SiFive build flows, this
renames the pass to make it clear that it is not generically useful.
This leaves the pass on by default since the pass will only do anything
if the correct annotations exist.
This change was suggested here:
https://github.com/llvm/circt/pull/1875#discussion_r716070526
This adds another metadata emitter. This purpose of this pass is to
collect every blackbox module (or extmodule) which will need to be
stubbed or filled in. This excludes blackbox modules which have inlined
or imported verilog.
There are two separate metadata files generated for this: one for
blackboxes instantiated under the DUT as denoted by the
MarkDUTAnnotation. The other is a list of blackboxes not instantiated
under the DUT.
This is currently a simple class that traverses pairs of Affine memory
access operations and uses the upstream `checkMemrefAccessDependence`
function. The results are stored in a convenient data structure that
can be queried to inform scheduling decisions. A test pass is added,
which outputs the results as attributes for verification.
Add a pass to handle all annotation scattering. This pass is table driven, with customizable scattering per-annotation-class. When this is fleshed out, it will replace the annotation handling code in the parser.
Right now, this supports a couple testing annotation to make test cases against.
Until this is live in the pipelines, add an option to the parser to bypass annotation handling and scattering to enable testing.
* [LowerToHW] Lower mainModule and DesignUnderTest attributes into moduleHierarchyFile attribute.
Since these are currently only used for the export module hierarchy
pass, these have been replaced with a more generic attribute marking
which modules should have their hierarchies exported to output files.
* [SV] Add ExportModuleHierarchy pass.
This adds a pass that collects the full module hierarchy into a JSON
string, which is then exported as part of an sv.verbatim op. The pass
collects a hierarchy for each module with the firrtl.moduleHierarchyFile
attribute.
The pass can be enabled in firtool by providing the
--export-module-hierarchy option.
This adds the prefix-modules pass to FIRRTL. This pass looks for
modules annotated with the `NestedPrefixModulesAnnotation` and prefixes
the names of all modules instantiated underneath it. This pass will
duplicate modules as necessary to give submodules unique names. The
annotation can be attached to module definitions, as well as specific
instances.
The supported annotation is:
```json
{
class = "sifive.enterprise.firrtl.NestedPrefixModulesAnnotation",
prefix = "MyPrefix_",
inclusive = true
}
```
If `inclusive` is false, it will not attach the prefix to target module,
only to modules instantiated underneath it.
* [Handshake] Refactor handshake tablegen files
No functional changes; this commit creates an identical structure to the rest of the dialects in CIRCT wrt. how and where the various TableGen'erated files are included.
Just pass down the output filename instead of a lambda, there is no
need for the extra abstraction here. While here, change the timer
in the various flavors of output to be more specific than "Output".
* [Handshake] Support handshake.InstanceOp in handshake-runner
This commit adds support for executing handshake.InstanceOp operations in the handshake-runner.
This is enabled by mostly leveraging the existing executeHandshakeFunction function. When encountering an InstanceOp, a new value- and time map is created, representing the values accessible within the scope of the function referenced by the InstanceOp. In this map, associations between the operands passed to the InstanceOp and the SSA names of the arguments of the function that the InstanceOp references, are created. Return values from the InstanceOp are inserted into the valueMap of the enclosing (caller) scope.
Apart from this, made a slight modification to the structure of the handshake-runner; split up a few functions as well as added an enclosing class to reduce the number of arguments being passed around (i.e., the store, which is global across all std.op executions, InstanceOp executions, etc.).
BlackBoxMemory creates modules with bundles types to replace memory
operations. If this runs after LowerTypes, then we hit the LowerToHW
pass with a bunch of bundle types around. This pass is not often used,
and this must have regressed at some point.
This also adds an integration test to ensure that CHIRRTL memories are being
properly lowered to verilog.
This pass provides a structured way to handle IR features that are not
supported by all tools, and this lowering option reflects a specific
limitation of the Yosys tool.
Right now the pass isn't super helpful: it just rejects unsupported operations
with an error. This is progress towards Issue #1592.
This adds an implementation of the RemoveCHIRRTL pass called
LowerCHIRRTL. This pass takes the CHIRRTL memory operations, `seqmem`
and `combmem`, and transforms them into standard FIRRTL `mem`
operations.
Co-authored-by: Andrew Lenharth <andrew@lenharth.org>
Co-authored-by: Fabian Schuiki <fabian@schuiki.ch>
Co-authored-by: Andrew Young <youngar17@gmail.com>
Add a `--parse-only` option to `firtool` which causes the program to
stop after the FIR/MLIR and annotation input files have been parsed and
processed, and writes the resulting MLIR module to the output. This is
interesting and useful since `firtool` performs a unique combination of
input translation and annotation scattering that is not trivially
reproduced with `circt-translate` and `circt-opt`. Useful for test case
reduction.
- Update/rewrite the `circt-reduce` tool with a custom proof-of-concept
reducer for the FIRRTL dialect. This is supposed to be a pathfinding
exercise and just uses FIRRTL as an example. The intent is for other
dialects to be able to produce sets of their own reducers that will
then be combined by the tool to operate on some input IR.
At this point, `circt-reduce` can be used to reduce FIRRTL test cases by
converting as many `firrtl.module` ops into `firrtl.extmodule` ops as
possible while still maintaining some interesting characteristic.
- Extend `circt-reduce` to support exploratively applying passes to the
input in an effort to reduce its size. Also add the ability to specify
an entire list of potential reduction strategies/patterns which are
tried in order. This allows for reductions with big effect, like
removing entire modules, to be tried first, before taking a closer
look at individual instructions.
- Add reduction strategies to `circt-reduce` that try to replace the
right hand side of FIRRTL connects with `invalidvalue`, and generally
try to remove operations if they have no results or no users of their
results.
- Add a reduction pattern to `circt-reduce` that replaces instances of
`firrtl.extmodule` with a `firrtl.wire` for each port. This can
significantly reduce the complexity of test cases by pruning the
module hierarchy of unused modules.
- Move the `Reduction` class and sample implementations into a separate
header and implementation file. These currently live in
`tools/circt-reduce`, but should later move into a dedicated reduction
framework, maybe in `include/circt/Reduce`, where dialects can easily
access them and provide their own reduction implementations.
* Extract reset-related test cases from the existing Scala FIRRTL
compiler code; specifically from `InferResets`, `CheckResets`,
`RemoveReset`, and `FullAsyncResetTransform`.
* Add the `InferResets` transformation pass to the FIRRTL dialect, which
assigns asynchronous resets to registers without reset, and replaces
`reset` types with either `uint<1>` or `asyncreset`, as appropriate.
* Add the `--infer-resets` option to firtool, on by default.
Inlining and IMConstProp generate additional opportunities for
canonicalization, especially around registers with invalid/constant
reset signals and values. To leverage these, firtool should run the
canonicalizer again just before going into the output-specific
pipelines.
Add the `--split-input-file` and `--verify-diagnostics` options to
firtool. This brings it more in line with other tools such as circt-opt,
and simplifies writing integration tests against firtool.
Add a `circt-reduce` utility, which basically follows the "build a
custom mlir-reduce" steps described in the MLIR documentation. The
intent here is to have a first step towards a CIRCT-specific reduction
utility. At a later stage, we may want to start populating the reducer
framework with reduction patterns specific to CIRCT (like fan-in/-out
cone isolation, port removal, etc).
This pass runs a strongly connected components (SCC) detection to check
combinational cycles in the IR. The current implementation assumes the
firrtl-lower-types and firrtl-expand-whens has been applied before this pass.
This turns on the FIRRTL inliner by default. This pass has some
questionable behaviour where it will delete any module not reachable
from the top level module. This is an optimization that prevents the
pass from performing uneccesary work, while not leaving unprocessed
modules in the code. This is also the mechanism through which modules
which had all instances inlined will be deleted. We may want to decide
if this behaviour is desirable before merging this commit.
Merge the `CheckWidhts` pass into the `InferWidths` pass, which already
has all the necessary information to complain to the user about
uninferred widths. This commit also improves error reporting a bit by
tracking additional location information on the constraint expression
such that we can point the user at the sites where a connection may
cause problems.
Fixes#1297.
In a couple of places in our build system, we wanted to create targets
that depended on generated files. We were not passing the full path to
the generated files, e.g. `CosimScheme.h`, and CMake was unable to find
the it. CMake was then searching the current directory for a
matching file with a prefix, and would find the unprocessed
file, e.g. `CosimSchema.h.in`, and use that instead. A policy change
CMP0115 in newer version of CMake causes this to spit out many warnings
about it how it will no longer search for source files. For more
information about the policy see
https://cmake.org/cmake/help/latest/policy/CMP0115.html
This change provides the full path to the generated file, which allows
cmake to find the intended file and not produce so many warnings.
Rewrite LowerTypes to simplify and improve performance.
Walks the operations in reverse order. This lets it visit users before defs. Users can usually be expanded out to multiple operations (think mux of a bundle to muxes of each field) with a temporary subWhatever op inserted. When processing an aggregate producer, we blow out the op as appropriate, then walk the users, often those are subWhatever ops which can be bypassed and deleted. Function arguments are logically last on the operation visit order.
Each processing of an op peels one layer of aggregate type off. Because new ops are inserted immediately above the current up, the walk will visit them next, effectively recusing on the aggregate types, without recusing. These potentially temporary ops (if the aggregate is complex) effectively serve as the worklist. Often aggregates are shallow, so the new ops are the final ones.
There is no global map. When you update an aggregate producer, you build a small vector of it's expansion, which you use to update it's users. Once the users of an aggregate are updated, there is no reason to store mapping data on them any longer.
This structure makes it relatively easy to to do connect-expansion and partial-connect-legalization along the way. connects get processed before their source and dest.
This gives a 40% improvement on a medium sifive core and hasn't been tuned yet.
Co-authored-by: Prithayan Barua <prithayan@gatech.edu>
Co-authored-by: Prithayan Barua <prithayan@gmail.com>
Emit a warning after lowering `FIRRTL` operations to `HW` dialect,
if there are `annotations` remaining on the `FIRRTL` operation.
This is required to detect missing passes in FIRRTL dialect to remove the annotations.
The warnings are disabled by default.
- Use a set to record all the annotations remaining on different operations.
- Emit a warning for each annotation only once. So if the same annotation is found on different operations, only one warning is emitted.
- Add an option to `LowerFIRRTLToHW` pass to enable the warnings
- The option is disabled by defailt
- Use`emit-annotation-warning=true` to emit the warnings
- Add option `emit-annotation-warning` to `firtool` , which should be passed to `createLowerFIRRTLToHWPass`
- Note: The `emitWarn` will crash when trying to print the `InstanceOp`. Reason for crash:
1. If we try to print the old `InstanceOp` operation while traversing the operations in a module, the symbol referring to the module is invalid. Hence `getReferencedModule` crashes.
2. The traversal is on the new temporary module body, which has moved(`splice`) the old operations, https://github.com/llvm/circt/blob/main/lib/Conversion/FIRRTLToHW/LowerToHW.cpp#L825
3. Seems like the original symbol on the operation gets deleted during the `splice`, hence the invalid temporary IR.
- To fix the crash, we don't print the operations by using `mlir::emitWarn`, and just print the source location.
- Use `std::mutex` when updating the `StringSet<> alreadyPrinted` in class `CircuitLoweringState`
- `CircuitLoweringState` object is shared between threads working on modules, hence the lock is required when updating the set. (https://github.com/llvm/circt/blob/main/lib/Conversion/FIRRTLToHW/LowerToHW.cpp#L208)
* Add a `GrandCentralTaps` pass which consumes the FIRRTL Grand Central
data and memory taps annotations, and generates the corresponding
blackbox data tap modules with hierarchical Verilog identifiers
inside.
* [FIRRTL] Add Grand Central Interface Support
* [FIRRTL] Add Grand Central Interface Tests
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
We previously disabled multithreading when parsing the input file
to save cost on some mutexes etc, since the parser wasn't threaded.
Now however, the verifier is threaded, and disabling multithreading
is disabling it as well.
Just stop doing this. This provides an aggregate speedup for me,
e.g. shrinking total firtool time from 29.9s to 26.7s on a large
design (18.6s -> 15.2s in the parser) which is a pretty big speedup.
It was decided that "black box" should be consistently used as two words
in the code base. See #1209.
```
Blackbox -> BlackBox
the blackbox -> the black box
```
To paraphrase Aliaksei over slack, "The people always wanted
imconstprop, what could possibly go wrong" 🙈
Admittedly, I might be paraphrasing that wrong.
This pass has been subjected to fuzz-testing for quite some time, and it
is surprising (in a negative usability sense) that it is not enabled by
default.
Some FIRRTL-to-LLHD tests were using firtool with uninitialized ports,
and this change switched them to use circt-translate instead.
* In addition to the `--blackbox-path` option which specifies the
overall search path for black box files (including `BlackBoxPathAnno`
annotations), add a separate `--blackbox-resource-path` option which
only affects the `BlackBoxResourceAnno` annotations. These get moved
into the Scala/sbt artifacts directory, and the resource path should
generally point there. Path annotations in general will want to remain
relative to the input FIR file, which this additional enables.
* Move the width inference pass up in the pipeline such that it runs
before the canonicalization passes. This is useful since width
inference itself does not depend on canonicalization, but in turn
enables a lot of canonicalization patterns to run.
* Add the `BlackBoxReader` transformation pass which is modeled after
the `BlackBoxSourceHelper` Scala implementation. It honors a set of
FIRRTL annotations that declare source code for black boxes to be
copied to an output directory. This pass reads those source files into
an operation in the IR, such that they can be written to the output
during emission. Annotation can be done inline, as a separate path, or
the rather Java-specific resource mechanism.
Required changes:
- The vector namespace in MLIR was colliding with the std::vector type
- Missing MemRef dialect dependency in circt-opt
- Missing Standard dialect dependency in ExportLLHD
This makes sure not to rename FIRRTL to HWRTL :-), and I spot checked a
many things to avoid changing general references to RTL (e.g. when referring
to external tools) but I suspect that I missed some. Please let me know (or
directly correct) any mistakes in this mechanical patch.
The difference is that we no longer run the dtor for the MLIRContext
that we parse a bunch of IR into. This avoids spending time
deallocating memory, which is pointless immediately before process
exit.