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"
32 #define GEN_PASS_DEF_HWEXPORTMODULEHIERARCHY
33 #include "circt/Dialect/SV/SVPasses.h.inc"
37 using namespace circt;
44 HWExportModuleHierarchyPass> {
49 void printHierarchy(hw::InstanceOp &inst, SymbolTable &symbolTable,
50 llvm::json::OStream &j,
51 SmallVectorImpl<Attribute> &symbols,
unsigned &
id);
53 void extractHierarchyFromTop(
hw::HWModuleOp op, SymbolTable &symbolTable,
54 llvm::raw_ostream &os,
55 SmallVectorImpl<Attribute> &symbols);
57 void runOnOperation()
override;
62 hw::InstanceOp &inst, SymbolTable &symbolTable, llvm::json::OStream &j,
63 SmallVectorImpl<Attribute> &symbols,
unsigned &
id) {
65 auto innerSym = inst.getInnerSymAttr();
67 auto &ns = moduleNamespaces.try_emplace(moduleOp, moduleOp).first->second;
69 StringAttr::get(inst.getContext(), ns.newName(inst.getInstanceName())));
70 inst->setAttr(
"inner_sym", innerSym);
74 j.attribute(
"instance_name", (
"{{" + Twine(
id++) +
"}}").str());
76 innerSym.getSymName()));
77 j.attribute(
"module_name", (
"{{" + Twine(
id++) +
"}}").str());
78 symbols.push_back(inst.getModuleNameAttr());
79 j.attributeArray(
"instances", [&] {
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);
96 hw::HWModuleOp op, SymbolTable &symbolTable, llvm::raw_ostream &os,
97 SmallVectorImpl<Attribute> &symbols) {
98 llvm::json::OStream j(os, 2);
103 j.attribute(
"instance_name",
"{{0}}");
104 j.attribute(
"module_name",
"{{0}}");
106 j.attributeArray(
"instances", [&] {
108 for (auto op : op.getOps<hw::InstanceOp>())
109 printHierarchy(op, symbolTable, j, symbols, id);
117 mlir::ModuleOp mlirModule = getOperation();
118 std::optional<SymbolTable *> symbolTable;
121 auto attr = op->getAttrOfType<ArrayAttr>(
"firrtl.moduleHierarchyFile");
124 for (
auto file : attr.getAsRange<hw::OutputFileAttr>()) {
126 symbolTable = &getAnalysis<SymbolTable>();
128 std::string jsonBuffer;
129 llvm::raw_string_ostream os(jsonBuffer);
130 SmallVector<Attribute> symbols;
134 auto builder = ImplicitLocOpBuilder::atBlockEnd(
136 builder.create<emit::FileOp>(file.getFilename(), [&] {
137 builder.create<sv::VerbatimOp>(jsonBuffer, ValueRange{},
138 builder.getArrayAttr(symbols));
143 markAllAnalysesPreserved();
151 return std::make_unique<HWExportModuleHierarchyPass>();
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.
std::unique_ptr< mlir::Pass > createHWExportModuleHierarchyPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.