Skip to content

Add conservative Chisel module-only extraction and CIRCT-backed module graph support - #130

Open
okcomputer2000 wants to merge 7 commits into
fmagent-project:mainfrom
okcomputer2000:chip-integration
Open

Add conservative Chisel module-only extraction and CIRCT-backed module graph support#130
okcomputer2000 wants to merge 7 commits into
fmagent-project:mainfrom
okcomputer2000:chip-integration

Conversation

@okcomputer2000

Copy link
Copy Markdown
Contributor

Summary

This PR adds a conservative Chisel hardware extraction path on top of the current main branch.

The first version stays intentionally narrow:

  • analysis units: Module, RawModule, BlackBox, ExtModule, MultiIOModule
  • Bundle is treated as context only, not as a standalone unit
  • graph relations are limited to the module instantiation graph
  • source filtering is conservative, and CIRCT-emitted Verilog is treated as authoritative when available

Approach

The implementation adds a dedicated Chisel path instead of trying to stretch the generic Scala/function extraction flow:

  • detect Chisel source files conservatively
  • extract only hardware-module units from Chisel/Scala source
  • keep Chisel test-file handling path-aware so src/main/... production files are not dropped by filename heuristics
  • build module-to-module edges from instantiation structure
  • when CIRCT-emitted Verilog is available, use it to authoritatively filter the module set and override source-derived edges

This keeps the Chisel path isolated and minimizes coupling with the existing non-Chisel pipeline.

What is included

  • Chisel-specific extraction support
  • conservative module classification
  • module-instantiation edge construction
  • CIRCT sidecar graph loading and parsing
  • integration with the existing extraction and topdown-layer pipeline

What is intentionally not included

  • Bundle as an independent analysis unit
  • broader Scala semantic extraction
  • non-module graph relations
  • deeper behavior inference beyond conservative module detection and instantiation links

Validation

Tested locally against public Chisel codebases and local sample trees, including:

  • schoeberl/chisel-examples
  • ucb-bar/chisel2-deprecated
  • ucb-bar/chipyard
    • fpga/src/main/scala
    • generators/chipyard/src/main/scala
    • generators/chipyard/src/main/resources/vsrc

Also validated the relevant FM-Agent pipeline stages locally by running the real
run_extraction and generate_topdown_layers flow on a local test project, and stopping before any LLM-driven stages.

Current limitations

  • module detection is still intentionally conservative and may skip some valid hardware-like Scala declarations
  • CIRCT integration currently depends on emitted Verilog sidecar input rather than a deeper direct FIRRTL/CIRCT integration
  • Bundle is only preserved as surrounding context inside extracted modules
  • graph precision is limited to module instantiation relationships in this version

Next steps

  • expand coverage only where real Chisel code demonstrates missed module forms
  • evaluate whether a second version should add more Chisel-specific structure while keeping module-only output as the default
  • improve CIRCT-driven validation and fixtures as more real-world examples are collected

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 84c924d0f3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/chisel_support.py
Comment on lines +155 to +158
CHISEL_EXT_TO_LANG = {
"scala": "chisel",
"sc": "chisel",
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add Scala extensions to verification

When this mapping enables extraction of .scala/.sc Chisel modules, the verification stage still filters candidates through src/verification.py::EXT_TO_LANG, which has no .scala or .sc entries. In a normal full run those extracted modules are therefore never submitted for verification, so Chisel specs can be produced without any checker coverage.

Useful? React with 👍 / 👎.

Comment thread src/generate_topdown_layers.py Outdated
Comment on lines +327 to +328
if lang_key == "chisel":
for callee_fqn in global_chisel_edges.get(fqn, set()) if global_chisel_edges else ():

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Populate Chisel edges when building entry graphs

When _build_call_graph is called directly outside generate_topdown_layers—for example the entry-selection path at src/entry_reasoning_pipeline.py:365-369global_chisel_edges is left as None. This branch then takes the Chisel path and continues without adding any module-instantiation edges, so entry reachability treats every Chisel module as a leaf and can omit all submodules from an entry-focused run.

Useful? React with 👍 / 👎.

Comment thread src/generate_topdown_layers.py Outdated
Comment on lines +767 to +769
chisel_callees = sorted(global_chisel_edges.get(fqn, set()))
entry[phase_callees_key] = sorted(set(chisel_callees) & phase_fqns)
entry["all_callees"] = chisel_callees

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep supplemental Chisel edges in layer JSON

If extra_call_edges supplies a Chisel dependency, _build_call_graph has already merged it into phase_callees/all_callees, but this override replaces those fields with only global_chisel_edges. The generated prompt metadata then drops the supplemental callee/caller relationship, so caller expectations from explicit edge files are not surfaced for Chisel modules.

Useful? React with 👍 / 👎.

@haoran-ding haoran-ding left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR does not use https://github.com/llvm/circt. All code about supporting a new language should be put under src/languages and register the interface in registry.py.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2015fc560b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

add_definitions(${LLVM_DEFINITIONS})

add_subdirectory(include)
add_subdirectory(lib)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include the missing CIRCT pass implementation

When ./install.sh --with-chisel reaches the CMake configure at tools/chisel-circt, this add_subdirectory(lib) requires a tools/chisel-circt/lib/CMakeLists.txt (confirmed by cmake --help-command add_subdirectory), but a repo-wide search of tools/chisel-circt shows no lib/ directory or implementation of the FMAgentChiselCirct target that the plugin links against. As a result the optional Chisel plugin cannot configure/build, so the advertised CIRCT-backed Chisel support is unusable.

Useful? React with 👍 / 👎.


output_dir = os.path.join(proj_dir, "spec_prompts")
os.makedirs(output_dir, exist_ok=True)
global_chisel_edges = chisel_call_edges(proj_dir)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the registered CIRCT graph for Chisel layers

When users configure the new CIRCT path via FM_AGENT_CHISEL_CIRCT_INPUT, extraction builds/persists src/languages/chisel.py's .codegraph/chisel_module_graph.json, but this layer step calls the separate legacy src/chisel_backend.py path, which reads only fm_agent/chisel_circt_module_graph.json/extracted-source fallbacks; _build_call_graph then special-cases Chisel and skips the registry edges. In that CIRCT-backed run, any edge only known to the new pass is missing from phase*_callees/all_callees, so generated Chisel layer prompts are not using the authoritative module graph this commit adds.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 261aee6791

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/languages/chisel.py
Comment on lines +241 to +244
graph = self.load_graph()
if graph is not None or not allow_build:
return graph
return self.build_graph()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Rebuild the CIRCT graph when its input changes

When FM_AGENT_CHISEL_CIRCT_INPUT is regenerated or changed after a prior run, this returns the persisted .codegraph/chisel_module_graph.json before ever calling build_graph. Although persist_graph records a fingerprint containing the input mtime/size, load_graph never validates it, so resume/direct API runs can silently use the old module set and edges, causing newly added modules to be excluded from extraction and stale dependencies to drive layer generation.

Useful? React with 👍 / 👎.

Comment thread src/languages/chisel.py
Comment on lines +1237 to +1241
parts = line.replace("(", " ").replace(")", " ").replace("{", " ").split()
for idx, token in enumerate(parts[:-1]):
if token == "new":
name = parts[idx + 1]
if name in known_names:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize instantiated generic module names

Without a CIRCT graph, a generic Chisel instantiation such as Module(new Child[Int]) is tokenized as Child[Int], which cannot match the extracted module name Child in known_names. The fallback therefore omits the Top→Child dependency and places both modules in the same layer (losing the caller/callee contract context); package-qualified instantiations have the same failure mode.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 846da77df7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +328 to +346
if lang_key == "chisel":
for callee_fqn in chisel_edges.get(fqn, set()):
if callee_fqn == fqn:
continue
all_callees_map[fqn].add(callee_fqn)
if callee_fqn in phase_fqns:
callees_map[fqn].add(callee_fqn)
callers_map[callee_fqn].add(fqn)
for edge in extra_edges_by_caller_fqn.get(fqn, ()):
_add_resolved_extra_edge(
fqn,
edge,
phase_fqns,
callees_map,
callers_map,
all_callees_map,
edge_aliases_map,
)
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply callsite-selected supplemental edges to Chisel

When an extra-edge rule selects callers through caller.callsite_names rather than an exact FQN, Chisel modules never receive that edge: this branch only applies extra_edges_by_caller_fqn and immediately continues. For example, an edge targeting every module containing CallMe() leaves the corresponding Chisel module disconnected, despite src/call_graph_edges.py defining callsite selectors to apply to every matching function. Fresh evidence beyond the earlier supplemental-edge finding is that the direct-FQN loop is now present here, while the callsite loop used by every non-Chisel path is still absent.

Useful? React with 👍 / 👎.

@okcomputer2000

Copy link
Copy Markdown
Contributor Author

This PR adds Chisel support as a language backend under src/languages and registers it in src/languages/registry.py.

Current status:

  • Chisel module extraction is implemented in src/languages/chisel.py.
  • A CIRCT pass/plugin is added to identify hardware modules and build a module instantiation graph.
  • When CIRCT input is available, CIRCT is treated as the authority for module discovery and module-instantiation edges.
  • Python only slices source bodies for the matched Chisel module declarations.
  • Supported extracted units are currently Module, RawModule, ExtModule, BlackBox, and MultiIOModule.
  • Bundle is kept as context and is not extracted as a standalone unit.

Known limitations:

  • For Chisel, the graph here is a module instantiation graph, not a traditional software function call graph.
  • The current Chisel/FIRRTL/CIRCT flow reliably provides source start locations, but not stable full source ranges.
  • Because of that, the Python side still needs a small amount of source slicing logic to cut module bodies from Scala files.

Validation:

  • Tested on local checkouts of schoeberl/chisel-examples, ucb-bar/chisel2-deprecated, and ucb-bar/chipyard.
  • Verified the CIRCT-backed extraction path, module graph generation, and run_extraction integration.

Next steps:

  • Keep CIRCT authoritative for module identification and module-instantiation edges.
  • Reduce the remaining Chisel-specific source heuristics further.
  • If upstream CIRCT/Chisel can provide stable full source ranges later, simplify the Scala source slicing layer further.

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.

2 participants