Skip to content

Cloning and matching #614

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 49 commits into from
Jul 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
510fd12
basic build working, not generating sv yet
mkorbel1 Jul 21, 2025
b565958
wip
mkorbel1 Jul 21, 2025
2f140f1
working out new approach
mkorbel1 Jul 21, 2025
7ee9246
partial assignment on outputs working
mkorbel1 Jul 21, 2025
7bddbb2
basic subset temp working
mkorbel1 Jul 21, 2025
343d03f
making progress to collapse assignments without partials
mkorbel1 Jul 22, 2025
06f3b47
todo
mkorbel1 Jul 22, 2025
59ee3e1
dont find structs not connected
mkorbel1 Jul 22, 2025
02d9030
refactor struct assign gen
mkorbel1 Jul 22, 2025
7716a34
functional working for all four cases
mkorbel1 Jul 22, 2025
bf8a139
some cleanup
mkorbel1 Jul 22, 2025
1650344
wip net stuff
mkorbel1 Jul 22, 2025
1075350
got net connection almost working
mkorbel1 Jul 23, 2025
96202f6
fix test
mkorbel1 Jul 23, 2025
8c1f51f
fix test again
mkorbel1 Jul 23, 2025
e15961e
add interface clones
mkorbel1 Jul 23, 2025
72dcfdf
fix synth assignment assertions
mkorbel1 Jul 23, 2025
7742baf
fix struct elements as ports without struct as port
mkorbel1 Jul 23, 2025
90d02fd
testing for matched port errors
mkorbel1 Jul 23, 2025
98dae52
various port matches
mkorbel1 Jul 23, 2025
fe8492e
update clones on structs
mkorbel1 Jul 23, 2025
f5672ca
more testing for nets, careful of partials and merging
mkorbel1 Jul 23, 2025
c5e800a
check matched array port sv generated
mkorbel1 Jul 24, 2025
b5267ce
update docs for match APIs
mkorbel1 Jul 24, 2025
119f810
basic interface connection api
mkorbel1 Jul 24, 2025
8bc11b8
use connect api with pair
mkorbel1 Jul 24, 2025
5e01cb7
doc and cleanup
mkorbel1 Jul 24, 2025
687036e
update user guide docs
mkorbel1 Jul 24, 2025
481b18a
update docs, tutorials, examples
mkorbel1 Jul 24, 2025
ec9bc80
Add packed to Logic
mkorbel1 Jul 24, 2025
7b9241e
make net determination on structurs cache
mkorbel1 Jul 24, 2025
2f78810
add doc for internal class
mkorbel1 Jul 24, 2025
a992c4a
some more cleanup
mkorbel1 Jul 24, 2025
67e7ea4
fix documentation, fix clone return type for logicnet
mkorbel1 Jul 24, 2025
0197bbd
improvements after review suggestions
mkorbel1 Jul 24, 2025
e194457
wip cleanup
mkorbel1 Jul 24, 2025
2753088
undo tag to group deprecation
mkorbel1 Jul 25, 2025
12974e0
add named onto packed things
mkorbel1 Jul 25, 2025
229628e
cleanup todo
mkorbel1 Jul 25, 2025
86867af
fix wording in modules doc
mkorbel1 Jul 25, 2025
1eb0e28
clean up interface documentation
mkorbel1 Jul 25, 2025
f481bf4
some more cleanup of docs and stuff
mkorbel1 Jul 25, 2025
fb614d6
refactor names of functions
mkorbel1 Jul 25, 2025
eae52b2
thinking of more things to test
mkorbel1 Jul 26, 2025
f7e245a
handling of consts as typed ports
mkorbel1 Jul 28, 2025
bbbc824
fix typo
mkorbel1 Jul 28, 2025
3a1006e
fix bug with output usage from struct partial assign, move to struct …
mkorbel1 Jul 29, 2025
5d390ca
fix typos and missinc copyrights
mkorbel1 Jul 29, 2025
dbab02e
fix test
mkorbel1 Jul 29, 2025
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 benchmark/many_seq_and_comb_benchmark.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ class _MCUInterface extends Interface<_MCUInterfaceTag> {
Logic get outputData => port('outputData');

final int? memorySizeOverride;

@override
_MCUInterface clone() =>
_MCUInterface(memorySizeOverride: memorySizeOverride);
}

class _MemoryControllerUnit extends Module {
Expand Down
55 changes: 30 additions & 25 deletions doc/tutorials/chapter_8/01_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ The `Logic.port` constructor makes interface port definitions a little cleaner b

When connecting an `Interface` to a `Module`, you should always create a new instance of the `Interface` so you don't modify the one being passed in through the constructor. Modifying the same `Interface` as was passed would have negative consequences if multiple `Modules` were consuming the same `Interface`, and also breaks the rules for `Module` input and output connectivity.

The `connectIO` function under the hood calls `addInput` and `addOutput` directly on the `Module` and connects those `Module` ports to the correct ports on the `Interfaces`. Connection is based on signal names. You can use the `uniquify` Function argument in `connectIO` to uniquify inputs and outputs in case you have multiple instances of the same `Interface` connected to your module. You can also use the `setPort` function to directly set individual ports on the `Interface` instead of via tagged set of ports.
The `connectIO` function under the hood calls `addInput` and `addOutput` directly on the `Module` and connects those `Module` ports to the correct ports on the `Interface`s. Connection is based on signal names. You can use the `uniquify` Function argument in `connectIO` to uniquify inputs and outputs in case you have multiple instances of the same `Interface` connected to your module.

`Module` has functions called `addInterfacePorts` and `addPairInterfacePorts` which conveniently call `connectIO` and `pairConnectIO` and return the "internal" copy of the interface to use within the `Module`. For these to work, all `Interface`s must implement a `clone()` method so that an internal copy can be created.

## Counter Module

Expand Down Expand Up @@ -77,7 +79,7 @@ class Counter extends Module {

## Counter Module Interface

Let us see how we can change the `ROHD` module to `Counter` interface. First, we can create a enum `CounterDirection` that have tags of `inward`, `outward` and `misc`. You can think of this as what is the category you want to group your ports. This category can be reuse between modules. `inward` port group all inputs port, `outward` group all outputs port and `misc` group all miscellanous port such as `clk`.
Let us see how we can change the `ROHD` module to `Counter` interface. First, we can create a enum `CounterDirection` that have tags of `inward`, `outward` and `misc`. You can think of this as what is the category you want to group your ports. This category can be reuse between modules. `inward` port group all inputs port, `outward` group all output ports, and `misc` group all miscellanous ports such as `clk`.

Then, we can create our interface `CounterInterface` that extends from parents `Interface<TagType>`. The `TagType` is the enum that we create earlier. Let create the getters to all ports for `Counter` to allows us to send signals to the interface.

Expand All @@ -97,16 +99,28 @@ class CounterInterface extends Interface<CounterDirection> {

final int width;
CounterInterface({this.width = 8}) {
setPorts([Logic.port('en'), Logic.port('reset')], [CounterDirection.inward]);
setPorts([
Logic.port('en'),
], [
CounterDirection.inward
]);

setPorts([
Logic.port('val', width),
], [
CounterDirection.outward
]);

setPorts([Logic.port('clk')], [CounterDirection.misc]);
setPorts([
Logic.port('clk'),
Logic.port('reset'),
], [
CounterDirection.misc
]);
}

@override
CounterInterface clone() => CounterInterface(width: width);
}
```

Expand All @@ -115,32 +129,23 @@ Next, we want to modify the `Counter` module constructor to receive the interfac
```dart
// create a new interface instance. Let make it a private variable.
late final CounterInterface _intf;
Counter(CounterInterface intf): super('counter') {}
Counter(CounterInterface intf): super(name: 'counter') {}
```

Now, let use the `connectIO()` function. As mentioned [previously](#rohd-interfaces), this function called `addInput` and `addOutput` that help us register the port. Therefore, we can pass the `module`, `interface`, `inputTags`, and `outputTags` as the arguments of the `connectIO` function.
Now, let use the `addInterfacePorts` function. As mentioned [previously](#rohd-interfaces), this function called `addInput` and `addOutput` (via `connectIO`) that help us register the ports. Therefore, we can pass the `module`, `interface`, `inputTags`, and `outputTags` as the arguments of the `addInterfacePorts` function.

```dart
Counter(CounterInterface intf) : super(name: 'counter') {
_intf = CounterInterface(width: intf.width)
..connectIO(this, intf,
inputTags: {CounterDirection.inward, CounterDirection.misc},
outputTags: {CounterDirection.outward});

final nextVal = Logic(name: 'nextVal', width: intf.width);

nextVal <= _intf.val + 1;

Sequential(_intf.clk, [
If.block([
Iff(_intf.reset, [
_intf.val < 0,
]),
ElseIf(_intf.en, [
_intf.val < nextVal,
])
]),
]);
_intf = addInterfacePorts(intf,
inputTags: {CounterDirection.inward, CounterDirection.misc},
outputTags: {CounterDirection.outward});

_intf.val <=
flop(
_intf.clk,
reset: _intf.reset,
(_intf.val + 1).named('nextVal'),
);
}
```

Expand Down
27 changes: 13 additions & 14 deletions doc/tutorials/chapter_8/answers/exercise_1_spi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class SPIInterface extends Interface<SPIDirection> {
SPIDirection.peripheralOutput
]);
}

@override
SPIInterface clone() => SPIInterface();
}

class Controller extends Module {
Expand All @@ -48,13 +51,11 @@ class Controller extends Module {

// define a new interface, and connect it
// to the interface passed in.
intf = SPIInterface()
..connectIO(
this,
intf,
inputTags: {SPIDirection.peripheralOutput}, // Add inputs
outputTags: {SPIDirection.controllerOutput}, // Add outputs
);
intf = addInterfacePorts(
intf,
inputTags: {SPIDirection.peripheralOutput}, // Add inputs
outputTags: {SPIDirection.controllerOutput}, // Add outputs
);

intf.cs <= Const(1);

Expand Down Expand Up @@ -82,13 +83,11 @@ class Peripheral extends Module {
late final SPIInterface shiftRegIntF;

Peripheral(SPIInterface periIntF) : super(name: 'shift_register') {
shiftRegIntF = SPIInterface()
..connectIO(
this,
periIntF,
inputTags: {SPIDirection.controllerOutput},
outputTags: {SPIDirection.peripheralOutput},
);
shiftRegIntF = addInterfacePorts(
periIntF,
inputTags: {SPIDirection.controllerOutput},
outputTags: {SPIDirection.peripheralOutput},
);

const regWidth = 8;
final data = Logic(name: 'data', width: regWidth);
Expand Down
34 changes: 14 additions & 20 deletions doc/tutorials/chapter_8/counter_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class CounterInterface extends Interface<CounterDirection> {
CounterInterface({this.width = 8}) {
setPorts([
Logic.port('en'),
Logic.port('reset'),
], [
CounterDirection.inward
]);
Expand All @@ -27,35 +26,30 @@ class CounterInterface extends Interface<CounterDirection> {

setPorts([
Logic.port('clk'),
Logic.port('reset'),
], [
CounterDirection.misc
]);
}

@override
CounterInterface clone() => CounterInterface(width: width);
}

class Counter extends Module {
late final CounterInterface _intf;

Counter(CounterInterface intf) : super(name: 'counter') {
_intf = CounterInterface(width: intf.width)
..connectIO(this, intf,
inputTags: {CounterDirection.inward, CounterDirection.misc},
outputTags: {CounterDirection.outward});

final nextVal = Logic(name: 'nextVal', width: intf.width);

nextVal <= _intf.val + 1;

Sequential(_intf.clk, [
If.block([
Iff(_intf.reset, [
_intf.val < 0,
]),
ElseIf(_intf.en, [
_intf.val < nextVal,
])
]),
]);
_intf = addInterfacePorts(intf,
inputTags: {CounterDirection.inward, CounterDirection.misc},
outputTags: {CounterDirection.outward});

_intf.val <=
flop(
_intf.clk,
reset: _intf.reset,
(_intf.val + 1).named('nextVal'),
);
}
}

Expand Down
10 changes: 6 additions & 4 deletions doc/tutorials/chapter_9/rohd_vf_example/lib/counter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class MyCounterInterface extends Interface<CounterDirection> {

setPorts([Logic.port('clk')], [CounterDirection.misc]);
}

@override
MyCounterInterface clone() => MyCounterInterface(width: width);
}

/// A simple counter which increments once per [clk] edge whenever
Expand All @@ -35,10 +38,9 @@ class MyCounter extends Module {
late final MyCounterInterface counterintf;

MyCounter(MyCounterInterface intf) : super(name: 'counter') {
counterintf = MyCounterInterface(width: intf.width)
..connectIO(this, intf,
inputTags: {CounterDirection.inward, CounterDirection.misc},
outputTags: {CounterDirection.outward});
counterintf = addInterfacePorts(counterintf,
inputTags: {CounterDirection.inward, CounterDirection.misc},
outputTags: {CounterDirection.outward});

_buildLogic();
}
Expand Down
4 changes: 3 additions & 1 deletion doc/user_guide/_docs/A02-logical_signals.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Logical Signals"
permalink: /docs/logical-signals/
excerpt: "Logic signals"
last_modified_at: 2022-12-21
last_modified_at: 2025-7-24
toc: true
---

Expand All @@ -18,6 +18,8 @@ var x = Logic();
var bus = Logic(name: 'b', width: 8)
```

There are other types like [`LogicArray`](https://intel.github.io/rohd/rohd/LogicArray-class.html)s and [`LogicStructure`](https://intel.github.io/rohd/rohd/LogicStructure-class.html)s which extend from `Logic`, as well.

#### The value of a signal

You can access the current value of a signal using `value`. You cannot access this as part of synthesizable ROHD code. ROHD supports X and Z values and propagation. If the signal is valid (no X or Z in it), you can also convert it to an `int` with `value.toInt()` (ROHD will throw an exception otherwise). If the signal has more bits than a dart `int` (64 bits, usually), you need to use `value.toBigInt()` to get a `BigInt` (again, ROHD will throw an exception otherwise).
Expand Down
5 changes: 4 additions & 1 deletion doc/user_guide/_docs/A04-assignment.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Assignment"
permalink: /docs/assignment/
excerpt: "Assignment"
last_modified_at: 2024-08-02
last_modified_at: 2025-7-24
toc: true
---

Expand All @@ -13,6 +13,9 @@ var a = Logic(), b = Logic();

// assign `a` to always have the same value as `b`
a <= b;

// or, equivalently, you can use the `gets` function, which may be more convenient in some situations
a.gets(b);
```

It is also possible to do a partial assignment to a signal using `assignSubset`.
Expand Down
10 changes: 5 additions & 5 deletions doc/user_guide/_docs/A05-logic-math-compare.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Simple logical, mathematical, and comparison operations"
permalink: /docs/logic-math-compare/
excerpt: "Simple logical, mathematical, and comparison operations"
last_modified_at: 2022-12-06
last_modified_at: 2025-7-24
toc: true
---

Expand All @@ -26,9 +26,9 @@ a_eq_b <= a.eq(b) // equality NOTE: == is for Object equality
a_neq_b <= a.neq(b) // inequality NOTE: != is for Object inequality of Logic's
a_lt_b <= a.lt(b) // less than NOTE: < is for conditional assignment
a_lte_b <= a.lte(b) // less than or equal NOTE: <= is for assignment
a_gt_b <= (a > b) // greater than NOTE: careful with order of operations, > needs parentheses in this case
// Note: a_gt_b <= a.gt(b) is also supported for greater than.
a_gte_b <= (a >= b) // greater than or equal NOTE: careful with order of operations, >= needs parentheses in this case
// Note: a_gte_b <= a.gte(b) is also supported for greater than or equal.
a_gt_b <= a.gt(b) // greater than
a_gt_b <= (a > b) // greater than (alt) NOTE: careful with order of operations, > needs parentheses in this case
a_gte_b <= a.gte(b) // greater than or equal
a_gte_b <= (a >= b) // greater than or equal (alt) NOTE: careful with order of operations, >= needs parentheses in this case
answer <= mux(selectA, a, b) // answer = selectA ? a : b
```
Loading