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;
}
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);
}
}
}
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;
}
}
}
}
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;
}
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++;
}
}
Aggregations