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
6 changes: 6 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04",

"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "24"
}
},

"updateContentCommand": "tool/gh_codespaces/run_setup.sh",

"customizations": {
Expand Down
20 changes: 20 additions & 0 deletions doc/user_guide/_docs/A19-logic-structures.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,26 @@ rvStruct.elements[0] <= ready;
rvStruct.elements[1] <= valid;
```

## Promoting nested fields

Use `flattenOuter` to promote fields from direct child structures into a new generic `LogicStructure`. The new fields are clones connected to their original sources, so the original structure remains unchanged. By default, promoted names are prefixed with the direct child structure name to avoid collisions.

```dart
final config = LogicStructure([
Logic(name: 'mode', width: 2),
Logic(name: 'valid'),
], name: 'config');
final control = LogicStructure([
Logic(name: 'enable'),
config,
], name: 'control');

final flattened = control.flattenOuter();
// Field names: enable, config_mode, config_valid.
```

Only direct non-array child structures are promoted. Nested grandchildren remain structures, and a duplicate resulting field name throws `LogicConstructionException`.

## Making your own structure

Referencing elements by index is often not ideal for named signals. We can do better by building our own structure that inherits from `LogicStructure`.
Expand Down
48 changes: 47 additions & 1 deletion doc/user_guide/_docs/A20-logic-arrays.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Logic Arrays"
permalink: /docs/logic-arrays/
last_modified_at: 2022-6-5
last_modified_at: 2026-7-21
toc: true
---

Expand All @@ -22,6 +22,50 @@ LogicArray([5, 5, 5], 128);

As long as the total width of a `LogicArray` and another type of `Logic` (including `Logic`, `LogicStructure`, and another `LogicArray`) are the same, assignments and bitwise operations will work in per-element order. This means you can assign two `LogicArray`s of different dimensions to each other as long as the total width matches.

## Typed and value-domain arrays

Use `LogicArrayOf<T>` when every leaf has the same specialized `Logic` type. It preserves the normal array dimensions while exposing typed leaves with `typedLeafElements` and `elementAt`. `LogicArray` is `LogicArrayOf<Logic>`, so it retains its existing construction, port, clone, naming, and array APIs while also identifying its leaves as `Logic`. For example, this creates a two-dimensional array of samples with separate data and valid fields:

```dart
class Sample extends LogicStructure {
final Logic data;
final Logic valid;

factory Sample({String? name}) => Sample._(
Logic(name: 'data', width: 8),
Logic(name: 'valid'),
name: name ?? 'sample',
);

Sample._(this.data, this.valid, {required String name})
: super([data, valid], name: name);

@override
Sample clone({String? name}) => Sample(name: name ?? this.name);
}

final samples = LogicArrayOf<Sample>(
[2, 3],
Sample.new,
dimensionNames: ['row_', 'column_'],
);

final bottomRightData = samples.elementAt([1, 2]).data;
```

When typed array leaves are themselves arrays, use `flattenNestedDimensions<U>()` to create one rectangular `LogicArrayOf<U>` with all nested dimensions concatenated. The full address is preserved: `nested.elementAt(outerIndex).elementAt(innerIndex)` maps to `flattened.elementAt([...outerIndex, ...innerIndex])`. Every sibling nested array must have matching dimensions and leaf width.

Use `LogicValueArray` for fixed-width array data outside the hardware graph. It keeps values in row-major order and supports indexing, reshaping, transposition, and slice operations. `LogicValueArrayOf` adds a codec so application-level values can use the same operations while converting to and from packed `LogicValue`s.

```dart
final values = LogicValueArray.fromInts([2, 3], 8, [1, 2, 3, 4, 5, 6]);
final transposed = values.transpose2D(); // Dimensions: [3, 2]

final signals = values.toLogicArray(name: 'values');
```

`LogicValueArray.putInto` drives a compatible `LogicArray` or `LogicArrayOf`, while `LogicArrayOf.logicValues` captures its current packed values. Use `LogicArrayOf.valueArrayOf` and `putValueArrayOf` when a `LogicValueCodec` converts typed value-domain data at the hardware boundary.

## Unpacked arrays

In SystemVerilog, there is a concept of "packed" vs. "unpacked" arrays which have different use cases and capabilities. In ROHD, all arrays act the same and you get the best of both worlds. You can indicate when constructing a `LogicArray` that some number of the dimensions should be "unpacked" as a hint to `Synthesizer`s. Marking an array with a non-zero `numUnpackedDimensions`, for example, will make that many of the dimensions "unpacked" in generated SystemVerilog signal declarations.
Expand All @@ -43,6 +87,8 @@ You can declare ports of `Module`s as being arrays (including with some dimensio

Array ports in generated SystemVerilog will match dimensions (including unpacked) as specified when the port is created.

Use `addTypedInput` and `addTypedOutput` for `LogicArrayOf` ports. These methods preserve the array's specialized leaf type, allowing the module to access fields such as `samples.elementAt([1, 2]).data` directly.

## Elements of arrays

To iterate through or access elements of a `LogicArray` (or bits of a simple `Logic`), use [`elements`](https://intel.github.io/rohd/rohd/Logic/elements.html). Using the normal `[n]` accessors will return the `n`th bit regardless for `LogicArray` and `Logic` to maintain API consistency.
Expand Down
Loading
Loading