BusSubset constructor
Constructs a Module that accesses a subset from bus which ranges
from startIndex to endIndex (inclusive of both).
When, bus has a width of '1', startIndex and endIndex are ignored
in the generated SystemVerilog.
Implementation
BusSubset(Logic bus, this.startIndex, this.endIndex,
{super.name = 'bussubset'})
: _isNet = bus.isNet {
// If a converted index value is still -ve then it's an Index out of bounds
// on a Logic Bus
if (startIndex < 0 || endIndex < 0) {
throw Exception(
'Start ($startIndex) and End ($endIndex) must be greater than or '
'equal to 0.');
}
// If the +ve indices are more than Logic bus width, Index out of bounds
if (endIndex > bus.width - 1 || startIndex > bus.width - 1) {
throw Exception(
'Index out of bounds, indices $startIndex and $endIndex must be less'
' than ${bus.width}');
}
_originalName = Naming.unpreferredName('original_${bus.name}');
_subsetName =
Naming.unpreferredName('subset_${endIndex}_${startIndex}_${bus.name}');
final newWidth = (endIndex - startIndex).abs() + 1;
if (_isNet) {
original = addInOut(_originalName, bus, width: bus.width);
subset =
LogicNet(width: newWidth, name: _subsetName, naming: Naming.unnamed);
final internalSubset = addInOut(_subsetName, subset, width: newWidth);
if (startIndex > endIndex) {
// reverse case
for (var i = 0; i < newWidth; i++) {
internalSubset.quietlyMergeSubsetTo(
original[startIndex - i] as LogicNet,
start: endIndex + i,
);
}
} else {
// normal case
(original as LogicNet).quietlyMergeSubsetTo(
internalSubset,
start: startIndex,
);
}
} else {
original = addInput(_originalName, bus, width: bus.width);
subset = addOutput(_subsetName, width: newWidth);
// so that people can't do a slice assign, not (yet?) implemented
subset.makeUnassignable(
reason:
'The output of a (non-LogicNet) BusSubset ($this) is read-only.');
_setup();
}
}