Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
82e900e
move synthesis naming to a common naming utility so all synthesizers …
desmonddak Apr 17, 2026
85f88ce
dart 3.11 parameter_assignments pickiness
desmonddak Apr 17, 2026
b1de1e5
Merge branch 'main' into central_naming
desmonddak Apr 17, 2026
b7087c4
conflict resolved and dart format . works
desmonddak Apr 17, 2026
4a55214
properly assign naming spaces for instances vs signals
desmonddak Apr 18, 2026
ed7be36
format issue
desmonddak Apr 18, 2026
ab09aed
Controllable enforcement of signal vs instance name uniqueness.
desmonddak Apr 19, 2026
520d280
Refactored to Namer class. No external API changes for ROHD
desmonddak Apr 19, 2026
61d0319
signal registry
desmonddak Apr 20, 2026
becdb36
module context name uniquification instead of signal/instance split
desmonddak May 1, 2026
a86f80c
Merge branch 'main' into central_naming
desmonddak May 3, 2026
d5904a6
cleanup of port vs signal name assumptions, constant merging and sign…
desmonddak May 3, 2026
3645293
Add ModuleServices singleton and SvService
desmonddak May 6, 2026
510ee01
Add netlist synthesizer, NetlistService, and supporting infrastructure
desmonddak May 6, 2026
2f7f0d1
formatting
desmonddak May 6, 2026
b1015ea
first passing version of SystemC translated tests
desmonddak May 8, 2026
8619328
SystemC and SV tests are comingled.
desmonddak May 8, 2026
f23023c
we need sudo in installation scripts
desmonddak May 8, 2026
3acf699
avoid a race and using a lock for SystemC
desmonddak May 8, 2026
035711c
cascade introduced
desmonddak May 9, 2026
b473a8e
use BigInt.one shifted instead of a platform-dependent constant
desmonddak May 9, 2026
5beb745
JS platform skip SystemC
desmonddak May 9, 2026
57cfec5
cleanup tmp_test after systemc tests
desmonddak May 9, 2026
289b3cc
create test dir
desmonddak May 9, 2026
38e6f65
cascade issue
desmonddak May 9, 2026
5beddb4
yet another JS issue
desmonddak May 9, 2026
636c68b
trying to match devcontainer to normal ci
desmonddak May 9, 2026
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
14 changes: 13 additions & 1 deletion .github/workflows/general.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,29 @@ jobs:
- name: Install software - Icarus Verilog
run: tool/gh_actions/install_iverilog.sh

- name: Install software - Accellera SystemC
run: tool/gh_actions/install_systemc.sh

- name: Pre-build SystemC PCH and Makefile
run: tool/gh_actions/setup_systemc_pch.sh

- name: Run project tests
run: tool/gh_actions/run_tests.sh

- name: Run SystemC tests
run: dart test test/systemc_vector_test.dart

- name: Check temporary test files
run: tool/gh_actions/check_tmp_test.sh

# https://github.com/devcontainers/ci/blob/main/docs/github-action.md
- name: Build dev container and run tests in it
uses: devcontainers/ci@v0.3
with:
runCmd: tool/gh_actions/run_tests.sh
runCmd: |
tool/gh_actions/run_tests.sh
dart test test/systemc_vector_test.dart
tool/gh_actions/check_tmp_test.sh

deploy-documentation:
name: Deploy Documentation
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ You can also open this repository in a GitHub Codespace to run the example in yo
- **Simple and fast build**, free of complex build systems and EDA vendor tools
- Can use the excellent pub.dev **package manager** and all the packages it has to offer
- Built-in event-based **fast simulator** with **4-value** (0, 1, X, and Z) support and a **waveform dumper** to .vcd file format
- Conversion of modules to equivalent, human-readable, structurally similar **SystemVerilog** for integration or downstream tool consumption
- Conversion of modules to equivalent, human-readable, structurally similar **SystemVerilog** and **SystemC** for integration or downstream tool consumption
- **Run-time dynamic** module port definitions (numbers, names, widths, etc.) and internal module logic, including recursive module contents
- Leverage the [ROHD Hardware Component Library (ROHD-HCL)](https://github.com/intel/rohd-hcl) with reusable and configurable design and verification components.
- Simple, free, **open source tool stack** without any headaches from library dependencies, file ordering, elaboration/analysis options, +defines, etc.
Expand Down
4 changes: 2 additions & 2 deletions doc/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The `Simulator` acts as a statically accessible driver of the overall simulation

### Synthesizer

A separate type of object responsible for taking a `Module` and converting it to some output, such as SystemVerilog.
A separate type of object responsible for taking a `Module` and converting it to some output, such as SystemVerilog or SystemC.

## Organization

Expand All @@ -44,7 +44,7 @@ Contains a collection of `Module` implementations that can be used as primitive

### Synthesizers

Contains logic for synthesizing `Module`s into some output. It is structured to maximize reusability across different output types (including those not yet supported).
Contains logic for synthesizing `Module`s into some output (e.g. SystemVerilog, SystemC). It is structured to maximize reusability across different output types.

### Utilities

Expand Down
22 changes: 21 additions & 1 deletion doc/user_guide/_docs/A21-generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ last_modified_at: 2023-11-13
toc: true
---

Hardware in ROHD is convertible to an output format via `Synthesizer`s, the most popular of which is SystemVerilog. Hardware in ROHD can be converted to logically equivalent, human-readable SystemVerilog with structure, hierarchy, ports, and names maintained.
Hardware in ROHD is convertible to an output format via `Synthesizer`s. The most popular output format is SystemVerilog, with SystemC also available. Hardware in ROHD can be converted to logically equivalent, human-readable SystemVerilog or SystemC with structure, hierarchy, ports, and names maintained.

The simplest way to generate SystemVerilog is with the helper method `generateSynth` in `Module`:

Expand All @@ -28,6 +28,26 @@ void main() async {

The `generateSynth` function will return a `String` with the SystemVerilog `module` definitions for the top-level it is called on, as well as any sub-modules (recursively). You can dump the entire contents to a file and use it anywhere you would any other SystemVerilog.

## SystemC generation

ROHD can also generate SystemC (C++ with the SystemC library) from the same hardware description. Use the `generateSystemC` helper method:

```dart
void main() async {
final myModule = MyModule();
await myModule.build();

final generatedSc = myModule.generateSystemC();

// write it to a file
File('myHardware.h').writeAsStringSync(generatedSc);
}
```

The generated SystemC uses `SC_MODULE`, `SC_METHOD`, and `SC_CTHREAD` constructs. Combinational logic becomes `SC_METHOD` processes, sequential logic (flip-flops and `Sequential` blocks) sharing the same clock and reset are consolidated into a single `SC_CTHREAD`, and sub-modules are instantiated with port bindings. All signal types map to SystemC equivalents (`bool`, `sc_uint<N>`, `sc_biguint<N>`).

For more control over SystemC generation, use `SynthBuilder` with `SystemCSynthesizer()` directly.

## Controlling naming

### Modules
Expand Down
2 changes: 1 addition & 1 deletion doc/user_guide/_get-started/01-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Features of ROHD include:
- **Simple and fast build**, free of complex build systems and EDA vendor tools
- Can use the excellent pub.dev **package manager** and all the packages it has to offer
- Built-in event-based **fast simulator** with **4-value** (0, 1, X, and Z) support and a **waveform dumper** to .vcd file format
- Conversion of modules to equivalent, human-readable, structurally similar **SystemVerilog** for integration or downstream tool consumption
- Conversion of modules to equivalent, human-readable, structurally similar **SystemVerilog** and **SystemC** for integration or downstream tool consumption
- **Run-time dynamic** module port definitions (numbers, names, widths, etc.) and internal module logic, including recursive module contents
- Leverage the [ROHD Hardware Component Library (ROHD-HCL)](https://github.com/intel/rohd-hcl) with reusable and configurable design and verification components.
- Simple, free, **open source tool stack** without any headaches from library dependencies, file ordering, elaboration/analysis options, +defines, etc.
Expand Down
40 changes: 12 additions & 28 deletions example/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,16 @@
// allow `print` messages (disable lint):
// ignore_for_file: avoid_print

// Import necessary dart packages for this file.
// Import necessary dart pacakges for this file.
import 'dart:async';

// Import the ROHD package.
import 'package:rohd/rohd.dart';

// Define a class Counter that extends ROHD's abstract Module class.
class Counter extends Module {
// For convenience, map interesting outputs to short variable names for
// consumers of this module.
Logic get val => output('val');

// This counter supports any width, determined at run-time.
final int width;

Counter(Logic en, Logic reset, Logic clk,
{this.width = 8, super.name = 'counter'}) {
// Register inputs and outputs of the module in the constructor.
// Module logic must consume registered inputs and output to registered
// outputs.
en = addInput('en', en);
reset = addInput('reset', reset);
clk = addInput('clk', clk);
addOutput('val', width: width);

// We can use the `flop` function to automate creation of a `Sequential`.
val <= flop(clk, reset: reset, en: en, val + 1);
}
}
// Re-export the Counter module from the library examples so that
// existing tests that `import 'example/example.dart'` still see it.
import 'package:rohd/src/examples/oven_fsm_modules.dart' show Counter;
export 'package:rohd/src/examples/oven_fsm_modules.dart' show Counter;

// Let's simulate with this counter a little, generate a waveform, and take a
// look at generated SystemVerilog.
Expand Down Expand Up @@ -76,8 +57,9 @@ Future<void> main({bool noPrint = false}) async {
// Let's also print a message every time the value on the counter changes,
// just for this example to make it easier to see before we look at waves.
if (!noPrint) {
counter.val.changed
.listen((e) => print('@${Simulator.time}: Value changed: $e'));
counter.val.changed.listen(
(e) => print('@${Simulator.time}: Value changed: $e'),
);
}

// Start off with a disabled counter and asserting reset at the start.
Expand Down Expand Up @@ -115,7 +97,9 @@ Future<void> main({bool noPrint = false}) async {

// We can take a look at the waves now.
if (!noPrint) {
print('To view waves, check out waves.vcd with a waveform viewer'
' (e.g. `gtkwave waves.vcd`).');
print(
'To view waves, check out waves.vcd with a waveform viewer'
' (e.g. `gtkwave waves.vcd`).',
);
}
}
117 changes: 117 additions & 0 deletions example/filter_bank.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (C) 2025-2026 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// filter_bank.dart
// A polyphase FIR filter bank design example exercising:
// - Deep hierarchy with shared sub-module definitions
// - Interface (FilterDataInterface)
// - LogicStructure (FilterSample)
// - LogicArray (coefficient storage)
// - Pipeline (pipelined MAC accumulation)
// - FiniteStateMachine (FilterController)
//
// The filter bank has two channels that share an identical MacUnit definition.
// A controller FSM sequences: idle → loading → running → draining → done.
//
// 2026 March 26
// Author: Desmond Kirkpatrick <desmond.a.kirkpatrick@intel.com>

import 'dart:async';

import 'package:rohd/rohd.dart';

// Import module definitions.
import 'package:rohd/src/examples/filter_bank_modules.dart';

// Re-export so downstream consumers (e.g. devtools loopback) can use.
export 'package:rohd/src/examples/filter_bank_modules.dart';

// ──────────────────────────────────────────────────────────────────
// Standalone simulation entry point
// ──────────────────────────────────────────────────────────────────

Future<void> main({bool noPrint = false}) async {
const dataWidth = 16;
const numTaps = 3;

// Low-pass-ish coefficients (scaled integers)
const coeffs0 = [1, 2, 1]; // channel 0: symmetric LPF kernel
const coeffs1 = [1, -2, 1]; // channel 1: high-pass kernel

final clk = SimpleClockGenerator(10).clk;
final reset = Logic(name: 'reset');
final start = Logic(name: 'start');
final samplesIn = LogicArray([2], dataWidth, name: 'samplesIn');
final validIn = Logic(name: 'validIn');
final inputDone = Logic(name: 'inputDone');

final dut = FilterBank(
clk,
reset,
start,
samplesIn,
validIn,
inputDone,
numTaps: numTaps,
dataWidth: dataWidth,
coefficients: [coeffs0, coeffs1],
);

// Before we can simulate or generate code, we need to build it.
await dut.build();

// Set a maximum time for the simulation so it doesn't keep running forever.
Simulator.setMaxSimTime(500);

// Attach a waveform dumper so we can see what happens.
if (!noPrint) {
WaveDumper(dut, outputPath: 'filter_bank.vcd');
}

// Kick off the simulation.
unawaited(Simulator.run());

// ── Reset ──
reset.inject(1);
start.inject(0);
samplesIn.elements[0].inject(0);
samplesIn.elements[1].inject(0);
validIn.inject(0);
inputDone.inject(0);

await clk.nextPosedge;
await clk.nextPosedge;
reset.inject(0);

// ── Start filtering ──
await clk.nextPosedge;
start.inject(1);
await clk.nextPosedge;
start.inject(0);
validIn.inject(1);

// ── Feed sample stream: impulse response test ──
// Send a single '1' followed by zeros to get the impulse response
samplesIn.elements[0].inject(1);
samplesIn.elements[1].inject(1);
await clk.nextPosedge;

for (var i = 0; i < 8; i++) {
samplesIn.elements[0].inject(0);
samplesIn.elements[1].inject(0);
await clk.nextPosedge;
}

// ── Signal end of input ──
validIn.inject(0);
inputDone.inject(1);
await clk.nextPosedge;
inputDone.inject(0);

// ── Wait for drain ──
for (var i = 0; i < 15; i++) {
await clk.nextPosedge;
}

await Simulator.endSimulation();
}
Loading
Loading