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
1 change: 1 addition & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ analyzer:
exclude:
- doc/tutorials/chapter_9/rohd_vf_example
- packages/rohd_hierarchy
- packages/rohd_waveform
- rohd_devtools_extension
- rohd_extension

Expand Down
3 changes: 3 additions & 0 deletions packages/rohd_hierarchy/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.1.0

- Initial release of source-agnostic hierarchy models, addressing, adapters, and search utilities.
57 changes: 34 additions & 23 deletions packages/rohd_hierarchy/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# rohd_hierarchy

An incremental design dictionary for hardware module hierarchies.
Source-agnostic hierarchy models, addressing, and search utilities for hardware
module navigation.

`rohd_hierarchy` represents a hardware design as an incremental design
dictionary: a tree of module occurrences and signals, plus compact addresses
that let tools refer to any object without repeatedly sending full paths or
structural context.

## Motivation

Expand Down Expand Up @@ -37,7 +43,7 @@ occurrence and every signal reachable by walking the hierarchy tree.
### Compact, canonical addressing

`rohd_hierarchy` assigns each object a **canonical address** — a short
sequence of child indices (e.g. `0.2.4`) that uniquely identifies it within
sequence of child indices, such as `0.2.4`, that uniquely identifies it within
the tree.

Addresses are **relative within each occurrence**: an occurrence's address
Expand All @@ -54,7 +60,7 @@ At each step, both sides agree on the addresses, so subsequent data
requests (waveform samples, signal values, schematic fragments) carry
only the compact address, not the full path or structural description.

## Package overview
## What It Provides

`rohd_hierarchy` is a source-agnostic Dart package that implements this
dictionary model. It provides data models, search utilities, and adapter
Expand All @@ -76,7 +82,7 @@ transport layer.
direction, and optional value. Signals with a `direction` serve as
ports (input, output, inout).

### Services & adapters
### Services and adapters

- **`HierarchyService`** — A mixin providing tree-walking search and
navigation: `searchSignals()`, `searchOccurrences()`,
Expand Down Expand Up @@ -115,8 +121,8 @@ transport layer.
```dart
import 'package:rohd_hierarchy/rohd_hierarchy.dart';

final dict = NetlistHierarchyAdapter.fromJson(netlistJsonString);
final root = dict.root; // the top-level dictionary table
final hierarchy = NetlistHierarchyAdapter.fromJson(netlistJsonString);
final root = hierarchy.root; // The top-level dictionary table.
```

### Wrapping an existing tree
Expand All @@ -126,7 +132,7 @@ parser, a ROHD simulation, or any other source), wrap it to gain search
and address resolution:

```dart
final dict = BaseHierarchyAdapter.fromTree(rootNode);
final hierarchy = BaseHierarchyAdapter.fromTree(rootNode);
```

### Incremental expansion by a remote agent
Expand All @@ -136,7 +142,7 @@ dictionary one level at a time:

```dart
// Agent receives the root table
final root = dict.root;
final root = hierarchy.root;

// Agent picks a child to expand (e.g. child 2)
final child = root.children[2];
Expand All @@ -151,14 +157,15 @@ Once both sides share the dictionary, data requests use addresses only:

```dart
// Resolve a human-readable pathname to a canonical address
final addr = dict.pathnameToAddress('Counter/clk');
final address = hierarchy.pathnameToAddress('Counter/clk');

// Send the compact address over the wire: "0.1"
final wire = addr!.toDotString();
// Send the compact address over the wire, for example: "0".
final wireAddress = address!.toDotString();

// The other side resolves it back
final resolved = dict.occurrenceByAddress(OccurrenceAddress.fromDotString(wire));
final pathname = dict.addressToPathname(addr!);
// The other side resolves it back as a signal address.
final resolvedSignal =
hierarchy.signalByAddress(OccurrenceAddress.fromDotString(wireAddress));
final pathname = hierarchy.addressToPathname(address, asSignal: true);
```

### Searching the dictionary
Expand All @@ -169,13 +176,13 @@ Segments are split on `/` or `.` and matched as case-sensitive substrings:

```dart
// Find all signals whose path contains 'cpu' then 'clk'
final signals = dict.searchSignals('cpu/clk');
final signals = hierarchy.searchSignals('cpu/clk');

// Find occurrences containing 'counter'
final modules = dict.searchOccurrences('counter');
final modules = hierarchy.searchOccurrences('counter');

// Tab-completion for partial paths
final completions = dict.autocompletePaths('Top/CPU/');
final completions = hierarchy.autocompletePaths('Top/CPU/');
```

#### Regex / glob search
Expand All @@ -185,22 +192,22 @@ and `?` are auto-converted. Use `**` to match across hierarchy levels:

```dart
// All 'clk' signals anywhere in the design
final clocks = dict.searchSignalsRegex('Top/**/clk');
final clocks = hierarchy.searchSignalsRegex('Top/**/clk');

// Signals named d0–d15 in any regfile
final data = dict.searchSignalsRegex('Top/**/regfile/d[0-9]+');
final data = hierarchy.searchSignalsRegex('Top/**/regfile/d[0-9]+');

// Either 'clk' or 'reset' anywhere
final resets = dict.searchSignalsRegex('Top/**/(clk|reset)');
final resets = hierarchy.searchSignalsRegex('Top/**/(clk|reset)');

// All cache channels ch0–ch2
final channels = dict.searchOccurrencesRegex('Top/mem_ctrl/ch[0-2]');
final channels = hierarchy.searchOccurrencesRegex('Top/mem_ctrl/ch[0-2]');

// Signals containing 'mux' in their name
final muxed = dict.searchSignalsRegex('Top/**/.*mux.*');
final muxed = hierarchy.searchSignalsRegex('Top/**/.*mux.*');

// All signals in a specific module
final all = dict.searchSignalsRegex('Top/CPU/ALU/*');
final all = hierarchy.searchSignalsRegex('Top/CPU/ALU/*');
```

### Constructing occurrences manually
Expand Down Expand Up @@ -244,3 +251,7 @@ print(root.signals.first.path()); // 'Counter/clk'
| **Canonical** | `buildAddresses()` assigns deterministic indices in tree order. The same design always produces the same addresses. |
| **No global namespace** | Each occurrence's address table is self-contained. Adding or removing a sibling subtree does not invalidate addresses in unrelated parts of the tree. |
| **Transport-independent** | The package defines the dictionary model, not the wire protocol. Any transport (VM service, JSON-RPC, gRPC, WebSocket) can carry the compact addresses. |

----------------
Copyright (C) 2026 Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
7 changes: 7 additions & 0 deletions packages/rohd_waveform/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/

# Avoid committing pubspec.lock for library packages; see
# https://dart.dev/guides/libraries/private-files#pubspeclock.
pubspec.lock
3 changes: 3 additions & 0 deletions packages/rohd_waveform/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.1.0

- Initial release of waveform data models, service APIs, repositories, and signal data helpers.
28 changes: 28 additions & 0 deletions packages/rohd_waveform/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
BSD 3-Clause License

Copyright (C) 2021-2026 Intel Corporation

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 changes: 58 additions & 0 deletions packages/rohd_waveform/README.md
Comment thread
desmonddak marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# rohd_waveform

Pure-Dart waveform data services and models for ROHD wave viewers.

This package supplies waveform value data to remote clients, viewers, and
debugging tools while using [`rohd_hierarchy`](../rohd_hierarchy) for module
and signal structure. It defines the boundary between a waveform source, such
as a simulator, debugger, VCD/Wellen reader, or DevTools connection, and a UI
that needs signal values over time.

## Service

`rohd_waveform` provides a small service layer for requesting, caching, and
streaming waveform values:

- `SignalWaveformApi` defines the source-facing API for loading waveform data,
streaming incremental updates, reading the current simulation time, and
retrieving value snapshots.
- `SignalWaveformRepository` wraps a `SignalWaveformApi`, waits for asynchronous
sources to become ready, caches signal metadata and waveform values, and can
synthesize computed sub-field waveforms from parent signal data.
- `SignalDataService` exposes a signal-centric interface for clients that work
with `SignalOccurrence` objects from `rohd_hierarchy`.
- `RepositorySignalDataService` adapts the repository cache into `WaveData`
objects for wave viewers and other clients.

The package does not include a waveform backend. Applications provide a
concrete `SignalWaveformApi` implementation for their data source, while this
package handles the shared service contract, caching, and transfer models.

## Models

The package also includes waveform-specific models used across the service
boundary:

- `ModuleStructure` — top-level waveform structure metadata and hierarchy roots.
- `WaveformData` — transfer payload returned by a `SignalWaveformApi` fetch or
stream. It carries a signal ID, data points, and whether the values were
computed, but it does not provide hierarchy metadata or lookup behavior.
- `SignalWaveform` — repository/client-side waveform state for one signal. It
can be built from `WaveformData`, appended to over time, queried by time or
range, and linked back to `SignalOccurrence` metadata through a lookup
function.
- `WaveformUpdateEvent` — event payload for waveform update notifications.
- `WaveData` — combined `SignalOccurrence` metadata and waveform data returned
by `SignalDataService`.
- `Data`, `WaveFormat`, and `MetaData` — waveform data primitives.

In short, use `WaveformData` at the service/API boundary and `SignalWaveform`
inside clients or repositories that need cached state, incremental appends,
metadata access, or waveform queries.

For hierarchy types such as `HierarchyOccurrence` and `SignalOccurrence`,
import `package:rohd_hierarchy/rohd_hierarchy.dart` directly.

----------------
Copyright (C) 2026 Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
1 change: 1 addition & 0 deletions packages/rohd_waveform/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include: ../../analysis_options.yaml
23 changes: 23 additions & 0 deletions packages/rohd_waveform/lib/rohd_waveform.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (C) 2024-2026 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// rohd_waveform.dart
// Waveform data models and APIs for wave viewers.
//
// 2026 July 15
// Author: Desmond Kirkpatrick <desmond.a.kirkpatrick@intel.com>

/// Waveform data models and APIs for wave viewers.
///
/// This library provides waveform-specific data models:
/// - `ModuleStructure` - top-level waveform structure
/// - `SignalWaveform` - waveform data with backpointer to signal metadata
/// - `Data`, `WaveFormat`, and `MetaData` - waveform data primitives
///
/// For hierarchy types such as `HierarchyOccurrence` and `SignalOccurrence`,
/// import 'package:rohd_hierarchy/rohd_hierarchy.dart' directly.
library;

export 'src/models/models.dart';
export 'src/waveform_api.dart';
export 'src/waveform_repository.dart';
34 changes: 34 additions & 0 deletions packages/rohd_waveform/lib/src/models/data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (C) 2024-2026 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// data.dart
// An entity that describes the data of a signal.
//
// 2024 January 29
// Author: Desmond Kirkpatrick <desmond.a.kirkpatrick@intel.com>

/// A class that represents the data of a signal.
///
/// It contains a time and a value.
class Data {
/// The time of the data.
int time;

/// The value of the data.
String value;
Comment thread
desmonddak marked this conversation as resolved.

/// Creates a new instance of [Data].
///
/// Requires [time] and [value] as parameters.
Data({required this.time, required this.value});

/// Converts the [Data] instance into a JSON Map.
Map<String, dynamic> toJson() => {'time': time, 'value': value};

/// Creates a new instance of [Data] from a JSON Map.
factory Data.fromJson(Map<String, dynamic> json) =>
Data(time: json['time'] as int, value: json['value'] as String);

/// Creates an empty data point at time zero with value `0`.
factory Data.empty() => Data(time: 0, value: '0');
}
Loading
Loading