CIRCT  20.0.0git
SpecializeOption.cpp
Go to the documentation of this file.
1 //===- SpecializeOption.cpp -------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
11 #include "mlir/IR/ImplicitLocOpBuilder.h"
12 #include "mlir/IR/Threading.h"
13 #include "mlir/Pass/Pass.h"
14 
15 namespace circt {
16 namespace firrtl {
17 #define GEN_PASS_DEF_SPECIALIZEOPTION
18 #include "circt/Dialect/FIRRTL/Passes.h.inc"
19 } // namespace firrtl
20 } // namespace circt
21 
22 using namespace mlir;
23 using namespace circt;
24 using namespace firrtl;
25 
26 namespace {
27 struct SpecializeOptionPass
28  : public circt::firrtl::impl::SpecializeOptionBase<SpecializeOptionPass> {
29  using SpecializeOptionBase::numInstances;
30  using SpecializeOptionBase::selectDefaultInstanceChoice;
31 
32  void runOnOperation() override {
33  auto circuit = getOperation();
34 
35  DenseMap<StringAttr, OptionCaseOp> selected;
36  if (auto choiceAttr = circuit.getSelectInstChoiceAttr()) {
37  for (auto attr : choiceAttr.getAsRange<StringAttr>()) {
38  const auto optionAndCase = attr.getValue().str();
39  size_t eq = optionAndCase.find("=");
40  if (eq == std::string::npos) {
41  mlir::emitError(circuit.getLoc(),
42  "invalid option format: \"" + optionAndCase + '"');
43  return signalPassFailure();
44  }
45 
46  std::string optionName = optionAndCase.substr(0, eq);
47  auto optionOp = circuit.lookupSymbol<OptionOp>(optionName);
48  if (!optionOp) {
49  mlir::emitError(circuit.getLoc(), "unknown option \"")
50  << optionName << '"';
51  return signalPassFailure();
52  }
53 
54  std::string caseName = optionAndCase.substr(eq + 1);
55  auto caseOp = optionOp.lookupSymbol<OptionCaseOp>(caseName);
56  if (!caseOp) {
57  mlir::emitError(circuit.getLoc(), "invalid option case \"")
58  << caseName << '"';
59  return signalPassFailure();
60  }
61  selected[StringAttr::get(&getContext(), optionName)] = caseOp;
62  }
63  }
64 
65  bool failed = false;
66  mlir::parallelForEach(
67  &getContext(), circuit.getOps<FModuleOp>(), [&](auto module) {
68  module.walk([&](firrtl::InstanceChoiceOp inst) {
69  auto it = selected.find(inst.getOptionNameAttr());
70  FlatSymbolRefAttr target;
71  if (it == selected.end()) {
72  if (!selectDefaultInstanceChoice) {
73  inst.emitError("missing specialization for option ")
74  << inst.getOptionNameAttr();
75  failed = true;
76  return;
77  }
78  target = inst.getDefaultTargetAttr();
79  } else
80  target = inst.getTargetOrDefaultAttr(it->second);
81 
82  ImplicitLocOpBuilder builder(inst.getLoc(), inst);
83  auto newInst = builder.create<InstanceOp>(
84  inst->getResultTypes(), target, inst.getNameAttr(),
85  inst.getNameKindAttr(), inst.getPortDirectionsAttr(),
86  inst.getPortNamesAttr(), inst.getAnnotationsAttr(),
87  inst.getPortAnnotationsAttr(), builder.getArrayAttr({}),
88  UnitAttr{}, inst.getInnerSymAttr());
89  inst.replaceAllUsesWith(newInst);
90  inst.erase();
91 
92  ++numInstances;
93  });
94  });
95 
96  bool analysisPreserved = numInstances == 0;
97  circuit->walk([&](OptionOp optionOp) {
98  optionOp->erase();
99  analysisPreserved = false;
100  });
101  if (analysisPreserved)
102  markAllAnalysesPreserved();
103 
104  if (failed)
105  signalPassFailure();
106  }
107 };
108 } // namespace
109 
110 std::unique_ptr<Pass>
111 firrtl::createSpecializeOptionPass(bool selectDefaultInstanceChoice) {
112  auto pass = std::make_unique<SpecializeOptionPass>();
113  pass->selectDefaultInstanceChoice = selectDefaultInstanceChoice;
114  return pass;
115 }
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:55
std::unique_ptr< mlir::Pass > createSpecializeOptionPass(bool selectDefaultInstanceChoice=false)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21