Extrema constructor

Extrema(
  1. List<Logic> signals, {
  2. bool max = true,
})

Finds an extrema of List<Logic> signals. Inputs need not be the same width, and will all be considered positive unsigned numbers.

If max is true, will find maximum value, else will find minimum.

Outputs the index and val of the extrema in the list of signals.

Implementation

Extrema(List<Logic> signals, {bool max = true}) {
  // List to consume inputs internally.
  final logics = <Logic>[];

  // Adds input for every element in the signals list, to logics.
  for (var i = 0; i < signals.length; i++) {
    logics.add(addInput('signal$i', signals[i], width: signals[i].width));
  }

  // Check if list is empty
  if (logics.isEmpty) {
    throw RohdHclException('List cannot be empty.');
  }

  // Find the max width of all inputs.
  var maxWidth = 0;
  for (var i = 0; i < logics.length; i++) {
    if (logics[i].width > maxWidth) {
      maxWidth = logics[i].width;
    }
  }

  // Check max width and prepend with 0s. Will make all inputs same width.
  for (var i = 0; i < logics.length; i++) {
    if (logics[i].width < maxWidth) {
      logics[i] = logics[i].zeroExtend(maxWidth);
    }
  }

  // Find indexWidth, initialize extremaIndex and extremaVal.
  final indexWidth = log2Ceil(logics.length);
  Logic extremaIndex = Const(0, width: indexWidth);
  var extremaVal = logics[0];

  // If max is true, find max value. Else, find min value.
  for (var i = 1; i < logics.length; i++) {
    final compareVal =
        max ? logics[i].gt(extremaVal) : logics[i].lt(extremaVal);
    extremaVal = Logic(name: 'muxOut$i', width: maxWidth)
      ..gets(mux(compareVal, logics[i], extremaVal));
    extremaIndex = mux(compareVal, Const(i, width: indexWidth), extremaIndex);
  }

  // Generate outputs here.
  addOutput('index', width: extremaIndex.width);
  index <= extremaIndex;

  addOutput('val', width: extremaVal.width);
  val <= extremaVal;
}