Repository: intel/rohd
Pull request #499 (2024-08-02 17:01:48)

Fix bug in `LogicStructure.getRange` calculations
<!-- Please make sure you check out the contribution guidelines before submitting a pull request! -->

## Description & Motivation

The logic which calculated which elements should exist within a call to `slice` or `getRange` in `LogicStructure` generated inaccurate results in some scenarios.  This PR fixes the bug and adds more tests around it.

## Related Issue(s)

N/A

## Testing

Added new tests for corner cases, plus existing tests cover a lot of the existing cases

## Backwards-compatibility

> Is this a breaking change that will not be backwards-compatible? If yes, how so?

No

## Documentation

> Does the change require any updates to documentation? If so, where? Are they included?

No



Patch:
diff --git a/lib/src/signals/logic_structure.dart b/lib/src/signals/logic_structure.dart
index 6e72dcac..6fac9d61 100644
--- a/lib/src/signals/logic_structure.dart
+++ b/lib/src/signals/logic_structure.dart
@@ -179,10 +179,17 @@ class LogicStructure implements Logic {
       final elementStart = index;
       final elementEnd = index + element.width;
 
-      final elementInRange = ((elementStart >= modifiedStartIndex) &&
-              (elementStart < modifiedEndIndex)) ||
-          ((elementEnd > modifiedStartIndex) &&
-              (elementEnd <= modifiedEndIndex));
+      // if the element is even partially within the range, then include it
+      // OR, if it is wholly contained within the range, include it
+      final elementInRange =
+          // end is within the element
+          (modifiedEndIndex > elementStart && modifiedEndIndex < elementEnd) ||
+              // start is within the element
+              (modifiedStartIndex >= elementStart &&
+                  modifiedStartIndex < elementEnd) ||
+              //element is fully contained
+              (modifiedEndIndex >= elementEnd &&
+                  modifiedStartIndex <= elementStart);
 
       if (elementInRange) {
         // figure out the subset of `element` that needs to be included


Test patch:
diff --git a/test/logic_array_test.dart b/test/logic_array_test.dart
index 96ee7703..9d2689c6 100644
--- a/test/logic_array_test.dart
+++ b/test/logic_array_test.dart
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 Intel Corporation
+// Copyright (C) 2023-2024 Intel Corporation
 // SPDX-License-Identifier: BSD-3-Clause
 //
 // logic_array_test.dart
@@ -579,6 +579,70 @@ void main() {
     });
   });
 
+  group('access logicarray', () {
+    test('slice one bit of 1d array', () async {
+      final la = LogicArray([3], 8);
+      final slice = la.slice(9, 9);
+      expect(slice.width, 1);
+      la.elements[1].put(bin('00000010'));
+      expect(slice.value.toInt(), 1);
+    });
+
+    test('slice 2 bits of one element of 1d array', () async {
+      final la = LogicArray([3], 8);
+      final slice = la.slice(10, 9);
+      expect(slice.width, 2);
+      la.elements[1].put(bin('00000110'));
+      expect(slice.value.toInt(), bin('11'));
+    });
+
+    test('slice 2 bits spanning two elements of 1d array', () async {
+      final la = LogicArray([3], 8);
+      final slice = la.slice(8, 7);
+      expect(slice.width, 2);
+      la.elements[1].put(1, fill: true);
+      la.elements[0].put(0, fill: true);
+      expect(slice.value.toInt(), bin('10'));
+    });
+
+    test('slice 2 bits spanning 2 arrays of 2d array', () async {
+      final la = LogicArray([3, 2], 8);
+      final slice = la.slice(16, 15);
+      expect(slice.width, 2);
+      la.elements[1].elements[0].put(1, fill: true);
+      la.elements[0].elements[1].put(0, fill: true);
+      expect(slice.value.toInt(), bin('10'));
+    });
+
+    test('slice more than one element of array', () async {
+      final la = LogicArray([3], 8);
+      final slice = la.slice(19, 4);
+      expect(slice.width, 16);
+      la.elements[2].put(LogicValue.x);
+      la.elements[1].put(0);
+      la.elements[0].put(1, fill: true);
+      expect(slice.value, LogicValue.of('xxxx000000001111'));
+    });
+
+    test('slice more than one element of array at the edges', () async {
+      final la = LogicArray([3], 8);
+      final slice = la.slice(16, 7);
+      expect(slice.width, 10);
+      la.elements[2].put(LogicValue.x);
+      la.elements[1].put(0);
+      la.elements[0].put(1, fill: true);
+      expect(slice.value, LogicValue.of('x000000001'));
+    });
+
+    test('slice exactly one element of array', () async {
+      final la = LogicArray([3], 8);
+      final slice = la.slice(15, 8);
+      expect(slice.width, 8);
+      la.elements[1].put(1, fill: true);
+      expect(slice.value, LogicValue.of('11111111'));
+    });
+  });
+
   group('logicarray passthrough', () {
     Future<void> testArrayPassthrough(SimpleLAPassthrough mod,
         {bool checkNoSwizzle = true,