getRange method
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;
// 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
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();
}