[RFC] Interoperability dialect (#4126)

This commit is contained in:
Martin Erhart 2022-10-25 10:50:46 +02:00 committed by GitHub
parent 08980d0229
commit c0f0d4c97d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 963 additions and 175 deletions

View File

@ -0,0 +1,594 @@
# Interoperability Dialect Rationale
This document describes the various design points of the Interop dialect, a
dialect that is used to represent partially lowered interoperability layers and
that provides common interfaces and utilities for automated interop generation.
This follows in the spirit of other
[MLIR Rationale docs](https://mlir.llvm.org/docs/Rationale/).
- [Interoperability Dialect Rationale](#interoperability-dialect-rationale)
- [Introduction](#introduction)
- [Procedural Interop](#procedural-interop)
- [Representing Partial Lowerings](#representing-partial-lowerings)
- [Interop Mechanisms](#interop-mechanisms)
- [Instance-side Lowering](#instance-side-lowering)
- [Container-side Lowering](#container-side-lowering)
- [Bridging between Interop Mechanisms](#bridging-between-interop-mechanism)
- [How to use this dialect](#how-to-use-this-dialect)
- [Design considerations](#design-considerations)
## Introduction
The increasing number of CIRCT-based backends as well as the usage of many
external tools raises questions about interoperability and composition of
those tools. Are we supposed to write interop-layers between them by hand or
can this also be automatically generated? Can we generate interfaces to the
outside in multiple standardized formats/languages automatically?
Let's pick simulation as a concrete example. We have Verilator, CIRCT-based
event-driven (e.g., `llhd-sim`) and potentially non-event-driven simulators
that could be mixed using interop to use the faster, more constraint
one for most of the design and switch to the slower, more general one for
parts of the design that require the generality.
They all provide their own interface for writing testbenches in a way that
suits them best. Verilator has its custom C++ interface as well as SystemC
support, `llhd-sim` expects the testbench to be written in LLHD (e.g., compiled
from SystemVerilog), and nobody knows what the interface of the third would look
like (maybe a custom C-header?). This means, if we want to simulate a design
with all three, we have to write the testbench three times or at least some
layer between the TB and the simulator interfaces. This dialect aims to solve
this issue by auto-generating an interface from a selection of standarized
formats (e.g., a SystemC or SystemVerilog module) such that the testbench has
to be written only once and switching to another simulator just means changing
one CLI argument.
What if we have to use some blackbox Verilog code in the design? Is it compiled
by a (not yet existent) SystemVerilog front-end and simulated by the CIRCT-based
simulators or could it also be useful to simulate the blackbox using Verilator
and everything surrounding it using the CIRCT-based simulator? This dialect can
provide the latter by implementing an interop operation and one lowering per
simulator rather than custom pair-wise interop implementations.
We make a clear distinction between procedural and structural interop because
it is not possible to provide direct interop between a purely structural
language and a purely procedural language. To achieve interop between them,
one has to use at least one bridging language that has (some) support for both
as a translation layer.
## Procedural Interop
The `interop` dialect provides a few operations to represent partially lowered
procedural interop instances presented in the
[next section](#representing-partial-lowerings) as well as an interface to be
implemented by the surrounding module and rewrite patterns to call into those
interface implementations presented in the section about
['Container-side Lowering'](#container-side-lowering).
It also provides common rewrite patterns to insert translation layers between
different interop mechanisms like textural C++, C-foreign-functions, Verilog,
etc. They are discussed in more detail in the sections
['Interop Mechanisms'](#interop-mechanisms) and
['Bridging between Interop Mechanisms'](#bridging-between-interop-mechanisms).
### Representing Partial Lowerings
There are four operations to represent partially lowered procedural interop in
the IR:
* `interop.procedural.alloc`
* `interop.procedural.init`
* `interop.procedural.update`
* `interop.procedural.dealloc`
The `alloc` operation returns a variadic list of values that represent
persistent state, i.e., state that has to persist across multiple executions
of the `update` operation. For example, it can be lowered to C++ class fields
that are persistent across multiple calls of a member function, or to global
simulator state that persists over simulation cycles, etc.
Additionally, it has an attribute that specifies the interop mechanism under
which the state types are valid (the `cpp` in the example below). This is
necessary to allow bridging patterns to map the types to valid types in the
other interop mechanism, e.g., to an opaque pointer, if it does not support
the same types.
```mlir
%state = interop.procedural.alloc cpp : !emitc.ptr<!emitc.opaque<"VBar">>
```
The `init` operation takes the variadic list of states from the `alloc`
operation as operands and has a body with a `return` operation that has a
variadic list of operands that matches the types of the states and
represent the initial values to be assigned to the state values. The assignment
will be inserted by the container-side lowering of the interop operations.
The operation also has an interop mechanism attribute for the same reason as
above and, additionally, to wrap the operations in the body in a way to make
them executable in the other interop mechanism, e.g., wrap them in a
`extern "C"` function to make it callable from C or LLVM IR.
```mlir
interop.procedural.init cpp %state : !emitc.ptr<!emitc.opaque<"VBar">> {
%0 = systemc.cpp.new() : () -> !emitc.ptr<!emitc.opaque<"VBar">>
interop.return %0 : !emitc.ptr<!emitc.opaque<"VBar">>
}
```
The `update` operation is similar to the `alloc` operation in that it has an
interop mechanism attribute for the same reason and takes the state values as
operands, but also passes them on to the body via block arguments using
pass-by-value semantics. In addition to the state values, it also takes a variadic
list of inputs and also passes them on to the body. The `return` inside the body
then returns the result values after doing some computation inside the body.
If the state needs to be mutated, it has to be a pointer type. If we need to be
able to change the actual state value in the future, we could return updated
states via the `return` operation (currently not allowed).
```mlir
%1 = interop.procedural.update cpp [%state](%x, %x) :
[!emitc.ptr<!emitc.opaque<"VBar">>](i32, i32) -> i32 {
^bb0(%arg0: !emitc.ptr<!emitc.opaque<"VBar">>, %arg1: i32, %arg2: i32):
interop.return %5 : i32
}
```
The `dealloc` operation shall be executed right before the state requested by
the `alloc` operation is released. This allows the instance to do some cleanup,
e.g., when the state type was a pointer and the instance performed some
`malloc`. Structurally the operation is the same as the `update` operation, but
without input and output values. The state is also passed by value.
```mlir
interop.procedural.dealloc cpp %state : !emitc.ptr<!emitc.opaque<"VBar">> {
^bb0(%arg0: !emitc.ptr<!emitc.opaque<"VBar">>):
systemc.cpp.delete %arg0 : !emitc.ptr<!emitc.opaque<"VBar">>
interop.return
}
```
### Interop Mechanisms
A variety of interop mechanisms can be supported. This allows to perform interop
on different abstraction levels and only fall back to C-foreign-functions when
nothing else is supported.
Currently supported interop mechanisms:
* CFFI: C-foreign-functions, i.e., all interop operations are lowered to C
functions and function calls.
* CPP: textual C++, i.e., the interop operations are lowered to the `systemc`
and `emitc` dialects and printed as C++ code. In the future, more dialects
(such as `scf`) could be supported.
Adding a new interop mechanism requires changes to the `interop` dialect. At
a minimum, the table-gen enum has to be modified and a bridging pattern has to
be added.
### Instance-side Lowering
The instance-side lowering always has to happen before the container-side
lowering since that pass should create the interop operations that will then
be picked up by the container-side lowering pass and properly embedded in the
context of the container operation.
To illustrate how this works, consider a design represented in `hw`, `comb`, and
`seq`. We want to simulate that design using Verilator and provide a SystemC
wrapper (basically what Verilator itself can also do using the SystemC Output
Mode `--sc`). As a first step, the
top-level module has to be cloned without the region and a
`systemc.interop.verilated` operation has to be inserted in the body to
instantiate the previously cloned module (here represented as the extern module
`@Bar`) as a verilated module. The input and output ports get connected 1-1.
The original design is then exported through `ExportVerilog` and verilated,
while our wrapper module is lowered by the instance-side lowering.
```mlir
hw.module.extern @Bar (%a: i32, %b: i32) -> (c: i32)
hw.module @Foo (%x: i32) -> (y: i32) {
%c = systemc.interop.verilated "inst" @Bar (a: %x: i32, b: %x: i32) -> (c: i32)
hw.output %c : i32
}
```
As a result, the above code example is lowered to the following code. This is
implemented as a pattern on the `systemc.interop.verilated` operation in the
dialect conversion framework. Note that it is required to provide a rewrite
pattern for this lowering to enable one-shot lowering of all interop operations
in a design during a lowering pipeline. The patterns for all instance-side
interop lowerings of a dialect are provided by a population function
(e.g., `populateInstanceInteropLoweringPatterns(RewritePatternSet&)`) exposed
in their public API. Each dialect should also provide a pass with all its
instance-side lowering patterns populated for partial interop lowering.
```mlir
hw.module @Foo(%x: i32) -> (y: i32) {
%state = interop.procedural.alloc cpp : !emitc.ptr<!emitc.opaque<"VBar">>
interop.procedural.init cpp %state : !emitc.ptr<!emitc.opaque<"VBar">> {
%2 = systemc.cpp.new() : () -> !emitc.ptr<!emitc.opaque<"VBar">>
interop.return %2 : !emitc.ptr<!emitc.opaque<"VBar">>
}
%1 = interop.procedural.update cpp [%state](%x, %x) :
[!emitc.ptr<!emitc.opaque<"VBar">>](i32, i32) -> i32 {
^bb0(%arg0: !emitc.ptr<!emitc.opaque<"VBar">>, %arg1: i32, %arg2: i32):
%2 = systemc.cpp.member_access %arg0 arrow "a" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
systemc.cpp.assign %2 = %arg1 : i32
%3 = systemc.cpp.member_access %arg0 arrow "b" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
systemc.cpp.assign %3 = %arg2 : i32
%4 = systemc.cpp.member_access %arg0 arrow "eval" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> (() -> ())
systemc.cpp.call_indirect %4() : () -> ()
%5 = systemc.cpp.member_access %arg0 arrow "c" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
interop.return %5 : i32
}
interop.procedural.dealloc cpp %state : !emitc.ptr<!emitc.opaque<"VBar">> {
^bb0(%arg0: !emitc.ptr<!emitc.opaque<"VBar">>):
systemc.cpp.delete %arg0 : !emitc.ptr<!emitc.opaque<"VBar">>
interop.return
}
hw.output %1 : i32
}
```
In this example, it is possible to do the `HWToSystemC` conversion before or
after the instance-side interop lowering, but that might not be the case in
all situations.
### Container-side Lowering
The container-side interop lowering is slightly more complex than the
instance-side lowering, because it consists of an interface that needs to be
implemented by the container operations (in our example that's the
`systemc.module` operation) and four rewrite patterns that are provided by the
interop dialect and call those interface implementations. Typically, the
interface is implemented as an external model on the container operation, thus
the external model and the four rewrite patterns have to be registered in the
container-side lowering pass.
Similar to the instance-side lowering, each dialect has to provide a function
to register all external models implementing the interop interface of that
dialect as well as a pass that has all those models, the four rewrite patterns,
and all the bridging patterns, provided by the interop dialect, registered.
The `ProceduralContainerInteropOpInterface` provides four function that have
to be implemented:
```cpp
LogicalResult allocState(PatternRewriter&, ProceduralAllocOp, ProceduralAllocOpAdaptor);
LogicalResult initState(PatternRewriter&, ProceduralInitOp, ProceduralInitOpAdaptor);
LogicalResult updateState(PatternRewriter&, ProceduralUpdateOp, ProceduralUpdateOpAdaptor);
LogicalResult deallocState(PatternRewriter&, ProceduralDeallocOp, ProceduralDeallocOpAdaptor);
```
They are responsible for lowering the respective interop operation in a similar
fashion as regular rewrite patterns.
Let's take a look at how the example from the previous section is further
lowered. After the `convert-hw-to-systemc` pass it looks like the following:
```mlir
systemc.module @Foo(%x: !systemc.in<!systemc.uint<32>>,
%y: !systemc.out<!systemc.uint<32>>) {
systemc.ctor {
systemc.method %update
}
%update = systemc.func {
%0 = systemc.signal.read %x : !systemc.in<!systemc.uint<32>>
%state = interop.procedural.alloc cpp : !emitc.ptr<!emitc.opaque<"VBar">>
interop.procedural.init cpp %state : !emitc.ptr<!emitc.opaque<"VBar">> {
%1 = systemc.cpp.new() : () -> !emitc.ptr<!emitc.opaque<"VBar">>
interop.return %1 : !emitc.ptr<!emitc.opaque<"VBar">>
}
%2 = systemc.convert %0 : (!systemc.uint<32>) -> i32
%3 = interop.procedural.update cpp [%state](%2, %2) :
[!emitc.ptr<!emitc.opaque<"VBar">>](i32, i32) -> i32 {
^bb0(%arg0: !emitc.ptr<!emitc.opaque<"VBar">>, %arg1: i32, %arg2: i32):
%4 = systemc.cpp.member_access %arg0 arrow "a" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
systemc.cpp.assign %4 = %arg1 : i32
%5 = systemc.cpp.member_access %arg0 arrow "b" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
systemc.cpp.assign %5 = %arg2 : i32
%6 = systemc.cpp.member_access %arg0 arrow "eval" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> (() -> ())
systemc.cpp.call_indirect %6() : () -> ()
%7 = systemc.cpp.member_access %arg0 arrow "c" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
interop.return %7 : i32
}
interop.procedural.dealloc cpp %state : !emitc.ptr<!emitc.opaque<"VBar">> {
^bb0(%arg0: !emitc.ptr<!emitc.opaque<"VBar">>):
systemc.cpp.delete %arg0 : !emitc.ptr<!emitc.opaque<"VBar">>
interop.return
}
%8 = systemc.convert %3 : (i32) -> !systemc.uint<32>
systemc.signal.write %y, %8
}
}
```
Note that the `alloc`, `init`, and `dealloc` interop operations were not moved
to the final locations yet, although, the pass could be modified to do this.
In the SystemC lowering, the interop interface implementation performs the
movement of these operation to the final location. Doing the lowering leads to
the following:
```mlir
systemc.module @Foo(%x: !systemc.in<!systemc.uint<32>>,
%y: !systemc.out<!systemc.uint<32>>) {
%state = systemc.cpp.variable : !emitc.ptr<!emitc.opaque<"VBar">>
systemc.ctor {
%0 = systemc.cpp.new() : () -> !emitc.ptr<!emitc.opaque<"VBar">>
systemc.cpp.assign %state = %0 : !emitc.ptr<!emitc.opaque<"VBar">>
systemc.method %update
}
%update = systemc.func {
%1 = systemc.signal.read %x : !systemc.in<!systemc.uint<32>>
%2 = systemc.convert %1 : (!systemc.uint<32>) -> i32
%3 = systemc.cpp.member_access %state arrow "a" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
systemc.cpp.assign %3 = %2 : i32
%4 = systemc.cpp.member_access %state arrow "b" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
systemc.cpp.assign %4 = %2 : i32
%5 = systemc.cpp.member_access %state arrow "eval" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> (() -> ())
systemc.cpp.call_indirect %5() : () -> ()
%6 = systemc.cpp.member_access %state arrow "c" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
%7 = systemc.convert %6 : (i32) -> !systemc.uint<32>
systemc.signal.write %y, %7
}
systemc.cpp.destructor {
systemc.cpp.delete %state : !emitc.ptr<!emitc.opaque<"VBar">>
}
}
```
### Bridging between Interop Mechanisms
As we have already seen, the instance-side lowering adds an attribute to the
interop operations to indicate the interop mechanism that has to be supported
to use the bodies operations and types directly. But what happens when the
instance annotated the operations to be textual C++, but the interface
implementation of the container operation only supports CFFI?
In that case, the dialect that lowers the instance could also provide a lowering
pattern for that particular interop mechanism (instead of registering the
bridging patterns), or there can be patterns that convert the interop operations
to another interop mechanism. Using the dialect conversion framework, this will
then allow the pass to legalize all operations in the IR by using that extra
pattern instead of failing because of an illegal operation for which no pattern
matches.
Let's take a closer look into the CPP to CFFI bridging pattern. It will convert
the interop operations from earlier to CFFI compatible versions.
The `alloc` operation
```mlir
%state = interop.procedural.alloc cpp : !emitc.ptr<!emitc.opaque<"VBar">>
```
is converted to a version where all types are replaced by opaque pointers:
```mlir
%state = interop.procedural.alloc cffi : !llvm.ptr
```
For the `update` operation
```mlir
%1 = interop.procedural.update cpp [%state](%x, %x) :
[!emitc.ptr<!emitc.opaque<"VBar">>](i32, i32) -> i32 {
^bb0(%arg0: !emitc.ptr<!emitc.opaque<"VBar">>, %arg1: i32, %arg2: i32):
%2 = systemc.cpp.member_access %arg0 arrow "a" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
systemc.cpp.assign %2 = %arg1 : i32
%3 = systemc.cpp.member_access %arg0 arrow "b" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
systemc.cpp.assign %3 = %arg2 : i32
%4 = systemc.cpp.member_access %arg0 arrow "eval" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> (() -> ())
systemc.cpp.call_indirect %4() : () -> ()
%5 = systemc.cpp.member_access %arg0 arrow "c" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
interop.return %5 : i32
}
```
the state types are also converted to opaque pointers and the body is replaced
with a function call. The original body is moved to a function in another file
that will be piped through `ExportSystemC` to generate the textual C++ that
exports it as a `extern "C"` function.
```mlir
systemc.cpp.func externC @update (%arg0: !emitc.ptr<!emitc.opaque<"void">>,
%arg1: i32, %arg2: i32) -> i32 {
%0 = emitc.cast %arg0 : !emitc.ptr<!emitc.opaque<"void">> to
!emitc.ptr<!emitc.opaque<"VBar">>
%2 = systemc.cpp.member_access %0 arrow "a" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
systemc.cpp.assign %2 = %arg1 : i32
%3 = systemc.cpp.member_access %0 arrow "b" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
systemc.cpp.assign %3 = %arg2 : i32
%4 = systemc.cpp.member_access %0 arrow "eval" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> (() -> ())
systemc.cpp.call_indirect %4() : () -> ()
%5 = systemc.cpp.member_access %0 arrow "c" :
(!emitc.ptr<!emitc.opaque<"VBar">>) -> i32
interop.return %5 : i32
}
// ----- other file
func.func @update (%arg0: !llvm.ptr, %arg1: i32, %arg2: i32) -> i32
%1 = interop.procedural.update cffi [%state](%x, %x) :
[!llvm.ptr](i32, i32) -> i32 {
^bb0(%arg0: !llvm.ptr, %arg1: i32, %arg2: i32):
%1 = func.call @update(%arg0, %arg1, %arg2) : (!llvm.ptr, i32, i32) -> i32
interop.return %1 : i32
}
```
The `init` and `dealloc` operations follow the same pattern as the `update`
operation.
### How to use this dialect
First, we need to distinguish between the different ways this dialect might want
to be used in another dialect or downstream repository:
* Use existing dialects that implement interop lowerings in a specialized
pipeline: this requires implementing a new pass in the downstream tool that
registers all the rewrite patterns and external models from the upstream
dialects required to make the pass succeed in that specialized environment.
Having a specialized pass allows to reduce the number of dependent dialect as
all dialects, external models, and patterns that could potentially be needed
have to be registered upfront in MLIR. It's also more convenient to have a
one-shot pass instead of a series of partial lowerings.
* Add a new tool or IR that can be used as an instance: implement the
instance-side lowering pass for your dialect and expose a function to
populate the rewrite pattern in a provided pattern set.
* Add a new IR that can be used as a container for other interop instances:
implement the container-side interop interface and a container-side lowering
pass that registers the implemented interface, the four container-side
lowering patterns and bridging patterns provided by the `interop` dialect.
* Add a new interop mechanism: this is currently not supported and requires
modifications to the `interop` dialect. Adding a new mechanism requires
extending the `InteropMechanism` table-gen enum and adding a bridging pattern
to CFFI at a minimum.
### Design considerations
This section aims to provide explanations for certain design decisions. It will
take the form of a Q&A.
**Why does the container-side lowering use interfaces that are called from a**
**rewrite pattern?**
Generally speaking, switching between interfaces and rewrite patterns allows us
to control the dependency direction between the container interop operations
and the interop lowering pass.
When using external models to describe the lowering, the pass does not need to
know about that interop operation, it just needs to know about the interface
that describes the external model. However, the interop operation needs to know
about the interop lowering pass.
When using rewrite patterns (without any interfaces), the pattern needs to
depend on the interop operation and the interop lowering pass needs to depend on
the patterns.
While this is also a design consideration, it is not the main concern here.
Note that the lowering patterns should be provided by the operation that is
the closest surrounding op (in terms of regions) to the unrealized interop
operation and that supports interop.
To illustrate why this approach was taken, we can take a look at some of the
alternatives considered:
* The dialect exports a function to populate a rewrite pattern that matches on
the container operation of that dialect. This has the disadvantage that all
interop casts inside that container have to be handled in that single pattern
and the pattern thus needs to walk the region. Another problem is that we need
the closest operation to perform the interop lowering and the rewrite pattern
driver walks top-down, thus the pattern would need to stop walking at operations
that also support interop, but it can only know that if it gets a list of such
operations or if all of the interop supporting operations implement an interface.
* The dialect exports a function to populate a rewrite pattern that matches on
the interop cast operation. The disadvantage there is that we then potentially
have a lot of rewrite patterns matching on the same operation and we thus need
to specify the matching condition to only succeed when the closest interop
supporting operation is the one that provided the rewrite pattern. Therefore,
we would still need to know which operations support interop. Alternatively,
the pattern returns the operation it would match on and the infra tries all
of them and selectes the one with the closest operation returned, however,
that doesn't fit the dialect conversion framework very well and would be
rather bad performance-wise.
* The dialect adds a trait to the operations that support interop. The interop
rewrite patterns could then be provided by the downstream dialect, match on
the unrealized interop operations, and add as a matching condition that no
other operation having the interop trait is closer to the unrealized interop
operation. This still has the disadvantage that the conversion framework has
to cycle through potentially many patterns matching on the same operations
and check quite expensive matching conditions.
* Current implementation: The dialect implements an external model for the
interop operation. The lowering pass infra then provides the rewrite patterns
that match on the unrealized interop operations (one per op) and checks for
the closest parent operation that implements the interface and then calls the
lowering provided by the interface implementation.
**Why is instance-side lowering implemented using rewrite patterns?**
We also have the option to implement the lowering patterns in an interface or
directly provide a rewrite pattern with the same trade-offs as mentioned in the
beginning of the above question. The only advantage of the interface approach
is the inversion of the dependencies which is not important for us since we
implement partial lowering passes for every dialect anyways. The pattern based
approach is more straight-forward to implement though.
**Why are those interfaces implemented as external models?**
Because the interface implementations need to implement a lowering pattern that
might have to create operations from a few different dialects, it needs to
include all of them and link against them. This can add a big burden to some
other user that just wants to use the dialect but is not interested in the
interop functionality. It also helps to avoid dependency cycles.
**How are the dialects registered that a pass depends on (for which ops may be**
**created)?**
We have partial lowering passes for each dialect. They have a complete picture
of what operations they create in the instance- and container-side lowerings
and can thus register exactly those. The container-side lowerings also need
to register the dialects needed for the interop mechanism conversion patterns
which are fixed by the `interop` dialect.
When implementing a specialized tool one can set up a specialized one-shot
pass for interop which registers everything that can occur at that stage of
the pipeline.
**Why have unrealized interp operations instead of lowering directly?**
They allow us to get rid of the tight coupling between the instance interop
operations and the surrounding container interop operations. It enables
partial lowering at various places throughout a lowering pipeline and helps
keeping the number of dependences on dialects in the lowering pass low.
**Is there a possibility to support multiple interop mechanisms per instance**
**operation?**
We have to distinguish the case where we know the interop mechanism statically
at the point in time when we create the lowering pass and the case where the
mechanism is selected dynamically in the lowering pass.
The first case is easy to support because one can implement multiple patterns
that lower the instance operation in different ways and register the one that
fits the best.
In a dynamic setting, this is still possible by registering multiple patterns
for the same op, but the set of operations they match on needs to be disjoint
and must not depend on any parent operations. As a result, it might be tricky
to add a specialized lowering without copy-pasting the original lowering
pattern and restricting its match condition.
**How are the bridges between interop mechanisms provided?**
They are provided by the interop dialect as rewrite patterns similar to how the
rewrite patterns for the instance interop to interop cast conversion is provided
by the other dialects. This has the advantage that these conversions, which
usually follow a common pattern, have to be implemented only once.
**Why are the interop operations four separate operations instead of one with**
**three regions?**
This allows to move the code fragments for allocation and deallocation to their
final location not only during the container-side lowering, but also during a
regular transformation pass that, e.g., collects all the state that needs to be
persistent over multiple cycles in a simulator and inserts allocation code at
the top-level.
**Why is there a separate `interop.alloc` operation? Why not make it part of**
**`interop.init`?**
We need to have an operation returning SSA values for the state that which can
be used in the other unrealized interop operations to link them together (we
always need to know what alloc, update, and dealloc operations belong together).
Returning those values from the `init` operation would lead to less flexibility,
a more complicated `init` operation, and might be misleading as the body returns
the values that need to be assigned to the state variables by the container-side
pass, but the returned values would be the state variables.
**Why is this a separate dialect?**
This dialect provides infrastructure and utilities for all dialects that want
to implement some kind of interop. Those dialects need to depend on this one.
The only dialect where it could make sense to add this functionality to is HW,
but we don't want to bloat HW since it is the core dialect that everyone depends
on (also the dialects that don't need interop).

View File

@ -0,0 +1,3 @@
# Interop Dialect
[include "Dialects/Interop.md"]

View File

@ -59,6 +59,7 @@ digraph G {
Seq [URL="https://circt.llvm.org/docs/Dialects/Seq/"]
HW [URL="https://circt.llvm.org/docs/Dialects/HW/"]
Comb [URL="https://circt.llvm.org/docs/Dialects/Comb/"]
Interop [URL="https://circt.llvm.org/docs/Dialects/Interop/"]
}
LLHD [URL="https://circt.llvm.org/docs/Dialects/LLHD/"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 169 KiB

View File

@ -4,24 +4,24 @@
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: G Pages: 1 -->
<svg width="779pt" height="992pt"
viewBox="0.00 0.00 778.87 992.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg width="770pt" height="992pt"
viewBox="0.00 0.00 769.87 992.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 988)">
<title>G</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-988 774.87,-988 774.87,4 -4,4"/>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-988 765.87,-988 765.87,4 -4,4"/>
<g id="clust1" class="cluster">
<title>cluster_mlir_frontends</title>
<polygon fill="none" stroke="black" points="173.87,-901 173.87,-976 413.87,-976 413.87,-901 173.87,-901"/>
<text text-anchor="middle" x="293.87" y="-960.8" font-family="Times,serif" font-size="14.00">Upstream frontends (selection)</text>
<polygon fill="none" stroke="black" points="164.87,-901 164.87,-976 404.87,-976 404.87,-901 164.87,-901"/>
<text text-anchor="middle" x="284.87" y="-960.8" font-family="Times,serif" font-size="14.00">Upstream frontends (selection)</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_mlir</title>
<polygon fill="none" stroke="black" points="123.87,-802 123.87,-893 411.87,-893 411.87,-802 123.87,-802"/>
<text text-anchor="middle" x="267.87" y="-877.8" font-family="Times,serif" font-size="14.00">Upstream MLIR</text>
<polygon fill="none" stroke="black" points="114.87,-802 114.87,-893 402.87,-893 402.87,-802 114.87,-802"/>
<text text-anchor="middle" x="258.87" y="-877.8" font-family="Times,serif" font-size="14.00">Upstream MLIR</text>
</g>
<g id="clust3" class="cluster">
<title>cluster_std_arith_dialect</title>
<polygon fill="none" stroke="black" points="265.87,-810 265.87,-862 403.87,-862 403.87,-810 265.87,-810"/>
<polygon fill="none" stroke="black" points="256.87,-810 256.87,-862 394.87,-862 394.87,-810 256.87,-810"/>
</g>
<g id="clust4" class="cluster">
<title>cluster_circt</title>
@ -30,57 +30,57 @@
</g>
<g id="clust6" class="cluster">
<title>cluster_RTL</title>
<polygon fill="none" stroke="black" points="281.87,-356 281.87,-431 491.87,-431 491.87,-356 281.87,-356"/>
<text text-anchor="middle" x="386.87" y="-415.8" font-family="Times,serif" font-size="14.00">Core dialects</text>
<polygon fill="none" stroke="black" points="234.87,-356 234.87,-431 528.87,-431 528.87,-356 234.87,-356"/>
<text text-anchor="middle" x="381.87" y="-415.8" font-family="Times,serif" font-size="14.00">Core dialects</text>
</g>
<g id="clust9" class="cluster">
<title>cluster_input_langs</title>
<polygon fill="none" stroke="black" points="421.87,-901 421.87,-976 762.87,-976 762.87,-901 421.87,-901"/>
<text text-anchor="middle" x="592.37" y="-960.8" font-family="Times,serif" font-size="14.00">Input languages</text>
<polygon fill="none" stroke="black" points="412.87,-901 412.87,-976 753.87,-976 753.87,-901 412.87,-901"/>
<text text-anchor="middle" x="583.37" y="-960.8" font-family="Times,serif" font-size="14.00">Input languages</text>
</g>
<!-- PyTorch -->
<g id="node1" class="node">
<title>PyTorch</title>
<polygon fill="white" stroke="black" points="405.87,-945 331.87,-945 331.87,-909 405.87,-909 405.87,-945"/>
<text text-anchor="middle" x="368.87" y="-923.3" font-family="Times,serif" font-size="14.00">PyTorch</text>
<polygon fill="white" stroke="black" points="396.87,-945 322.87,-945 322.87,-909 396.87,-909 396.87,-945"/>
<text text-anchor="middle" x="359.87" y="-923.3" font-family="Times,serif" font-size="14.00">PyTorch</text>
</g>
<!-- CF -->
<g id="node5" class="node">
<title>CF</title>
<polygon fill="#beaed4" stroke="black" points="395.87,-854 341.87,-854 341.87,-818 395.87,-818 395.87,-854"/>
<text text-anchor="middle" x="368.87" y="-832.3" font-family="Times,serif" font-size="14.00">CF</text>
<polygon fill="#beaed4" stroke="black" points="386.87,-854 332.87,-854 332.87,-818 386.87,-818 386.87,-854"/>
<text text-anchor="middle" x="359.87" y="-832.3" font-family="Times,serif" font-size="14.00">CF</text>
</g>
<!-- PyTorch&#45;&gt;CF -->
<g id="edge1" class="edge">
<title>PyTorch&#45;&gt;CF</title>
<path fill="none" stroke="black" d="M364.62,-908.84C364.47,-907.06 364.34,-905.19 364.22,-903.24"/>
<polygon fill="black" stroke="black" points="367.7,-902.84 363.78,-893 360.71,-903.14 367.7,-902.84"/>
<path fill="none" stroke="black" d="M355.62,-908.84C355.47,-907.06 355.34,-905.19 355.22,-903.24"/>
<polygon fill="black" stroke="black" points="358.7,-902.84 354.78,-893 351.71,-903.14 358.7,-902.84"/>
</g>
<!-- PyTorch&#45;&gt;CF -->
<!-- Polygeist -->
<g id="node2" class="node">
<title>Polygeist</title>
<polygon fill="white" stroke="black" points="317.87,-945 235.87,-945 235.87,-909 317.87,-909 317.87,-945"/>
<text text-anchor="middle" x="276.87" y="-923.3" font-family="Times,serif" font-size="14.00">Polygeist</text>
<polygon fill="white" stroke="black" points="308.87,-945 226.87,-945 226.87,-909 308.87,-909 308.87,-945"/>
<text text-anchor="middle" x="267.87" y="-923.3" font-family="Times,serif" font-size="14.00">Polygeist</text>
</g>
<!-- Affine -->
<g id="node4" class="node">
<title>Affine</title>
<polygon fill="#beaed4" stroke="black" points="257.87,-854 199.87,-854 199.87,-818 257.87,-818 257.87,-854"/>
<text text-anchor="middle" x="228.87" y="-832.3" font-family="Times,serif" font-size="14.00">Affine</text>
<polygon fill="#beaed4" stroke="black" points="248.87,-854 190.87,-854 190.87,-818 248.87,-818 248.87,-854"/>
<text text-anchor="middle" x="219.87" y="-832.3" font-family="Times,serif" font-size="14.00">Affine</text>
</g>
<!-- Polygeist&#45;&gt;Affine -->
<g id="edge2" class="edge">
<title>Polygeist&#45;&gt;Affine</title>
<path fill="none" stroke="black" d="M267.61,-908.84C266.49,-906.77 265.3,-904.56 264.07,-902.26"/>
<polygon fill="black" stroke="black" points="266.89,-900.14 259.07,-893 260.73,-903.46 266.89,-900.14"/>
<path fill="none" stroke="black" d="M258.61,-908.84C257.49,-906.77 256.3,-904.56 255.07,-902.26"/>
<polygon fill="black" stroke="black" points="257.89,-900.14 250.07,-893 251.73,-903.46 257.89,-900.14"/>
</g>
<!-- Polygeist&#45;&gt;CF -->
<!-- SCF -->
<g id="node3" class="node">
<title>SCF</title>
<polygon fill="#beaed4" stroke="black" points="185.87,-854 131.87,-854 131.87,-818 185.87,-818 185.87,-854"/>
<text text-anchor="middle" x="158.87" y="-832.3" font-family="Times,serif" font-size="14.00">SCF</text>
<polygon fill="#beaed4" stroke="black" points="176.87,-854 122.87,-854 122.87,-818 176.87,-818 176.87,-854"/>
<text text-anchor="middle" x="149.87" y="-832.3" font-family="Times,serif" font-size="14.00">SCF</text>
</g>
<!-- Calyx -->
<g id="node11" class="node">
@ -94,8 +94,8 @@
<!-- SCF&#45;&gt;Calyx -->
<g id="edge3" class="edge">
<title>SCF&#45;&gt;Calyx</title>
<path fill="none" stroke="black" d="M161.29,-817.87C166.97,-777.81 181.14,-677.75 188.01,-629.23"/>
<polygon fill="black" stroke="black" points="191.5,-629.55 189.44,-619.16 184.57,-628.57 191.5,-629.55"/>
<path fill="none" stroke="black" d="M152.96,-817.87C160.18,-777.81 178.21,-677.75 186.96,-629.23"/>
<polygon fill="black" stroke="black" points="190.44,-629.62 188.77,-619.16 183.56,-628.38 190.44,-629.62"/>
</g>
<!-- Pipeline -->
<g id="node13" class="node">
@ -109,14 +109,14 @@
<!-- Affine&#45;&gt;Pipeline -->
<g id="edge4" class="edge">
<title>Affine&#45;&gt;Pipeline</title>
<path fill="none" stroke="black" d="M240.85,-817.77C260.64,-789.32 300.24,-732.4 323.23,-699.36"/>
<polygon fill="black" stroke="black" points="326.13,-701.31 328.97,-691.11 320.38,-697.32 326.13,-701.31"/>
<path fill="none" stroke="black" d="M232.82,-817.77C254.19,-789.32 296.97,-732.4 321.81,-699.36"/>
<polygon fill="black" stroke="black" points="324.8,-701.2 328.01,-691.11 319.2,-697 324.8,-701.2"/>
</g>
<!-- Arith -->
<g id="node6" class="node">
<title>Arith</title>
<polygon fill="#beaed4" stroke="black" points="327.87,-854 273.87,-854 273.87,-818 327.87,-818 327.87,-854"/>
<text text-anchor="middle" x="300.87" y="-832.3" font-family="Times,serif" font-size="14.00">Arith</text>
<polygon fill="#beaed4" stroke="black" points="318.87,-854 264.87,-854 264.87,-818 318.87,-818 318.87,-854"/>
<text text-anchor="middle" x="291.87" y="-832.3" font-family="Times,serif" font-size="14.00">Arith</text>
</g>
<!-- Handshake -->
<g id="node10" class="node">
@ -130,14 +130,14 @@
<!-- Arith&#45;&gt;Handshake -->
<g id="edge6" class="edge">
<title>Arith&#45;&gt;Handshake</title>
<path fill="none" stroke="black" d="M298.83,-810C295.24,-765.95 287.81,-674.83 284.09,-629.23"/>
<polygon fill="black" stroke="black" points="287.57,-628.84 283.27,-619.16 280.59,-629.41 287.57,-628.84"/>
<path fill="none" stroke="black" d="M290.79,-810C288.9,-765.95 284.99,-674.83 283.04,-629.23"/>
<polygon fill="black" stroke="black" points="286.53,-629 282.6,-619.16 279.54,-629.3 286.53,-629"/>
</g>
<!-- Arith&#45;&gt;Calyx -->
<g id="edge7" class="edge">
<title>Arith&#45;&gt;Calyx</title>
<path fill="none" stroke="black" d="M289.17,-810C268.42,-765.65 225.36,-673.61 204.18,-628.32"/>
<polygon fill="black" stroke="black" points="207.3,-626.73 199.89,-619.16 200.96,-629.7 207.3,-626.73"/>
<path fill="none" stroke="black" d="M281.14,-810C262.14,-765.75 222.77,-674.01 203.29,-628.62"/>
<polygon fill="black" stroke="black" points="206.39,-626.97 199.23,-619.16 199.96,-629.73 206.39,-626.97"/>
</g>
<!-- FIRRTLParser -->
<g id="node7" class="node">
@ -233,23 +233,23 @@
<g id="node9" class="node">
<title>Scheduling</title>
<g id="a_node9"><a xlink:href="https://circt.llvm.org/docs/Scheduling/" xlink:title="Scheduling">
<polygon fill="#fdc086" stroke="black" points="522.87,-763 426.87,-763 426.87,-727 522.87,-727 522.87,-763"/>
<text text-anchor="middle" x="474.87" y="-741.3" font-family="Times,serif" font-size="14.00">Scheduling</text>
<polygon fill="#fdc086" stroke="black" points="513.87,-763 417.87,-763 417.87,-727 513.87,-727 513.87,-763"/>
<text text-anchor="middle" x="465.87" y="-741.3" font-family="Times,serif" font-size="14.00">Scheduling</text>
</a>
</g>
</g>
<!-- Scheduling&#45;&gt;Pipeline -->
<g id="edge21" class="edge">
<title>Scheduling&#45;&gt;Pipeline</title>
<path fill="none" stroke="black" d="M433,-722.13C417.05,-713.79 398.86,-704.3 382.89,-695.95"/>
<polygon fill="black" stroke="black" points="431.6,-725.35 442.09,-726.88 434.84,-719.14 431.6,-725.35"/>
<polygon fill="black" stroke="black" points="384.26,-692.72 373.77,-691.19 381.02,-698.92 384.26,-692.72"/>
<path fill="none" stroke="black" d="M426.33,-721.86C411.67,-713.65 395.06,-704.35 380.4,-696.14"/>
<polygon fill="black" stroke="black" points="424.85,-725.04 435.29,-726.88 428.27,-718.94 424.85,-725.04"/>
<polygon fill="black" stroke="black" points="382,-693.02 371.56,-691.19 378.58,-699.13 382,-693.02"/>
</g>
<!-- Scheduling&#45;&gt;MSFT -->
<g id="edge43" class="edge">
<title>Scheduling&#45;&gt;MSFT</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M495.8,-718.62C514.12,-694.64 539.4,-656.8 549.87,-619 554.14,-603.58 555.13,-598.11 549.87,-583 546.33,-572.86 539.96,-563.19 533.23,-554.96"/>
<polygon fill="black" stroke="black" points="492.8,-716.77 489.4,-726.8 498.32,-721.08 492.8,-716.77"/>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M489.36,-718.97C509.84,-695.29 538.07,-657.7 549.87,-619 554.53,-603.7 555.13,-598.11 549.87,-583 546.33,-572.86 539.96,-563.19 533.23,-554.96"/>
<polygon fill="black" stroke="black" points="486.48,-716.94 482.47,-726.75 491.72,-721.58 486.48,-716.94"/>
<polygon fill="black" stroke="black" points="535.69,-552.46 526.47,-547.24 530.43,-557.07 535.69,-552.46"/>
</g>
<!-- Handshake&#45;&gt;FIRRTL -->
@ -265,7 +265,7 @@
<polygon fill="black" stroke="black" points="194.75,-557.05 191.11,-547.1 187.75,-557.15 194.75,-557.05"/>
</g>
<!-- Calyx_native -->
<g id="node30" class="node">
<g id="node31" class="node">
<title>Calyx_native</title>
<polygon fill="#ffff99" stroke="black" points="147.6,-521.54 147.6,-536.46 104.41,-547 43.33,-547 0.13,-536.46 0.13,-521.54 43.33,-511 104.41,-511 147.6,-521.54"/>
<text text-anchor="middle" x="73.87" y="-525.3" font-family="Times,serif" font-size="14.00">Calyx native</text>
@ -282,16 +282,16 @@
<g id="node21" class="node">
<title>HW</title>
<g id="a_node21"><a xlink:href="https://circt.llvm.org/docs/Dialects/HW/" xlink:title="HW">
<polygon fill="white" stroke="black" points="411.87,-400 357.87,-400 357.87,-364 411.87,-364 411.87,-400"/>
<text text-anchor="middle" x="384.87" y="-378.3" font-family="Times,serif" font-size="14.00">HW</text>
<polygon fill="white" stroke="black" points="380.87,-400 326.87,-400 326.87,-364 380.87,-364 380.87,-400"/>
<text text-anchor="middle" x="353.87" y="-378.3" font-family="Times,serif" font-size="14.00">HW</text>
</a>
</g>
</g>
<!-- FIRRTL&#45;&gt;HW -->
<g id="edge10" class="edge">
<title>FIRRTL&#45;&gt;HW</title>
<path fill="none" stroke="black" d="M280.34,-510.7C294.15,-492.08 317.55,-462.03 340.87,-439 341.63,-438.25 342.31,-437.65 342.96,-437.13"/>
<polygon fill="black" stroke="black" points="345.11,-439.89 350.87,-431 340.82,-434.36 345.11,-439.89"/>
<path fill="none" stroke="black" d="M278.07,-510.8C288.45,-493.3 305.1,-465.23 320.15,-439.84"/>
<polygon fill="black" stroke="black" points="323.31,-441.38 325.4,-431 317.29,-437.81 323.31,-441.38"/>
</g>
<!-- Pipeline&#45;&gt;Calyx -->
<g id="edge5" class="edge">
@ -303,58 +303,58 @@
<!-- MSFT&#45;&gt;HW -->
<g id="edge11" class="edge">
<title>MSFT&#45;&gt;HW</title>
<path fill="none" stroke="black" d="M491.89,-510.7C472.21,-489.37 439.63,-454.04 425.53,-438.48"/>
<polygon fill="black" stroke="black" points="428.13,-436.14 418.87,-431 422.9,-440.8 428.13,-436.14"/>
<path fill="none" stroke="black" d="M503.06,-510.99C496.24,-490.24 481.62,-455.86 455.87,-439 433.59,-424.42 418.27,-441.12 397.26,-435.12"/>
<polygon fill="black" stroke="black" points="398.43,-431.81 387.87,-431 395.62,-438.22 398.43,-431.81"/>
</g>
<!-- TCL -->
<g id="node40" class="node">
<g id="node41" class="node">
<title>TCL</title>
<polygon fill="#7fc97f" stroke="black" points="623.87,-111 497.87,-111 497.87,-75 629.87,-75 629.87,-105 623.87,-111"/>
<polyline fill="none" stroke="black" points="623.87,-111 623.87,-105 "/>
<polyline fill="none" stroke="black" points="629.87,-105 623.87,-105 "/>
<text text-anchor="middle" x="563.87" y="-89.3" font-family="Times,serif" font-size="14.00">Placements (tcl)</text>
<polygon fill="#7fc97f" stroke="black" points="655.87,-111 529.87,-111 529.87,-75 661.87,-75 661.87,-105 655.87,-111"/>
<polyline fill="none" stroke="black" points="655.87,-111 655.87,-105 "/>
<polyline fill="none" stroke="black" points="661.87,-105 655.87,-105 "/>
<text text-anchor="middle" x="595.87" y="-89.3" font-family="Times,serif" font-size="14.00">Placements (tcl)</text>
</g>
<!-- MSFT&#45;&gt;TCL -->
<g id="edge37" class="edge">
<title>MSFT&#45;&gt;TCL</title>
<path fill="none" stroke="black" d="M529.84,-510.93C559,-486.16 606.87,-437.26 606.87,-383 606.87,-383 606.87,-383 606.87,-237 606.87,-196.89 604.59,-186.04 591.87,-148 588.72,-138.59 584.11,-128.8 579.53,-120.19"/>
<polygon fill="black" stroke="black" points="582.56,-118.44 574.65,-111.39 576.44,-121.83 582.56,-118.44"/>
<path fill="none" stroke="black" d="M537.59,-512.25C576.24,-489.38 638.87,-443.05 638.87,-383 638.87,-383 638.87,-383 638.87,-237 638.87,-196.89 636.59,-186.04 623.87,-148 620.72,-138.59 616.11,-128.8 611.53,-120.19"/>
<polygon fill="black" stroke="black" points="614.56,-118.44 606.65,-111.39 608.44,-121.83 614.56,-118.44"/>
</g>
<!-- ESI&#45;&gt;space_above_RTL -->
<!-- ESI&#45;&gt;HW -->
<g id="edge12" class="edge">
<title>ESI&#45;&gt;HW</title>
<path fill="none" stroke="black" d="M343.65,-510.83C342.98,-494.42 343.19,-468.94 350.91,-440.68"/>
<polygon fill="black" stroke="black" points="354.29,-441.58 353.82,-431 347.59,-439.56 354.29,-441.58"/>
<path fill="none" stroke="black" d="M345.93,-510.8C347,-493.61 348.7,-466.21 350.26,-441.18"/>
<polygon fill="black" stroke="black" points="353.76,-441.2 350.89,-431 346.77,-440.76 353.76,-441.2"/>
</g>
<!-- ServiceDesc -->
<g id="node38" class="node">
<g id="node39" class="node">
<title>ServiceDesc</title>
<polygon fill="#7fc97f" stroke="black" points="477.87,-112 301.87,-112 301.87,-74 483.87,-74 483.87,-106 477.87,-112"/>
<polyline fill="none" stroke="black" points="477.87,-112 477.87,-106 "/>
<polyline fill="none" stroke="black" points="483.87,-106 477.87,-106 "/>
<text text-anchor="middle" x="392.87" y="-96.8" font-family="Times,serif" font-size="14.00">ESI system description</text>
<text text-anchor="middle" x="392.87" y="-81.8" font-family="Times,serif" font-size="14.00">(JSON/Capnp)</text>
<polygon fill="#7fc97f" stroke="black" points="509.87,-112 333.87,-112 333.87,-74 515.87,-74 515.87,-106 509.87,-112"/>
<polyline fill="none" stroke="black" points="509.87,-112 509.87,-106 "/>
<polyline fill="none" stroke="black" points="515.87,-106 509.87,-106 "/>
<text text-anchor="middle" x="424.87" y="-96.8" font-family="Times,serif" font-size="14.00">ESI system description</text>
<text text-anchor="middle" x="424.87" y="-81.8" font-family="Times,serif" font-size="14.00">(JSON/Capnp)</text>
</g>
<!-- ESI&#45;&gt;ServiceDesc -->
<g id="edge36" class="edge">
<title>ESI&#45;&gt;ServiceDesc</title>
<path fill="none" stroke="black" d="M319.09,-510.77C275.25,-480.53 190.87,-417.79 190.87,-383 190.87,-383 190.87,-383 190.87,-237 190.87,-196.89 179.17,-177.94 205.87,-148 227.78,-123.43 260.1,-109.74 291.72,-102.21"/>
<polygon fill="black" stroke="black" points="292.49,-105.63 301.51,-100.06 290.99,-98.79 292.49,-105.63"/>
<path fill="none" stroke="black" d="M317.45,-511.43C291.6,-494.4 253.67,-465.55 231.87,-431 220.07,-412.31 218.87,-405.1 218.87,-383 218.87,-383 218.87,-383 218.87,-237 218.87,-196.55 210.3,-177.59 237.87,-148 260.11,-124.13 292.17,-110.58 323.48,-102.97"/>
<polygon fill="black" stroke="black" points="324.62,-106.3 333.61,-100.7 323.09,-99.47 324.62,-106.3"/>
</g>
<!-- FSM&#45;&gt;space_above_RTL -->
<!-- FSM&#45;&gt;HW -->
<g id="edge13" class="edge">
<title>FSM&#45;&gt;HW</title>
<path fill="none" stroke="black" d="M207.43,-510.87C228.35,-490.33 266.4,-456.5 305.87,-439 320.81,-432.38 329.73,-438.28 341.59,-435.17"/>
<polygon fill="black" stroke="black" points="343.18,-438.29 350.87,-431 340.31,-431.9 343.18,-438.29"/>
<path fill="none" stroke="black" d="M218.1,-511.1C232.89,-501.35 251.12,-488.4 265.87,-475 281.49,-460.8 279.41,-450.88 296.87,-439 302.18,-435.39 306.24,-435.54 310.48,-434.89"/>
<polygon fill="black" stroke="black" points="311.97,-438.06 319.87,-431 309.29,-431.6 311.97,-438.06"/>
</g>
<!-- HWArith&#45;&gt;space_above_RTL -->
<!-- HWArith&#45;&gt;HW -->
<g id="edge14" class="edge">
<title>HWArith&#45;&gt;HW</title>
<path fill="none" stroke="black" d="M426.08,-510.83C426.76,-494.42 426.54,-468.94 418.83,-440.68"/>
<polygon fill="black" stroke="black" points="422.14,-439.56 415.91,-431 415.44,-441.58 422.14,-439.56"/>
<path fill="none" stroke="black" d="M411,-510.57C403.48,-500.57 394.42,-487.53 387.87,-475 382.22,-464.2 377.08,-452.25 372.59,-440.64"/>
<polygon fill="black" stroke="black" points="375.77,-439.14 368.98,-431 369.21,-441.59 375.77,-439.14"/>
</g>
<!-- MooreMIR -->
<g id="node18" class="node">
@ -369,30 +369,30 @@
<!-- MooreMIR&#45;&gt;HW -->
<g id="edge15" class="edge">
<title>MooreMIR&#45;&gt;HW</title>
<path fill="none" stroke="black" d="M574.68,-510.94C544.96,-491.42 493.53,-459.49 445.87,-439 438.32,-435.76 433.43,-436.46 428.09,-435.27"/>
<polygon fill="black" stroke="black" points="429.41,-432.03 418.87,-431 426.47,-438.38 429.41,-432.03"/>
<path fill="none" stroke="black" d="M582.2,-510.69C559.49,-489.63 517.83,-454.94 474.87,-439 441.87,-426.76 424.85,-446.07 396.92,-435.36"/>
<polygon fill="black" stroke="black" points="398.4,-432.18 387.87,-431 395.36,-438.49 398.4,-432.18"/>
</g>
<!-- LLHD -->
<g id="node23" class="node">
<g id="node24" class="node">
<title>LLHD</title>
<g id="a_node23"><a xlink:href="https://circt.llvm.org/docs/Dialects/LLHD/" xlink:title="LLHD">
<polygon fill="white" stroke="black" points="457.87,-328 399.87,-328 399.87,-292 457.87,-292 457.87,-328"/>
<text text-anchor="middle" x="428.87" y="-306.3" font-family="Times,serif" font-size="14.00">LLHD</text>
<g id="a_node24"><a xlink:href="https://circt.llvm.org/docs/Dialects/LLHD/" xlink:title="LLHD">
<polygon fill="white" stroke="black" points="375.87,-328 317.87,-328 317.87,-292 375.87,-292 375.87,-328"/>
<text text-anchor="middle" x="346.87" y="-306.3" font-family="Times,serif" font-size="14.00">LLHD</text>
</a>
</g>
</g>
<!-- MooreMIR&#45;&gt;LLHD -->
<g id="edge17" class="edge">
<title>MooreMIR&#45;&gt;LLHD</title>
<path fill="none" stroke="black" d="M592.37,-510.77C577.45,-477.84 541.4,-404.93 494.87,-356 486.66,-347.37 476.54,-339.47 466.7,-332.78"/>
<polygon fill="black" stroke="black" points="468.48,-329.76 458.19,-327.22 464.65,-335.62 468.48,-329.76"/>
<path fill="none" stroke="black" d="M598.44,-510.95C594.55,-476.01 580.53,-396.16 531.87,-356 482.34,-315.12 450.09,-345.61 385.81,-328.44"/>
<polygon fill="black" stroke="black" points="386.67,-325.04 376.09,-325.55 384.67,-331.75 386.67,-325.04"/>
</g>
<!-- Seq -->
<g id="node20" class="node">
<title>Seq</title>
<g id="a_node20"><a xlink:href="https://circt.llvm.org/docs/Dialects/Seq/" xlink:title="Seq">
<polygon fill="white" stroke="black" points="343.87,-400 289.87,-400 289.87,-364 343.87,-364 343.87,-400"/>
<text text-anchor="middle" x="316.87" y="-378.3" font-family="Times,serif" font-size="14.00">Seq</text>
<polygon fill="white" stroke="black" points="448.87,-400 394.87,-400 394.87,-364 448.87,-364 448.87,-400"/>
<text text-anchor="middle" x="421.87" y="-378.3" font-family="Times,serif" font-size="14.00">Seq</text>
</a>
</g>
</g>
@ -402,227 +402,236 @@
<g id="node22" class="node">
<title>Comb</title>
<g id="a_node22"><a xlink:href="https://circt.llvm.org/docs/Dialects/Comb/" xlink:title="Comb">
<polygon fill="white" stroke="black" points="483.87,-400 425.87,-400 425.87,-364 483.87,-364 483.87,-400"/>
<text text-anchor="middle" x="454.87" y="-378.3" font-family="Times,serif" font-size="14.00">Comb</text>
<polygon fill="white" stroke="black" points="520.87,-400 462.87,-400 462.87,-364 520.87,-364 520.87,-400"/>
<text text-anchor="middle" x="491.87" y="-378.3" font-family="Times,serif" font-size="14.00">Comb</text>
</a>
</g>
</g>
<!-- space_above_RTL&#45;&gt;Comb -->
<!-- SV -->
<g id="node24" class="node">
<g id="node25" class="node">
<title>SV</title>
<g id="a_node24"><a xlink:href="https://circt.llvm.org/docs/Dialects/SV/" xlink:title="SV">
<polygon fill="white" stroke="black" points="343.87,-328 289.87,-328 289.87,-292 343.87,-292 343.87,-328"/>
<text text-anchor="middle" x="316.87" y="-306.3" font-family="Times,serif" font-size="14.00">SV</text>
<g id="a_node25"><a xlink:href="https://circt.llvm.org/docs/Dialects/SV/" xlink:title="SV">
<polygon fill="white" stroke="black" points="443.87,-328 389.87,-328 389.87,-292 443.87,-292 443.87,-328"/>
<text text-anchor="middle" x="416.87" y="-306.3" font-family="Times,serif" font-size="14.00">SV</text>
</a>
</g>
</g>
<!-- Seq&#45;&gt;SV -->
<g id="edge16" class="edge">
<title>Seq&#45;&gt;SV</title>
<path fill="none" stroke="black" d="M316.87,-363.7C316.87,-355.98 316.87,-346.71 316.87,-338.11"/>
<polygon fill="black" stroke="black" points="320.37,-338.1 316.87,-328.1 313.37,-338.1 320.37,-338.1"/>
<path fill="none" stroke="black" d="M420.63,-363.7C420.08,-355.98 419.42,-346.71 418.8,-338.11"/>
<polygon fill="black" stroke="black" points="422.29,-337.83 418.09,-328.1 415.31,-338.33 422.29,-337.83"/>
</g>
<!-- ExportVerilog -->
<g id="node28" class="node">
<g id="node29" class="node">
<title>ExportVerilog</title>
<g id="a_node28"><a xlink:href="https://circt.llvm.org/docs/VerilogGeneration/" xlink:title="ExportVerilog">
<polygon fill="#fdc086" stroke="black" points="332.87,-256 216.87,-256 216.87,-220 332.87,-220 332.87,-256"/>
<text text-anchor="middle" x="274.87" y="-234.3" font-family="Times,serif" font-size="14.00">ExportVerilog</text>
<g id="a_node29"><a xlink:href="https://circt.llvm.org/docs/VerilogGeneration/" xlink:title="ExportVerilog">
<polygon fill="#fdc086" stroke="black" points="472.87,-256 356.87,-256 356.87,-220 472.87,-220 472.87,-256"/>
<text text-anchor="middle" x="414.87" y="-234.3" font-family="Times,serif" font-size="14.00">ExportVerilog</text>
</a>
</g>
</g>
<!-- Seq&#45;&gt;ExportVerilog -->
<g id="edge28" class="edge">
<title>Seq&#45;&gt;ExportVerilog</title>
<path fill="none" stroke="black" d="M297.34,-356C291.72,-347.55 286.21,-337.77 282.87,-328 276.05,-308.1 274.21,-284.3 273.99,-266.33"/>
<polygon fill="black" stroke="black" points="277.49,-266.24 274.02,-256.23 270.49,-266.22 277.49,-266.24"/>
<path fill="none" stroke="black" d="M438.88,-356C443.74,-347.49 448.39,-337.68 450.87,-328 454.83,-312.5 455.57,-307.29 450.87,-292 447.86,-282.22 442.36,-272.62 436.55,-264.33"/>
<polygon fill="black" stroke="black" points="439.27,-262.13 430.48,-256.23 433.67,-266.33 439.27,-262.13"/>
</g>
<!-- HW&#45;&gt;LLHD -->
<g id="edge18" class="edge">
<title>HW&#45;&gt;LLHD</title>
<path fill="none" stroke="black" d="M395.74,-363.7C400.86,-355.56 407.06,-345.69 412.71,-336.7"/>
<polygon fill="black" stroke="black" points="415.76,-338.43 418.12,-328.1 409.83,-334.71 415.76,-338.43"/>
<path fill="none" stroke="black" d="M352.14,-363.7C351.36,-355.98 350.44,-346.71 349.58,-338.11"/>
<polygon fill="black" stroke="black" points="353.05,-337.71 348.58,-328.1 346.09,-338.4 353.05,-337.71"/>
</g>
<!-- llhd_sim -->
<g id="node26" class="node">
<g id="node27" class="node">
<title>llhd_sim</title>
<polygon fill="#fdc086" stroke="black" points="431.87,-256 357.87,-256 357.87,-220 431.87,-220 431.87,-256"/>
<text text-anchor="middle" x="394.87" y="-234.3" font-family="Times,serif" font-size="14.00">llhd&#45;sim</text>
<polygon fill="#fdc086" stroke="black" points="339.87,-256 265.87,-256 265.87,-220 339.87,-220 339.87,-256"/>
<text text-anchor="middle" x="302.87" y="-234.3" font-family="Times,serif" font-size="14.00">llhd&#45;sim</text>
</g>
<!-- HW&#45;&gt;llhd_sim -->
<g id="edge29" class="edge">
<title>HW&#45;&gt;llhd_sim</title>
<path fill="none" stroke="black" d="M386.63,-356C388.4,-330.89 391.11,-292.32 392.94,-266.39"/>
<polygon fill="black" stroke="black" points="396.44,-266.41 393.66,-256.19 389.46,-265.92 396.44,-266.41"/>
<path fill="none" stroke="black" d="M328.54,-356C321.65,-347.75 314.96,-338.08 310.87,-328 302.9,-308.39 301.16,-284.4 301.26,-266.27"/>
<polygon fill="black" stroke="black" points="304.77,-266.17 301.52,-256.09 297.77,-266 304.77,-266.17"/>
</g>
<!-- SystemC -->
<g id="node25" class="node">
<g id="node26" class="node">
<title>SystemC</title>
<g id="a_node25"><a xlink:href="https://circt.llvm.org/docs/Dialects/SystemC/" xlink:title="SystemC">
<polygon fill="white" stroke="black" points="553.87,-328 473.87,-328 473.87,-292 553.87,-292 553.87,-328"/>
<text text-anchor="middle" x="513.87" y="-306.3" font-family="Times,serif" font-size="14.00">SystemC</text>
<g id="a_node26"><a xlink:href="https://circt.llvm.org/docs/Dialects/SystemC/" xlink:title="SystemC">
<polygon fill="white" stroke="black" points="573.87,-328 493.87,-328 493.87,-292 573.87,-292 573.87,-328"/>
<text text-anchor="middle" x="533.87" y="-306.3" font-family="Times,serif" font-size="14.00">SystemC</text>
</a>
</g>
</g>
<!-- Comb&#45;&gt;SystemC -->
<g id="edge19" class="edge">
<title>Comb&#45;&gt;SystemC</title>
<path fill="none" stroke="black" d="M475.94,-356C481.45,-349.46 487.4,-342.4 492.91,-335.86"/>
<polygon fill="black" stroke="black" points="495.68,-338.01 499.45,-328.1 490.33,-333.49 495.68,-338.01"/>
<path fill="none" stroke="black" d="M506.87,-356C510.63,-349.73 514.67,-343 518.45,-336.7"/>
<polygon fill="black" stroke="black" points="521.46,-338.48 523.6,-328.1 515.46,-334.88 521.46,-338.48"/>
</g>
<!-- Interop -->
<g id="node23" class="node">
<title>Interop</title>
<g id="a_node23"><a xlink:href="https://circt.llvm.org/docs/Dialects/Interop/" xlink:title="Interop">
<polygon fill="white" stroke="black" points="312.37,-400 243.37,-400 243.37,-364 312.37,-364 312.37,-400"/>
<text text-anchor="middle" x="277.87" y="-378.3" font-family="Times,serif" font-size="14.00">Interop</text>
</a>
</g>
</g>
<!-- LLHD&#45;&gt;llhd_sim -->
<g id="edge34" class="edge">
<title>LLHD&#45;&gt;llhd_sim</title>
<path fill="none" stroke="black" d="M420.46,-291.7C416.59,-283.73 411.92,-274.1 407.62,-265.26"/>
<polygon fill="black" stroke="black" points="410.69,-263.57 403.17,-256.1 404.4,-266.63 410.69,-263.57"/>
<path fill="none" stroke="black" d="M335.99,-291.7C330.88,-283.56 324.67,-273.69 319.02,-264.7"/>
<polygon fill="black" stroke="black" points="321.9,-262.71 313.62,-256.1 315.98,-266.43 321.9,-262.71"/>
</g>
<!-- SV&#45;&gt;ExportVerilog -->
<g id="edge27" class="edge">
<title>SV&#45;&gt;ExportVerilog</title>
<path fill="none" stroke="black" d="M306.48,-291.7C301.6,-283.56 295.68,-273.69 290.29,-264.7"/>
<polygon fill="black" stroke="black" points="293.28,-262.88 285.13,-256.1 287.27,-266.48 293.28,-262.88"/>
<path fill="none" stroke="black" d="M416.37,-291.7C416.15,-283.98 415.89,-274.71 415.64,-266.11"/>
<polygon fill="black" stroke="black" points="419.14,-266 415.36,-256.1 412.14,-266.2 419.14,-266"/>
</g>
<!-- ExportSystemC -->
<g id="node27" class="node">
<g id="node28" class="node">
<title>ExportSystemC</title>
<polygon fill="#fdc086" stroke="black" points="583.37,-256 454.37,-256 454.37,-220 583.37,-220 583.37,-256"/>
<text text-anchor="middle" x="518.87" y="-234.3" font-family="Times,serif" font-size="14.00">ExportSystemC</text>
<polygon fill="#fdc086" stroke="black" points="616.37,-256 487.37,-256 487.37,-220 616.37,-220 616.37,-256"/>
<text text-anchor="middle" x="551.87" y="-234.3" font-family="Times,serif" font-size="14.00">ExportSystemC</text>
</g>
<!-- SystemC&#45;&gt;ExportSystemC -->
<g id="edge25" class="edge">
<title>SystemC&#45;&gt;ExportSystemC</title>
<path fill="none" stroke="black" d="M515.1,-291.7C515.65,-283.98 516.32,-274.71 516.93,-266.11"/>
<polygon fill="black" stroke="black" points="520.42,-266.33 517.64,-256.1 513.44,-265.83 520.42,-266.33"/>
<path fill="none" stroke="black" d="M538.32,-291.7C540.32,-283.9 542.74,-274.51 544.97,-265.83"/>
<polygon fill="black" stroke="black" points="548.37,-266.66 547.47,-256.1 541.59,-264.92 548.37,-266.66"/>
</g>
<!-- VCDTrace -->
<g id="node35" class="node">
<g id="node36" class="node">
<title>VCDTrace</title>
<polygon fill="#7fc97f" stroke="black" points="436.87,-184 346.87,-184 346.87,-148 442.87,-148 442.87,-178 436.87,-184"/>
<polyline fill="none" stroke="black" points="436.87,-184 436.87,-178 "/>
<polyline fill="none" stroke="black" points="442.87,-178 436.87,-178 "/>
<text text-anchor="middle" x="394.87" y="-162.3" font-family="Times,serif" font-size="14.00">Trace (vcd)</text>
<polygon fill="#7fc97f" stroke="black" points="334.87,-184 244.87,-184 244.87,-148 340.87,-148 340.87,-178 334.87,-184"/>
<polyline fill="none" stroke="black" points="334.87,-184 334.87,-178 "/>
<polyline fill="none" stroke="black" points="340.87,-178 334.87,-178 "/>
<text text-anchor="middle" x="292.87" y="-162.3" font-family="Times,serif" font-size="14.00">Trace (vcd)</text>
</g>
<!-- llhd_sim&#45;&gt;VCDTrace -->
<g id="edge35" class="edge">
<title>llhd_sim&#45;&gt;VCDTrace</title>
<path fill="none" stroke="black" d="M394.87,-219.7C394.87,-211.98 394.87,-202.71 394.87,-194.11"/>
<polygon fill="black" stroke="black" points="398.37,-194.1 394.87,-184.1 391.37,-194.1 398.37,-194.1"/>
<path fill="none" stroke="black" d="M300.39,-219.7C299.29,-211.98 297.97,-202.71 296.74,-194.11"/>
<polygon fill="black" stroke="black" points="300.19,-193.51 295.31,-184.1 293.26,-194.5 300.19,-193.51"/>
</g>
<!-- SystemCFile -->
<g id="node36" class="node">
<g id="node37" class="node">
<title>SystemCFile</title>
<polygon fill="#7fc97f" stroke="black" points="578.37,-184 457.37,-184 457.37,-148 584.37,-148 584.37,-178 578.37,-184"/>
<polyline fill="none" stroke="black" points="578.37,-184 578.37,-178 "/>
<polyline fill="none" stroke="black" points="584.37,-178 578.37,-178 "/>
<text text-anchor="middle" x="520.87" y="-162.3" font-family="Times,serif" font-size="14.00">SystemC (c++)</text>
<polygon fill="#7fc97f" stroke="black" points="610.37,-184 489.37,-184 489.37,-148 616.37,-148 616.37,-178 610.37,-184"/>
<polyline fill="none" stroke="black" points="610.37,-184 610.37,-178 "/>
<polyline fill="none" stroke="black" points="616.37,-178 610.37,-178 "/>
<text text-anchor="middle" x="552.87" y="-162.3" font-family="Times,serif" font-size="14.00">SystemC (c++)</text>
</g>
<!-- ExportSystemC&#45;&gt;SystemCFile -->
<g id="edge26" class="edge">
<title>ExportSystemC&#45;&gt;SystemCFile</title>
<path fill="none" stroke="black" d="M519.36,-219.7C519.58,-211.98 519.85,-202.71 520.09,-194.11"/>
<polygon fill="black" stroke="black" points="523.59,-194.2 520.38,-184.1 516.59,-194 523.59,-194.2"/>
<path fill="none" stroke="black" d="M552.11,-219.7C552.22,-211.98 552.36,-202.71 552.48,-194.11"/>
<polygon fill="black" stroke="black" points="555.98,-194.15 552.62,-184.1 548.98,-194.05 555.98,-194.15"/>
</g>
<!-- SVFile -->
<g id="node37" class="node">
<g id="node38" class="node">
<title>SVFile</title>
<polygon fill="#7fc97f" stroke="black" points="326.87,-184 212.87,-184 212.87,-148 332.87,-148 332.87,-178 326.87,-184"/>
<polyline fill="none" stroke="black" points="326.87,-184 326.87,-178 "/>
<polyline fill="none" stroke="black" points="332.87,-178 326.87,-178 "/>
<text text-anchor="middle" x="272.87" y="-162.3" font-family="Times,serif" font-size="14.00">SystemVerilog</text>
<polygon fill="#7fc97f" stroke="black" points="468.87,-184 354.87,-184 354.87,-148 474.87,-148 474.87,-178 468.87,-184"/>
<polyline fill="none" stroke="black" points="468.87,-184 468.87,-178 "/>
<polyline fill="none" stroke="black" points="474.87,-178 468.87,-178 "/>
<text text-anchor="middle" x="414.87" y="-162.3" font-family="Times,serif" font-size="14.00">SystemVerilog</text>
</g>
<!-- ExportVerilog&#45;&gt;SVFile -->
<g id="edge20" class="edge">
<title>ExportVerilog&#45;&gt;SVFile</title>
<path fill="none" stroke="black" d="M274.37,-219.7C274.15,-211.98 273.89,-202.71 273.64,-194.11"/>
<polygon fill="black" stroke="black" points="277.14,-194 273.36,-184.1 270.14,-194.2 277.14,-194"/>
<path fill="none" stroke="black" d="M414.87,-219.7C414.87,-211.98 414.87,-202.71 414.87,-194.11"/>
<polygon fill="black" stroke="black" points="418.37,-194.1 414.87,-184.1 411.37,-194.1 418.37,-194.1"/>
</g>
<!-- Moore -->
<g id="node29" class="node">
<g id="node30" class="node">
<title>Moore</title>
<polygon fill="#ffff99" stroke="black" points="740.6,-828.54 740.6,-843.46 714.98,-854 678.75,-854 653.13,-843.46 653.13,-828.54 678.75,-818 714.98,-818 740.6,-828.54"/>
<text text-anchor="middle" x="696.87" y="-832.3" font-family="Times,serif" font-size="14.00">Moore</text>
<polygon fill="#ffff99" stroke="black" points="731.6,-828.54 731.6,-843.46 705.98,-854 669.75,-854 644.13,-843.46 644.13,-828.54 669.75,-818 705.98,-818 731.6,-828.54"/>
<text text-anchor="middle" x="687.87" y="-832.3" font-family="Times,serif" font-size="14.00">Moore</text>
</g>
<!-- Moore&#45;&gt;MooreMIR -->
<g id="edge31" class="edge">
<title>Moore&#45;&gt;MooreMIR</title>
<path fill="none" stroke="black" d="M691.37,-817.73C675.23,-766.98 627.87,-618.06 608.39,-556.8"/>
<polygon fill="black" stroke="black" points="611.67,-555.55 605.3,-547.08 604.99,-557.67 611.67,-555.55"/>
<path fill="none" stroke="black" d="M682.88,-817.73C668.24,-766.98 625.28,-618.06 607.6,-556.8"/>
<polygon fill="black" stroke="black" points="610.93,-555.72 604.8,-547.08 604.2,-557.66 610.93,-555.72"/>
</g>
<!-- Calyx_native&#45;&gt;HW -->
<g id="edge33" class="edge">
<title>Calyx_native&#45;&gt;HW</title>
<path fill="none" stroke="black" d="M83.21,-510.83C95.85,-489.57 120.57,-454.31 152.87,-439 189.86,-421.47 295.76,-447.78 341.56,-434.68"/>
<polygon fill="black" stroke="black" points="342.86,-437.94 350.87,-431 340.28,-431.43 342.86,-437.94"/>
<path fill="none" stroke="black" d="M103.9,-510.89C141,-490.53 206.6,-457.05 266.87,-439 285.94,-433.29 295.99,-440.27 310.62,-435.41"/>
<polygon fill="black" stroke="black" points="312.35,-438.46 319.87,-431 309.33,-432.15 312.35,-438.46"/>
</g>
<!-- FIRFile -->
<g id="node31" class="node">
<g id="node32" class="node">
<title>FIRFile</title>
<polygon fill="#7fc97f" stroke="black" points="495.87,-854 447.87,-854 447.87,-818 501.87,-818 501.87,-848 495.87,-854"/>
<polyline fill="none" stroke="black" points="495.87,-854 495.87,-848 "/>
<polyline fill="none" stroke="black" points="501.87,-848 495.87,-848 "/>
<text text-anchor="middle" x="474.87" y="-832.3" font-family="Times,serif" font-size="14.00">.fir</text>
<polygon fill="#7fc97f" stroke="black" points="486.87,-854 438.87,-854 438.87,-818 492.87,-818 492.87,-848 486.87,-854"/>
<polyline fill="none" stroke="black" points="486.87,-854 486.87,-848 "/>
<polyline fill="none" stroke="black" points="492.87,-848 486.87,-848 "/>
<text text-anchor="middle" x="465.87" y="-832.3" font-family="Times,serif" font-size="14.00">.fir</text>
</g>
<!-- FIRFile&#45;&gt;FIRRTLParser -->
<g id="edge23" class="edge">
<title>FIRFile&#45;&gt;FIRRTLParser</title>
<path fill="none" stroke="black" d="M502.11,-821.81C512.81,-815.09 523.94,-805.82 529.87,-794 543.22,-767.39 541.37,-754.47 529.87,-727 511.51,-683.18 469.48,-646.95 438.78,-624.98"/>
<polygon fill="black" stroke="black" points="440.65,-622.02 430.45,-619.16 436.65,-627.76 440.65,-622.02"/>
<path fill="none" stroke="black" d="M493.11,-821.81C503.81,-815.09 514.94,-805.82 520.87,-794 534.22,-767.39 531.86,-754.67 520.87,-727 503.86,-684.22 464.5,-647.6 435.9,-625.26"/>
<polygon fill="black" stroke="black" points="437.85,-622.35 427.78,-619.07 433.61,-627.91 437.85,-622.35"/>
</g>
<!-- FIRFile&#45;&gt;Scheduling -->
<!-- Chisel -->
<g id="node32" class="node">
<g id="node33" class="node">
<title>Chisel</title>
<polygon fill="#ffff99" stroke="black" points="515.69,-919.54 515.69,-934.46 490.61,-945 455.13,-945 430.04,-934.46 430.04,-919.54 455.13,-909 490.61,-909 515.69,-919.54"/>
<text text-anchor="middle" x="472.87" y="-923.3" font-family="Times,serif" font-size="14.00">Chisel</text>
<polygon fill="#ffff99" stroke="black" points="506.69,-919.54 506.69,-934.46 481.61,-945 446.13,-945 421.04,-934.46 421.04,-919.54 446.13,-909 481.61,-909 506.69,-919.54"/>
<text text-anchor="middle" x="463.87" y="-923.3" font-family="Times,serif" font-size="14.00">Chisel</text>
</g>
<!-- Chisel&#45;&gt;CF -->
<!-- Chisel&#45;&gt;FIRFile -->
<g id="edge22" class="edge">
<title>Chisel&#45;&gt;FIRFile</title>
<path fill="none" stroke="black" d="M473.25,-908.84C473.53,-896.28 473.92,-878.98 474.25,-864.5"/>
<polygon fill="black" stroke="black" points="477.76,-864.18 474.48,-854.11 470.76,-864.03 477.76,-864.18"/>
<path fill="none" stroke="black" d="M464.25,-908.84C464.53,-896.28 464.92,-878.98 465.25,-864.5"/>
<polygon fill="black" stroke="black" points="468.76,-864.18 465.48,-854.11 461.76,-864.03 468.76,-864.18"/>
</g>
<!-- SVVHDL -->
<g id="node33" class="node">
<g id="node34" class="node">
<title>SVVHDL</title>
<polygon fill="#ffff99" stroke="black" points="755.15,-919.54 755.15,-934.46 721.01,-945 672.73,-945 638.59,-934.46 638.59,-919.54 672.73,-909 721.01,-909 755.15,-919.54"/>
<text text-anchor="middle" x="696.87" y="-923.3" font-family="Times,serif" font-size="14.00">SV/VHDL</text>
<polygon fill="#ffff99" stroke="black" points="746.15,-919.54 746.15,-934.46 712.01,-945 663.73,-945 629.59,-934.46 629.59,-919.54 663.73,-909 712.01,-909 746.15,-919.54"/>
<text text-anchor="middle" x="687.87" y="-923.3" font-family="Times,serif" font-size="14.00">SV/VHDL</text>
</g>
<!-- SVVHDL&#45;&gt;Moore -->
<g id="edge30" class="edge">
<title>SVVHDL&#45;&gt;Moore</title>
<path fill="none" stroke="black" d="M696.87,-908.84C696.87,-896.28 696.87,-878.98 696.87,-864.5"/>
<polygon fill="black" stroke="black" points="700.37,-864.11 696.87,-854.11 693.37,-864.11 700.37,-864.11"/>
<path fill="none" stroke="black" d="M687.87,-908.84C687.87,-896.28 687.87,-878.98 687.87,-864.5"/>
<polygon fill="black" stroke="black" points="691.37,-864.11 687.87,-854.11 684.37,-864.11 691.37,-864.11"/>
</g>
<!-- PyFile -->
<g id="node34" class="node">
<g id="node35" class="node">
<title>PyFile</title>
<polygon fill="#ffff99" stroke="black" points="624.14,-919.54 624.14,-934.46 596.45,-945 557.29,-945 529.6,-934.46 529.6,-919.54 557.29,-909 596.45,-909 624.14,-919.54"/>
<text text-anchor="middle" x="576.87" y="-923.3" font-family="Times,serif" font-size="14.00">Python</text>
<polygon fill="#ffff99" stroke="black" points="615.14,-919.54 615.14,-934.46 587.45,-945 548.29,-945 520.6,-934.46 520.6,-919.54 548.29,-909 587.45,-909 615.14,-919.54"/>
<text text-anchor="middle" x="567.87" y="-923.3" font-family="Times,serif" font-size="14.00">Python</text>
</g>
<!-- PyFile&#45;&gt;PyCDE -->
<g id="edge38" class="edge">
<title>PyFile&#45;&gt;PyCDE</title>
<path fill="none" stroke="black" d="M574.82,-908.83C570.53,-874.2 559.75,-793.59 544.87,-727 537.2,-692.71 525.56,-653.94 517.6,-628.79"/>
<polygon fill="black" stroke="black" points="520.92,-627.68 514.54,-619.22 514.25,-629.81 520.92,-627.68"/>
<path fill="none" stroke="black" d="M565.43,-908.91C560.45,-874.42 548.49,-794.06 535.87,-727 529.51,-693.21 520.96,-654.55 515.2,-629.29"/>
<polygon fill="black" stroke="black" points="518.56,-628.3 512.92,-619.33 511.74,-629.86 518.56,-628.3"/>
</g>
<!-- SystemCFile&#45;&gt;ServiceDesc -->
<!-- SystemCFile&#45;&gt;TCL -->
<!-- SoftwareAPI -->
<g id="node39" class="node">
<g id="node40" class="node">
<title>SoftwareAPI</title>
<polygon fill="none" stroke="black" stroke-dasharray="5,2" points="454.37,-38 325.37,-38 325.37,0 460.37,0 460.37,-32 454.37,-38"/>
<polyline fill="none" stroke="black" stroke-dasharray="5,2" points="454.37,-38 454.37,-32 "/>
<polyline fill="none" stroke="black" stroke-dasharray="5,2" points="460.37,-32 454.37,-32 "/>
<text text-anchor="middle" x="392.87" y="-22.8" font-family="Times,serif" font-size="14.00">Software API</text>
<text text-anchor="middle" x="392.87" y="-7.8" font-family="Times,serif" font-size="14.00">(e.g. py/c++/c#)</text>
<polygon fill="none" stroke="black" stroke-dasharray="5,2" points="486.37,-38 357.37,-38 357.37,0 492.37,0 492.37,-32 486.37,-38"/>
<polyline fill="none" stroke="black" stroke-dasharray="5,2" points="486.37,-38 486.37,-32 "/>
<polyline fill="none" stroke="black" stroke-dasharray="5,2" points="492.37,-32 486.37,-32 "/>
<text text-anchor="middle" x="424.87" y="-22.8" font-family="Times,serif" font-size="14.00">Software API</text>
<text text-anchor="middle" x="424.87" y="-7.8" font-family="Times,serif" font-size="14.00">(e.g. py/c++/c#)</text>
</g>
<!-- ServiceDesc&#45;&gt;SoftwareAPI -->
<g id="edge44" class="edge">
<title>ServiceDesc&#45;&gt;SoftwareAPI</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M392.87,-73.83C392.87,-66.13 392.87,-56.97 392.87,-48.42"/>
<polygon fill="black" stroke="black" points="396.37,-48.41 392.87,-38.41 389.37,-48.41 396.37,-48.41"/>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M424.87,-73.83C424.87,-66.13 424.87,-56.97 424.87,-48.42"/>
<polygon fill="black" stroke="black" points="428.37,-48.41 424.87,-38.41 421.37,-48.41 428.37,-48.41"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -17,6 +17,7 @@ add_subdirectory(FSM)
add_subdirectory(Handshake)
add_subdirectory(HW)
add_subdirectory(HWArith)
add_subdirectory(Interop)
add_subdirectory(LLHD)
add_subdirectory(Moore)
add_subdirectory(MSFT)

View File

@ -0,0 +1,9 @@
add_circt_dialect(Interop interop)
add_circt_dialect_doc(Interop interop)
set(LLVM_TARGET_DEFINITIONS Interop.td)
mlir_tablegen(InteropEnums.h.inc -gen-enum-decls)
mlir_tablegen(InteropEnums.cpp.inc -gen-enum-defs)
add_public_tablegen_target(CIRCTInteropEnumsIncGen)
add_dependencies(circt-headers CIRCTInteropEnumsIncGen)

View File

@ -0,0 +1,45 @@
//===- Interop.td - Interop dialect definition -------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This is the top level file for the Interop dialect.
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_INTEROP_INTEROP
#define CIRCT_DIALECT_INTEROP_INTEROP
include "mlir/IR/OpBase.td"
include "mlir/IR/OpAsmInterface.td"
include "mlir/IR/EnumAttr.td"
//===----------------------------------------------------------------------===//
// Interop Dialect
//===----------------------------------------------------------------------===//
def InteropDialect : Dialect {
let name = "interop";
let summary = "Provides interoperability between backends and tools";
let description = [{
This dialect defines the `interop` dialect which defines operations and
interfaces necessary to provide interoperability between backends and
and external tools without the need of writing custom pairwise interop
solutions.
}];
let cppNamespace = "::circt::interop";
}
//===----------------------------------------------------------------------===//
// Interop Operations
//===----------------------------------------------------------------------===//
// Base class for the operations in this dialect.
class InteropOp<string mnemonic, list<Trait> traits = []> :
Op<InteropDialect, mnemonic, traits>;
#endif // CIRCT_DIALECT_INTEROP_INTEROP

View File

@ -0,0 +1,22 @@
//===- InteropDialect.h - Interop dialect declaration -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines an Interop MLIR dialect.
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_INTEROP_INTEROPDIALECT_H
#define CIRCT_DIALECT_INTEROP_INTEROPDIALECT_H
#include "circt/Support/LLVM.h"
#include "mlir/IR/Dialect.h"
// Pull in the dialect definition.
#include "circt/Dialect/Interop/InteropDialect.h.inc"
#endif // CIRCT_DIALECT_INTEROP_INTEROPDIALECT_H

View File

@ -0,0 +1,23 @@
//===- InteropOps.h - Declare Interop dialect operations --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the operation classes for the Interop dialect.
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_INTEROP_INTEROPOPS_H
#define CIRCT_DIALECT_INTEROP_INTEROPOPS_H
#include "circt/Dialect/Interop/InteropDialect.h"
#define GET_OP_CLASSES
#include "circt/Dialect/Interop/InteropEnums.h.inc"
// Clang format shouldn't reorder these headers.
#include "circt/Dialect/Interop/Interop.h.inc"
#endif // CIRCT_DIALECT_INTEROP_INTEROPOPS_H

View File

@ -23,6 +23,7 @@
#include "circt/Dialect/HW/HWDialect.h"
#include "circt/Dialect/HWArith/HWArithDialect.h"
#include "circt/Dialect/Handshake/HandshakeDialect.h"
#include "circt/Dialect/Interop/InteropDialect.h"
#include "circt/Dialect/LLHD/IR/LLHDDialect.h"
#include "circt/Dialect/MSFT/MSFTDialect.h"
#include "circt/Dialect/Moore/MooreDialect.h"
@ -46,6 +47,7 @@ inline void registerAllDialects(mlir::DialectRegistry &registry) {
firrtl::FIRRTLDialect,
fsm::FSMDialect,
handshake::HandshakeDialect,
interop::InteropDialect,
llhd::LLHDDialect,
msft::MSFTDialect,
moore::MooreDialect,

View File

@ -17,6 +17,7 @@ add_subdirectory(FSM)
add_subdirectory(Handshake)
add_subdirectory(HW)
add_subdirectory(HWArith)
add_subdirectory(Interop)
add_subdirectory(LLHD)
add_subdirectory(Moore)
add_subdirectory(MSFT)

View File

@ -0,0 +1,19 @@
add_circt_dialect_library(CIRCTInteropDialect
InteropDialect.cpp
InteropOps.cpp
ADDITIONAL_HEADER_DIRS
${CIRCT_MAIN_INCLUDE_DIR}/circt/Dialect/Interop
DEPENDS
MLIRInteropIncGen
CIRCTInteropEnumsIncGen
LINK_COMPONENTS
Support
LINK_LIBS PUBLIC
MLIRIR
)
add_dependencies(circt-headers MLIRInteropIncGen)

View File

@ -0,0 +1,30 @@
//===- InteropDialect.cpp - Implement the Interop dialect -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the Interop dialect.
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Interop/InteropOps.h"
using namespace circt;
using namespace circt::interop;
//===----------------------------------------------------------------------===//
// Dialect specification.
//===----------------------------------------------------------------------===//
void InteropDialect::initialize() {
// Register operations.
addOperations<
#define GET_OP_LIST
#include "circt/Dialect/Interop/Interop.cpp.inc"
>();
}
#include "circt/Dialect/Interop/InteropDialect.cpp.inc"

View File

@ -0,0 +1,26 @@
//===- InteropOps.cpp - Implement the Interop operations ------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the Interop operations.
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Interop/InteropOps.h"
#include "mlir/IR/Builders.h"
using namespace circt;
using namespace circt::interop;
//===----------------------------------------------------------------------===//
// TableGen generated logic.
//===----------------------------------------------------------------------===//
// Provide the autogenerated implementation guts for the Op classes.
#define GET_OP_CLASSES
#include "circt/Dialect/Interop/Interop.cpp.inc"
#include "circt/Dialect/Interop/InteropEnums.cpp.inc"

View File

@ -19,6 +19,7 @@
// DIALECT-NEXT: handshake
// DIALECT-NEXT: hw
// DIALECT-NEXT: hwarith
// DIALECT-NEXT: interop
// DIALECT-NEXT: llhd
// DIALECT-NEXT: llvm
// DIALECT-NEXT: memref

View File

@ -39,6 +39,7 @@ target_link_libraries(circt-opt
CIRCTHW
CIRCTHWArith
CIRCTHWArithToHW
CIRCTInteropDialect
CIRCTHWToLLHD
CIRCTHWToSystemC
CIRCTHWTransforms

View File

@ -16,6 +16,7 @@ target_link_libraries(circt-reduce
CIRCTFIRRTLTransforms
CIRCTFSM
CIRCTHandshake
CIRCTInteropDialect
CIRCTLLHD
CIRCTMoore
CIRCTMSFT