📄 flagdesign.java
字号:
package com.sun.electric.tool.generator.flag;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.sun.electric.database.geometry.Orientation;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.Export;
import com.sun.electric.database.hierarchy.HierarchyEnumerator;
import com.sun.electric.database.hierarchy.Library;
import com.sun.electric.database.prototype.PortCharacteristic;
import com.sun.electric.database.topology.Geometric;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.database.variable.VarContext;
import com.sun.electric.technology.ArcProto;
import com.sun.electric.tool.generator.flag.router.Router;
import com.sun.electric.tool.generator.flag.router.SogRouterAdapter;
import com.sun.electric.tool.generator.flag.router.ToConnect;
import com.sun.electric.tool.generator.flag.scan.Scan;
import com.sun.electric.tool.generator.layout.AbutRouter;
import com.sun.electric.tool.generator.layout.LayoutLib;
import com.sun.electric.tool.generator.layout.TechType;
import com.sun.electric.tool.generator.layout.LayoutLib.Corner;
import com.sun.electric.tool.ncc.basic.NccCellAnnotations;
import com.sun.electric.tool.user.ExportChanges;
/** Super class for the physical design objects of all Cells */
public class FlagDesign {
public static final double DEF_SIZE = LayoutLib.DEF_SIZE;
private final FlagConfig config;
private final Scan scan;
private final Router router;
private final SogRouterAdapter sogRouterAdapter;
public TechType tech() {return config.techTypeEnum.getTechType();}
// public static Rectangle2D findColBounds(Collection<NodeInst> stages) {
// double minX, minY, maxX, maxY;
// minX = minY = Double.MAX_VALUE;
// maxX = maxY = Double.MIN_VALUE;
// for (NodeInst ni : stages) {
// Rectangle2D bounds = ni.findEssentialBounds();
// error(bounds==null,
// "Layout Cell is missing essential bounds: "+
// ni.getProto().describe(false));
// minX = Math.min(minX, bounds.getMinX());
// maxX = Math.max(maxX, bounds.getMaxX());
// minY = Math.min(minY, bounds.getMinY());
// maxY = Math.max(maxY, bounds.getMaxY());
// }
// return new Rectangle2D.Double(minX, minY, maxX-minX, maxY-minY);
// }
// private void sortPortInstsBotToTop(List<PortInst> pis) {
// Collections.sort(pis, new Comparator<PortInst>() {
// public int compare(PortInst p1, PortInst p2) {
// double diff = p1.getCenter().getY() -
// p2.getCenter().getY();
// return (int) Math.signum(diff);
// }
// });
// }
// private Rectangle2D getPortInstBounds(ToConnect toConn) {
// double minX, minY, maxX, maxY;
// minX = minY = Double.MAX_VALUE;
// maxX = maxY = Double.MIN_VALUE;
// for (PortInst pi : toConn.getPortInsts()) {
// double x = pi.getCenter().getX();
// double y = pi.getCenter().getY();
// if (x<minX) minX=x;
// if (x>maxX) maxX=x;
// if (y<minY) minY=y;
// if (y>maxY) maxY=y;
// }
// return new Rectangle2D.Double(minX, minY, maxX-minX, maxY-minY);
// }
// private void connect2PinM3(ToConnect toConn) {
// prln("M3 "+toConn.toString());
// PortInst pi1 = toConn.getPortInsts().get(0);
// PortInst pi2 = toConn.getPortInsts().get(1);
// error(!connectsToM3(pi1) || ! connectsToM3(pi2),
// "only 1 of 2 pins connects to m3");
// double x1 = pi1.getCenter().getX();
// double x2 = pi2.getCenter().getX();
// error(x1!=x2, "m3 net not vertical");
//
// LayoutLib.newArcInst(tech().m3(), SIGNAL_WID, pi1, pi2);
//
// }
// private void dumpChannels(LayerChannels m2chan, LayerChannels m3chan) {
// prln("m2 channels");
// prln(m2chan.toString());
//
// prln("m3 channels");
// prln(m3chan.toString());
// }
// private List<ToConnect> reduceToTwoPinX(List<List<PortInst>> portLists) {
// List<ToConnect> twoPins = new ArrayList<ToConnect>();
// while (portLists.size()>1) {
// ClosestClusters cc = findClosest(portLists);
// ToConnect tc = new ToConnect(null);
// tc.addPortInst(cc.pair.p1);
// tc.addPortInst(cc.pair.p2);
// twoPins.add(tc);
// List<PortInst> pl1 = portLists.get(cc.ndx1);
// List<PortInst> pl2 = portLists.get(cc.ndx2);
// pl1.addAll(pl2);
// portLists.remove(cc.ndx2);
// }
// return twoPins;
// }
/** Convert each ToConnect with more than two pins to multiple two
* pin TwoConnects */
// private List<ToConnect> reduceToTwoPin(List<ToConnect> toConns) {
// List<ToConnect> twoPins = new ArrayList<ToConnect>();
// for (ToConnect tc : toConns) {
// // Skip Exported net that touches no stage PortInsts
// if (tc.size()==0) continue;
//
// // Some PortInsts on a ToConnect may already be connected in
// // schematic by abut router
// List<List<PortInst>> connPorts = groupConnectedPorts(tc);
//
// // Generate a list of two pin ToConnects that connects
// // disconnected pin lists.
// twoPins.addAll(reduceToTwoPinX(connPorts));
// }
// return twoPins;
// }
private void fattenVerticalM3(Map<Double, PortInst> bot,
Map<Double, PortInst> top) {
for (Double x : bot.keySet()) {
PortInst piBot = bot.get(x);
PortInst piTop = top.get(x);
if (piTop==null) continue;
LayoutLib.newArcInst(tech().m3(), config.m3PwrGndWid,
piBot, piTop);
}
}
// Hack until I get a chance to fatten based upon need.
// private void fattenPwrGnd(List<NodeInst> stages) {
// Rectangle2D colBounds = findBounds(stages.get(0).getParent());
// NodeInst topInst = stages.get(stages.size()-1);
// Map<Double, PortInst> topPwr = new TreeMap<Double, PortInst>();
// Map<Double, PortInst> topGnd = new TreeMap<Double, PortInst>();
// getM3PwrGndExports(topPwr, topGnd, topInst, colBounds.getMaxY());
//
// NodeInst botInst = stages.get(0);
// Map<Double, PortInst> botPwr = new TreeMap<Double, PortInst>();
// Map<Double, PortInst> botGnd = new TreeMap<Double, PortInst>();
// getM3PwrGndExports(botPwr, botGnd, botInst, colBounds.getMinY());
//
// fattenVerticalM3(botGnd, topGnd);
// fattenVerticalM3(botPwr, topPwr);
// }
private static class CloseToBound implements Comparator<PortInst> {
private Rectangle2D bound;
private double distToBound(PortInst pi) {
double x = pi.getCenter().getX();
double l = Math.abs(x - bound.getMinX());
double r = Math.abs(x - bound.getMaxX());
double y = pi.getCenter().getY();
double b = Math.abs(y - bound.getMinY());
double t = Math.abs(y - bound.getMaxY());
return Math.min(Math.min(l, r),
Math.min(t, b));
}
public CloseToBound(Rectangle2D bound) {this.bound=bound;}
public int compare(PortInst pi1, PortInst pi2) {
double d = distToBound(pi1) - distToBound(pi2);
return (int) Math.signum(d);
}
}
private void reExportIfPortNameMatches(List<String> expNms,
List<PortInst> ports) {
if (ports.isEmpty()) return;
Cell parent = ports.get(0).getNodeInst().getParent();
for (Iterator<String> sIt=expNms.iterator(); sIt.hasNext();) {
String nm = sIt.next();
if (parent.findExport(nm)!=null) {
sIt.remove();
} else {
}
}
}
/** If PortInst name matches Export name then export PortInst and
* remove PortInst and export name from respective lists. */
private void exportPortInstsWithMatchingNames(List<String> expNames,
List<PortInst> ports) {
for (Iterator<String> sIt=expNames.iterator(); sIt.hasNext();) {
String expNm = sIt.next();
for (Iterator<PortInst> pIt=ports.iterator(); pIt.hasNext();) {
PortInst pi = pIt.next();
String portNm = pi.getPortProto().getName();
if (expNm.equals(portNm)) {
Export.newInstance(pi.getNodeInst().getParent(),
pi, expNm);
sIt.remove();
pIt.remove();
break;
}
}
}
}
private void exportTheRest(List<String> expNames, List<PortInst> ports) {
for (int i=0; i<expNames.size(); i++) {
String expNm = expNames.get(i);
if (i>=ports.size()) {
prln("Error: Schematic export: "+expNm+
" couldn't be added to layout");
continue;
}
PortInst pi = ports.get(i);
Export.newInstance(pi.getNodeInst().getParent(),
pi, expNm);
}
}
/** Re-export all ports that the schematic exports. Don't do power
* and ground because they are handled by another method.
* There are three criteria for selecting which PortInst to export. First,
* prefer a PortInst with the same as the export. Second, prefer a PortInst
* without connections. Third, prefer a PortInst that is close to the cell
* boundary. */
private void reExport(Cell layCell, List<ToConnect> toConns) {
Rectangle2D colBounds = Utils.findBounds(layCell);
CloseToBound closeToBound = new CloseToBound(colBounds);
for (ToConnect tc : toConns) {
if (tc.numPortInsts()>0 && tc.isExported() && !tc.isPowerOrGround()) {
// separate out connected and not connected PortInsts
// Because PortInst.hasConnections() is so slow, make sure
// we do this test once. Keeping two different lists accomplishes
// this.
List<PortInst> unconnPorts = new ArrayList<PortInst>();
List<PortInst> connPorts = new ArrayList<PortInst>();
for (PortInst pi : tc.getPortInsts()) {
if (pi.hasConnections()) connPorts.add(pi);
else unconnPorts.add(pi);
}
Collections.sort(connPorts, closeToBound);
Collections.sort(unconnPorts, closeToBound);
// allPorts sorted by following criterea in order of importance:
// 1) no arcs connected
// 2) distance to boundary
List<PortInst> allPorts = new ArrayList<PortInst>();
allPorts.addAll(unconnPorts);
allPorts.addAll(connPorts);
List<String> expNames = new ArrayList<String>();
expNames.addAll(tc.getExportName());
exportPortInstsWithMatchingNames(expNames, allPorts);
exportTheRest(expNames, allPorts);
}
}
}
private static class CompareLayInstSchPos implements Comparator<NodeInst> {
Map<NodeInst, SchematicPosition> layInstToSchPos;
public int compare(NodeInst ni1, NodeInst ni2) {
SchematicPosition sp1, sp2;
sp1 = layInstToSchPos.get(ni1);
sp2 = layInstToSchPos.get(ni2);
return sp1.compareTo(sp2);
}
public CompareLayInstSchPos(Map<NodeInst, SchematicPosition> layInstToSchPos) {
this.layInstToSchPos = layInstToSchPos;
}
}
// sort layout instances according to X-coordinate in schematic
private List<NodeInst> getSortedLayInsts(SchematicVisitor visitor) {
List<NodeInst> layInsts =
new ArrayList<NodeInst>(visitor.getLayInsts());
Map<NodeInst, SchematicPosition> layInstSchPos =
visitor.getLayInstSchematicPositions();
CompareLayInstSchPos compareLayInstSchPos =
new CompareLayInstSchPos(layInstSchPos);
Collections.sort(layInsts, compareLayInstSchPos);
return layInsts;
}
private Map<Cell,Integer> getCellCounts(List<NodeInst> layInsts) {
Map<Cell,Integer> cellToCount = new HashMap<Cell,Integer>();
for (NodeInst ni : layInsts) {
Cell c = (Cell) ni.getProto();
Integer cnt = cellToCount.get(c);
if (cnt==null) cnt = 0;
cellToCount.put(c, cnt+1);
}
return cellToCount;
}
// Print report in the same order as sortedLayInsts
private void printInstanceReport(List<NodeInst> sortedLayInsts) {
prln("Here are the Cell's I've instantiated: ");
Map<Cell,Integer> cellToCount = getCellCounts(sortedLayInsts);
for (NodeInst ni : sortedLayInsts) {
Cell c = (Cell) ni.getProto();
Integer cnt = cellToCount.get(c);
if (cnt!=null) {
prln(" "+cnt+" "+c.describe(false));
// Only print report the first time we encounter the Cell
cellToCount.remove(c);
}
}
}
// private boolean isPlain(NodeInst ni) {
// return ni.getProto().getName().contains("aPlainStage");
// }
//
// // infinityA and infinityB need to be stretched to the height of infinityC
// private void stretchInfinityAB(List<NodeInst> layInsts) {
// Cell parent = layInsts.get(0).getParent();
// Cell dummyStage = STAGE_LIB.findNodeProto("aDummyStage{lay}");
// if (!layInsts.get(0).getParent().getName().contains("infinityA") &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -