RecursiveModulePriorityEncoderNode constructor

RecursiveModulePriorityEncoderNode(
  1. Logic seq, {
  2. String name = 'priority_encode_node',
  3. int depth = 0,
  4. bool reserveName = false,
  5. bool reserveDefinitionName = false,
  6. String? definitionName,
})

Construct the Node for a Recursive Priority Tree.

Implementation

RecursiveModulePriorityEncoderNode(
  Logic seq, {
  super.name = 'priority_encode_node',
  int depth = 0,
  super.reserveName,
  super.reserveDefinitionName,
  String? definitionName,
}) : super(
          definitionName:
              definitionName ?? 'PriorityEncodeNode_W${seq.width}') {
  seq = addInput('seq', seq, width: seq.width);
  if (seq.width == 1) {
    addOutput('ret') <= ~seq[0];
  } else if (seq.width == 2) {
    final l = seq[0].named('leftLeafLead');
    final r = seq[1].named('rightLeafLead');
    addOutput('ret', width: 2);
    Combinational([
      If.block([
        Iff(l, [
          ret < Const(0, width: 2),
        ]),
        ElseIf(r, [
          ret < [Const(0), Const(1)].swizzle(),
        ]),
        Else([
          ret < [Const(1), Const(0)].swizzle(),
        ]),
      ]),
    ]);
  } else {
    final divisor = (log(seq.width - 1) / log(2)).floor();
    final split = pow(2.0, divisor).toInt();

    final left = RecursiveModulePriorityEncoderNode(seq.getRange(0, split),
            name: 'left', depth: depth + 1)
        .ret;
    var right = RecursiveModulePriorityEncoderNode(
            seq.getRange(split, seq.width),
            name: 'right',
            depth: depth + 1)
        .ret;
    if (right.width < left.width) {
      right = right.zeroExtend(left.width);
    }
    final l = left[-1].named('leftLead');
    final r = right[-1].named('rightLead');
    addOutput('ret', width: right.width + 1);
    final rhs = ((right.width > 1)
            ? [Const(0), Const(1), right.slice(-2, 0)]
                .swizzle()
                .named('zo_right')
            : [Const(0), Const(1)].swizzle().named('zo'))
        .named('rhs');
    Combinational([
      If.block([
        Iff(l & r, [
          ret <
              [Const(1), Const(0, width: right.width)].swizzle().named('lr'),
        ]),
        ElseIf(~l, [
          ret < [Const(0), left.slice(-1, 0)].swizzle().named('zl'),
        ]),
        Else([
          ret < rhs,
        ]),
      ]),
    ]);
  }
}