Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/rohd.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright (C) 2021-2023 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause

export 'src/diagnostics/module_service.dart';
export 'src/diagnostics/module_services.dart';
export 'src/diagnostics/waveform_service.dart';
export 'src/exceptions/exceptions.dart';
export 'src/external.dart';
export 'src/finite_state_machine.dart';
Expand All @@ -12,6 +15,7 @@ export 'src/signals/signals.dart';
export 'src/simulator.dart';
export 'src/swizzle.dart';
export 'src/synthesizers/synthesizers.dart';
export 'src/synthesizers/systemverilog/sv_service.dart';
export 'src/utilities/naming.dart';
export 'src/values/values.dart';
export 'src/wave_dumper.dart';
72 changes: 72 additions & 0 deletions lib/src/diagnostics/module_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (C) 2026 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// module_service.dart
// Common base types shared by all module-scoped services.
//
// 2026 June 23
// Author: Desmond Kirkpatrick <desmond.a.kirkpatrick@intel.com>

import 'package:rohd/rohd.dart';

/// The common contract implemented by every module-scoped service that
/// registers with [ModuleServices].
///
/// A service wraps some derived view of a built [Module] (synthesis output,
/// netlist, source trace, waveform, etc.) and exposes a JSON-serialisable
/// summary via [toJson]. Concrete services additionally expose their own
/// format-specific accessors; consumers reach them through
/// [ModuleServices.lookup] or the service's own `current` accessor rather than
/// through getters on the registry.
abstract interface class ModuleService {
/// The top-level [Module] this service operates on.
Module get module;

/// A JSON-serialisable summary of this service.
Map<String, Object?> toJson();
}

/// A [ModuleService] that emits output to one or more files.
///
/// Establishes the common output convention shared by synthesis, netlist,
/// trace, and waveform services:
/// - [outputPath] — the default file or directory written by [write].
/// - [multiFile] — whether [write] emits one file per module definition
/// (a directory) or a single combined file.
/// - [write] — performs the write, honouring [multiFile].
abstract class OutputService implements ModuleService {
/// The default location written by [write].
///
/// Interpreted as a directory when [multiFile] is `true`, otherwise as a
/// single file path. May be `null` when no default has been configured, in
/// which case a path must be passed to [write].
String? get outputPath;

/// Whether [write] emits one file per module definition (`true`) or a single
/// combined file (`false`).
bool get multiFile;

/// Writes this service's output to [path], or to [outputPath] when [path] is
/// omitted.
void write([String? path]);
}

/// An [OutputService] that generates source-code text, keyed per module
/// definition.
///
/// 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 {
/// The combined single-file generated output (including any header).
String get output;

/// The generated output keyed by module definition name
/// ([Module.definitionName]).
Map<String, String> get contentsByDefinitionName;

/// The generated output for a single module [definitionName], or `null` when
/// that definition was not generated.
String? moduleOutput(String definitionName) =>
contentsByDefinitionName[definitionName];
}
73 changes: 73 additions & 0 deletions lib/src/diagnostics/module_services.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (C) 2026 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// module_services.dart
// Slim, type-keyed registry of module-scoped services for DevTools and other
// inspection tools.
//
// 2026 April 25
// Author: Desmond Kirkpatrick <desmond.a.kirkpatrick@intel.com>

import 'package:rohd/rohd.dart';
import 'package:rohd/src/diagnostics/inspector_service.dart';

/// A slim, type-keyed registry of [ModuleService]s.
///
/// Services register themselves here on construction (keyed by their concrete
/// type) and are retrieved with [lookup]. The registry intentionally exposes
/// no per-format accessors: each service owns its own JSON and output methods,
/// reached through [lookup] or the service's own static `current` accessor.
///
/// The registry references no specific service type, so it is identical across
/// all feature branches that contribute services.
///
/// **Auto-registered:**
/// - [rootModule] / [hierarchyJSON] — set by [Module.build].
class ModuleServices {
ModuleServices._();

/// The singleton instance.
static final ModuleServices instance = ModuleServices._();

// ─── Hierarchy (auto-registered by Module.build) ──────────────

/// The most recently built top-level [Module].
///
/// Set automatically at the end of [Module.build].
Module? rootModule;

/// Returns the module hierarchy as a JSON string.
///
/// DevTools evaluates this via `EvalOnDartLibrary` to display the module
/// hierarchy. Richer design views (e.g. a slim netlist) are composed by the
/// DevTools client from the relevant registered service.
String get hierarchyJSON {
ModuleTree.rootModuleInstance = rootModule;
return ModuleTree.instance.hierarchyJSON;
}

// ─── Type-keyed service registry ──────────────────────────────

final Map<Type, ModuleService> _services = <Type, ModuleService>{};

/// Registers [service] under the type argument [T].
///
/// Replaces any previously registered service of the same type.
void register<T extends ModuleService>(T service) {
_services[T] = service;
}

/// Returns the registered service of type [T], or `null` if none.
T? lookup<T extends ModuleService>() => _services[T] as T?;

/// Removes the registered service of type [T], if any.
void unregister<T extends ModuleService>() {
_services.remove(T);
}

/// Resets all services. Intended for test teardown.
void reset() {
rootModule = null;
_services.clear();
}
}
Loading
Loading