Repository: intel/rohd (dart)

Issue:
Add documentation for `selectIndex` and `selectFrom` in the user guide
### Motivation

These are useful utilities and it's not easy enough to discover them.

### Desired solution

Perhaps in the `logic-arrays` part of the user guide, add some discussion of them.  They are also useful for non-arrays, so its worth some consideration on the best location.

### Alternatives considered

_No response_

### Additional details

_No response_

Pull request:
Description and Motivation
Adding documentation in user guide doc/user_guide/_docs/A20-logic-arrays.md on selectFrom and selectIndex usage and how to use them.
 
Related issue
[#520](https://github.com/intel/rohd/issues/520)
 
Testing 
No
 
Backwards compatibility
No
 
Documentation
Update doc/user_guide/_docs/A20-logic-arrays.md and provided example code example/logic_array.dart and example/mux.dart

Patch:
diff --git a/doc/user_guide/_docs/A20-logic-arrays.md b/doc/user_guide/_docs/A20-logic-arrays.md
index 67632d0f2..3ce96c16e 100644
--- a/doc/user_guide/_docs/A20-logic-arrays.md
+++ b/doc/user_guide/_docs/A20-logic-arrays.md
@@ -46,3 +46,34 @@ Array ports in generated SystemVerilog will match dimensions (including unpacked
 ## 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.
+
+## Index-based Selection in an Array
+
+The [`selectIndex`](https://intel.github.io/rohd/rohd/IndexedLogic/selectIndex.html) and [`selectFrom`](https://intel.github.io/rohd/rohd/Logic/selectFrom.html) methods are used to select a value from a `LogicArray` or from a list of `Logic` elements based on an index. These methods are useful for creating dynamic selection logic in hardware design. They can be used in 2 ways as shown below.
+
+### 1. Using a `LogicArray` type
+
+```dart
+final arrayA = LogicArray([4], 8, name: 'arrayA'); // A 1D array with four 8-bit element
+final id = Logic(name: 'id', width: 3);
+
+selectIndexValueArrayA <= arrayA.elements.selectIndex(id, defaultValue: defaultValue);
+selectFromValueArrayA <= id.selectFrom(arrayA.elements, defaultValue: defaultValue);
+```
+
+An example code is given to demonstrate a usage of selectIndex and selectFrom for logic arrays.
+Please see code here: [logic_array.dart](https://github.com/intel/rohd/blob/main/example)
+
+### 2. Using a list of `Logic` elements
+
+```dart
+final inputA = Logic(name: 'inputA', width: 8);
+final inputB = Logic(name: 'inputB', width: 8);
+final inputC = Logic(name: 'inputC', width: 8);
+final listA = <Logic>[inputA, inputB, inputC];
+
+final id = Logic(name: 'id', width: 3);
+
+selectIndexValueListA <= listA.selectIndex(id, defaultValue: defaultValue);
+selectFromValueListA <= id.selectFrom(listA, defaultValue: defaultValue);
+```
diff --git a/example/logic_array.dart b/example/logic_array.dart
new file mode 100644
index 000000000..bd5d8d6a3
--- /dev/null
+++ b/example/logic_array.dart
@@ -0,0 +1,117 @@
+// Copyright (C) 2025 Intel Corporation
+// SPDX-License-Identifier: BSD-3-Clause
+//
+// logic_array.dart
+// A very basic example of a Logic Array module
+// to show case the selectIndex and selectFrom
+//
+// 2025 March 04
+// Author: Ramli, Nurul Izziany <nurul.izziany.ramli@intel.com>
+
+// Though we usually avoid them, for this example,
+// allow `print` messages (disable lint):
+// ignore_for_file: avoid_print
+
+// Import necessary dart pacakges for this file.
+import 'dart:async';
+
+// Import the ROHD package.
+import 'package:rohd/rohd.dart';
+
+class LogicArrayExample extends Module {
+  Logic get index => input('index');
+  Logic get selectIndexValue => output('selectIndexValue');
+  Logic get selectFromValue => output('selectFromValue');
+
+  LogicArrayExample(LogicArray arrayA, Logic index, Logic selectIndexValue,
+      Logic selectFromValue)
+      : super(name: 'logic_array_example') {
+    //
+    arrayA = addInputArray('arrayA', arrayA,
+        dimensions: arrayA.dimensions, elementWidth: arrayA.elementWidth);
+    index = addInput('index', index, width: index.width);
+    selectIndexValue =
+        addOutput('selectIndexValue', width: arrayA.elementWidth);
+    selectFromValue = addOutput('selectFromValue', width: arrayA.elementWidth);
+
+    final defaultValue = Const(0, width: arrayA.elementWidth);
+
+    // Use selectIndex or selectFrom to select a value from an array
+    selectIndexValue <=
+        arrayA.elements.selectIndex(index, defaultValue: defaultValue);
+    selectFromValue <=
+        index.selectFrom(arrayA.elements, defaultValue: defaultValue);
+  }
+}
+
+Future<void> main({bool noPrint = false}) async {
+  // Define local signals
+  final arrayA =
+      LogicArray([4], 8, name: 'arrayA'); // A 1D array with 4 8-bit elements
+  final id = Logic(name: 'id', width: 3);
+  final selectIndexValue = Logic(name: 'selectIndexValue', width: 8);
+  final selectFromValue = Logic(name: 'selectFromValue', width: 8);
+
+  final logicArrayExample =
+      LogicArrayExample(arrayA, id, selectIndexValue, selectFromValue);
+
+  // Build the module
+  await logicArrayExample.build();
+
+  final systemVerilogCode = logicArrayExample.generateSynth();
+  if (!noPrint) {
+    print(systemVerilogCode);
+  }
+
+  // Simulate the module
+  if (!noPrint) {
+    WaveDumper(logicArrayExample);
+  }
+
+  // Set the input values
+  arrayA.elements[0].inject(1);
+  arrayA.elements[1].inject(2);
+  arrayA.elements[2].inject(3);
+  arrayA.elements[3].inject(4);
+
+  // Print a message when the id and the outputs value changes
+  if (!noPrint) {
+    logicArrayExample.index.changed
+        .listen((e) => print('@${Simulator.time}: ID Value changed: $e'));
+    logicArrayExample.selectIndexValue.changed.listen(
+        (e) => print('@${Simulator.time}: SelectIndex Value changed: $e'));
+    logicArrayExample.selectFromValue.changed.listen(
+        (e) => print('@${Simulator.time}: SelectFrom Value changed: $e'));
+  }
+
+  // Set the index value to 0, 1, 2, 3 over time
+  Simulator.registerAction(27, () => id.put(0));
+  Simulator.registerAction(37, () => id.put(1));
+  Simulator.registerAction(47, () => id.put(2));
+  Simulator.registerAction(57, () => id.put(3));
+  Simulator.registerAction(67, () => id.put(4));
+
+  // Set a maximum time for the simulation so it doesn't keep running forever.
+  Simulator.setMaxSimTime(100);
+
+  // Print a message when we're done with the simulation, too!
+  Simulator.registerAction(100, () {
+    if (!noPrint) {
+      print('Simulation completed!');
+    }
+  });
+
+  // Kick off the simulator (but don't await it)!
+  if (!noPrint) {
+    print('Starting simulation...');
+  }
+  unawaited(Simulator.run());
+
+  await Simulator.simulationEnded;
+
+  // 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`).');
+  }
+}


Test patch:
diff --git a/test/example_test.dart b/test/example_test.dart
index b34d251fc..efe562cc9 100644
--- a/test/example_test.dart
+++ b/test/example_test.dart
@@ -12,6 +12,7 @@ import 'package:test/test.dart';
 
 import '../example/example.dart' as counter;
 import '../example/fir_filter.dart' as fir_filter;
+import '../example/logic_array.dart' as logic_array;
 import '../example/oven_fsm.dart' as fsm;
 import '../example/tree.dart' as tree;
 
@@ -35,4 +36,8 @@ void main() {
   test('fsm example', () async {
     await fsm.main(noPrint: true);
   });
+
+  test('logic array example', () async {
+    await logic_array.main(noPrint: true);
+  });
 }