Description
We propose a mechanism for linking multiple MLIR files in firtool. Specifically, this involves combining multiple circuits into a single one.
All modules instantiated within another module (i.e., all firrtl.instance
operations) must have corresponding declarations in the same circuit, which can be either a firrtl.module or a firrtl.extmodule
serving as an interface. Notably, a module can have both an interface (as an extmodule
) and an implementation (as a module
) within the same circuit.
The linking process works as follows: First, we verify that each instance has a corresponding declaration. Then, all circuits are concatenated into one. Finally, we iterate through all extmodules to find matching public module implementations, replacing them when possible and any remaining extmodules are treated as blackboxes.
For example, there are two .mlir
files:
GCD.mlir
module {
firrtl.circuit "GCD" {
firrtl.module @GCD(out %output: !firrtl.bundle<valid: uint<1>, bits: bundle<z: uint<32>>>, in %input: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>, bits: bundle<x: uint<32>, y: uint<32>>>, in %reset: !firrtl.uint<1>, in %clock: !firrtl.clock) attributes {convention = #firrtl<convention scalarized>} {
...
%sub = firrtl.instance sub1 interesting_name @Subtractor(in a: !firrtl.uint<32>, in b: !firrtl.uint<32>, out z: !firrtl.uint<32>)
...
}
firrtl.extmodule @Subtractor(in a: !firrtl.uint<32>, in b: !firrtl.uint<32>, out z: !firrtl.uint<32>) attributes {defname = "Subtractor"}
}
}
Subtractor.mlir
module {
firrtl.circuit "Subtractor" {
firrtl.module @Subtractor(in %a: !firrtl.uint<32>, in %b: !firrtl.uint<32>, out %z: !firrtl.uint<32>) attributes {convention = #firrtl<convention scalarized>} {
...
}
}
}
We can pass them to firtool together by
firtool GCD.mlir Subtractir.mlir
and produce a complete circuit:
module {
firrtl.circuit "GCD"
firrtl.module @GCD(out %output: !firrtl.bundle<valid: uint<1>, bits: bundle<z: uint<32>>>, in %input: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>, bits: bundle<x: uint<32>, y: uint<32>>>, in %reset: !firrtl.uint<1>, in %clock: !firrtl.clock) attributes {convention = #firrtl<convention scalarized>} {
...
%sub = firrtl.instance sub1 interesting_name @Subtractor(in a: !firrtl.uint<32>, in b: !firrtl.uint<32>, out z: !firrtl.uint<32>)
...
}
firrtl.module @Subtractor(in %a: !firrtl.uint<32>, in %b: !firrtl.uint<32>, out %z: !firrtl.uint<32>) attributes {convention = #firrtl<convention scalarized>} {
...
}
}
}