circt
circt copied to clipboard
[FIRRTL][LayerSink] Analyze instances and conservatively don't sink them if not safe
Instances and anything else with side-effects cannot be sunk into a layer without changing the behavior of the base program.
Consider this FIRRTL input:
FIRRTL version 4.0.0
circuit DUT :
layer T, bind :
extmodule Unknown :
output p : UInt<1>
public module DUT :
inst u of Unknown
layerblock T :
node n = u.p
Presently, firtool
(via LayerSink) puts the instance of u
into the layer:
// Generated by CIRCT firtool-1.80.0g20240805_461c631
// external module Unknown
module DUT_T();
Unknown u (
.p (/* unused */)
);
endmodule
module DUT();
endmodule
// ----- 8< ----- FILE "layers_DUT_T.sv" ----- 8< -----
// Generated by CIRCT firtool-1.80.0g20240805_461c631
`ifndef layers_DUT_T
`define layers_DUT_T
bind DUT DUT_T t ();
`endif // layers_DUT_T
More specifically -- in case pipeline changes -- the following fed to layer sink exhibits the problem:
firrtl.circuit "DUT" {
firrtl.layer @T bind { }
firrtl.extmodule @Unknown(out p : !firrtl.uint<1>)
firrtl.module public @DUT() attributes {convention = #firrtl<convention scalarized>} {
// Who knows what this instance does, do not sink!
%u_p = firrtl.instance u @Unknown(out p : !firrtl.uint<1>)
firrtl.layerblock @T {
%n = firrtl.node %u_p : !firrtl.uint<1>
}
}
}