This makes this more efficient (not doing a full mlir::Module walk to
look up uncached symbols), makes the diagnostics in ExportVerilog
come out with the correct location info again, and changes this accessor
to return null on failure, instead of emitting an error from the accessor.
There are still larger design changes that would make sense here
conceptually, but I'm not going to work on typedefs much.
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.
Change the Grand Central Views/Interfaces pass to apply an outer
module-level prefix (derived from a NestedPrefixModulesAnnotation that
was handled by the PrefixModules pass) and an inner prefix set by an
optional PrefixInterfacesAnnotation. Modify RenameModules to set the
outer prefix by adding a "prefix" field to the circuit-level, outermost
AugmentedBundleType.
Supporting this, add a getter to retrieve the "prefix" field of an
AugmentedBundleType.
Add two tests: (1) test that PrefixModules correctly updates Grand
Central interface annotations and (2) test that the GrandCentral pass
correctly applies a prefix coming from PrefixModules and from a
PrefixInterfacesAnnotation. As part of (2), ensure that the
PrefixInterfacesAnnotation is removed.
Update FIRRTL rationale document with information about how Grand
Central-generated interfaces can be prefixed.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
With the new CMake functionality upstream, we need to set the
ENABLE_AGGREGATION option when we call add_mlir_library. The easiest
way to do this is to just rely on the upstream helper
add_mlir_public_c_api_library, which does this and other important
settings for us.
Also, ensure the MSFT dialect's CAPI marks all of the public functions
as being exported.
The `parseKeywordOrString` function was recently added to the MLIR
parser, and we can simplify some code by using it. We can remove the
functions `parsePort` from SV and `parseIdentifier` from FIRRTL. These
functions all print a string as a keyword unless it contains illegal
characters, where it would print as a string.
Closes#1656 by removing the LLHD insert operations and replacing the extract operations as described in the issue.
Some notes/observations:
- Semantics of accessing out of bounds for both slices and single elements in LLHD were partially implemented to return a default value depending on the type (only for non-signal arrays in `llhd.dyn_extract_slice`) or UB. This PR defines it to be UB as this is also what HW does (I think).
- Field accesses to structs are checked, though.
- Extract slice operations cannot return a wider type (at most equal size), I think this is not the case in HW
- `llhd.sig.array_slice` does not work for a full slice of an array with one element (also `llhd.sig.extract` with signal of `i1`) as it requires a `i0` value as index, but this is not supported by `HWIntegerType` (e.g., `llhd.sig.array_slice %array at %index : (!llhd.sig<!hw.array<1xi32>>) -> !llhd.sig<!hw.array<1xi32>>`). A full slice, however, works for more elements in the array. `hw.array_slice` has the same behavior, I don't know if this is intended, or whether it should be enabled, or returning the same number of elements should be forbidden. Seems a bit inconsistent to me this way.
- Removed `sig` type support for `llhd.shr` in `LLHDToLLVM` as it was wrong in the first place (see #1988 ) and it lowered to an operation removed with this PR. It requires concatenating two signals in some way, this seems too complicated to quickly include in this PR.
Instead of having helper methods with a GroupInterface parameter, we instead add
InterfaceMethods to the GroupInterface for logic relating to port driving / reading in
groups.
This makes way for dimensions that can refer to declarations within the
module, like parameters.
Note that this exposes some design problems with TypeAliasType.
I just xfailed a test for now (the expected diagnostics are emitted on
the wrong line now) where ExportVerilog is implementing verification of
these decls instead of the verifier. I will tackle that as its own
separate workstream, since type parameters needs a sound design as well.
This analysis depends on the MemoryDependenceAnalysis and uses the
dependences to compute a partially complete CyclicProblem for each
AffineForOp loop nest.
The primary contribution of this change is to add port directions and
names to the instance op. This fixes the issue where we had to fetch
this information from the referenced module, which was not guaranteed to
be thread safe.
The printed form of the instance op is now a hybrid between the HW
instance op and a FIRRTL module, printing the entire "module signature"
at the end. This is quite verbose but needs to be in the IR format (i.e.
every op has to be parsable using only local information).
```mlir
firrtl.instance test @simple(in a: !firrtl.uint<1>, out b: !firrtl.uint<1>)
```
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.
Extend the SV dialect to cover all simulation control system tasks
(`$stop`, `$finish`, and `$exit`), and all severity message tasks
(`$fatal`, `$error`, `$warning`, `$info`). This change includes added
support for diagnostic verbosity in stop, finish, and fatal, as well as
optional messages and interpolation operands for fatal, error, warning,
and info.
A subsequent PR will make use of these to lower from the FIRRTL dialect.
Add an attribute to indicate the file containing the op should be put in a specific filelist at emission time. This attribute allows files to exist in multiple filelists.
Extend the assert, assume, and cover verification operations to support
optional arguments for interpolation into the message string. Also clean
things up a bit by factoring out the commonalities of the verif ops into
a `VerifOp` parent class.
Adjust the parser for printf-encoded verification ops to leverage the
new message interpolation behaviour, passing through any operands to the
`printf` op. Also update the `LowerToHW` pass to carry the message
interpolation over into the SV dialect.
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>
The `FirMemory` is a struct with the relevant `FIRRTL` memory properties.
It was constructed during `LowerToHW` for lowering the `FIRRTL::MemOp` by
extracting its attributes.
But the `FirMemory` is also required during the memory metadata generation.
In this checkin we move the `FirMemory` struct out of `LowerToHW` and add it
to the `FIRRTLOps.h`.
This also fixes the memory names emitted during the metadata generation.
When port directions and names are moved on to the instance op these
fields can be taken directly off of the module. In many cases this
new builder greatly simplifies the process of creating a new instance operation.
Add an optional message and list of operands to be interpolated into the
message to the verification operations in the SV dialect (immediate and
concurrent). This message is expected to be printed when the assertion
fails, and is emitted as `... else $error(msg, operands...)`.
Also add a new `defer` field to immediate assertions which allows for
the emission of `assert #0` ("observed deferred assertion") and `assert
final` ("final deferred assertion"). There are use cases in the FIRRTL
dialect that will make use of this feature in a follow-up commit.
This commit also adjusts the parsing/printing of verification ops in the
SV dialect to accomodate the optional label and optional message parts
more easily.
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.
Instead of walking the entire design hierarchy to rename a module that
conflicts with a symbol, just add a "verilogName" attribute to it. This
encodes a simple idea that the verilog name of a module is the contents
of the verilogName attribute or the symbol name if not present, just
like it already is for external modules.
XMRs or hirarchical names are really annoying. They have context-dependent lookup rules. They resolve to multiple elements. They resolve to external elements. They require whole-world assumptions to resolve; resolving on a partial circt might indicate something isn't refereced which really is after linkign in external code.
This implements a purely syntactic XMR. It does not try to link the name to existing circuit elements, this requires expensive analysis. Frontends need to mark path elements with don't touch (or equivalent) where they want a path preserved.
The prior implementation was trying to rename symbols, which is
fraught because they occur in types and would require rebuilding
type hierarchies. Use GlobalNameTable to handle the needs here
instead.
This fixes Issue #1967
This change removes the `portAnnotations` and `portNames` attributes
from the FExtModule and FModule op's argument lists. Here are
the differences that this change makes as far as I can tell:
1. Less obvious that these attributes exist on the operation (bad thing)
2. We don't have redundant `portAnnotations()` and
`getPortAnnotations()` functions defined (good thing)
3. We don't have redundant verification of the attribute from the
`AnnotationArrayAttr` type constraint and `FModuleLike` verifier
(might be a good thing).
4. Does not affect the builder methods, as these ops do not use the
generated builder methods. (no effect)
Given what I have seen in other interfaces, I think this is the way to
go.
Covert freechips.rocketchip.annotations.InternalVerifBlackBoxAnnotation annotations to a generalized set of annotations that works not just for cover, but assert and assume extraction too. Process those annotations in ExtractTestCode.
Add fold patterns for `BitCastOp`.
1. Input and result types are same, then `BitCast` is redundant
2. If `BitCast`s are chained to form the same result type as the original
input, then they are redundant.
Renames the handshake passes to be in line with the naming convention used in the remainder of the CIRCT passes.
- `create-dataflow` -> `lower-std-to-handshake`
- `analyze-dataflow` -> `handshake-analyze`
- `canonicalize-dataflow` -> `handshake-canonicalize`
- `remove-block-structure` -> `handshake-remove-block-structure`
Add memory metadata emission to `CreatesifiveMetadata`.
The metadata is used for memory macro substitution by memory generator tools.
A subsequent checkin will delay the `CreatesifiveMetadata` pass in
the FIRRTL pipeline.
Add portAttributes and portDirections arguments to ComponentOp. I also remove unpackAttribute,
as it remains unused (and thus untested). This closes#1950.
This change mostly affects FIRRTL, where Calyx has a small update to
make sure that some previously copied code matches identically.
This change removes the special handing for port directions when there
are zero ports. Port directions are represented using an APInt as
a bitvector, and since APInts previously did not support 0 bit wide integers
there was some logic to handle this as a special case. Since APInts
have been updated to allow 0 bit wide integers, this commit removes this
special handling.
In addition to this, some other cleanups included are:
- Moving the port direction logic from FIRRTLInterfaces to
FIRRTLAttributes. Since the port direction logic is not tied to the
FModuleLike interface anymore, it can be used for other things like
InstanceOps.
- Removing the `direction::attrKey` which was used as the attribute name
for directions. Since this string is not a part of any OpInterface, it
is unclear what code should use it. A future change should be made
to stop using string literals and use
`FModuleLike::getPortDirectionsAttrName()` where appropriate.
- Fix printing of directions, and make them work with regular streams.
This lets us use it in `printModuleSignature()`.
- Remove some verification from FExtModule which is already handled by
FModuleLike.
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.
This change renames the `getBodyBlock()` function to `getBody()`, which matches
the CircuitOp API. In a module there is only ever one region with one block in
it, and there is rarely a reason to get the Region. Naming this wasn't possible
before as `FunctionLike` was squatting on the `getBody()` name, which has
recently been dropped.
This moves support for port directions, names, types, and (port)
annotations into the `FModuleLike` operation interface. This also
removes the `FunctionLike` trait from `FExtModules` and `FModule`
operations.
Dropping support for `FuncLike` means that we are free to represent port
types as an array of types, instead of a functional type. This brings
some simplicity as port names and annotations were already arrays.
Another large difference is that we no longer support function argument
attributes. There was a significant amount of complex code written to
support `argAttrs` and `portAnnotations` at the same time. Removing the
unused `argAttr` support simplified our code and IR printed format.
This work is not totally complete, but I decided to cut it here before
the change became too large. Some additional follow up work is:
1. Cleaning up the Direction attribute, utilizing new APInt 0 bit
support.
2. Simplify FModuleOp's inputs TypeContraints so that the real
verification is done by the FModuleLike verifier. Port existing tests
over to the new verification logic.
3. Update `InstanceOp` and `MemOp` to use the same function names as
`FModuleLike`, e.g. `getPortName()` instead of `getPortNameStr()`.
In an earlier change, I made InferResets always mark the InstanceGraph
analysis as preserved, under the assumption that the pass does not
modify the instance graph. This turns out to be incorrect as it can add
arguments to a module and must recreate the instance ops to reflect
that.
This change adds a function `InstanceGraph::replaceInstance(old, new)`
which allows the InstanceGraph to stay updated by the pass. This is the
first function added to the InstanceGraph to allow updating the cached
analysis. This function is slightly more efficient then adding a
separate `addInstance(new)` and removeInstance(old)` functions.
* [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.
Move singleton headers like circt/Conversion/LLHDToLLVM/LLHDToLLVM.h
up to circt/Conversion/LLHDToLLVM.h since that is the only thing in that
directory.
Fix a linker issue introduced during the ExportVerilog rework. The
implementation defined for `createExportVerilogFilePass()` was causing
problems as this was included in both `firtool `and `circt-opt`.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Changes a cell's instanceName argument from StringAttr to FlatSymbolRefAttr. This will be necessary for the
addition of an InvokeOp, which needs to verify that the instance being invoked actually exists. Since primitives
(namely multi-cycle ones) may also be invokeable, this is required for all cells. This also verifies there is no name
shadowing with symbol names for components and cells.
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.
No functional changes. This PR simply renames DeviceDB to PlacementDB within the MSFT dialect. The "DeviceDB" name may be used in a future PR and live alongside the PlacementDB.
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>
Move the source locator parsing inside FIRRTL's parser into a utility
method called maybeStringToLocation. Make this change because source
locators can show up in places other than FIRRTL text. Namely, source
locators are used inside Object Model 2.0 JSON (and could also show up
in annotations).
Note: this utility has a super, super wacky API and should be cleaned up
later. However, this intentionally done (for now) as a direct, NFC
conversion of the existing code inside the parser.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
We've switched to Python-based generators. Ping-ponging between IR modifying
C++ and IR modifying Python was a massive mistake for pointer safety reasons.
Add a new `bitcast` operation to `FIRRTL` dialect, which will be directly
lowered to `hw::bitcast` operation.
The `bitcast` operation can be used to directly cast a `vector` or `bundle`
type to a flattened `uint`, without blowing out the fields.
This operation will be used to simplify lowering of aggregate memory data
type in `LowerTypes`.
Removes the result type from the comb.concat type signature since it can be
deduced from the inputs.
For example, this previous signature:
```mlir
%0 = comb.concat %false, %b : (i1, i4) -> i5
```
is simplified to:
```mlir
%0 = comb.concat %false, %b : i1, i4
```
Address #1623.
Adds builders to initialize bodies for IfOp, WhileOp, CombGroupOp, GroupOp, WiresOp, and ControlOp.
This also removes their default builders, since it would be odd to want a Calyx container without a body.
The rest is necessary clean-up in SCFToCalyx and CompileControl. Closes#1884.
This adds canonicalization patterns for empty IfOp, WhileOp, SeqOp, and ParOp bodies. For the former two,
we also check to see if the (optional) Group and conditional are used. if not, we remove them as well. This also
loosens the verification restrictions for empty bodies in a WhileOp and IfOp. IMO, these are still valid with an
empty body.
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>
Apply @lattner's suggestion in #1903 to have just a single `newName`
implementation that takes a twine, and use twine's fast-path for the
StringRef case to make things quick.
This adds a pattern for when then and else regions are both ParOps. It also takes into consideration
the parent region of the IfOp, since we don't want to unintentionally change the behavior when pulling
out EnableOps. I also do not touch anything that's not immediately within the given ParOp's body;
doing so may also change the behavior of the program. The case where the then and else regions are
different, e.g. SeqOp and ParOp, should never pull out an EnableOp; it will always produce worse code.
Move the `CircuitNamespace` helper struct from the current Grand Central
source files into a public header file. This acts like a symbol table
specifically for `firrtl.circuit` ops and is useful for avoiding name
conflicts when generating additional modules.
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
Adds some canonicalization methods for SeqOp and ParOp to replace the pattern rewrite in SCFToCalyx.
This is similar to the native compiler's Collapse Control pass. For the cells section, uses CHECK-DAG
since we don't particularly care what order the cells are listed in. This was previously causing test failures,
after adding the -canonicalize flag.
Switches the GroupGoOp, GroupDoneOp, and AssignOp to match the native compiler representation.
We're still pretty dependent on the native compiler, so it seems right to keep the IRs as similar as
possible. Closes#1873.
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 adds a new `EmitMetadata` pass to FIRRTL which a dumping ground for
any simple metadata generation passes that don't make sense to implement
as a standalone pass. The first pass implemented is `RetimeModules`
which just collects the name of any annotated module and emits it into a
JSON array.
This moves OutputFileAttr from an AttrDef to a StructAttr. This
StructAttr prevented us from puting member functions on the attribute
which were need.
This adds the ability to normalize filenames when creating an
OutputFileAttr, which is helpful when creating these from FIRRTL
annotations.
This also removes the cmake magic for generating StructAttrs in the HW
dialect, as there were none left.
Add support to add multi-bit mask type for FIRRTL memories.
This is required for flattening an aggregate memory data type, and enabling
a finer mask granularity by extracting individual bits from the memory data element.
The mask width was hard coded to 1 bit, this PR will remove that restriction.
zexti and trunci operations generate handshake components which wrap around FIRRTL `pad` and `bits` operations. The builder for each of these ops is used to support `index_cast`, which pads or truncates an input type compared to the fixed index-width (64 bits).
The `hw::InstanceOp` (which `msft::InstanceOp` lowers to) convenience
builder gets its argNames and resultNames from the `hw::HWModuleOp`. So we
have to lower `msft::MSFTModuleOp` before we lower `msft::InstanceOp`.
* [FIRRTL] Rename ResetType to AnyResetType, add actual ResetType
The FIRRTL dialect currently has things like `AsyncResetType` or
`ClockType` which are the actual types, but `ResetType` is a constraint
that captures `asyncreset`, `reset`, and `uint<1>`. Rename this to
`AnyResetType` and add a `ResetType` that represents the actual
buildable `firrtl.reset` type in analogy to the others.
* [FIRRTL] Add async reset const check to LowerToHW
When lowering a `firrtl.regreset` with async reset in `LowerToHW`, check
that the reset value is a constant. This is a common constraint imposed
by EDA software and is enforced on the Scala side as well (in the
CheckResets pass).
This also finally enables the `async-reset-errors.mlir` integration test
that we had for quite a while now.
Fix a compiler warning where a struct was forward declared as a class.
Apparently this can cause linker problems with the Microsoft C++ ABI.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Add builders that don't require a guard for AssignOp and the GroupOp ports. Now, we no longer need to add
an empty Value constructor for `guard` when building the operation.
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 helper methods for the IfOp. The IfOp inherits from CalyxContainer, which has the SingleBlock trait,
so it should be guaranteed that each region has a single block. I've renamed the getters to remain in line
with the getBody helper for other Calyx containers.
Closes#1810
The changes to `hw.module` and `hw.instance` make them incompatible with `msft.module` and `msft.instance` as far as the python bindings are concerned. I'm not sure what I want to do here so I've marked that test as `xfail` for the moment.
The compiledGroups attribute is only used during the (currently incomplete) lowering process of Calyx IR
to signify which groups are attributed to the calyx.enable during compilation. This maintains the invariant
that all Group symbols are referenced throughout the life time of a Calyx program. This PR adds another
builder to skip initializing it. Closes#1844.
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.
This includes export verilog and legalizenames support.
This is just a minimal first step. It has several issues that we
need to improve over time:
1) Support variadic operators.
2) Support better .mlir syntax
3) Precedence aware printing in generated verilog.
https://llvm.discourse.group/t/rfc-representing-pipelined-loops/4171/1
for more discussion.
This defines the operation's syntax more or less as discussed,
including round-trip tests for the five running examples we've had.
In order to reduce test churn, the existing PipelineOp and the
StandardToStaticLogic pass are left untouched for now. Ultimately, the
new pipeline operation could replace the existing PipelineOp.
The verbatim op can be used for macro substitution with values. This PR adds
support for macro substitution with symbols.
For example,
```mlir
sv.verbatim "MACRO({{0}}, {{1}} reg={{4}}, {{3}})"
(%add, %xor) : i8,i8
{symbols= [@reg1, @module1, @instance1]}
```
In the above operation, `0` and `1` will be replaced by `%add` and `%xor` ,
`4` with the verilog name of the symbol `@instance1` and `3` with the
verilog name of the symbol `@module1`.
Changes in this commit:
1. Add the optional array of symbols as an attribute to the `VerbatimOp`
2. Add a type constraint for an array of `FlatSymbolRefAttr`, this can be pushed to `mlir`.
3. Update `ExportVerilog` to get the verilog name for any symbol. Most of the changes
in `ExportVerilog` is just to ensure the final symbol names can be tracked.
4. Update docs and test cases.
When the MLIR parser reads in an empty region it does not create a
block. The SymbolTable trait requires that the region has a block.
Adding the SingleBlock trait to the interface operation fixes this
issue.
* [SCFToCalyx] Add calyx::ProgramOp conversion [2/13]
This commit introduces logic for converting a top-level MLIR 'module' into a calyx::ProgramOp.
The implementation works around an issue/restriction of the current infrastructure, being that a top-level 'module' cannot be overwritten. see: https://llvm.discourse.group/t/de-privileging-moduleop-in-translation-apis/3733/26
Furthermore, an input program is legalized using a `ConversionTarget`.
This takes a similar approach to the FIRRTL structure. We define an entry-point component by
using its name in the ProgramOp. This is guaranteed to be unique since each ComponentOp
name is a `Symbol`.
Add a new enumerated attribute that defines the write-under-write
behavior of HW memories. Two flavors are added: (1) undefined behavior
and (2) port-ordered behavior.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This makes it more efficient by storing it as a first-class attribute,
rather than as an interpreted dictionary. This exposes a bunch of
ways in which StructAttr is unnecessarily different than AttrDef,
which is filed as LLVM PR 51909
This also renames it to hw.verbatim.parameter.value, and gives it a
proper type. This makes it possible to do attribute checking without
the overhead of introducing an attribute interface.
This also switches the module build() methods to take an ArrayAttr for
parameters instead of an ArrayRef<ParameterAttr>. This is more consistent
with instances and is easier to work with.
* [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.
- Adds python bindings for MSFTModuleOp and InstanceOp.
- Re-use as much as possible from `circt.hw._hw_ops_ext`. Required changes to
ODS definitions.
- Found and fixed some bugs.
Fixes the emitter so that an `ElseRegion` for the `IfOp` is emitted, if it exists. This required
adding a regionIndex variable to determine whether the current region should be the ThenRegion
or ElseRegion of an IfOp.
Adds a moduleop to the MSFT dialect. For now, it's mostly like hw.module but adds parameters to represent the specific parameterization of a parameterized module. Also necessarily adds a msft.output since hw.output expects to be in a hw.module.
Step 3 of #1755.
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.
Remove a lot of assertions and checks that are validated by the ODS and `verifyInstanceOp` function. Secondly,
use SymbolOpUserInterface in MSFT dialect to avoid O(n) lookup when verifying the InstanceOp.
This makes both hw.module* and hw.instance carry an argNames/resultNames
array attribute for the port names, and the verifier checks that they
line up.
This makes various queries on the instances much much faster (because
you don't need to resolve the module being referenced) and makes the
code more obviously correct in multithreaded situations.
This adds a combinational trait to Calyx operations. We can throw this on all non-memory operations for now,
since they are all combinational. Eventually we'll need to split this off. Closes#1739. Also fixes a bug where it
was considering a memory load as a store, since the address ports are used when both storing and loading to
a MemoryOp. A test is added to verify this no longer occurs.
As discussed in #1769, some verifiers should be added to avoid giving the sources of group ports / assignments
logically complex expressions. Also adds a verifier to ensure that GroupOp isn't being used as a CombGroupOp, and
makes the necessary refactoring. This will be removed when native Calyx supports complex arguments for sources.
This PR focuses on (2) objectives. First, verifying that combinational groups are indeed combinational.
Combinational components are not supported yet, so component instances are always assumed to be
combinational for now. Second, we also verify that certain ports are written or read together. For example,
it does not make sense to write to a register without write_en being high. To aid in this, I added helper
functions to access certain ports on primitive operations.
This pulls the port names and port types inline into the argument list,
and adds result port names to the output signature. This increases readability
and is a stepping stone to hw.instance maintaining its own port names.
This makes room for printing port names in the argument and result
list. Unfortunately we cannot use a custom<> directive with result
types, so we have to take over printing for the whole thing.
Add support for lowering to concurrent instead of immediate verification statements.
This emulates the SFC behavior of lowering printf encoded verification statements to concurrent statements.
1. Added `isConcurrent` attribute to `FIRRTL` `assert/assume/cover`, and set the attribute only when lowering printf encoded statements.
2. Added a enum attribute `eventControl` with default value set to `AtPosEdge`, this can be used to represent the `sv::EventControlAttr`. FIRRTL dialect is not using the `eventControl` attribute currently.
3. Also update the `LowerToHW` to lower the corresponding concurrent statements, depending on the `isConcurrent` attribute.
4. Add corresponding test cases.
dds support for attributes on primitive ports. No emission is necessary for the ports of
a primitive. Calyx primitive attributes are already supported as well. This closes#1744.
Part of #1758, move name dropping later in the pipeline. This makes the parser simpler, but more importantly, keeps names around until after we've processed annotations, some of which produce better output or might require the original names.
`msft.instance` is intended to be like `hw.instance` but with headroom for MSFT-specific additions. It will lower to `hw.instance`. This just creates the op.
Step one of #1755 .
Add a `firrtl.verbatim.wire` operation which is similar to `*.expr` but
the resulting value has wire semantics. This is useful if the verbatim
string refers to a wire or port, and allows verbatims to be used in
connects or force statements.
Add a `firrtl.force` operation which properly lowers to the
corresponding `sv.force` operation. There is additional discussion in
PR #1665 regarding the proliferation of these operations. If we end up
replicating a lot of the SV ops in the FIRRTL dialect, we might want to
look into ways to use casts and a general scheme to reuse the SV ops to
work with the FIRRTL-typed values directly.
This change unblocks work on the Grand Central signal driving PR for
now, but we'll have to revisit these ops likely in the future.
Allow the `sv.verbatim.expr` operation to produce an `InOutType` as
well, which is useful if the verbatim expression refers to a wire or
por. Operations such as `sv.force` can then be used to drive the expr.
Change PortInfo::getAttribute to return an llvm::Optional instead of
std::optional. Generally, llvm:: is preferred over std:: and this also
works around MSVC wanting <optional> to be explicitly included for the
std:: variant to work.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This PR is a collective effort to add Calyx attributes and emit them in the native compiler. This requires the addition of
attributes for BlockArguments. The second part of the effort is proper emission of attributes that are found in the native
compiler. Lastly, we add an optional attribute dictionary to the ComponentOp.
This speeds up verification by using a prebuilt symbol table to look up
the referenced module instead of a linear walk of the IR. A similar
change was recently made to the FIRRTL InstanceOp in 438ffeb0.
Rewrite the Grand Central Views/Interface pass to fully support the
Grand Central Chisel API. Specifically, enable support for interfaces
that instantiate other interfaces, support n-dimensional vectors of
interfaces, and add generation of XMRs to drive the interfaces.
Change Grand Central annotation scattering to represent interfaces with
a recursive structure. Interfaces which instantiate other interfaces
will show up as BundleTypes in the elements where they are instantiated.
This keeps the interface representation intact until the Grand Central
pass can choose to handle this however it wants.
Also, change scattering to using numeric IDs instead of relying on string
matching to keep track of interface membership.
Add an MLIR Attribute hierarchy to represent this recursive structure.
Use this to factor out verification logic from business logic that
generates interfaces.
After this rewrite, the pass now works in the following way:
1. Extraction information is pulled out from the circuit along with
annotations that describe the interfaces.
2. The full circuit is walked to build up information about companions,
parents, and leaves that will be connected to the interface.
3. Interface annotations on the circuit are then recursively walked to
generate interfaces, instantiate interfaces, and generate XMRs in a
"mappings" file that drives the interfaces.
A CircuitNamespace utility is added to generate unique symbols for
interfaces and binds that need to be created.
Interfaces (and other collateral) are only extracted if an
ExtractGrandCentralAnnotation is present. This is a deviation from the
Scala FIRRTL Compiler Grand Central pass where absence of that
annotation will cause an assert to fire.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Make the GrandCentralTaps utility "InstancePaths" generally available by
moving it out of the anonymous namespace in GrandCentralTaps and into
circt::firrtl to cohabitate with InstanceGraph. This is a generally
useful utility for computing paths.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
* [Calyx] Implement combinational groups
Adds a new kind of groups `CombOpGroup` for representing combinational groups. Fixes#1735.
- Combinational groups have no terminators.
- `group_go` and `group_done` are implicitly not allowed in comb_groups since they only accept `GroupOp`s as a parent.
- A new interface `GroupOpInterface` has been implemented to allow for sharing most of the logic for validation/emission of both `GroupOp` and `CombGroupOp`
Some of the tests in errors.mlir were failing - i suspect this is due to changes in the ordering of how validators are applied. Modified where necessary to isolate the error that is tested for.
We have decided that we want the default options in CIRCT to make use of
newer SystemVerilog constructs which improve the quality of output. In
the initial commit for adding a lowering option for `alwaysComb`
printing, we defaulted to print `always_comb` as `always @(*)`. This
flips the default setting and the changes the flag name to
`noAlwaysComb`, which is more in line with our desired output.
This is probably not the end of our efforts to customize the lowering of
`alwaysComb`: `always @(*)` and `always_comb` are not 100% equivalent
and have differences in their behavior at time 0.
Before, there was an early short-circuit to ensure that if the Value has no defining operation, we would not
TypeSwitch on it. A block argument will not have a defining operation. This led to the problem in #1724;
since %done is a block argument of the ComponentOp, we just short-circuited. This pull request now
checks to see if the value is a BlockArgument, and emits the respective port.