Skip to content

[debug][firrtl] Add source-level type debug info: dbg.enumdef/subfiel…#1

Open
fkhaidari wants to merge 1 commit intomainfrom
fk-sc/debug-info
Open

[debug][firrtl] Add source-level type debug info: dbg.enumdef/subfiel…#1
fkhaidari wants to merge 1 commit intomainfrom
fk-sc/debug-info

Conversation

@fkhaidari
Copy link
Copy Markdown
Owner

…d/moduleinfo + FIRRTL intrinsic lowering

Extends the dbg dialect and the firrtl-lower-intrinsics pass to carry Chisel-level source types, enum definitions, and constructor parameters through the CIRCT pipeline, making them available to downstream consumers (Tywaves, HGDB, hw-debug-info exporters).

dbg dialect changes:

  • Add dbg.enumdef op: declares an enumeration type by name, FQN, and a DictionaryAttr variant map (Int → String). Produces an !dbg.enumdef SSA token consumed by dbg.variable and dbg.subfield.
  • Add dbg.subfield op: like dbg.variable but for aggregate fields; carries optional typeName, params (ArrayAttr of DictionaryAttr), and enumDef operand. Returns !dbg.subfield.
  • Add dbg.moduleinfo op: records the Chisel class name and constructor params for the enclosing module.
  • Extend dbg.variable with optional typeName, params, and enumDef operand (AttrSizedOperandSegments).
  • Add EnumDefType and SubFieldType type definitions to DebugTypes.td.
  • Add EnumDefDeduplication canonicalization pattern: collapses duplicate dbg.enumdef ops with identical FQN and variant map within a block.

FIRRTL intrinsic lowering:

  • Introduce DebugIntrinsicPreScan (new header FIRRTLDebugPreScan.h): a pre-pass struct populated by buildDebugPreScan() before applyPartialConversion runs. Performs three ordered walks:
    1. circt_debug_enumdef → emit dbg.enumdef, populate enumDefMap.
    2. circt_debug_typetag (leaf, non-empty parent) → collect LeafMeta (typeName, params, enumDefVal) into leafMetaMap; erase leaf ops.
    3. circt_debug_typenode (PreOrder) → emit dbg.scope, populate scopeMap keyed by FQN; erase typenode ops.
  • Add CirctDebugTypeTagConverter: lowers root circt_debug_typetag ops to dbg.variable. For aggregate signals, recursively builds dbg.struct/dbg.array via buildDebugAggregateWithMeta, wrapping annotated leaf fields in dbg.subfield with enum/type metadata.
  • Add CirctDebugModuleInfoConverter: lowers circt_debug_moduleinfo to dbg.moduleinfo, parsing the ctorParams JSON string to ArrayAttr.
  • Add CirctDebugTypeNodeConverter: fallback converter (should be unreachable after pre-scan); emits an error and erases the op.
  • Add CirctDebugTypeDefConverter: no-op eraser for circt_debug_typedef.
  • Add ElideScopeTokenNode conversion pattern: removes firrtl.node ops whose result type converts to !dbg.scope (zero-width UInt → ScopeType).
  • Wire populateDebugLowerings() into LowerIntrinsicsPass::runOnOperation after the pre-scan step.
  • Add dependentDialects = ["debug::DebugDialect"] to LowerIntrinsics pass.
  • Link CIRCTDebug into CIRCTFIRRTL CMake target.

MaterializeDebugInfo pass:

  • Skip port/wire/reg materialization for names already covered by a root circt_debug_typetag intrinsic, preventing duplicate dbg.variable ops.
  • Update materializeVariable call site for the new dbg.variable operand signature (typeName, params, enumRef all null).

DebugInfo analysis:

  • Propagate enumDef value from dbg.variable into DIVariable.

FIR parser:

  • Reject non-passive element types for cmem/smem with a clear diagnostic (behavioral memory element type must be passive).

LowerCHIRRTL pass:

  • Override visitInvalidOp to visit non-FIRRTL ops (e.g. dbg.variable) so their operands are updated when they reference CHIRRTL memory port values.

Tests:

  • test/Dialect/Debug/ops.mlir: parse/print round-trip for new ops.
  • test/Dialect/Debug/enumdef-ssa-roundtrip.mlir: dbg.enumdef + dbg.variable SSA round-trip.
  • test/Dialect/Debug/enumdef-canonicalize.mlir: deduplication of identical/diverging dbg.enumdef ops.
  • test/Dialect/Debug/subfield-enumdef-ssa.mlir: dbg.subfield with enum SSA round-trip.
  • test/Dialect/Debug/variable-enumdef-ssa.mlir: dbg.variable with enumDef operand.
  • test/Dialect/FIRRTL/lower-intrinsics-debug.mlir: end-to-end lowering of moduleinfo, enumdef, scalar/bundle/vec typetag, typenode hierarchy, and bundle-with-enum-field cases through firrtl-lower-intrinsics.

Extends the `dbg` dialect and `firrtl-lower-intrinsics` to propagate
Chisel type names, enum definitions, and constructor parameters into
MLIR so downstream consumers (Tywaves, HGDB) can access them.

- New `dbg` ops: `dbg.enumdef`, `dbg.subfield`, `dbg.moduleinfo`.
  `dbg.variable` gets optional `typeName` / `params` / `enumDef`.
- Frontend intrinsics `circt_debug_{var,subfield,enumdef,moduleinfo}`
  are lowered in two phases: a pre-scan collects enumdefs and leaf
  metadata into `DebugIntrinsicPreScan`, then `CirctDebugVarConverter`
  walks each aggregate into `dbg.struct` / `dbg.array`, wrapping every
  leaf and intermediate aggregate in `dbg.subfield` with its typeName.
- Non-passive root aggregates are emitted with 0 SSA operands;
  the converter looks up the matching port/wire by name.
- `MaterializeDebugInfo` skips names already covered by `circt_debug_var`
  to avoid duplicate `dbg.variable`.
- Tests in `test/Dialect/Debug/` and `test/Dialect/FIRRTL/lower-intrinsics-debug.mlir`.

Signed-off-by: fkhaidari <khaidari.fg@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant