Skip to content
Merged
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
### Breaking Changes

- `FiniteStateMachine` and `State` now require Dart enum state identifiers. Replace integer, string, or custom-object identifiers with enum members; update reset and transition targets accordingly. `currentState` and `nextState` are now `LogicEnum` signals (<https://github.com/intel/rohd/pull/599>).
- Removed all deprecated APIs: `StateMachine`, `FF`, `IfBlock`, `ExternalModule`, `LogicValues`, `Logic.bit`, `valueInt`, `valueBigInt`, `hasValidValue`, `isFloating`, `LogicValue.length`, `LogicValue.bit`, the `LogicValue.from...` constructors and `LogicValue.from(iterable)`, global concatenation helpers, gate `y` output aliases including `Add.out`, `getReceivers`, `getDrivers`, `getConditionals`, `FiniteStateMachine.clk`, `Pipeline.clk`, `Port`, `PairInterface.modify`, the `PairInterface.clone` constructor, `LogicStructure.bit`, `Module.unpreferredName`, `Module.isUnpreferred`, `Dumper`, `WaveDumper`, `SynthBuilder.top`, `SynthBuilder.getFileContents()`, `SynthesisResult.toFileContents()` and backend overrides, `CustomSystemVerilog`, `SystemVerilogSynthesizer.instantiationVerilogWithParameters`, `Module.generateSynth`, `ModuleTree.hierarchyJSON`, `NetlistSynthesisResult.toFileContents()`, and `SystemVerilogService.contentsByName`. See the [0.7.0 migration guide](doc/releases.md#core-api-migration-for-070) for replacements. The legacy `Swizzle` module and `List` concatenation aliases remain available but are deprecated in favor of `Concat`, `concat`, and `rconcat`.
- Removed long-deprecated and obsolete APIs: `StateMachine`, `FF`, `IfBlock`, `ExternalModule`, `LogicValues`, `Logic.bit`, `valueInt`, `valueBigInt`, `hasValidValue`, `isFloating`, `LogicValue.length`, `LogicValue.bit`, the `LogicValue.from...` constructors and `LogicValue.from(iterable)`, global concatenation helpers, gate `y` output aliases including `Add.out`, `getReceivers`, `getDrivers`, `getConditionals`, `FiniteStateMachine.clk`, `Pipeline.clk`, `Port`, `PairInterface.modify`, the `PairInterface.clone` constructor, `LogicStructure.bit`, `Module.unpreferredName`, `Module.isUnpreferred`, `Dumper`, `WaveDumper`, `SynthBuilder.top`, `SynthBuilder.getFileContents()`, `SynthesisResult.toFileContents()` and backend overrides, `CustomSystemVerilog`, `SystemVerilogSynthesizer.instantiationVerilogWithParameters`, `Module.generateSynth`, `ModuleTree.hierarchyJSON`, `NetlistSynthesisResult.toFileContents()`, and `SystemVerilogService.contentsByName`. See the [0.7.0 migration guide](doc/releases.md#core-api-migration-for-070) for replacements. The legacy `Swizzle` module and `List` concatenation aliases remain available but are deprecated in favor of `Concat`, `concat`, and `rconcat`.

### Major Features

Expand Down Expand Up @@ -69,6 +69,7 @@

### Bug Fixes

- Avoid a circular-assignment assertion when merging connected net aliases makes a net-to-net connection redundant during synthesis.
- Made file-free, retained VCD waveform capture available on web platforms for DartPad and other browser workflows (<https://github.com/intel/rohd/issues/273>).
- Preserve four-state `z` values through procedural assignments and muxes, including SystemVerilog’s bitwise merge behavior for unknown mux controls (<https://github.com/intel/rohd/issues/570>).
- Replaced per-wire simulator lifecycle subscriptions with a shared weak wire registry, so discarded elaborations no longer retain callbacks or degrade future simulation ticks (<https://github.com/intel/rohd/issues/708>).
Expand Down
43 changes: 19 additions & 24 deletions doc/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,11 @@ coordinated release.

### Core API migration for 0.7.0

ROHD 0.7.0 removes all deprecated APIs, including those deprecated in 0.6.x
and APIs whose deprecation release is not recorded, and completes a few older
breaking renames and merges. Migrate consumers before widening a `^0.6.11`
core constraint to include 0.7.x. The independently versioned shared packages
do not need breaking releases just because core removes these APIs.
ROHD 0.7.0 removes long-deprecated and obsolete APIs and completes a few older
breaking renames and merges. Recent deprecations, including `Swizzle`,
`swizzle`, and `rswizzle`, remain available. Migrate affected consumers to the
replacement APIs and release them with a `^0.7.0` core constraint rather than
trying to support both 0.6.x and 0.7.x.

“Deprecated in” gives the first tagged release whose changelog explicitly
records the deprecation. “Not recorded” means the changelog does not identify
Expand Down Expand Up @@ -387,11 +387,10 @@ require hierarchy 0.1.1 to be published first. ROHD 0.7.0 does require hierarchy
0.1.1 for its new APIs, so publish hierarchy before ROHD. Widgets accepts ROHD
0.6.10 through 0.7.x and can be published before ROHD 0.7.0.

The viewer compatibility releases are `rohd_wave_viewer` 0.1.1,
`dart_wellen` 0.1.1, and `rohd_schematic_viewer` 0.2.5. They accept ROHD
0.6.11 through 0.7.x and widen shared-package constraints to accept both
0.1.x and 0.2.x. They do not need the new shared-package releases first.
Publish `dart_wellen` before the wave viewer.
Assess the viewers and their dependencies against ROHD 0.7.0 before assigning
release versions. Packages requiring changes should depend on ROHD `^0.7.0`
rather than attempting to span 0.6.x and 0.7.x. Publish `dart_wellen` before
the wave viewer if the latter requires a new `dart_wellen` release.

Widgets and viewers retain Flutter 3.44 as their lower bound and allow
Material UI 1.1.0 through 1.x, including 1.7.0. Resolving the newer UI stack
Expand All @@ -402,22 +401,18 @@ and 2.x. The application, wave viewer, and waveform package allow Equatable
2.x and 3.x. These changes do not increase package Dart language-version floors.

The DevTools application requires hierarchy and waveform 0.1.1 and widgets
0.1.2, but accepts the published wave viewer and `dart_wellen` 0.1.0 and
schematic viewer 0.2.4 as well as the planned compatibility releases. Its
Cupertino Icons range accepts 1.x and 2.x. Checkout CI uses local ROHD and
companion-package overrides, allowing the published viewers to be checked
against the current sources despite their ROHD `^0.6.11` constraints.
Final hosted resolution with ROHD 0.7.0 still requires the compatibility
viewer releases. A build using local overrides is a development check,
not proof of hosted resolution.
0.1.2. Its Cupertino Icons range accepts 1.x and 2.x. Checkout CI uses local
ROHD and companion-package overrides; these allow development checks but do
not prove that hosted dependencies resolve together. Final hosted resolution
with ROHD 0.7.0 requires compatible viewer releases and corresponding
dependency constraints.

The published wave viewer and `dart_wellen` 0.1.0 use Flutter Rust Bridge 2.7.0
together; do not override that runtime independently. The planned 0.1.1 releases
must use Flutter Rust Bridge 2.7.1 consistently in their Dart runtime dependency,
Rust runtime and generator dependencies, and generated bindings. Use the wave
viewer Makefile to regenerate and validate the bridge before preparing either
archive. A dependency-constraint edit alone is not sufficient for this runtime
update.
together; do not override that runtime independently. If updating Flutter Rust
Bridge, use the same version consistently in Dart runtime, Rust runtime and
generator dependencies, and generated bindings. Use the wave viewer Makefile
to regenerate and validate the bridge before preparing either archive. A
dependency-constraint edit alone is not sufficient for this runtime update.

`rohd_source_navigator` has only hosted Dart dependencies and can be published
independently of ROHD and the Flutter packages. Once its version is available on
Expand Down
3 changes: 2 additions & 1 deletion lib/src/concat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import 'package:rohd/rohd.dart';
@Deprecated('Use Concat instead.')
class Swizzle extends Concat {
/// Constructs a deprecated [Swizzle] module.
Swizzle(List<Logic> signals, {super.name = 'swizzle'}) : super(signals);
@Deprecated('Use Concat instead.')
Swizzle(super.signals, {super.name = 'swizzle'});
}

/// Provides concatenation utilities for lists of [Logic]s.
Expand Down
18 changes: 14 additions & 4 deletions lib/src/synthesizers/utilities/synth_module_definition.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4342,6 +4342,17 @@ class SynthModuleDefinition {
assignments.whereType<PartialSynthAssignment>().toList();
assignments.removeWhere((e) => e is PartialSynthAssignment);

// Net-to-net connections are bidirectional. Remember the ones whose
// endpoints are distinct before merging, since their getters resolve and
// overwrite those endpoints as merges proceed.
final distinctNetConnections = <SynthAssignment>{
for (final assignment in assignments)
if (assignment.src.isNet &&
assignment.dst.isNet &&
assignment.src != assignment.dst)
assignment,
};

while (prevAssignmentCount != assignments.length) {
// keep looping until it stops shrinking
final reducedAssignments = <SynthAssignment>[];
Expand All @@ -4368,10 +4379,9 @@ class SynthModuleDefinition {
internalSignals.add(src);
}

if (src == dst && src.isConstant) {
// looks like this assignment does nothing -- some sort of circular
// constant assignment, can just remove it

if (src == dst &&
(src.isConstant || distinctNetConnections.contains(assignment))) {
// A net connection can become redundant after its endpoints merge.
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/src/utilities/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
/// A utility for ROHD configuration file.
class Config {
/// The version of the ROHD framework.
static const String version = '0.6.11';
static const String version = '0.7.0';
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: rohd
version: 0.6.11
version: 0.7.0
description: The Rapid Open Hardware Development (ROHD) framework, a framework for describing and verifying hardware.
homepage: https://intel.github.io/rohd-website
repository: https://github.com/intel/rohd
Expand Down
4 changes: 2 additions & 2 deletions rohd_devtools_extension/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ dependencies:
material_ui: ">=1.1.0 <1.3.0"
path: ^1.9.0
path_provider: ^2.1.0
rohd: ^0.6.11
rohd: ^0.7.0
rohd_devtools_widgets:
path: ../packages/rohd_devtools_widgets
rohd_hierarchy: ^0.1.1
rohd_schematic_viewer: ^0.2.4
rohd_schematic_viewer: ^0.2.5
rohd_source_navigator: ^0.1.0
rohd_wave_viewer: ^0.1.1
# Shares the viewer's extended monitored-waveform model.
Expand Down
9 changes: 6 additions & 3 deletions test/concat_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -209,17 +209,20 @@ void main() {
final high = LogicValue.ofString('10');
final low = LogicValue.ofString('01');

// ignore: deprecated_member_use
// Exercise the deprecated alias during the 0.7.x compatibility window.
// ignore: deprecated_member_use_from_same_package
expect([high, low].swizzle(), LogicValue.ofString('1001'));
// ignore: deprecated_member_use
// Exercise the deprecated alias during the 0.7.x compatibility window.
// ignore: deprecated_member_use_from_same_package
expect([low, high].rswizzle(), LogicValue.ofString('1001'));
});

test('deprecated Swizzle module preserves direct construction', () async {
final high = Logic(width: 2)..put(0x2);
final low = Logic(width: 2)..put(0x1);

// ignore: deprecated_member_use
// Exercise the deprecated module during the 0.7.x compatibility window.
// ignore: deprecated_member_use_from_same_package
final legacy = Swizzle([high, low]);
await legacy.build();

Expand Down
125 changes: 125 additions & 0 deletions test/logic_name_config_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,42 @@ class _PreservedNetChain extends Module {
}
}

class _PreservedNetArrayLoop extends Module {
final aliases = <LogicArray>[];

_PreservedNetArrayLoop(int unpackedDimensions, {required bool reversed}) {
final source = addInput('source', Logic(width: 8), width: 8);
final first = LogicArray.net([4], 2,
name: 'shared',
naming: Naming.renameable,
numUnpackedDimensions: unpackedDimensions);
final second = LogicArray.net([4], 2,
name: 'shared',
naming: Naming.reserved,
numUnpackedDimensions: unpackedDimensions);
final junction = LogicArray.net([4], 2,
name: 'junction',
naming: Naming.mergeable,
numUnpackedDimensions: unpackedDimensions);
aliases.addAll([first, second, junction]);

for (var i = 0; i < 4; i++) {
first.elements[i] <= source.getRange(i * 2, i * 2 + 2);
if (reversed) {
first.elements[i] <= second.elements[i];
second.elements[i] <= junction.elements[i];
junction.elements[i] <= first.elements[i];
} else {
second.elements[i] <= first.elements[i];
junction.elements[i] <= second.elements[i];
first.elements[i] <= junction.elements[i];
}
}
addOutput('result', width: 8) <= junction.packed;
addOutput('early', width: 8) <= first.packed;
}
}

void main() {
tearDown(Simulator.reset);

Expand Down Expand Up @@ -307,6 +343,95 @@ void main() {
});
}

for (final reversed in [false, true]) {
test(
'same-name net aliases with redundant connection, reversed=$reversed',
() async {
final aliases = <LogicNet>[];
final dut = FunctionGeneratedModule((in1, in2, out1) {
final first = LogicNet(name: 'shared', naming: Naming.renameable);
final second = LogicNet(name: 'shared', naming: Naming.reserved);
final junction = LogicNet(name: 'junction', naming: Naming.mergeable);
first <= in1;
second <= in2;
if (reversed) {
first <= second;
second <= junction;
junction <= first;
} else {
second <= first;
junction <= second;
first <= junction;
}
aliases.addAll([first, second, junction]);
out1 <= junction;
});

await dut.build();
final definition = SystemVerilogSynthModuleDefinition(dut);
final shared = definition.getSynthLogic(aliases.first)!;
expect(shared.logics, containsAll(aliases));
for (final alias in aliases) {
expect(definition.getSynthLogic(alias), same(shared));
}
for (final assignment in definition.assignments) {
if (assignment is! PartialSynthAssignment) {
expect(assignment.src, isNot(same(assignment.dst)));
}
}

final vectors = [
for (final value in [0, 1, 'x', 'z'])
Vector({'in1': value, 'in2': 'z'}, {'out1': value}),
Vector({'in1': 'z', 'in2': 1}, {'out1': 1}),
Vector({'in1': 0, 'in2': 1}, {'out1': 'x'}),
Vector({'in1': 1, 'in2': 1}, {'out1': 1}),
];
await SimCompare.checkFunctionalVector(dut, vectors);
SimCompare.checkIverilogVector(dut, vectors);
});
}

for (final unpackedDimensions in [0, 1]) {
for (final reversed in [false, true]) {
test(
'same-name net arrays with redundant connection, '
'unpackedDimensions=$unpackedDimensions, reversed=$reversed',
() async {
final dut =
_PreservedNetArrayLoop(unpackedDimensions, reversed: reversed);
await dut.build();
final definition = SystemVerilogSynthModuleDefinition(dut);
final shared = definition.getSynthLogic(dut.aliases.first)!;
expect(shared.logics, containsAll(dut.aliases));
for (final alias in dut.aliases) {
expect(definition.getSynthLogic(alias), same(shared));
for (var i = 0; i < 4; i++) {
expect(definition.getSynthLogic(alias.elements[i])!.name,
'shared[$i]');
}
}
for (final assignment in definition.assignments) {
if (assignment is! PartialSynthAssignment) {
expect(assignment.src, isNot(same(assignment.dst)));
}
}
final sv = dut.dumpSystemVerilog();
expect(
sv,
contains(unpackedDimensions == 0
? 'wire [3:0][1:0] shared;'
: 'wire [1:0] shared [3:0];'));
final vectors = [
for (final value in [0, 0x96, 0xff, 'xxxxxxxx', 'zzzzzzzz'])
Vector({'source': value}, {'result': value, 'early': value}),
];
await SimCompare.checkFunctionalVector(dut, vectors);
SimCompare.checkIverilogVector(dut, vectors);
});
}
}

for (final naming in [Naming.reserved, Naming.renameable]) {
test('${naming.name} different names remain declared', () async {
final dut = FunctionGeneratedModule((in1, in2, out1) {
Expand Down
28 changes: 27 additions & 1 deletion test/pair_interface_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ class SimpleTop extends Module {
}
}

class _PairHarness extends Module {}

class PassthroughPairIntfModule extends Module {
PassthroughPairIntfModule(SimpleInterface intf1, SimpleInterface intf2,
{required bool useConditional, required bool useConnectApi}) {
Expand Down Expand Up @@ -310,11 +312,35 @@ void main() {
final mod = SimpleTop(Logic());
await mod.build();

// Make sure the "modify" went through:
// Make sure the port uniquification went through:
final sv = mod.dumpSystemVerilog();
expect(sv, contains('input logic simple_clk'));
});

test('cloned pair interface connects with uniquified ports', () async {
final source = PairInterface(
portsFromConsumer: [Logic(name: 'response')],
portsFromProvider: [Logic(name: 'request')],
);
final destination = source.clone();
final module = _PairHarness();

expect(
destination.ports.keys,
unorderedEquals(['response', 'request']),
);
destination.pairConnectIO(
module,
source,
PairRole.provider,
uniquify: (original) => 'outer_$original',
);
await module.build();

expect(module.inputs.keys, ['outer_response']);
expect(module.outputs.keys, ['outer_request']);
});

test('split preserves the interface type for each endpoint', () {
final pair = _EndpointPair();
final (provider, consumer) = pair.split();
Expand Down
Loading