12 #include "mlir/IR/BuiltinOps.h"
13 #include "llvm/Support/Debug.h"
15 #define DEBUG_TYPE "di"
18 using namespace circt;
28 void visitRoot(Operation *op);
46 slot = createModule();
47 slot->name = moduleName;
53 void DebugInfoBuilder::visitRoot(Operation *op) {
54 op->walk<WalkOrder::PreOrder>([&](Operation *op) {
55 if (
auto moduleOp = dyn_cast<hw::HWModuleOp>(op)) {
56 LLVM_DEBUG(llvm::dbgs()
57 <<
"Collect DI for module " << moduleOp.getNameAttr() <<
"\n");
58 auto &module = getOrCreateModule(moduleOp.getNameAttr());
60 visitModule(moduleOp, module);
61 return WalkResult::skip();
64 if (
auto moduleOp = dyn_cast<hw::HWModuleExternOp>(op)) {
65 LLVM_DEBUG(llvm::dbgs() <<
"Collect DI for extern module "
66 << moduleOp.getNameAttr() <<
"\n");
67 auto &module = getOrCreateModule(moduleOp.getNameAttr());
69 module.isExtern =
true;
72 for (
auto &port : moduleOp.getPortList()) {
73 auto *var = createVariable();
74 var->name = port.name;
76 module.variables.push_back(var);
79 return WalkResult::skip();
82 return WalkResult::advance();
94 bool hasVariables =
false;
95 bool hasInstances =
false;
96 moduleOp.walk([&](Operation *op) {
97 if (isa<debug::VariableOp>(op))
99 if (
auto scopeOp = dyn_cast<debug::ScopeOp>(op)) {
100 auto *node = createModule();
101 node->isInline =
true;
102 node->name = scopeOp.getModuleNameAttr();
104 scopes.insert({scopeOp, node});
112 auto getScope = [&](Value scopeValue) ->
DIModule & {
114 if (
auto scopeOp = scopeValue.getDefiningOp<debug::ScopeOp>())
115 return *scopes.lookup(scopeOp);
122 auto inputValues = moduleOp.getBody().getArguments();
123 auto outputValues = moduleOp.getBodyBlock()->getTerminator()->getOperands();
124 for (
auto &port : moduleOp.getPortList()) {
125 auto value = port.isOutput() ? outputValues[port.argNum]
126 : inputValues[port.argNum];
127 auto *var = createVariable();
128 var->name = port.name;
136 moduleOp->walk([&](Operation *op) {
137 if (
auto varOp = dyn_cast<debug::VariableOp>(op)) {
138 auto *var = createVariable();
139 var->name = varOp.getNameAttr();
140 var->loc = varOp.getLoc();
141 var->value = varOp.getValue();
142 getScope(varOp.getScope()).variables.push_back(var);
146 if (
auto scopeOp = dyn_cast<debug::ScopeOp>(op)) {
148 instance->name = scopeOp.getInstanceNameAttr();
149 instance->op = scopeOp;
150 instance->module = scopes.lookup(scopeOp);
151 getScope(scopeOp.getScope()).instances.push_back(instance);
156 if (
auto instOp = dyn_cast<hw::InstanceOp>(op)) {
158 getOrCreateModule(instOp.getModuleNameAttr().getAttr());
160 instance->name = instOp.getInstanceNameAttr();
161 instance->op = instOp;
162 instance->module = &childModule;
173 if (
auto wireOp = dyn_cast<hw::WireOp>(op)) {
174 auto *var = createVariable();
175 var->name = wireOp.getNameAttr();
176 var->loc = wireOp.getLoc();
188 DebugInfo::DebugInfo(Operation *op) : operation(op) {
calyx::InstanceOp createInstance(Location loc, OpBuilder &builder, ComponentOp component, SmallVectorImpl< Type > &resultTypes, StringRef instanceName, StringRef componentName)
A helper function to create calyx.instance operation.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
SmallVector< DIInstance *, 0 > instances
Levels of hierarchy nested under this module.
SmallVector< DIVariable *, 0 > variables
Variables declared within this module.
Debug information attached to an operation and the operations nested within.
llvm::SpecificBumpPtrAllocator< DIInstance > instanceAllocator
llvm::SpecificBumpPtrAllocator< DIModule > moduleAllocator
llvm::SpecificBumpPtrAllocator< DIVariable > variableAllocator
llvm::MapVector< StringAttr, DIModule * > moduleNodes
A mapping from module name to module debug info.
Helper to populate a DebugInfo with nodes.
void visitRoot(Operation *op)
DIInstance * createInstance()
DIVariable * createVariable()
DIModule * createModule()
DebugInfoBuilder(DebugInfo &di)
DIModule & getOrCreateModule(StringAttr moduleName)