processSsa method

  1. @override
Map<Logic, Logic> processSsa(
  1. Map<Logic, Logic> currentMappings, {
  2. required int context,
})
override

Given existing currentMappings, connects drivers and receivers accordingly to SsaLogics and returns an updated set of mappings.

This function may add new Conditionals to existing Conditionals.

This is used for Combinational.ssa.

Implementation

@override
Map<Logic, Logic> processSsa(Map<Logic, Logic> currentMappings,
    {required int context}) {
  // add an empty else if there isn't already one, since we need it for phi
  if (iffs.last is! Else) {
    iffs.add(Else([]));
  }

  // first connect direct drivers into the if statements
  for (final iff in iffs) {
    Conditional.connectSsaDriverFromMappings(iff.condition, currentMappings,
        context: context);
  }

  // calculate mappings locally within each if statement
  final phiMappings = <Logic, Logic>{};
  for (final conditionals in iffs.map((e) => e.then)) {
    var localMappings = {...currentMappings};

    for (final conditional in conditionals) {
      localMappings = conditional.processSsa(localMappings, context: context);
    }

    for (final localMapping in localMappings.entries) {
      if (!phiMappings.containsKey(localMapping.key)) {
        phiMappings[localMapping.key] = Logic(
          name: '${localMapping.key.name}_phi',
          width: localMapping.key.width,
          naming: Naming.mergeable,
        );
      }

      conditionals.add(phiMappings[localMapping.key]! < localMapping.value);
    }
  }

  final newMappings = <Logic, Logic>{...currentMappings}..addAll(phiMappings);

  // find all the SSA signals that are driven by anything in this if block,
  // since we need to ensure every case drives them or else we may create
  // an inferred latch
  final signalsNeedingInit = iffs
      .map((e) => e.then)
      .flattened
      .map((e) => e.calculateReceivers())
      .flattened
      .whereType<SsaLogic>()
      .toSet();
  for (final iff in iffs) {
    final alreadyDrivenSsaSignals = iff.then
        .map((e) => e.calculateReceivers())
        .flattened
        .whereType<SsaLogic>()
        .toSet();

    for (final signalNeedingInit in signalsNeedingInit) {
      if (!alreadyDrivenSsaSignals.contains(signalNeedingInit)) {
        iff.then.add(signalNeedingInit < 0);
      }
    }
  }

  return newMappings;
}