/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: FindVirtualEnd_Simple.java
* Written by: Andreas Uebelhoer, Alexander Bieles, Emre Selegin (Team 6)
*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.routing.experimentalLeeMoore1;
import com.sun.electric.tool.routing.experimentalLeeMoore1.LeeMoore.Tupel;
/**
*
* @author Sonny
*/
public class FindVirtualEnd_Simple implements FindVirtualEndInterface {
private static boolean X_DIRECTION; //const
private static boolean Y_DIRECTION; //const
private static int MAXLAYER;
public FindVirtualEnd_Simple(boolean xdir, boolean ydir, int l) {
X_DIRECTION = xdir;
Y_DIRECTION = ydir;
MAXLAYER = l;
}
public synchronized ConnectionPoints findVirtualEnd(RoutingPart rp, int id) {
Tupel start = rp.start;
Tupel ende = rp.end;
/*current algo:
* go to the boundary in this direction, which is shorter to the end_point
* at the boundary try to find a free point to use
* try this for all layers
*/
boolean routingDirection;
if (Math.abs(getMiddlePoint(start).getX_InsideRoutingArray() - getMiddlePoint(ende).getX_InsideRoutingArray())
>= Math.abs(getMiddlePoint(start).getY_InsideRoutingArray() - getMiddlePoint(ende).getY_InsideRoutingArray())) {
routingDirection = X_DIRECTION;
//route in Xdirection because its longer (on the x sided boundary)
if ((start.getX_InsideRoutingArray() <= ende.getX_InsideRoutingArray())) {
//we have to go to the right, because the start is on the left side of the end
for (int l = 0; l < MAXLAYER; l++) {
if (!isCorrectOddEvenLayerForRoutingDirection(l, routingDirection)) {
continue;
}
//Tupel vEnd = new Tupel(getHighIndexIn_X(this.id), 0, l, false);
for (int y = getLowIndexIn_Y(id) + 1; y < getHighIndexIn_Y(id) - 1; y += 10) {
//try to find a free position on the right boundary
Tupel vEnd = new Tupel(getHighIndexIn_X(id), y, l, false);
if (isFree(vEnd)) {
return makeReturnArg(vEnd, routingDirection, 1);
}
}
}
} else { //((start.getX_InsideRoutingArray() > ende.getX_InsideRoutingArray()) ) {
//we have to go to the left, because ... s.o.
for (int l = 0; l < MAXLAYER; l++) {
if (!isCorrectOddEvenLayerForRoutingDirection(l, routingDirection)) {
continue;
}
//Tupel vEnd = new Tupel(getLowIndexIn_X(this.id), 0, l, false);
for (int y = getLowIndexIn_Y(id) + 1; y < getHighIndexIn_Y(id) - 1; y += 10) {
//try to find a free position on the left boundary
Tupel vEnd = new Tupel(getLowIndexIn_X(id), y, l, false);
if (isFree(vEnd)) {
return makeReturnArg(vEnd, routingDirection, -1);
}
}
}
}
} else {
routingDirection = Y_DIRECTION;
//route in Ydirection, because its longer
if ((start.getY_InsideRoutingArray() <= ende.getY_InsideRoutingArray())) {
//we have to go to the top, because ... s.o.
for (int l = 0; l < MAXLAYER; l++) {
if (!isCorrectOddEvenLayerForRoutingDirection(l, routingDirection)) {
continue;
}
//Tupel vEnd = new Tupel(0, getHighIndexIn_Y(this.id), l, false);
for (int x = getLowIndexIn_X(id) + 1; x < getHighIndexIn_X(id) - 1; x += 10) {
//try to find a free position on the top boundary
Tupel vEnd = new Tupel(x, getHighIndexIn_Y(id), l, false);
if (isFree(vEnd)) {
return makeReturnArg(vEnd, routingDirection, 1);
}
}
}
} else { //((start.getY_InsideRoutingArray() > ende.getY_InsideRoutingArray()) ) {
//we have to go down, because ... s.o.
for (int l = 0; l < MAXLAYER; l++) {
if (!isCorrectOddEvenLayerForRoutingDirection(l, routingDirection)) {
continue;
}
//Tupel vEnd = new Tupel(0, getLowIndexIn_Y(this.id), l, false);
for (int x = getLowIndexIn_X(id) + 1; x < getHighIndexIn_X(id) - 1; x += 10) {
//try to find a free position on the bottom boundary
Tupel vEnd = new Tupel(x, getLowIndexIn_Y(id), l, false);
if (isFree(vEnd)) {
return makeReturnArg(vEnd, routingDirection, -1);
}
}
}
}
}
//TODO: no virtual connecting point was found in the desired routing direction, so try to go another to another side of your region
return new ConnectionPoints();
}
private Tupel getMiddlePoint(Tupel end) {
return WorkerThread.getMiddlePoint(end);
}
private boolean isCorrectOddEvenLayerForRoutingDirection(int layer, boolean direction) {
//direction==true => X-Dir
//layers are counted from 0, so we have add 1 to get the first layer index 1
if (direction == X_DIRECTION && (layer + 1) % 2 == 1) {
return true; //odd layers route in x-direction
}
if (direction == Y_DIRECTION && (layer + 1) % 2 == 0) {
return true; //even layer shall route in y-direction
}
return false;
}
private ConnectionPoints makeReturnArg(Tupel pkt, boolean direction, int range) {
if (direction == X_DIRECTION) {
//X-dir
return new ConnectionPoints(new Tupel(pkt.getX_InsideRoutingArray(), pkt.getY_InsideRoutingArray(), pkt.getLayer(), false), new Tupel(pkt.getX_InsideRoutingArray() + range, pkt.getY_InsideRoutingArray(), pkt.getLayer(), false));
} else {
//Y-direction
return new ConnectionPoints(new Tupel(pkt.getX_InsideRoutingArray(), pkt.getY_InsideRoutingArray(), pkt.getLayer(), false), new Tupel(pkt.getX_InsideRoutingArray(), pkt.getY_InsideRoutingArray() + range, pkt.getLayer(), false));
}
}
private boolean isFree(Tupel t) {
if (t.getX_InsideRoutingArray() >= 0 && t.getX_InsideRoutingArray() < WorkerThread.size_x
&& t.getY_InsideRoutingArray() >= 0 && t.getY_InsideRoutingArray() < WorkerThread.size_y
&& t.getLayer() >= 0 && t.getLayer() <= MAXLAYER) {
return WorkerThread.regionBoundaries[t.getX_InsideRoutingArray()][t.getY_InsideRoutingArray()][t.getLayer()];
} else {
//point not inside the grid
return false;
}
}
private static int getHighIndexIn_X(int rank) {
return WorkPool.getHighIndexIn_X(rank);
}
private static int getHighIndexIn_Y(int rank) {
return WorkPool.getHighIndexIn_Y(rank);
}
private static int getLowIndexIn_X(int rank) {
return WorkPool.getLowIndexIn_X(rank);
}
private static int getLowIndexIn_Y(int rank) {
return WorkPool.getLowIndexIn_Y(rank);
}
}