14 #include "mlir/IR/Attributes.h"
15 #include "mlir/IR/Builders.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/Support/Parallel.h"
20 using namespace circt;
21 using namespace firrtl;
24 struct MaterializeDebugInfoPass
25 :
public MaterializeDebugInfoBase<MaterializeDebugInfoPass> {
26 void runOnOperation()
override;
27 void materializeVariable(OpBuilder &
builder, StringAttr name, Value value);
28 Value convertToDebugAggregates(OpBuilder &
builder, Value value);
32 void MaterializeDebugInfoPass::runOnOperation() {
33 auto module = getOperation();
34 auto builder = OpBuilder::atBlockBegin(module.getBodyBlock());
37 for (
const auto &[port, value] :
38 llvm::zip(module.getPorts(), module.getArguments())) {
39 materializeVariable(
builder, port.name, value);
43 module.walk([&](Operation *op) {
44 TypeSwitch<Operation *>(op).Case<WireOp, NodeOp, RegOp, RegResetOp>(
46 builder.setInsertionPointAfter(op);
47 materializeVariable(
builder, op.getNameAttr(), op.getResult());
53 void MaterializeDebugInfoPass::materializeVariable(OpBuilder &
builder,
58 if (name.getValue().starts_with(
"_"))
60 if (
auto dbgValue = convertToDebugAggregates(
builder, value))
61 builder.create<debug::VariableOp>(value.getLoc(), name, dbgValue,
67 Value MaterializeDebugInfoPass::convertToDebugAggregates(OpBuilder &
builder,
70 .
Case<BundleType>([&](
auto type) {
71 SmallVector<Value> fields;
72 SmallVector<Attribute> names;
73 SmallVector<Operation *> subOps;
74 for (
auto [index, element] : llvm::enumerate(type.getElements())) {
75 auto subOp =
builder.create<SubfieldOp>(value.getLoc(), value, index);
76 subOps.push_back(subOp);
77 if (
auto dbgValue = convertToDebugAggregates(
builder, subOp)) {
78 fields.push_back(dbgValue);
79 names.push_back(element.name);
82 auto result =
builder.create<debug::StructOp>(
83 value.getLoc(), fields,
builder.getArrayAttr(names));
84 for (
auto *subOp : subOps)
85 if (subOp->use_empty())
89 .Case<FVectorType>([&](
auto type) -> Value {
90 SmallVector<Value> elements;
91 SmallVector<Operation *> subOps;
92 for (
unsigned index = 0; index < type.getNumElements(); ++index) {
93 auto subOp =
builder.create<SubindexOp>(value.getLoc(), value, index);
94 subOps.push_back(subOp);
95 if (
auto dbgValue = convertToDebugAggregates(
builder, subOp))
96 elements.push_back(dbgValue);
99 if (!elements.empty() && elements.size() == type.getNumElements())
100 result =
builder.create<debug::ArrayOp>(value.getLoc(), elements);
101 for (
auto *subOp : subOps)
102 if (subOp->use_empty())
106 .Case<FIRRTLBaseType>(
107 [&](
auto type) {
return type.isGround() ? value : Value{}; })
112 return std::make_unique<MaterializeDebugInfoPass>();
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.
std::unique_ptr< mlir::Pass > createMaterializeDebugInfoPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
bool isUselessName(StringRef name)
Return true if this is a possibly useless temporary name.