Module services#669
Conversation
…al/instance naming routine names
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.
Clarify comment Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This aligns central_naming with the simplified naming approach already adopted by all downstream branches (module_services, netlist, source_debug, systemc_trace, fst-writer). Changes: - Remove Namer._instanceNames cache field - Remove Namer.instanceNameOf(Module) method - Update synthesizers to use Namer.allocateName(String) directly - Remove destination tracking from _BusSubsetForStructSlice Benefit: Eliminates duplication across 5+ branches, making each branch truly orthogonal and mergeable without conflicts. Trade-off: Instance names no longer cached across synthesis passes, but all downstreams already use this simpler approach.
Uses Directory.createSync / dart:io — fails on JS with _Namespace error.
Introduce ModuleService/OutputService/CodegenService base types and replace the leaky ModuleServices singleton (per-service getters and inspection interfaces) with a generic register<T>/lookup<T> registry keyed by service type. SvService now extends CodegenService, exposes a stable cached synthOutput, and registers itself via the new registry. WaveformService registers as a ModuleService. Rewrites module_services_test.dart to the new API.
Defer deprecation of Module.generateSynth so simcompare and other call sites need not migrate per-branch; this keeps simcompare.dart identical to base and removes a recurring cross-branch merge conflict. SvService remains the richer API.
# Conflicts: # lib/src/synthesizers/utilities/synth_module_definition.dart # lib/src/synthesizers/utilities/synth_sub_module_instantiation.dart # test/instance_signal_name_collision_test.dart # test/naming_consistency_test.dart
# Conflicts: # lib/src/module.dart # lib/src/utilities/namer.dart # test/naming_cases_test.dart
# Conflicts: # lib/src/wave_dumper.dart
| /// | ||
| /// Establishes the common output convention shared by synthesis, netlist, | ||
| /// trace, and waveform services: | ||
| /// - [outputPath] — the default file or directory written by [write]. |
There was a problem hiding this comment.
i like this API because it's easy to understand, but should we be using some sort of URI object or something from Dart instead that supports referencing files, directories, and other weird stuff instead? im not sure the answer, genuine question
| /// Shared by the language code-generation services (e.g. SystemVerilog and | ||
| /// SystemC), which all produce a combined single-file [output] as well as | ||
| /// per-definition contents. | ||
| abstract class CodegenService extends OutputService { |
There was a problem hiding this comment.
nit: should it be CodeGenService?
| String get output; | ||
|
|
||
| /// The generated output keyed by module definition name | ||
| /// ([Module.definitionName]). |
There was a problem hiding this comment.
what if one definition generates multiple files? SynthBuilder supports that now
| /// // Or get the concatenated output (like generateSynth): | ||
| /// print(sv.allContents); | ||
| /// ``` | ||
| class SvService extends CodegenService { |
There was a problem hiding this comment.
question: what do you think about SystemVerilogService instead? more consistent with other stuff?
| /// The most recently built top-level [Module]. | ||
| /// | ||
| /// Set automatically at the end of [Module.build]. | ||
| Module? rootModule; |
There was a problem hiding this comment.
should this be @internal or something?
There was a problem hiding this comment.
it feels like this has a lot of duplicate code with the existing waveform_service? should this just use the service under the hood and be deprecated then?
|
(those were pending comments, figured i'd submit them for now, but i'm also adding relevant ones to #673 as well) |
Description & Motivation
This is a new API for dealing with services after a module has been built. Rather than adding more methods to
Module, we create services that can operate on a builtModule, like writing out waveforms, or synthesizing outputs like SystemVerilog.So instead of
'module.generateSynth(outputPath: 'build/${module.definitionName}.sv')for outputing SystemVerilog andWaveDumper(module, outputPath: 'build/${module.definitionName}.vcd')for outputing Waveforms, we use:As we add more services, this is a more consistent API with fewer surprises.
Related Issue(s)
None
Testing
Tests are converted to the new Service apis and run through.
Backwards-compatibility
No. But eventually, we would like to deprecate existing methods in favor of a services model.
Documentation
Small changes in the README.md and throughout the tutorial and tests.