Now that the Python bindings for ClassType can return a Python object
of the actual ClassType Python class, it would be useful to get the
ClassType's name from such an object. This includes the usual C API
boilerplate to call the accessor in C++, and the usual Python wrapper
to return a string through pybind.
A relatively new feature of MLIR Python bindings allows returned
MlirTypes to automatically be downcast to the actual concrete Python
class for the type. To enable this, a C API to get the type's TypeID
must be provided, and the rest just works. Opt-in for the OM dialect's
ClassType.
This PR add Evaluator support for Map values.
* EvaluatorValue now takes a MLIR context as a member to make it easy to
construct attributes from evaluated values.
* MapValue is added and created from om.map_create.
* CAPIs for MapType and StringType are added.
`llvm_unreachable()` only tells the compiler to assume that can't happen
(in release builds w/default build options), so this doesn't help anyway.
cc #3836.
This is a PR for new representation of Evaluator and list_create support.
`std::variant` has been used as runtime representation of Evaluator but it's difficult to use it as
data structure for more structured values such as list or map. So this PR instead introduces a base class `EvaluatorValue ` and derived classes, `AttributeValue`, `ListValue` and `ObjectValue`, as runtime representation of values.
Also terminology `ObjectValue` is changed to `EvaluatorValue` since runtime values will not be limited to Object.
Python and C bindings are changed accordingly.
This functionality was used primarily wrap handshake modules. Now that
handshake uses ESI channels it's no longer necessary. I don't think
there are any other users.
These binding are very shallow and only support the use case of a single
InnerSymProperties with a fieldID of 0. Current use cases only require this
limited functionality, and in the future we will probably be changing the
underlying attributes, so it doesn't make sense to expose it all now.
Change the FIRRTL emitter to use v3.0.0 of the FIRRTL specification.
Logic for emitting an older version of the spec is still preserved. There
is no option for choosing the spec version from the command line right
now.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This adds custom CAPI wrap and unwrap functionality for Object to
better align with the std::shared_ptr functionality. Object now
enables the shared_from_this functionality, which allows the unwrap
function to more seamlessly create shared pointers to the Object with
the appropriate reference count. Similarly, the wrap functionality is
updated to always allocate new shared pointers, to ensure reference
counts are incremented appropriately. This was done at the instantiate
API previously, but is now handled generically whenever an Object is
wrapped.
These changes are required to avoid double frees of Objects in
general. A test case has been added that demonstrated the faulty
behavior, which now succeeds.
This adds two APIs to the OM dialect, for querying if a Type is a
ClassType and for getting the ClassType from an Object. These simply
wrap the existing C++ functionality directly. A small test is added to
ensure they work as expected.
This adds the usual CAPI structure and dialect registration
boilerplate, as well as CAPIs around the Evaluator library.
The APIs are intended to be as minimal and straightforward as
possible, simply wrapping and unwrapping the C++ structures when
possible.
One slight divergence is in the ObjectValue type, which is a
std::variant between an Object shared pointer or an Attribute. The
normal approach of casting to and from a void pointer does not work
with std::variant, so a different representation of ObjectValue is
used instead. The discriminated union is simply represented as a
struct which only over has one field set. It might be possible to save
some space using a struct with a C union and a flag, but the
simplicity of the current approach seemed reasonable.
Another minor detail worth mentioning is that we must take some care
to ensure the shared pointers to Objects have their reference count
kept up to date. In the CAPI for the instantiate method, if we simply
return the shared pointer, the reference will be lost as the Object
pointer travels to C as a void pointer, so we allocate a new shared
pointer in the CAPI, which ensures the reference count accurately
reflect that we have handed out another reference.
* [SV] Move emitAsComment to SVAttributeAttr; remove SVAttributesAttr
Move the `emitAsComments` flag from `SVAttributesAttr` (plural) to
`SVAttributeAttr` (singular). Then remove `SVAttributesAttr` (plural)
since it only contains a single array field after `emitAsComments` is
gone.
Add add, remove, and read-modify-write functions to deal with SV
attributes on operations more conveniently. Also enforce deduplicated
SV attributes where easily possible. The new functions now allow for
easy addition and removal of individual SV attributes.
Adapt ExportVerilog to handle the fact that emission as comments is now
a per-attribute option. The emission code now can emit multiple
`/*...*/` and `(*...*)` groups if needed, but tries to pack as many
consecutive attributes with the same `emitAsComment` flag into one
group.
* [ExportVerilog] PP-ify SV attribute emission.
* Test pretty-printing of SV attributes on statements.
* Tweak whitespaces between SV attributes
---------
Co-authored-by: Will Dietz <will.dietz@sifive.com>
* LLVM.h: drop mlir::Optional.
It's an alias for std::optional now, just drop
instead of adding the templated using alias here as well
(which we'd have to remember to drop).
* Convert Optional -> std::optional.
Drop some unnecessary initializations, but keep them for fields for now.
Particularly:
StandardToHandshake.h: keep init for field, for omission in {} initializers.
FSMToSV: similarly keep the current initialization.
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.
* Bump LLVM
Bump LLVM to the current top-of-tree.
This requires changing a few `Attribute`s to the new `TypedAttr`
interface, since attributes no longer carry a type by default. We rely
on this type in quite a few places in the CIRCT codebase, which required
a switch over to `TypedAttr`.
See: https://reviews.llvm.org/D130092
Co-authored-by: John Demme <john.demme@microsoft.com>
Enables writing service generators in Python. Also switches to
string-base 'impl_types' (from Attributes) since Attributes are tied to
a context whereas Passes are not. Simplifies things by not having to
create a registry for each context.
This PR adds a `emitAsComments` field to SV attributes.
Unfortunately, some of vendor specific pragmas are not strictly
valid SV attributes. For example, (* cadence map_to_mux *) is not valid
SV attribute hence vendor compilers recognize comments as some sort of
attributes. From that reason, this commit provides fine-grained control of
emission style to users.
```
%0 = sv.wire {sv.attributes = #sv.attributes<[#sv.attribute<"foo bar">], emitAsComments>} : i1
```
should be emitted as
```
/* foo bar */
wire GEN;
```
`PassCommon` contains `getAndSortModules`, which is generally useful. Make it general by implementing `HWModuleLike` and `HWInstanceLike` and targeting those OpInterfaces instead. Involves a bit of ugliness when converting to/from the OpInterfaces to concrete module ops, but hopefully that'll go away as we add more functionality to said OpInterfaces.
An 'AppID' is intended to make browsing the instance hierarchy easier.
Instead of having to reason about instance names, users can specify an
'AppID' consisting of a (name, index) pair and browse the hierarchy that
way. Said browsing also looks through the instance hierarchy (with
several rules about transparency) to mask implementation details at
various levels of the hierarchy.
This commit adds an `AppID` attribute and exposes it through Python.
This is an initial commit for adding a CAPI for FSM as well as PyCDE support for constructing these.
See `test_fsm.py` for usage.
FSMs are constructed in a similar manner to PyCDE modules through a decorator on a class describing the FSM.
The FSM class may contain inputs (no outputs for now) and must provide
- A dictionary containing the states and their transitions
- A default state
State transitions may be either always taken, or taken based on some guard. This guard is defined by a function provided to the transition, which (like `@generator` functions) acts on the ports of the FSM.
The FSM will then be constructed with an output for each state, asserted when that state is active.
One important implementation note is the fact that the `fsm.machine` operation is treated as a PyCDE Module - there was surprisingly little friction slotting it into the current code and everything works as expected wrt. referencing `fsm.machine` in/out arguments through the transition guard functions.
However, modules instantiating the FSM expect a hardware-like interface, this being the ports of the `fsm.machine` operation + clock and reset signals. An `fsm.machine` op does not have these signals at the top level, since these are added during hardware lowering. To me, this is a sensible design choice, seeing that the FSM dialect should be applicable to both software and hardware representations (...eventually).
To get around this, the user will specify the intended name of the `clock` and optional `reset` signal of an FSM. A wrapper module is then created that provides the correct interface to the instantiating module, as well as instantiating the FSM through a `fsm.hw_instance` operation, doing the proper hoop-jumping to attach the clock signal (see `fsm_wrapper_class`).
There's still some work to do on the CIRCT side of the FSM dialect to clean it up a bit + make it a viable target for a front-end, but this commit represents the brunt of work on the PyCDE side.
Lots of boilerplate which should _really_ be autogenerated. Added support for SystemVerilog attributes to the python bindings for the SV and Seq dialects.
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.
To simplify the ownership model, MLIR core python bindings don't support
building a block before the operation. So we build a dummy operation
first, build the block, construct the array, move the block, then delete
the dummy op. The core MLIR C API doesn't have a region editing API, so
we need to add a specialized one in the MSFT C API.
A first step to have proper support of the Moore types in the C API. This focusses on the functions to create types and some SBV type functions needed to support the already existing moore operations in the external moore frontend compiler.
Since we are generating only pieces of a design (and FPGA resources are
obviously a property of the entire design), the devdb should be
independent of the 'top' module.
Also, since the devdb is supposed to act as an 'alternative view' of the
IR, load the IR's placements by default.
- Use the new dynamic instance op and its children to simplify the PlacementDB.
- Switch to new paradigm wherein all placements are done through the device db and get reflected in the IR. So for the life of PlacementDB, it "owns" all the placements.
- Rename "PhysicalRegionOp" to "DeclPhysicalRegionOp" to be more
descriptive of what it does.
- Rename "PhysLocationOp" to be more consistent with asm name.
- Add "PDPhysRegionOp" to eliminate random attribute from globalRef.
- Ditch old ref attribute since it's no longer necessary.
Keep the PhysLocation attribute for the actual physical location. Create
an op to refer to a global ref with the location attribute and the
subpath. Incremental change towards a new approach to dynamic instances.
This PR breaks tcl placement output in the way the integration test and pycde
enters the placements. Will be fixed shortly with the dynamic instance PR.
These complement the main add* APIs for putting entities into the
database and support moving entities around or removing entities
entirely after any initial placements.
This allows the user to specify a walk order through the placements'
columns and rows. If specified, the order is used to sort the indices
into the placements' maps. Else, the order is undefined as before.
Previously, a sub-path could be specified by encoding it in the name
of the attribute using a certain scheme. This is brittle and
non-standard. To make this more natural and robust, the sub-path is
added as a field of the attribute definition as a StringRef. It is not
required, in which case an empty StringRef can be used. The attribute
name for placement attributes is no longer used in any logic.
This refactors ExportQuartusTcl to use the hw::GlobalRefs and arrays
of hw::InnerRefAttrs directly. This greatly simplifies the
implementation, and removes the need for SwitchInstanceAttr. That
attribute will be fully removed in a follow up.
* [HW] Use StringAttr instead of StringRef in FieldInfo, nfc
This commit changes to use use StringAttr instead of StringRef
in FieldInfo to avoid unnecessary copies of field names.
Changes are mainly about parser/printer and CAPI.
This commit also changes Struct/UnionTypeImpl to use ArrayRefParameter
instead of ArrayRefOfSelfAllocationParameter in their tablegen
definition. And this deletes unnecessary allocators too.
This add the necessary Python binding boilerplate to create
PhysicalBounds and PhysicalRegionRef attributes. A new API is added to
System, which inserts a PhysicalRegion. A wrapper class for
PhysicalRegion allows creating a region, adding bounds, and getting a
reference attribute suitable for use with the add_attribute API.
This is the preferred way to output design collatoral. Closes
https://github.com/llvm/circt/issues/2068.
The ExportQuartusTcl pass is removed, and the functionality is moved
into LowerMSFTToHW. The pass now populates a SymbolCache of the things
we care about in the export, namely instances. It produces verbatim
ops containing the Tcl, which can then be emitted from ExportVerilog.
The old Python API to run the export is removed in favor of the new
approach. PyCDE now exports both System Verilog and Tcl using the
exportSplitVerilog API to output files into a directory.
This keeps the existing functionality based on attributes, and exports
to llvm::outs as part of the pass, in order to keep the existing
tests. Further changes based on the approach in #2068 will follow.
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.
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.
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.
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.
A RootedInstancePath is just an instance path prepended with the root (aka top) module which the instance path is relative to. If we structure the placements based on this, we no longer have to walk the instance hierarchy while exporting TCL! This patch also removes support for locations not inside of instance switches. That use case required the design be fully elaborated which isn't really done.
There were some bits of the ESI and MSFT native pybind11 modules that
directly called into the CIRCT C++ libraries. This moves that
functionality out of the modules and behind the C-API. This proper
layering needs to be enforced before we can implement the upcoming
migration to use the improved upstream Python binding mechanism.
Also, this ensures all of the C-API functions used by the Python
bindings are annotated with MLIR_CAPI_EXPORTED, which will also become
required.
This adds straightforward support for the TypeAliasType, as it stands
today, in the CAPI, then layers the Bindings directly on top of that.
Later improvements to the TypeAliasType's builder will of course
require refactoring part of this, but for now, this opens it up for
use in PyCDE.
Previously, different parameterizations of the same module would end
up using the most-recently registered generator and the
parameterization used when it was registered.
This includes the parameterization in the registered mapping, and
looks for that same parameterization when looking up generators. This
is trivially supported since we already store the parameterization as
an attribute on the Operation.
Added a few lines to the polynomial integration test to ensure the
behavior.
Prototype of "generators". This version runs the generator for each and every op to lower and each time it is called, a new HWModuleOp is created at the top level. To fix this, I plan on unique'ing on the operation's attributes, result types, and operand types. This'll involve some refactoring since as of this PR the HWModuleOp creation and instantiation are both in the same callback.
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.
* C API fails to link on builds that have CAPNP disabled, since some of
the symbols in the C++ API get dropped. Make the corresponding uses in
the C API conditional on the presence of the same ifdef, so things
link again.
* Uses it to create a sample ChannelType.
* Requires: https://reviews.llvm.org/D101734
* See https://gist.github.com/stellaraccident/4a73e395e5cc68a5244c8d88dd291396 for a hacky sample of this working.
* Attributes would be incremantal on top of this.
With this, defining a custom type is pretty simple:
```
mlir_type_subclass(m, "ChannelType", circtESITypeIsAChannelType)
.def_static("get",
[](MlirType inner) {
return py::cast(circtESIChannelTypeGet(inner));
})
.def_property_readonly(
"inner", [](MlirType self) { return circtESIChannelGetInner(self); });
```
I feel good enough about this mechanism to suggest that we just upstream it as a public header and then refactor the builtin types to use it, deprecating PyConcreteType and PyConcreteAttribute. It isn't necessary to couple these together, though, and landing in circt could let us get some mileage on it first.
I'm aware that to the uninitiated, some of the pybind goo may seem magic, but this is actually the *less* magical way to do this: it isn't using any spooky Pybind11/C++ level sharing and is doing the exact same thing as if you literally spelled out "class MyType(mlir.ir.Type):" in Python -- but of course, meta-programming that in C++ is a bit thicker :) It also interops pretty well with the existing CAPI<->Python casters, making this (I think) a strict improvement over even what we have upstream.
One thing I didn't get to is a `DefaultingMlirContext` helper (ended up not needing it), but this would be pretty easy to add.
- Registers the SV passes when the 'circt' Python module is imported and the ESI passes when 'circt.esi' is imported.
- Adds a Python 'export_verilog' call.
- Enables LLVM 'pretty' stack traces for easier debugging. Makes assertion messages appear in Python instead of just crashing with no output.
This change aims to remove all instances of `using namespace mlir` from
our header files. Many types have been manually imported into the
`circt` namespace in `circt/Support/LLVM.h`. These types include all
core MLIR functionality types (IR, Diagnostic), utility types, rewrite
patterns and conversions, builtin IR types and attrs, and the module op.
Not imported were any operations (other than ModuleOp), matchers (e.g.
m_Zero), anything in the `impl` namespace, and interfaces. There are
some problems with interface code generation from ODS, so some
interfaces were imported.
Some further cleanup would be useful to remove the `mlir::` namespace
qualifier where we no longer need it.
* make consistency in FIRRTL naming
* make consistency in RTL naming
* make consistency in StaticLogic naming
* make consistency in SV naming
* header naming correction
* minor fix
* run clang-format
* clang-format
* td format and fix lib/SV/ naming
* clang-format on /SV/
* change library name from libMLIRCAPIRTL to libCIRCTCAPIRTL
* change library name from liblibMLIRLLHDTransforms to libCIRCTLLHDTransforms
* change library name from liblibMLIRRTLToLLHD to libCIRCTRTLToLLHD
* rename library from liblibMLIRLLHDToLLVM to libCIRCTLLHDToLLVM
* rename library from libMLIRFIRRTLToLLHD to libCIRCTFIRRTLToLLHD
* rename library from libMLIRFIRRTLToRTL to libCIRCTFIRRTLToRTL
* rename library from libMLIRHandshakeToFIRRTL to libCIRCTHandshakeToFIRRTL
* rename library from libMLIRStandardToHandshake to libCIRCTStandardToHandshake
* rename library from libMLIRStandardToStaticLogic to libCIRCTStandardToStaticLogic
* rename library from libMLIRRTL to libCIRCTRTL
* rename library from libMLIRSV to libCIRCTSV
* rename library from libMLIRESI to libCIRCTESI
* rename library from libMLIRFIRRTL to libCIRCTFIRRTL
* rename library from libMLIRLLHD to libCIRCTLLHD
* rename library from libMLIRHandshakeOps to libCIRCTHandshakeOps
* rename library from libMLIRStaticLogicOps to libCIRCTStaticLogicOps
* alphabetically rearrange LIBS in CMakeLists.txt
* add LLVM license info to files header
* Add LLVM license info to files header
* Add LLVM license info to files header
* Add LLVM license info to file headers
* Revert "Add LLVM license info to files header"
This reverts commit 22869676ad.
* Add LLVM license info to file headers
* run git-clang-format
* add missing file descriptions
* run git clang-format
* Add LLVM license info to file headers
* Add LLVM license info to files header
* Enable cloning llvm submodule over HTTP
* Introduce C API
* Undo unrelated changes
* clang-format
* More format
* Add Header Comments
* Format
* Add basic test
* Add missing incantation
* Format
Co-authored-by: George <>