docs: def mergeSplitsOnInterfaces(root: LNode):
      """
      collect all split/concatenation nodes and group them by target interface
      """
      for ch in root.children:
          if ch.children:
              mergeSplitsOnInterfaces(ch)
  
      ctx = MergeSplitsOnInterfacesCtx()
      for ch in root.children:
          srcPorts = None
          try:
              if ch.name == "CONCAT":
                  p = single(ch.east, lambda x: True)
                  e = single(p.outgoingEdges, lambda x: True)
                  srcPorts = e.dsts
              elif ch.name == "SLICE":
                  p = single(ch.west, lambda x: True)
                  e = single(p.incomingEdges, lambda x: True)
                  srcPorts = e.srcs
          except (DuplicitValueExc, NoValueExc):
              continue
  
          if srcPorts is not None:
              for srcPort in srcPorts:
                  if isinstance(srcPort.parent, LPort):
                      # only for non primitive ports
                      rootPort = getRootIntfPort(srcPort)
                      ctx.register(rootPort, ch, e)
  
      # join them if it is possible
      for srcPort, splitsAndConcats in ctx.iterPortSplits():
          if len(splitsAndConcats) <= 1:
              continue
  
          name = "SPLIT" if srcPort.direction == PortType.OUTPUT else "CONCAT"
          newSplitNode = root.addNode(name)
          copyPort(srcPort, newSplitNode, True, "")
          n = splitsAndConcats[0][0]
          for i in range(max(len(n.west),
                             len(n.east))):
              copyPort(
                  srcPort, newSplitNode,
                  False, "[%d]" % i)
  
          reconnectPorts(root, srcPort, splitsAndConcats,
                         newSplitNode)