getRange method

  1. @override
Logic getRange(
  1. int startIndex,
  2. [int? endIndex]
)
override

Returns a subset Logic. It is inclusive of startIndex, exclusive of endIndex.

The startIndex must come before the endIndex. If startIndex and endIndex are equal, then a zero-width signal is returned. Negative/Positive index values are allowed. (The negative indexing starts from where the array ends)

If endIndex is not provided, width of the Logic will be used as the default values which assign it to the last index.

Logic nextVal = addOutput('nextVal', width: width);
// Example: val = 0xce, val.width = 8, bin(0xce) = "0b11001110"
// Negative getRange
nextVal <= val.getRange(-3, val.width); // = val.getRange(5,8) & output: 0b110, where the output.width=3

// Positive getRange
nextVal <= val.getRange(0, 6); // = val.slice(0, -2) & output: 0b001110, where the output.width=6

// Get range from startIndex
nextVal <= val.getRange(-3); // the endIndex will be auto assign to val.width

Implementation

@override
Logic getRange(int startIndex, [int? endIndex]) {
  endIndex ??= width;

  final modifiedStartIndex =
      IndexUtilities.wrapIndex(startIndex, width, allowWidth: true);
  final modifiedEndIndex =
      IndexUtilities.wrapIndex(endIndex, width, allowWidth: true);

  IndexUtilities.validateRange(modifiedStartIndex, modifiedEndIndex);

  // grab all elements that fall in this range, keeping track of the offset
  final matchingElements = <Logic>[];

  final requestedWidth = modifiedEndIndex - modifiedStartIndex;

  var index = 0;
  for (final element in leafElements) {
    // if the *start* or *end* of `element` is within [startIndex, endIndex],
    // then we have to include it in `matchingElements`
    final elementStart = index;
    final elementEnd = index + element.width;

    final elementInRange = ((elementStart >= modifiedStartIndex) &&
            (elementStart < modifiedEndIndex)) ||
        ((elementEnd > modifiedStartIndex) &&
            (elementEnd <= modifiedEndIndex));

    if (elementInRange) {
      // figure out the subset of `element` that needs to be included
      final elementStartGrab = max(elementStart, modifiedStartIndex) - index;
      final elementEndGrab = min(elementEnd, modifiedEndIndex) - index;

      matchingElements
          .add(element.getRange(elementStartGrab, elementEndGrab));
    }

    index += element.width;
  }

  assert(!(matchingElements.isEmpty && requestedWidth != 0),
      'If the requested width is not 0, expect to get some matches.');

  return matchingElements.rswizzle();
}