31
32
import com.sun.electric.technology.PrimitiveNode;
32
33
import com.sun.electric.technology.PrimitivePort;
33
34
import com.sun.electric.technology.Technology;
35
import com.sun.electric.technology.Xml;
36
import com.sun.electric.technology.Technology.TechPoint;
37
import com.sun.electric.technology.Xml.MenuNodeInst;
34
38
import com.sun.electric.technology.technologies.Generic;
35
39
import com.sun.electric.tool.user.User;
40
import com.sun.electric.tool.user.dialogs.ComponentMenu;
36
41
import com.sun.electric.util.math.EDimension;
37
42
import com.sun.electric.util.math.Orientation;
358
363
* @param arcAngle angle of zero length arcs created between contacts (usually zero)
359
364
* @param stayInside a polygonal area in which the new arc must reside (if not null).
360
365
* @param ep EditingPreferences with default sizes
366
* @param evenHor if even metal is horizontal
361
367
* @return a Route whose start can connect to startRE and whose end
362
368
* can connect to endRE. Returns null if no specification for the route exists.
364
public Route buildRoute(Cell cell, Point2D location, EDimension contactSize, int arcAngle, PolyMerge stayInside, EditingPreferences ep) {
370
public Route buildRoute(Cell cell, Point2D location, EDimension contactSize, int arcAngle, PolyMerge stayInside, EditingPreferences ep,
365
372
if (specifiedRoute == null) {
366
373
System.out.println("Error: Trying to build VerticalRoute without a call to specifyRoute() first");
385
// determine orientation of primitive
386
Orientation orient = Orientation.IDENT;
387
PrimitivePort pp = (PrimitivePort)specifiedRoute.remove(0);
388
PrimitiveNode pnp = pp.getParent();
390
// If no information about even metal is provided -> use old style
393
Xml.MenuPalette pal = ComponentMenu.getMenuPalette(pnp.getTechnology());
394
for(int index=0; index<pal.menuBoxes.size(); index++)
396
List<?> menuBoxList = pal.menuBoxes.get(index);
397
if (menuBoxList == null || menuBoxList.isEmpty()) continue;
398
for(int i=0; i<menuBoxList.size(); i++)
400
Object obj = menuBoxList.get(i);
401
if (obj instanceof MenuNodeInst)
403
MenuNodeInst mni = (MenuNodeInst)obj;
404
if (mni.protoName.equals(pnp.getName()))
406
orient = Orientation.fromAngle(mni.rotation);
407
// know what to do with 900 and 1800 angle rotations
408
if (mni.rotation == Orientation.R.getAngle() ||
409
mni.rotation == Orientation.R.getAngle())
411
double w = contactSize.getWidth();
412
contactSize = new EDimension(contactSize.getHeight(), w);
416
System.out.println(mni.rotation + "is not typical angle rotation and therefore no guarantee that contact will fit perfectly");
425
Technology.NodeLayer[] nodes = pnp.getNodeLayers();
426
boolean metalFound = false;
427
// look for the first metal layer
428
for (int i = 0; i < nodes.length && !metalFound; i++)
430
Technology.NodeLayer n = nodes[i];
431
com.sun.electric.technology.Layer.Function f = n.getLayer().getFunction();
432
if (!f.isMetal()) continue;
433
boolean evenM = f.getLevel() % 2 == 0;
434
if (!evenM) continue; // just looking for even metals
436
com.sun.electric.technology.EdgeH eh = n.getLeftEdge();
437
com.sun.electric.technology.EdgeV ev = n.getBottomEdge();
438
TechPoint[] pts = n.getPoints();
439
assert(pts.length == 2); // the assumption for now
440
long width = pts[1].getX().getGridValue(EPoint.ORIGIN) - pts[0].getX().getGridValue(EPoint.ORIGIN);
441
long height = pts[1].getY().getGridValue(EPoint.ORIGIN) - pts[0].getY().getGridValue(EPoint.ORIGIN);
442
long basedW = pnp.getBaseRectangle().getGridWidth();
443
long basedH = pnp.getBaseRectangle().getGridHeight();
444
// checking if node has any metal outside the selection area. If not, we can't determine the preferred orientation.
445
width -= basedW; // reduce the selection cut to determine if there is a reminder metal around to make the decision
447
assert(width >= 0 && height >= 0);
448
if (height == 0 && width == 0) continue; // nothing to check
449
boolean isHorizontal = width > height;
450
// time to rotate the contact including the cuts
451
if (!isHorizontal && evenM)
453
orient = Orientation.R;
454
double w = contactSize.getWidth();
455
contactSize = new EDimension(contactSize.getHeight(), w);
378
461
// pull off the first object, which will be a port, and create contact from that
379
PrimitivePort pp = (PrimitivePort)specifiedRoute.remove(0);
380
462
RouteElementPort node = RouteElementPort.newNode(cell, pp.getParent(), pp,
381
location, contactSize.getWidth(), contactSize.getHeight(), Orientation.IDENT, ep);
463
location, contactSize.getWidth(), contactSize.getHeight(), orient, ep);
383
465
route.setStart(node);
384
466
route.setEnd(node);