CIRCT  19.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 
9 #include "PassDetails.h"
10 #include "mlir/IR/ImplicitLocOpBuilder.h"
11 #include "mlir/IR/Threading.h"
12 
13 using namespace mlir;
14 using namespace circt;
15 using namespace firrtl;
16 
17 namespace {
18 struct SpecializeOptionPass
19  : public SpecializeOptionBase<SpecializeOptionPass> {
20  using SpecializeOptionBase::numInstances;
21  using SpecializeOptionBase::select;
22 
23  void runOnOperation() override {
24  auto circuit = getOperation();
25  if (select.empty()) {
26  markAllAnalysesPreserved();
27  return;
28  }
29 
30  DenseMap<StringAttr, OptionCaseOp> selected;
31  for (const auto &optionAndCase : select) {
32  size_t eq = optionAndCase.find("=");
33  if (eq == std::string::npos) {
34  mlir::emitError(circuit.getLoc(),
35  "invalid option format: \"" + optionAndCase + '"');
36  return signalPassFailure();
37  }
38 
39  std::string optionName = optionAndCase.substr(0, eq);
40  auto optionOp = circuit.lookupSymbol<OptionOp>(optionName);
41  if (!optionOp) {
42  mlir::emitWarning(circuit.getLoc(), "unknown option \"")
43  << optionName << '"';
44  continue;
45  }
46 
47  std::string caseName = optionAndCase.substr(eq + 1);
48  auto caseOp = optionOp.lookupSymbol<OptionCaseOp>(caseName);
49  if (!caseOp) {
50  mlir::emitWarning(circuit.getLoc(), "invalid option case \"")
51  << caseName << '"';
52  continue;
53  }
54  selected[StringAttr::get(&getContext(), optionName)] = caseOp;
55  }
56 
57  bool failed = false;
58  mlir::parallelForEach(
59  &getContext(), circuit.getOps<FModuleOp>(), [&](auto module) {
60  module.walk([&](firrtl::InstanceChoiceOp inst) {
61  auto it = selected.find(inst.getOptionNameAttr());
62  if (it == selected.end()) {
63  inst.emitError("missing specialization for option ")
64  << inst.getOptionNameAttr();
65  failed = true;
66  return;
67  }
68 
69  ImplicitLocOpBuilder builder(inst.getLoc(), inst);
70  auto newInst = builder.create<InstanceOp>(
71  inst->getResultTypes(), inst.getTargetOrDefaultAttr(it->second),
72  inst.getNameAttr(), inst.getNameKindAttr(),
73  inst.getPortDirectionsAttr(), inst.getPortNamesAttr(),
74  inst.getAnnotationsAttr(), inst.getPortAnnotationsAttr(),
75  builder.getArrayAttr({}), UnitAttr{}, inst.getInnerSymAttr());
76  inst.replaceAllUsesWith(newInst);
77  inst.erase();
78 
79  ++numInstances;
80  });
81  });
82 
83  if (failed)
84  signalPassFailure();
85  }
86 };
87 } // namespace
88 
89 std::unique_ptr<Pass> firrtl::createSpecializeOptionPass() {
90  return std::make_unique<SpecializeOptionPass>();
91 }
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:54
std::unique_ptr< mlir::Pass > createSpecializeOptionPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21