14#include "mlir/IR/Attributes.h"
15#include "mlir/IR/Builders.h"
16#include "mlir/Pass/Pass.h"
20#define GEN_PASS_DEF_MATERIALIZEDEBUGINFO
21#include "circt/Dialect/FIRRTL/Passes.h.inc"
27using namespace firrtl;
30struct MaterializeDebugInfoPass
31 :
public circt::firrtl::impl::MaterializeDebugInfoBase<
32 MaterializeDebugInfoPass> {
33 void runOnOperation()
override;
34 void materializeVariable(OpBuilder &builder, StringAttr name, Value value);
35 Value convertToDebugAggregates(OpBuilder &builder, Value value);
39void MaterializeDebugInfoPass::runOnOperation() {
40 auto module = getOperation();
41 auto builder = OpBuilder::atBlockBegin(module.getBodyBlock());
44 for (
const auto &[port, value] :
45 llvm::zip(module.getPorts(), module.getArguments())) {
46 materializeVariable(builder, port.name, value);
50 module.walk([&](Operation *op) {
51 TypeSwitch<Operation *>(op).Case<WireOp, NodeOp, RegOp, RegResetOp>(
53 builder.setInsertionPointAfter(op);
54 materializeVariable(builder, op.getNameAttr(), op.getResult());
60void MaterializeDebugInfoPass::materializeVariable(OpBuilder &builder,
65 if (name.getValue().starts_with(
"_"))
67 if (
auto dbgValue = convertToDebugAggregates(builder, value))
68 debug::VariableOp::create(builder, value.getLoc(), name, dbgValue,
74Value MaterializeDebugInfoPass::convertToDebugAggregates(OpBuilder &builder,
77 .
Case<BundleType>([&](
auto type) {
78 SmallVector<Value> fields;
79 SmallVector<Attribute> names;
80 SmallVector<Operation *> subOps;
81 for (
auto [index, element] :
llvm::enumerate(type.getElements())) {
83 SubfieldOp::create(builder, value.getLoc(), value, index);
84 subOps.push_back(subOp);
85 if (
auto dbgValue = convertToDebugAggregates(builder, subOp)) {
86 fields.push_back(dbgValue);
87 names.push_back(element.name);
90 auto result = debug::StructOp::create(builder, value.getLoc(), fields,
91 builder.getArrayAttr(names));
92 for (
auto *subOp : subOps)
93 if (subOp->use_empty())
97 .Case<FVectorType>([&](
auto type) -> Value {
98 SmallVector<Value> elements;
99 SmallVector<Operation *> subOps;
100 for (
unsigned index = 0; index < type.getNumElements(); ++index) {
102 SubindexOp::create(builder, value.getLoc(), value, index);
103 subOps.push_back(subOp);
104 if (
auto dbgValue = convertToDebugAggregates(builder, subOp))
105 elements.push_back(dbgValue);
108 if (!elements.empty() && elements.size() == type.getNumElements())
109 result = debug::ArrayOp::create(builder, value.getLoc(), elements);
110 for (
auto *subOp : subOps)
111 if (subOp->use_empty())
115 .Case<FIRRTLBaseType>(
116 [&](
auto type) {
return type.isGround() ? value : Value{}; })
This class implements the same functionality as TypeSwitch except that it uses firrtl::type_dyn_cast ...
FIRRTLTypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
bool isUselessName(StringRef name)
Return true if this is a possibly useless temporary name.