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  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 
151 std::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
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