CIRCT  20.0.0git
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 
17 #include "circt/Dialect/HW/HWOps.h"
19 #include "circt/Dialect/SV/SVOps.h"
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 
30 namespace circt {
31 namespace sv {
32 #define GEN_PASS_DEF_HWEXPORTMODULEHIERARCHY
33 #include "circt/Dialect/SV/SVPasses.h.inc"
34 } // namespace sv
35 } // namespace circt
36 
37 using namespace circt;
38 //===----------------------------------------------------------------------===//
39 // Pass Implementation
40 //===----------------------------------------------------------------------===//
41 
44  HWExportModuleHierarchyPass> {
45 
46 private:
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  printHierarchy(op, symbolTable, j, symbols, id);
87  }
88  }
89  });
90  });
91 }
92 
93 /// Return the JSON-serialized module hierarchy for the given module as the top
94 /// of the hierarchy.
96  hw::HWModuleOp op, SymbolTable &symbolTable, llvm::raw_ostream &os,
97  SmallVectorImpl<Attribute> &symbols) {
98  llvm::json::OStream j(os, 2);
99 
100  // As a special case for top-level module, set instance name to module name,
101  // since the top-level module is not instantiated.
102  j.object([&] {
103  j.attribute("instance_name", "{{0}}");
104  j.attribute("module_name", "{{0}}");
105  symbols.push_back(FlatSymbolRefAttr::get(op.getNameAttr()));
106  j.attributeArray("instances", [&] {
107  unsigned id = 1;
108  for (auto op : op.getOps<hw::InstanceOp>())
109  printHierarchy(op, symbolTable, j, symbols, id);
110  });
111  });
112 }
113 
114 /// Find the modules corresponding to the firrtl mainModule and DesignUnderTest,
115 /// and if they exist, emit a verbatim op with the module hierarchy for each.
117  mlir::ModuleOp mlirModule = getOperation();
118  std::optional<SymbolTable *> symbolTable;
119 
120  for (auto op : mlirModule.getOps<hw::HWModuleOp>()) {
121  auto attr = op->getAttrOfType<ArrayAttr>("firrtl.moduleHierarchyFile");
122  if (!attr)
123  continue;
124  for (auto file : attr.getAsRange<hw::OutputFileAttr>()) {
125  if (!symbolTable)
126  symbolTable = &getAnalysis<SymbolTable>();
127 
128  std::string jsonBuffer;
129  llvm::raw_string_ostream os(jsonBuffer);
130  SmallVector<Attribute> symbols;
131 
132  extractHierarchyFromTop(op, **symbolTable, os, symbols);
133 
134  auto builder = ImplicitLocOpBuilder::atBlockEnd(
135  UnknownLoc::get(mlirModule.getContext()), mlirModule.getBody());
136  builder.create<emit::FileOp>(file.getFilename(), [&] {
137  builder.create<sv::VerbatimOp>(jsonBuffer, ValueRange{},
138  builder.getArrayAttr(symbols));
139  });
140  }
141  }
142 
143  markAllAnalysesPreserved();
144 }
145 
146 //===----------------------------------------------------------------------===//
147 // Pass Creation
148 //===----------------------------------------------------------------------===//
149 
150 std::unique_ptr<mlir::Pass> sv::createHWExportModuleHierarchyPass() {
151  return std::make_unique<HWExportModuleHierarchyPass>();
152 }
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
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 > createHWExportModuleHierarchyPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
Definition: sv.py:1