Search in sources :

Example 1 with SelfHyperLoop

use of org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop in project elk by eclipse.

the class RoutingDirector method determineLoopRoutes.

/**
 * Sets the leftmost and rightmost ports of each {@link SelfHyperLoop} in the given {@link SelfLoopHolder}.
 */
public void determineLoopRoutes(final SelfLoopHolder slHolder) {
    // Start by giving IDs to all ports according to their order in the port list
    assignPortIds(slHolder.getLNode().getPorts());
    sortHyperLoopPortLists(slHolder);
    // Now assign stuff! Preferrably, assign leftmost and rightmost ports...
    for (SelfHyperLoop slLoop : slHolder.getSLHyperLoops()) {
        switch(slLoop.getSelfLoopType()) {
            case ONE_SIDE:
                determineOneSideLoopRoutes(slLoop);
                break;
            case TWO_SIDES_CORNER:
                determineTwoSideCornerLoopRoutes(slLoop);
                break;
            case TWO_SIDES_OPPOSING:
                determineTwoSideOpposingLoopRoutes(slLoop);
                break;
            case THREE_SIDES:
                determineThreeSideLoopRoutes(slLoop);
                break;
            case FOUR_SIDES:
                determineFourSideLoopRoutes(slLoop);
                break;
            default:
                assert false;
        }
        // Setup the loop's set of occupied port sides
        computeOccupiedPortSides(slLoop);
    }
    portPenalties = null;
}
Also used : SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)

Example 2 with SelfHyperLoop

use of org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop in project elk by eclipse.

the class RoutingSlotAssigner method createCrossingGraph.

// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Crossing Graph
/**
 * Create the crossing graph by creating one {@link HyperEdgeSegment} for each {@link SelfHyperLoop} and computing
 * the proper dependencies between them.
 */
private void createCrossingGraph(final SelfLoopHolder slHolder, final boolean[][] labelCrossingMatrix) {
    List<SelfHyperLoop> slLoops = slHolder.getSLHyperLoops();
    // Create an edge segment for each loop
    hyperEdgeSegments = new ArrayList<>(slLoops.size());
    slLoopToSegmentMap = new HashMap<>();
    for (SelfHyperLoop slLoop : slLoops) {
        HyperEdgeSegment segment = new HyperEdgeSegment(null);
        hyperEdgeSegments.add(segment);
        slLoopToSegmentMap.put(slLoop, segment);
    }
    // To be able to quickly count crossings later, we remember for each loop whether it's active at a given port
    // ID or not
    slLoopActivityOverPorts = new HashMap<>();
    computeLoopActivity(slHolder);
    // collisions on sides without ports. The routing space will be compacted at a later step.
    for (int firstIdx = 0; firstIdx < slLoops.size() - 1; firstIdx++) {
        SelfHyperLoop slLoop1 = slHolder.getSLHyperLoops().get(firstIdx);
        for (int secondIdx = firstIdx + 1; secondIdx < slLoops.size(); secondIdx++) {
            createDependencies(slLoop1, slHolder.getSLHyperLoops().get(secondIdx), labelCrossingMatrix);
        }
    }
}
Also used : HyperEdgeSegment(org.eclipse.elk.alg.layered.p5edges.orthogonal.HyperEdgeSegment) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)

Example 3 with SelfHyperLoop

use of org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop in project elk by eclipse.

the class RoutingSlotAssigner method shiftTowardsNodeOnSide.

private void shiftTowardsNodeOnSide(final SelfLoopHolder slHolder, final PortSide side, final int[] nextFreeRoutingSlotAtPort, final boolean[][] labelCrossingMatrix) {
    // We will iterate over the self loops that occupy that port side, sorted ascendingly by routing slot
    List<SelfHyperLoop> slLoops = slHolder.getSLHyperLoops().stream().filter(slLoop -> slLoop.getOccupiedPortSides().contains(side)).sorted((sl1, sl2) -> Integer.compare(sl1.getRoutingSlot(side), sl2.getRoutingSlot(side))).collect(Collectors.toList());
    // Find the indices of the first and last regular port on the port side
    int minLPortIndex = Integer.MAX_VALUE;
    int maxLPortIndex = Integer.MIN_VALUE;
    for (LPort lPort : slHolder.getLNode().getPorts()) {
        if (lPort.getSide() == side) {
            minLPortIndex = Math.min(minLPortIndex, lPort.id);
            maxLPortIndex = Math.max(maxLPortIndex, lPort.id);
        }
    }
    if (minLPortIndex == Integer.MAX_VALUE) {
        // won't cause label overlaps.
        for (int i = 0; i < slLoops.size(); i++) {
            slLoops.get(i).setRoutingSlot(side, i);
        }
    } else {
        int[] slotAssignedToLabel = new int[labelCrossingMatrix.length];
        Arrays.fill(slotAssignedToLabel, -1);
        // no label our loop label conflicts with is assigned to that slot
        for (SelfHyperLoop slLoop : slLoops) {
            boolean[] activeAtPort = slLoopActivityOverPorts.get(slLoop);
            int lowestAvailableSlot = 0;
            for (int portIndex = minLPortIndex; portIndex <= maxLPortIndex; portIndex++) {
                if (activeAtPort[portIndex]) {
                    lowestAvailableSlot = Math.max(lowestAvailableSlot, nextFreeRoutingSlotAtPort[portIndex]);
                }
            }
            // conflict-free slot
            if (slLoop.getSLLabels() != null) {
                int ourLabelIdx = slLoop.getSLLabels().id;
                Set<Integer> slotsWithLabelConflicts = new HashSet<>();
                for (int otherLabelIdx = 0; otherLabelIdx < labelCrossingMatrix.length; otherLabelIdx++) {
                    if (labelCrossingMatrix[ourLabelIdx][otherLabelIdx]) {
                        slotsWithLabelConflicts.add(slotAssignedToLabel[otherLabelIdx]);
                    }
                }
                // Find the first slot (starting with out lowest available) that does not appear in the set
                while (slotsWithLabelConflicts.contains(lowestAvailableSlot)) {
                    lowestAvailableSlot++;
                }
            }
            // Assign the loop to that routing slot and update out routing slot array
            slLoop.setRoutingSlot(side, lowestAvailableSlot);
            for (int portIndex = minLPortIndex; portIndex <= maxLPortIndex; portIndex++) {
                if (activeAtPort[portIndex]) {
                    nextFreeRoutingSlotAtPort[portIndex] = lowestAvailableSlot + 1;
                }
            }
            // If we have a label, update the label's routing slot
            if (slLoop.getSLLabels() != null) {
                slotAssignedToLabel[slLoop.getSLLabels().id] = lowestAvailableSlot;
            }
        }
    }
}
Also used : Arrays(java.util.Arrays) PortSide(org.eclipse.elk.core.options.PortSide) SelfLoopPort(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort) Set(java.util.Set) HashMap(java.util.HashMap) Collectors(java.util.stream.Collectors) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop) ArrayList(java.util.ArrayList) SelfLoopHolder(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder) HashSet(java.util.HashSet) HyperEdgeSegment(org.eclipse.elk.alg.layered.p5edges.orthogonal.HyperEdgeSegment) List(java.util.List) InternalProperties(org.eclipse.elk.alg.layered.options.InternalProperties) Map(java.util.Map) LPort(org.eclipse.elk.alg.layered.graph.LPort) OrthogonalRoutingGenerator(org.eclipse.elk.alg.layered.p5edges.orthogonal.OrthogonalRoutingGenerator) Queue(java.util.Queue) LinkedList(java.util.LinkedList) HyperEdgeSegmentDependency(org.eclipse.elk.alg.layered.p5edges.orthogonal.HyperEdgeSegmentDependency) SelfHyperLoopLabels(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoopLabels) LPort(org.eclipse.elk.alg.layered.graph.LPort) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop) HashSet(java.util.HashSet)

Example 4 with SelfHyperLoop

use of org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop in project elk by eclipse.

the class RoutingSlotAssigner method computeLabelCrossingMatrix.

// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Label Crossing Matrix
/**
 * Computes a two-dimensional array with elements set to {@code true} if the labels with the corresponding IDs
 * overlap.
 */
private boolean[][] computeLabelCrossingMatrix(final SelfLoopHolder slHolder) {
    // We need to start by giving the labels proper IDs
    int labelID = 0;
    for (SelfHyperLoop slLoop : slHolder.getSLHyperLoops()) {
        if (slLoop.getSLLabels() != null) {
            slLoop.getSLLabels().id = labelID++;
        }
    }
    boolean[][] crossingMatrix = new boolean[labelID][labelID];
    // Now check for each pair of labels whether or not they overlap
    List<SelfHyperLoop> slLoops = slHolder.getSLHyperLoops();
    for (int sl1Idx = 0; sl1Idx < slLoops.size(); sl1Idx++) {
        SelfHyperLoop slLoop1 = slLoops.get(sl1Idx);
        if (slLoop1.getSLLabels() != null) {
            for (int sl2Idx = sl1Idx + 1; sl2Idx < slLoops.size(); sl2Idx++) {
                SelfHyperLoop slLoop2 = slLoops.get(sl2Idx);
                if (slLoop2.getSLLabels() != null) {
                    boolean overlap = labelsOverlap(slLoop1, slLoop2);
                    crossingMatrix[slLoop1.getSLLabels().id][slLoop2.getSLLabels().id] = overlap;
                    crossingMatrix[slLoop2.getSLLabels().id][slLoop1.getSLLabels().id] = overlap;
                }
            }
        }
    }
    return crossingMatrix;
}
Also used : SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)

Example 5 with SelfHyperLoop

use of org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop in project elk by eclipse.

the class PortSideAssigner method assignToAllSides.

/**
 * Distributes self loops to all sides.
 */
private void assignToAllSides(final SelfLoopHolder slHolder) {
    // Obtain a list of self hyper loops, ordered descendingly by the number of involved ports. This will later tend
    // to place hyper loops with many ports not across corners, but on a single side
    List<SelfHyperLoop> slSortedLoops = new ArrayList<>(slHolder.getSLHyperLoops());
    slSortedLoops.sort((slLoop1, slLoop2) -> Integer.compare(slLoop2.getSLPorts().size(), slLoop1.getSLPorts().size()));
    // Iterate over our self loops and assign each to the next target
    Target[] assignmentTargets = Target.values();
    int currLoop = 0;
    for (SelfHyperLoop slLoop : slSortedLoops) {
        Target currTarget = assignmentTargets[currLoop % assignmentTargets.length];
        assignToTarget(slLoop, currTarget);
        currLoop++;
    }
}
Also used : ArrayList(java.util.ArrayList) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)

Aggregations

SelfHyperLoop (org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)18 PortSide (org.eclipse.elk.core.options.PortSide)10 LPort (org.eclipse.elk.alg.layered.graph.LPort)6 ArrayList (java.util.ArrayList)4 SelfHyperLoopLabels (org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoopLabels)4 SelfLoopPort (org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort)4 KVector (org.eclipse.elk.core.math.KVector)3 List (java.util.List)2 Collectors (java.util.stream.Collectors)2 SelfLoopHolder (org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder)2 InternalProperties (org.eclipse.elk.alg.layered.options.InternalProperties)2 HyperEdgeSegment (org.eclipse.elk.alg.layered.p5edges.orthogonal.HyperEdgeSegment)2 Arrays (java.util.Arrays)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 Map (java.util.Map)1 Queue (java.util.Queue)1 Set (java.util.Set)1 Stream (java.util.stream.Stream)1