connectInterfaces function

void connectInterfaces(
  1. InterfaceReference<PairInterface> intf1,
  2. InterfaceReference<PairInterface> intf2, {
  3. String? intf1PathNewName,
  4. String? intf2PathNewName,
  5. bool allowIntf1PathUniquification = true,
  6. bool allowIntf2PathUniquification = true,
  7. Set<String> exceptPorts = const {},
})

Connects intf1 to intf2, creating all necessary ports through the hierarchy.

If intf1PathNewName or intf2PathNewName are provided, then it will prefer to name new interfaces with those names. If allowIntf1PathUniquification or allowIntf2PathUniquification are false, then the interface names will not be uniquified on those paths. Uniquification also respects BridgeModule.allowUniquification at each level. The exceptPorts parameter is an optional set of strings representing the logical port names to be excluded.

Implementation

void connectInterfaces(
  InterfaceReference intf1,
  InterfaceReference intf2, {
  String? intf1PathNewName,
  String? intf2PathNewName,
  bool allowIntf1PathUniquification = true,
  bool allowIntf2PathUniquification = true,
  Set<String> exceptPorts = const {},
  // TODO(mkorbel): finish these,
  //  possibly wont be needed for connectInterfaces
  //  String Function(String logical, String? physical)? portUniquify1,
  //  String Function(String logical, String? physical)? portUniquify2,
}) {
  if (intf1.module.hasBuilt || intf2.module.hasBuilt) {
    throw RohdBridgeException('Cannot connect interfaces after build.');
  }

  final intf1Instance = intf1.module;
  final intf2Instance = intf2.module;

  if (intf1.role != intf2.role) {
    // up and down case
    final commonParent = findCommonParent(intf1Instance, intf2Instance);

    if (commonParent == intf1Instance || commonParent == intf2Instance) {
      throw RohdBridgeException(
          'Vertical connections should have the same role, but the common'
          ' parent of $intf1Instance and $intf2Instance is $commonParent,'
          ' but with mismatched roles ${intf1.role} and ${intf2.role},'
          ' respectively.');
    }

    if (commonParent == null) {
      throw RohdBridgeException('No common parent found between'
          ' $intf1Instance and $intf2Instance');
    }
    final unusedPortsOnDriver = intf1.getUnmappedInterfacePorts();
    final unusedPortOnReceiver = intf2.getUnmappedInterfacePorts();
    if (exceptPorts.isNotEmpty) {
      unusedPortsOnDriver.removeWhere(exceptPorts.contains);
      unusedPortOnReceiver.removeWhere(exceptPorts.contains);
    }

    if (unusedPortsOnDriver.isNotEmpty || unusedPortOnReceiver.isNotEmpty) {
      var errorString = 'Cannot connect interface ${intf1.name} '
          'at ${intf1Instance.name} to interface '
          '${intf2.name} at ${intf2Instance.name} '
          'because there are unmapped ports';
      if (unusedPortsOnDriver.isNotEmpty) {
        errorString += ' : $unusedPortsOnDriver on driver';
      }
      if (unusedPortOnReceiver.isNotEmpty) {
        errorString += ' : $unusedPortOnReceiver on receiver';
      }
      throw RohdBridgeException(errorString);
    }
    final intf1Top =
        (commonParent.getHierarchyDownTo(intf1Instance)![1] as BridgeModule)
            .pullUpInterface(
      intf1,
      newIntfName: intf1PathNewName,
      allowIntfUniquification: allowIntf1PathUniquification,
      exceptPorts: exceptPorts,
    );
    final intf2Top =
        (commonParent.getHierarchyDownTo(intf2Instance)![1] as BridgeModule)
            .pullUpInterface(
      intf2,
      newIntfName: intf2PathNewName,
      allowIntfUniquification: allowIntf2PathUniquification,
      exceptPorts: exceptPorts,
    );

    intf1Top.connectTo(intf2Top, exceptPorts: exceptPorts);
  } else if (intf1.role == intf2.role) {
    final intf1ToIntf2Path = intf1Instance.getHierarchyDownTo(intf2Instance);
    final intf2ToIntf1Path = intf2Instance.getHierarchyDownTo(intf1Instance);

    final intf1ContainsIntf2 = intf1ToIntf2Path != null;
    final intf2ContainsIntf1 = intf2ToIntf1Path != null;

    if (intf1ContainsIntf2) {
      intf1.module._pullUpInterfaceAndConnect(
        intf2,
        newIntfName: intf2PathNewName,
        allowIntfUniquification: allowIntf2PathUniquification,
        topToConnect: intf1,
        exceptPorts: exceptPorts,
      );
    } else if (intf2ContainsIntf1) {
      intf2.module._pullUpInterfaceAndConnect(
        intf1,
        newIntfName: intf1PathNewName,
        allowIntfUniquification: allowIntf1PathUniquification,
        topToConnect: intf2,
        exceptPorts: exceptPorts,
      );
    } else {
      // e.g. feed-through
      throw RohdBridgeException(
          'Unhandled directionality and hierarchy of driver and receiver.');
    }
  } else {
    throw RohdBridgeException(
        'Unknown directionality and hierarchy of driver and receiver.');
  }
}