CIRCT 20.0.0git
Loading...
Searching...
No Matches
HWLowerInstanceChoices.cpp
Go to the documentation of this file.
1//===- HWLowerInstanceChoices.cpp - IR Prepass for Emitter ----------------===//
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// This file implements the "prepare" pass that walks the IR before the emitter
10// gets involved. This allows us to do some transformations that would be
11// awkward to implement inline in the emitter.
12//
13// NOTE: This file covers the preparation phase of `ExportVerilog` which mainly
14// legalizes the IR and makes adjustments necessary for emission. This is the
15// place to mutate the IR if emission needs it. The IR cannot be modified during
16// emission itself, which happens in parallel.
17//
18//===----------------------------------------------------------------------===//
19
24#include "circt/Support/LLVM.h"
27#include "mlir/IR/ImplicitLocOpBuilder.h"
28#include "mlir/IR/SymbolTable.h"
29#include "mlir/Pass/Pass.h"
30
31namespace circt {
32#define GEN_PASS_DEF_HWLOWERINSTANCECHOICES
33#include "circt/Conversion/Passes.h.inc"
34} // namespace circt
35
36using namespace mlir;
37using namespace circt;
38using namespace hw;
39using namespace sv;
40using namespace ExportVerilog;
41
42namespace {
43
44struct HWLowerInstanceChoicesPass
45 : public circt::impl::HWLowerInstanceChoicesBase<
46 HWLowerInstanceChoicesPass> {
47 void runOnOperation() override;
48};
49
50} // end anonymous namespace
51
52LogicalResult ExportVerilog::lowerHWInstanceChoices(mlir::ModuleOp module) {
53 // Collect all instance choices & symbols.
54 SmallVector<InstanceChoiceOp> instances;
55 SymbolCache symCache;
56 for (Operation &op : *module.getBody()) {
57 if (auto sym = dyn_cast<SymbolOpInterface>(&op))
58 symCache.addSymbol(sym);
59
60 if (auto module = dyn_cast<HWModuleOp>(&op))
61 module.walk([&](InstanceChoiceOp inst) { instances.push_back(inst); });
62 }
63
64 // Build a namespace to generate unique macro names.
65 Namespace ns;
66 ns.add(symCache);
67
68 auto declBuilder = OpBuilder::atBlockBegin(module.getBody());
69 for (InstanceChoiceOp inst : instances) {
70 auto parent = inst->getParentOfType<HWModuleOp>();
71
72 auto defaultModuleOp = cast<HWModuleLike>(
73 symCache.getDefinition(inst.getDefaultModuleNameAttr()));
74
75 // Generate a macro name to describe the target of this instance.
76 SmallString<128> name;
77 {
78 llvm::raw_svector_ostream os(name);
79 os << "__circt_choice_" << parent.getName() << "_"
80 << inst.getInstanceName();
81 }
82
83 auto symName = ns.newName(name);
84 auto symNameAttr = declBuilder.getStringAttr(symName);
85 auto symRef = FlatSymbolRefAttr::get(symNameAttr);
86 declBuilder.create<MacroDeclOp>(inst.getLoc(), symNameAttr,
87 /*args=*/ArrayAttr{},
88 /*verilogName=*/StringAttr{});
89
90 // This pass now generates the macros and attaches them to the instance
91 // choice as an attribute. As a better solution, this pass should be moved
92 // out of the umbrella of ExportVerilog and it should lower the `hw`
93 // instance choices to a better SV-level representation of the operation.
94 ImplicitLocOpBuilder builder(inst.getLoc(), inst);
95 builder.create<sv::IfDefOp>(
96 symName, [&] {},
97 [&] {
98 builder.create<sv::MacroDefOp>(
99 symRef, builder.getStringAttr("{{0}}"),
100 builder.getArrayAttr(
101 {FlatSymbolRefAttr::get(defaultModuleOp.getNameAttr())}));
102 });
103 inst->setAttr("hw.choiceTarget", symRef);
104 }
105
106 return success();
107}
108
109void HWLowerInstanceChoicesPass::runOnOperation() {
110 ModuleOp module = getOperation();
111 if (failed(lowerHWInstanceChoices(module)))
112 signalPassFailure();
113}
114
115std::unique_ptr<mlir::Pass> circt::createHWLowerInstanceChoicesPass() {
116 return std::make_unique<HWLowerInstanceChoicesPass>();
117}
A namespace that is used to store existing names and generate new names in some scope within the IR.
Definition Namespace.h:30
void add(mlir::ModuleOp module)
Definition Namespace.h:48
StringRef newName(const Twine &name)
Return a unique name, derived from the input name, and add the new name to the internal namespace.
Definition Namespace.h:87
Default symbol cache implementation; stores associations between names (StringAttr's) to mlir::Operat...
Definition SymCache.h:85
LogicalResult lowerHWInstanceChoices(mlir::ModuleOp module)
Generates the macros used by instance choices.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
std::unique_ptr< mlir::Pass > createHWLowerInstanceChoicesPass()
Definition hw.py:1
Definition sv.py:1