Skip to content

[debug] Add circt_debug_* intrinsics for Chisel type metadata#5276

Open
fkhaidari wants to merge 1 commit intochipsalliance:mainfrom
fkhaidari:fk-sc/debug-info
Open

[debug] Add circt_debug_* intrinsics for Chisel type metadata#5276
fkhaidari wants to merge 1 commit intochipsalliance:mainfrom
fkhaidari:fk-sc/debug-info

Conversation

@fkhaidari
Copy link
Copy Markdown

@fkhaidari fkhaidari commented Apr 20, 2026

Hi! This PR adds source-level debug info collection for Chisel
Based on @rameloni's Tywaves work (#4015, #4224), but using intrinsics
instead of annotations as @fabianschuiki suggested in that thread.

Emits four intrinsics during elaboration:

  • circt_debug_var -- type + ctor params per signal
  • circt_debug_subfield -- aggregate hierarchy
  • circt_debug_moduleinfo -- module-level metadata (class, ctor params)
  • circt_debug_enumdef -- ChiselEnum definitions

Fully opt-in via --emit-debug-type-info. Without the flag, FIRRTL
output is bit-identical to main.

Companion CIRCT PR (intrinsic lowering + debug dialect extensions)
is in progress at [fkhaidari/circt#1] and will be submitted upstream
later

cc @fabianschuiki @rameloni @jackkoenig @seldridge

Contributor Checklist

  • Did you add Scaladoc to every public function/method?
  • Did you add at least one test demonstrating the PR?
  • Did you delete any extraneous printlns/debugging code?
  • Did you specify the type of improvement?
  • Did you add appropriate documentation in docs/src?
  • Did you request a desired merge strategy?
  • Did you add text to be included in the Release Notes for this change?

Type of Improvement

  • Feature (or new API)

Desired Merge Strategy

  • Rebase: You will rebase the PR onto master and it will be merged with a merge commit.

Release Notes

Add opt-in ChiselStage flag withDebug = true that emits circt_debug_*
intrinsics preserving Chisel-level type and parameter metadata in FIRRTL.

Reviewer Checklist (only modified by reviewer)

  • Did you add the appropriate labels? (Select the most appropriate one based on the "Type of Improvement")
  • Did you mark the proper milestone (Bug fix: 3.6.x, 5.x, or 6.x depending on impact, API modification or big change: 7.0)?
  • Did you review?
  • Did you check whether all relevant Contributor checkboxes have been checked?
  • Did you do one of the following when ready to merge:
    • Squash: You/ the contributor Enable auto-merge (squash) and clean up the commit message.
    • Merge: Ensure that contributor has cleaned up their commit history, then merge with Create a merge commit.

@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla Bot commented Apr 20, 2026

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: fkhaidari / name: fkhaidari (d8ed90a)

@fkhaidari fkhaidari force-pushed the fk-sc/debug-info branch 19 times, most recently from 1bc262a to a6036bf Compare April 27, 2026 01:39
Introduce an opt-in pass that injects CIRCT debug intrinsics carrying
Chisel-level type and constructor-parameter metadata through to FIRRTL,
so downstream tooling (waveform viewers, debuggers) can recover Bundle
field names, Vec shapes, ChiselEnum types and module parameters that
are otherwise lost during conversion.

The DebugIntrinsics emitter walks the elaborated circuit and appends
four kinds of secret intrinsics:

  - circt_debug_moduleinfo  per module (typeName + ctor params)
  - circt_debug_var         per top-level signal, port or memory
  - circt_debug_subfield    per Bundle/Vec element, linked by parent
  - circt_debug_enumdef     per ChiselEnum type (emitted once)

Constructor parameters are extracted via runtime reflection and
serialised to JSON. Booleans round-trip as native JSON bools; all
numeric types (Byte / Short / Int / Long / Float / Double) serialise
uniformly as JSON strings -- JSON has no NaN/Infinity literals and
Double-backed parsers lose precision on Long > 2^53, so a single string
shape avoids both pitfalls and gives downstream sinks one attribute
mapping to write. JDK and Scala stdlib classes are not recursed into
during nested ctor extraction; their constructors are implementation
details and produce no user-meaningful parameters. User toString
output embedded in the params payload is capped at 4 KiB to bound
emission size against pathological implementations.

Emission is disabled by default and activated by adding
EmitDebugIntrinsicsAnnotation to the annotation seq programmatically,
or by passing `--with-debug-intrinsics` on the CLI to any
circt.stage.ChiselStage entry point. Either form schedules the new
AddDebugIntrinsics phase between Elaborate and Convert; the phase is
a no-op without the annotation. After consuming it, the phase strips
EmitDebugIntrinsicsAnnotation from the seq so a second pass over the
same annotations does not double-emit intrinsics.

Includes unit tests for moduleinfo / var / subfield / enumdef emission
across scalar, Bundle, Vec, ChiselEnum, memory and hierarchy cases,
plus a docs section in docs/src/explanations/intrinsics.md.

Based on work of @rameloni

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