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
6dfe0f9
simplified forModule, improved code doc
desmonddak May 12, 2026
3800624
Merge branch 'central_naming' into netlist
desmonddak May 12, 2026
3c90e5d
more coverage for Namer
desmonddak May 12, 2026
49d196d
Merge branch 'central_naming' into netlist
desmonddak May 12, 2026
b2c9715
streamlined netlist optimization passes
desmonddak May 12, 2026
3e103f9
Add ModuleServices singleton and SvService
desmonddak May 6, 2026
d985446
Add netlist synthesizer, NetlistService, and supporting infrastructure
desmonddak May 6, 2026
831e3da
formatting
desmonddak May 6, 2026
38cf2aa
Merge branch 'central_naming' into netlist
desmonddak May 12, 2026
5e40679
Merge branch 'central_naming' into netlist
desmonddak May 12, 2026
be67018
streamlined netlist optimization passes
desmonddak May 12, 2026
7c11aa5
Merge branch 'netlist' of https://github.com/desmonddak/rohd into net…
desmonddak May 12, 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
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();
}
175 changes: 6 additions & 169 deletions example/oven_fsm.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2023-2024 Intel Corporation
// Copyright (C) 2023-2026 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// oven_fsm.dart
Expand All @@ -14,175 +14,12 @@ import 'dart:async';

import 'package:rohd/rohd.dart';

// Import the counter module implement in example.dart.
import './example.dart';
// Import module definitions (Counter, OvenModule, enums).
import 'package:rohd/src/examples/oven_fsm_modules.dart';

// Enumerated type named `OvenState` with four possible states:
// `standby`, `cooking`,`paused`, and `completed`.
enum OvenState { standby, cooking, paused, completed }

// One-hot encoded `Button` using dart enhanced enums.
// Represent start, pause, and resume as integer value 0, 1,
// and 2 respectively.
enum Button {
start(value: 0),
pause(value: 1),
resume(value: 2);

const Button({required this.value});

final int value;
}

// One-hot encoded `LEDLight` using dart enhanced enums.
// Represent yellow, blue, red, and green as integer value 0, 1,
// 2, and 3 respectively.
enum LEDLight {
yellow(value: 0),
blue(value: 1),
red(value: 2),
green(value: 3);

const LEDLight({required this.value});

final int value;
}

// Define a class OvenModule that extends ROHD's abstract Module class.
class OvenModule extends Module {
// A private variable with type FiniteStateMachine<OvenState> `_oven`.
//
// Use `late` to indicate that the value will not be null
// and will be assign in the later section.
late FiniteStateMachine<OvenState> _oven;

// We can expose an LED light output as a getter to retrieve it value.
Logic get led => output('led');

// This oven module receives a `button` and a `reset` input from runtime.
OvenModule(Logic button, Logic reset, Logic clk) : super(name: 'OvenModule') {
// Register inputs and outputs of the module in the constructor.
// Module logic must consume registered inputs and output to registered
// outputs. `led` output also added as the output port.
button = addInput('button', button, width: button.width);
reset = addInput('reset', reset);
clk = addInput('clk', clk);
final led = addOutput('led', width: button.width);

// Register local signals, `counterReset` and `en`
// for Counter module.
final counterReset = Logic(name: 'counter_reset');
final en = Logic(name: 'counter_en');

// An internal counter module that will be used to time the cooking state.
// Receive `en`, `counterReset` and `clk` as input.
final counter = Counter(en, counterReset, clk, name: 'counter_module');

// A list of `OvenState` that describe the FSM. Note that
// `OvenState` consists of identifier, events and actions. We
// can think of `identifier` as the state name, `events` is a map of event
// that trigger next state. `actions` is the behaviour of current state,
// like what is the actions need to be shown separate current state with
// other state. Represented as List of conditionals to be executed.
final states = [
// identifier: standby state, represent by `OvenState.standby`.
State<OvenState>(OvenState.standby,
// events:
// When the button `start` is pressed during standby state,
// OvenState will changed to `OvenState.cooking` state.
events: {
Logic(name: 'button_start')
..gets(button
.eq(Const(Button.start.value, width: button.width))):
OvenState.cooking,
},
// actions:
// During the standby state, `led` is change to blue; timer's
// `counterReset` is set to 1 (Reset the timer);
// timer's `en` is set to 0 (Disable value update).
actions: [
led < LEDLight.blue.value,
counterReset < 1,
en < 0,
]),

// identifier: cooking state, represent by `OvenState.cooking`.
State<OvenState>(OvenState.cooking,
// events:
// When the button `paused` is pressed during cooking state,
// OvenState will changed to `OvenState.paused` state.
//
// When the button `counter` time is elapsed during cooking state,
// OvenState will changed to `OvenState.completed` state.
events: {
Logic(name: 'button_pause')
..gets(button
.eq(Const(Button.pause.value, width: button.width))):
OvenState.paused,
Logic(name: 'counter_time_complete')..gets(counter.val.eq(4)):
OvenState.completed
},
// actions:
// During the cooking state, `led` is change to yellow; timer's
// `counterReset` is set to 0 (Do not reset);
// timer's `en` is set to 1 (Enable value update).
actions: [
led < LEDLight.yellow.value,
counterReset < 0,
en < 1,
]),

// identifier: paused state, represent by `OvenState.paused`.
State<OvenState>(OvenState.paused,
// events:
// When the button `resume` is pressed during paused state,
// OvenState will changed to `OvenState.cooking` state.
events: {
Logic(name: 'button_resume')
..gets(button
.eq(Const(Button.resume.value, width: button.width))):
OvenState.cooking
},
// actions:
// During the paused state, `led` is change to red; timer's
// `counterReset` is set to 0 (Do not reset);
// timer's `en` is set to 0 (Disable value update).
actions: [
led < LEDLight.red.value,
counterReset < 0,
en < 0,
]),

// identifier: completed state, represent by `OvenState.completed`.
State<OvenState>(OvenState.completed,
// events:
// When the button `start` is pressed during completed state,
// OvenState will changed to `OvenState.cooking` state.
events: {
Logic(name: 'button_start')
..gets(button
.eq(Const(Button.start.value, width: button.width))):
OvenState.cooking
},
// actions:
// During the start state, `led` is change to green; timer's
// `counterReset` is set to 1 (Reset value);
// timer's `en` is set to 0 (Disable value update).
actions: [
led < LEDLight.green.value,
counterReset < 1,
en < 0,
])
];

// Assign the _oven FiniteStateMachine object to private variable declared.
_oven =
FiniteStateMachine<OvenState>(clk, reset, OvenState.standby, states);
}

// An oven FiniteStateMachine that represent in getter.
FiniteStateMachine<OvenState> get ovenStateMachine => _oven;
}
// Re-export module definitions so test files that import this file
// get access to OvenModule, OvenState, Button, LEDLight, etc.
export 'package:rohd/src/examples/oven_fsm_modules.dart' hide Counter;

/// A helper function to wait for a number of cycles.
Future<void> waitCycles(Logic clk, int numCycles) async {
Expand Down
Loading
Loading