CIRCT 20.0.0git
Loading...
Searching...
No Matches
HWExportModuleHierarchy.cpp
Go to the documentation of this file.
1//===- HWExportModuleHierarchy.cpp - Export Module Hierarchy ----*- 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// Export the module and instance hierarchy information to JSON. This pass looks
9// for modules with the firrtl.moduleHierarchyFile attribute and collects the
10// hierarchy starting at those modules. The hierarchy information is then
11// encoded as JSON in an sv.verbatim op with the output_file attribute set.
12//
13//===----------------------------------------------------------------------===//
14
21#include "circt/Support/Path.h"
22#include "mlir/IR/Builders.h"
23#include "mlir/Pass/Pass.h"
24#include "mlir/Support/FileUtilities.h"
25#include "llvm/Support/FileSystem.h"
26#include "llvm/Support/JSON.h"
27#include "llvm/Support/Path.h"
28#include "llvm/Support/ToolOutputFile.h"
29
30namespace circt {
31namespace sv {
32#define GEN_PASS_DEF_HWEXPORTMODULEHIERARCHY
33#include "circt/Dialect/SV/SVPasses.h.inc"
34} // namespace sv
35} // namespace circt
36
37using namespace circt;
38//===----------------------------------------------------------------------===//
39// Pass Implementation
40//===----------------------------------------------------------------------===//
41
44 HWExportModuleHierarchyPass> {
45
46private:
47 DenseMap<Operation *, hw::InnerSymbolNamespace> moduleNamespaces;
48
49 void printHierarchy(hw::InstanceOp &inst, SymbolTable &symbolTable,
50 llvm::json::OStream &j,
51 SmallVectorImpl<Attribute> &symbols, unsigned &id);
52
53 void extractHierarchyFromTop(hw::HWModuleOp op, SymbolTable &symbolTable,
54 llvm::raw_ostream &os,
55 SmallVectorImpl<Attribute> &symbols);
56
57 void runOnOperation() override;
58};
59
60/// Recursively print the module hierarchy as serialized as JSON.
62 hw::InstanceOp &inst, SymbolTable &symbolTable, llvm::json::OStream &j,
63 SmallVectorImpl<Attribute> &symbols, unsigned &id) {
64 auto moduleOp = inst->getParentOfType<hw::HWModuleOp>();
65 auto innerSym = inst.getInnerSymAttr();
66 if (!innerSym) {
67 auto &ns = moduleNamespaces.try_emplace(moduleOp, moduleOp).first->second;
68 innerSym = hw::InnerSymAttr::get(
69 StringAttr::get(inst.getContext(), ns.newName(inst.getInstanceName())));
70 inst->setAttr("inner_sym", innerSym);
71 }
72
73 j.object([&] {
74 j.attribute("instance_name", ("{{" + Twine(id++) + "}}").str());
75 symbols.push_back(hw::InnerRefAttr::get(moduleOp.getModuleNameAttr(),
76 innerSym.getSymName()));
77 j.attribute("module_name", ("{{" + Twine(id++) + "}}").str());
78 symbols.push_back(inst.getModuleNameAttr());
79 j.attributeArray("instances", [&] {
80 // Only recurse on module ops, not extern or generated ops, whose internal
81 // are opaque.
82 auto *nextModuleOp =
83 symbolTable.lookup(inst.getModuleNameAttr().getValue());
84 if (auto module = dyn_cast<hw::HWModuleOp>(nextModuleOp)) {
85 for (auto op : module.getOps<hw::InstanceOp>()) {
86 if (!op.getDoNotPrint())
87 printHierarchy(op, symbolTable, j, symbols, id);
88 }
89 }
90 });
91 });
92}
93
94/// Return the JSON-serialized module hierarchy for the given module as the top
95/// of the hierarchy.
97 hw::HWModuleOp op, SymbolTable &symbolTable, llvm::raw_ostream &os,
98 SmallVectorImpl<Attribute> &symbols) {
99 llvm::json::OStream j(os, 2);
100
101 // As a special case for top-level module, set instance name to module name,
102 // since the top-level module is not instantiated.
103 j.object([&] {
104 j.attribute("instance_name", "{{0}}");
105 j.attribute("module_name", "{{0}}");
106 symbols.push_back(FlatSymbolRefAttr::get(op.getNameAttr()));
107 j.attributeArray("instances", [&] {
108 unsigned id = 1;
109 for (auto op : op.getOps<hw::InstanceOp>())
110 printHierarchy(op, symbolTable, j, symbols, id);
111 });
112 });
113}
114
115/// Find the modules corresponding to the firrtl mainModule and DesignUnderTest,
116/// and if they exist, emit a verbatim op with the module hierarchy for each.
118 mlir::ModuleOp mlirModule = getOperation();
119 std::optional<SymbolTable *> symbolTable;
120
121 for (auto op : mlirModule.getOps<hw::HWModuleOp>()) {
122 auto attr = op->getAttrOfType<ArrayAttr>("firrtl.moduleHierarchyFile");
123 if (!attr)
124 continue;
125 for (auto file : attr.getAsRange<hw::OutputFileAttr>()) {
126 if (!symbolTable)
127 symbolTable = &getAnalysis<SymbolTable>();
128
129 std::string jsonBuffer;
130 llvm::raw_string_ostream os(jsonBuffer);
131 SmallVector<Attribute> symbols;
132
133 extractHierarchyFromTop(op, **symbolTable, os, symbols);
134
135 auto builder = ImplicitLocOpBuilder::atBlockEnd(
136 UnknownLoc::get(mlirModule.getContext()), mlirModule.getBody());
137 builder.create<emit::FileOp>(file.getFilename(), [&] {
138 builder.create<sv::VerbatimOp>(jsonBuffer, ValueRange{},
139 builder.getArrayAttr(symbols));
140 });
141 }
142 }
143
144 markAllAnalysesPreserved();
145}
146
147//===----------------------------------------------------------------------===//
148// Pass Creation
149//===----------------------------------------------------------------------===//
150
151std::unique_ptr<mlir::Pass> sv::createHWExportModuleHierarchyPass() {
152 return std::make_unique<HWExportModuleHierarchyPass>();
153}
void printHierarchy(hw::InstanceOp &inst, SymbolTable &symbolTable, llvm::json::OStream &j, SmallVectorImpl< Attribute > &symbols, unsigned &id)
Recursively print the module hierarchy as serialized as JSON.
void runOnOperation() override
Find the modules corresponding to the firrtl mainModule and DesignUnderTest, and if they exist,...
void extractHierarchyFromTop(hw::HWModuleOp op, SymbolTable &symbolTable, llvm::raw_ostream &os, SmallVectorImpl< Attribute > &symbols)
Return the JSON-serialized module hierarchy for the given module as the top of the hierarchy.
DenseMap< Operation *, hw::InnerSymbolNamespace > moduleNamespaces
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition sv.py:1