📄 layoutlib.java
字号:
* ArcInst is useful because Electric uses the widest ArcInst on a * PortInst as a hint for the width to use for all future * arcs. Because Electric doesn't use the size of layer-pins as * width hints, the layer-pin is created in it's default size. * * <p> <code>newExport</code> seems very specialized, but it's * nearly the only one I use when generating layout. * @param cell the Cell to which to add the Export. * @param name the name of the Export. * @param role the Export's type. * @param ap the ArcProto indicating the layer on which to create * the Export. * @param w width of the ArcInst serving as a hint. * @param x the x-coordinate of the layer pin. * @param y the y-coordinate of the layer pin. */ public static Export newExport(Cell cell, String name, PortCharacteristic role, ArcProto ap, double w, double x, double y) { NodeProto np = ap.findOverridablePinProto(); error(np==null, "LayoutLib.newExport: This layer has no layer-pin"); double defSz = LayoutLib.DEF_SIZE; NodeInst ni = LayoutLib.newNodeInst(np, x, y, defSz, defSz, 0, cell); LayoutLib.newArcInst(ap, w, ni.getOnlyPortInst(), ni.getOnlyPortInst()); Export e = Export.newInstance(cell, ni.getOnlyPortInst(), name); e.setCharacteristic(role); return e; } public static Rectangle2D roundBounds(Rectangle2D r) { double w = DBMath.round(r.getWidth()); double h = DBMath.round(r.getHeight()); double x = DBMath.round(r.getX()); double y = DBMath.round(r.getY()); return new Rectangle2D.Double(x,y,w,h); } /** * Get the essential or regular bounds. If NodeInst * <code>node</code> has an Essential Bounds then return * it. Otherwise return the regular bounds. * @param node the NodeInst. * @return the Rectangle2D representing the bounds. */ public static Rectangle2D getBounds(NodeInst node) { Rectangle2D bounds = node.findEssentialBounds(); if (bounds==null) bounds = node.getBounds(); return roundBounds(bounds); } /** * Get the essential or regular bounds. If Cell c has an * Essential Bounds then return it. Otherwise return the regular * bounds. * @param c the Cell. * @return the Rectangle2D representing the bounds. */ public static Rectangle2D getBounds(Cell c) { Rectangle2D bounds = c.findEssentialBounds(); if (bounds==null) bounds = c.getBounds(); return roundBounds(bounds); } // --------------------- Abutment methods --------------------------------- // There are too many abutment methods. I need to figure out how // to eliminate some. /** * Move NodeInst so it's left edge is at <code>leftX</code> and * the y-coordinate of it's origin is at * <code>originY</code>. Don't alter the NodeInst's scale or * rotation. * @param node the NodeInst * @param leftX desired x-coordinate of left edge of <code>node</code>. * @param originY desired y-coordinate of <code>node</code>'s origin */ public static void abutLeft(NodeInst node, double leftX, double originY) { double cY = getPosition(node).getY(); Rectangle2D bd = node.findEssentialBounds(); error(bd==null, "can't abut NodeInsts that don't have essential-bounds"); LayoutLib.modNodeInst(node, leftX-bd.getX(), originY-cY, 0, 0, false, false, 0); } /** * Abut an array of NodeInsts left to right. Move the 0th NodeInst * so it's left edge is at <code>leftX</code> and it the * y-coordinate of its origin is at <code>originY</code>. Abut the * remaining nodes left to right. Don't alter any NodeInst's * scale or rotation. * @param leftX desired x-coordinate of left edge of 0th NodeInst. * @param originY desired y-coordinate of all NodeInst origins * @param nodeInsts the ArrayList of NodeInsts. */ public static void abutLeftRight(double leftX, double originY, Collection<NodeInst> nodeInsts) { NodeInst prev = null; for (NodeInst ni : nodeInsts) { if (prev==null) { abutLeft(ni, leftX, originY); } else { abutLeftRight(prev, ni); } prev = ni; } } /** * Abut two NodeInsts left to right. Move <code>rightNode</code> * so its left edge coincides with <code>leftNode</code>'s right * edge, and the y-coordinate of <code>rightNode</code>'s is equal * to the y-coordinate of <code>leftNode</code>'s origin. Don't * move <code>leftNode</code>. Don't alter any node's scale or * rotation. * @param leftNode the NodeInst that doesn't move. * @param rightNode the NodeInst that is moved to butt against * leftNode. */ public static void abutLeftRight(NodeInst leftNode, NodeInst rightNode) { abutLeft(rightNode, getBounds(leftNode).getMaxX(), getPosition(leftNode).getY()); } /** * Abut an array of NodeInsts left to right. Don't move the 0th * node. Abut remaining nodes left to right. Don't alter any * NodeInst's scale or rotation. * @param nodeInsts the ArrayList of NodeInsts */ public static void abutLeftRight(Collection<NodeInst> nodeInsts) { NodeInst prev = null; for (NodeInst ni : nodeInsts) { if (prev!=null) abutLeftRight(prev, ni); prev = ni; } } /** Move a NodeInst so it's bottom edge is at <code>botY</code>. * * <p>Place <code>node</code>'s origin at * <code>originX</code>. Don't alter <code>node</code>'s scale or * rotation. * @param node the NodeInst to move * @param originX desired x-coordinate of NodeInst's origin * @param botY desired y-coordinate of bottom edge of NodeInst */ public static void abutBottom(NodeInst node, double originX, double botY) { double cX = getPosition(node).getX(); Rectangle2D eb = node.findEssentialBounds(); error(eb==null, "can't abut a NodeInst that doesn't have Essential Bounds"); LayoutLib.modNodeInst(node, originX-cX, botY-eb.getMinY(), 0, 0, false, false, 0); } /** * Abut two NodeInsts bottom to top. Move <code>topNode</code> so * its bottom edge coincides with <code>bottomNode</code>'s top * edge, and the y-coordinate of <code>topNode</code>'s origin is * equal to the y-coorinate of <code>bottomNode</code>'s * origin. Don't move <code>bottomNode</code>. Don't alter any * node's scale or rotation. */ public static void abutBottomTop(NodeInst bottomNode, double space, NodeInst topNode) { abutBottom(topNode, getPosition(bottomNode).getX(), getBounds(bottomNode).getMaxY()+space); } /** * Abut a list of NodeInsts bottom to top. Move 0th NodeInst so * it's bottom edge is at botY and it's origin has the * x-coordinate, originX. Abut remaining nodes bottom to top. * Don't alter any NodeInst's scale or rotation. * @param originX desired x-coordinate of all NodeInst reference points. * Lambda units. * @param botY desired y-coordinate of bottom edge of first NodeInst. * @param nodeInsts Collection of NodeInsts to abut. */ public static void abutBottomTop(double originX, double botY, Collection<NodeInst> nodeInsts, double space) { NodeInst prev = null; for (NodeInst ni : nodeInsts) { if (prev==null){ abutBottom(ni, originX, botY); } else { abutBottomTop(prev, space, ni); } prev = ni; } } /** * Abut a list of NodeInsts bottom to top. Don't alter position * of 0th node. Abut the remaining nodes bottom to top. Don't * alter any NodeInst's scale or rotation. * @param nodeInsts the list of NodeInsts to abut. */ public static void abutBottomTop(Collection<NodeInst> nodeInsts, double space) { NodeInst prev = null; for (NodeInst ni : nodeInsts) { if (prev!=null) abutBottomTop(prev, space, ni); prev = ni; } } private static Point2D getPointAtCorner(NodeInst ni, Corner cnr) { Rectangle2D b = ni.findEssentialBounds(); double x = (cnr==Corner.TL || cnr==Corner.BL) ? b.getMinX() : b.getMaxX(); double y = (cnr==Corner.BL || cnr==Corner.BR) ? b.getMinY() : b.getMaxY(); return new Point2D.Double(x, y); } public static void alignCorners(NodeInst niFixed, Corner cnrFixed, NodeInst niMove, Corner cnrMove, double offsetX, double offsetY) { Point2D ptFixed = getPointAtCorner(niFixed, cnrFixed); Point2D ptMove = getPointAtCorner(niMove, cnrMove); double dx = ptFixed.getX() - ptMove.getX() + offsetX; double dy = ptFixed.getY() - ptMove.getY() + offsetY; niMove.move(dx, dy); } /** * Get the bounding box for the layer in the Cell. * Note this does not include geometry from sub-cells. * @param cell the cell to examine * @param function the layer's function * @return a bounding box around all instances of the layer in the cell */ public static Rectangle2D getBounds(Cell cell, Layer.Function function) { Rectangle2D bounds = null; Technology tech = cell.getTechnology(); Layer.Function.Set thisFunction = new Layer.Function.Set(function); // get layer from nodes for (Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); AffineTransform trans = ni.rotateOut(); Poly [] polys = tech.getShapeOfNode(ni, false, true, thisFunction); if (polys == null) continue; for (int i=0; i<polys.length; i++) { if (polys[i] == null) continue; if (polys[i].getLayer().getFunction() == function) { polys[i].transform(trans); if (bounds == null) bounds = polys[i].getBox(); else bounds = bounds.createUnion(polys[i].getBox()); } } } // get layer from arcs for (Iterator<ArcInst> it = cell.getArcs(); it.hasNext(); ) { ArcInst ai = it.next(); Poly [] polys = tech.getShapeOfArc(ai, thisFunction); if (polys == null) continue; for (int i=0; i<polys.length; i++) { if (polys[i] == null) continue; if (polys[i].getLayer().getFunction() == function) { if (bounds == null) bounds = polys[i].getBox(); else bounds = bounds.createUnion(polys[i].getBox()); } } } return bounds; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -