Skip to content

Module services api#673

Open
desmonddak wants to merge 113 commits into
intel:mainfrom
desmonddak:module_services_api
Open

Module services api#673
desmonddak wants to merge 113 commits into
intel:mainfrom
desmonddak:module_services_api

Conversation

@desmonddak

Copy link
Copy Markdown
Contributor

Description & Motivation

This is a subset of the PR #669 that introduces the new API for Services attached to a module (outputters like wave dumpers, netlisters, translators, tracing services, etc).

Related Issue(s)

None

Testing

This runs a full dart test with the new API in place in the tests.

Backwards-compatibility

Is this a breaking change that will not be backwards-compatible? If yes, how so?

No, we retain the old interfaces but they should eventually be deprecated.
WaveDumper
generateSynth
...

Documentation

Does the change require any updates to documentation? If so, where? Are they included?

Some examples have been modified to match.

Introduces a singleton service registry (ModuleServices) that provides a
unified query surface for DevTools and inspection tools. Module.build()
now registers the root module with ModuleServices.instance.

Also adds SvService which wraps SystemVerilog synthesis and registers
with ModuleServices for DevTools access to SV metadata.

This is a clean separation: no netlist code is included. The netlist
branch will later extend ModuleServices with a netlistService field.
Directory.uri always appends a trailing slash, making
  entity.uri.pathSegments.last == ""
so name.startsWith(_systemCTempPrefix) was never true — tmp_sc_*
directories were never deleted.

Switch to entity.path.split('/').last which gives the bare directory
name without the trailing-slash artefact.
pch/ is a persistent precompiled-header cache, pre-built by CI before
tests run and reused across test files for speed.  It is not test
output pollution.  Exclude it from the tmp_test emptiness check.
Re-add SystemCFfiCosim.cleanupCache() (lost in the SystemC service split) and
its tearDownAll hook so check_tmp_test.sh passes. Bump actions/setup-node to
node-version 24 (Node 20 is deprecated on GitHub Actions runners).
Introduces a singleton service registry (ModuleServices) that provides a
unified query surface for DevTools and inspection tools. Module.build()
now registers the root module with ModuleServices.instance.

Also adds SvService which wraps SystemVerilog synthesis and registers
with ModuleServices for DevTools access to SV metadata.

This is a clean separation: no netlist code is included. The netlist
branch will later extend ModuleServices with a netlistService field.
@mkorbel1 mkorbel1 mentioned this pull request Jul 16, 2026
Comment thread lib/src/utilities/simcompare.dart
Comment thread lib/src/diagnostics/module_service.dart
Comment thread lib/src/diagnostics/module_service.dart Outdated
Comment thread lib/src/diagnostics/module_service.dart Outdated
Comment thread lib/src/synthesizers/systemverilog/sv_service.dart Outdated
Comment thread lib/rohd.dart Outdated
Comment thread tool/gh_actions/check_tmp_test.sh Outdated
Comment thread tool/gh_actions/run_tests.sh Outdated
Comment thread dart_test.yaml Outdated
Comment thread README.md
Comment thread lib/src/module.dart Outdated
/// // Or get the concatenated output (like generateSynth):
/// print(sv.allContents);
/// ```
class SystemVerilogService extends CodeGenService {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Something doesn't feel quite right to me in this API. Some thoughts:

  • If I want to generate some SV (pretty common), why am I constructing a "service"? Though the abstraction levels as a service make sense to me.
  • Why does the act of constructing said service immediately produce the output?
  • In what cases do I want to run the SynthBuilder with a selected synthesizer instead of this service?
  • When there are multiple synthesizers (e.g. SystemC), will I have multiple services or one service that takes multiple synthesizers?

The two APIs currently are basically:

  • Turn this module into SV quickly (generateSynth function on module)
  • Make a thing that builds an output based on this Synthesizer and give me outputs I can do more work with (SynthBuilder with Synthesizer arg)

This is deprecating the first, but keeping the second, and there's still some API overlap.

I think this is close to right, but something is a little off. Thoughts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Let me ponder this.

I have NetlistService, SystemVerilogService, SystemCService, TraceService, and WaveformService. So some of this is trying to go for least surprise even though they are not fully symmetric. For example, the outputing services need to be setup after the build. WaveformService tracks with the simulator running, so it is truly a live 'service', but the output services execute (though we could use an api that says 'generate' for those.

I never thought of SynthBuilder as a user API.

Here is a live usage on HCL:

 final adder = FloatingPointAdderSinglePath(clk: clk, fp1, fp2);
      await adder.build();
      NetlistService(adder,
          outputPath: '$buildDir/${adder.definitionName}.json');
      final sv =
          SystemVerilogService(adder, outputPath: '$buildDir/${adder.definitionName}.sv'
              // embedSourceTraceComments: false,
              );
      final sc = SystemCService(adder,
          outputPath: '$buildDir/${adder.definitionName}.sc', multiFile: false);
      TraceService(adder, svService: sv, scService: sc).write('x.flc.json');
      WaveformService(adder,
          format: WaveOutputFormat.fst,
          outputPath: '$buildDir/${adder.definitionName}.fst');

@desmonddak desmonddak Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

One additional thing: the synthesizers must run to store FLC info. Then the TraceService can access to generate FLC.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think of these services as constructing an in-memory view that can be further manipulated (written to file, written to string, perhaps searched, etc). The only challenge I face is that if we change any line numbers then trace gets broken.

Comment thread lib/src/synthesizers/systemverilog/system_verilog_service.dart
Comment thread lib/src/synthesizers/systemverilog/system_verilog_service.dart
Comment thread lib/src/synthesizers/systemverilog/system_verilog_service.dart Outdated
Comment thread lib/src/module.dart Outdated
Comment thread test/fsm_test.dart
Comment thread lib/src/synthesizers/systemverilog/system_verilog_service.dart Outdated
Comment thread test/waveform_service_test.dart
Comment thread tool/gh_actions/run_tests.sh Outdated
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