11#include "mlir/IR/ImplicitLocOpBuilder.h"
12#include "mlir/IR/Threading.h"
13#include "mlir/Pass/Pass.h"
17#define GEN_PASS_DEF_SPECIALIZEOPTION
18#include "circt/Dialect/FIRRTL/Passes.h.inc"
24using namespace firrtl;
27struct SpecializeOptionPass
28 :
public circt::firrtl::impl::SpecializeOptionBase<SpecializeOptionPass> {
31 void runOnOperation()
override {
32 auto circuit = getOperation();
34 DenseMap<StringAttr, OptionCaseOp> selected;
35 if (
auto choiceAttr = circuit.getSelectInstChoiceAttr()) {
36 for (
auto attr : choiceAttr.getAsRange<StringAttr>()) {
37 const auto optionAndCase = attr.getValue().str();
38 size_t eq = optionAndCase.find(
"=");
39 if (eq == std::string::npos) {
40 mlir::emitError(circuit.getLoc(),
41 "invalid option format: \"" + optionAndCase +
'"');
42 return signalPassFailure();
45 std::string optionName = optionAndCase.substr(0, eq);
46 auto optionOp = circuit.lookupSymbol<OptionOp>(optionName);
48 mlir::emitError(circuit.getLoc(),
"unknown option \"")
50 return signalPassFailure();
53 std::string caseName = optionAndCase.substr(eq + 1);
54 auto caseOp = optionOp.lookupSymbol<OptionCaseOp>(caseName);
56 mlir::emitError(circuit.getLoc(),
"invalid option case \"")
58 return signalPassFailure();
60 selected[StringAttr::get(&getContext(), optionName)] = caseOp;
65 mlir::parallelForEach(
66 &getContext(), circuit.getOps<FModuleOp>(), [&](
auto module) {
67 module.walk([&](firrtl::InstanceChoiceOp inst) {
68 auto it = selected.find(inst.getOptionNameAttr());
69 FlatSymbolRefAttr target;
70 if (it == selected.end()) {
71 if (!selectDefaultInstanceChoice) {
72 inst.emitError(
"missing specialization for option ")
73 << inst.getOptionNameAttr();
77 target = inst.getDefaultTargetAttr();
79 target = inst.getTargetOrDefaultAttr(it->second);
81 ImplicitLocOpBuilder builder(inst.getLoc(), inst);
82 auto newInst = builder.create<InstanceOp>(
83 inst->getResultTypes(), target, inst.getNameAttr(),
84 inst.getNameKindAttr(), inst.getPortDirectionsAttr(),
85 inst.getPortNamesAttr(), inst.getAnnotationsAttr(),
86 inst.getPortAnnotationsAttr(), builder.getArrayAttr({}),
87 UnitAttr{}, UnitAttr{}, inst.getInnerSymAttr());
88 inst.replaceAllUsesWith(newInst);
95 bool analysisPreserved = numInstances == 0;
96 circuit->walk([&](OptionOp optionOp) {
98 analysisPreserved =
false;
100 if (analysisPreserved)
101 markAllAnalysesPreserved();
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.