router.java
来自「The ElectricTM VLSI Design System is an 」· Java 代码 · 共 699 行 · 第 1/2 页
JAVA
699 行
DEF_SIZE, DEF_SIZE, 0, parent);
// left vertical m1
LayoutLib.newArcInst(tech().m1(), config.signalWid,
pL, m1m2a.getOnlyPortInst());
m2PortA = m1m2a.getOnlyPortInst();
} else {
// left port connects to m2
m2PortA = pL;
}
PortInst m2PortB = null;
if (connectsToM1(pR)) {
// right port connects to m1
NodeInst m1m2b =
LayoutLib.newNodeInst(tech().m1m2(),
pR.getCenter().getX(),
m2R.getTrackCenter(),
DEF_SIZE, DEF_SIZE, 0, parent);
LayoutLib.newArcInst(tech().m1(), config.signalWid,
m1m2b.getOnlyPortInst(),
pR);
m2PortB = m1m2b.getOnlyPortInst();
} else {
m2PortB = pR;
}
if (m3!=null) {
NodeInst m2m3a =
LayoutLib.newNodeInst(tech().m2m3(),
m3.getTrackCenter(),
m2L.getTrackCenter(),
DEF_SIZE, DEF_SIZE, 0, parent);
// left horizontal m2
newM2SignalWire(m2PortA, m2m3a.getOnlyPortInst());
NodeInst m2m3b =
LayoutLib.newNodeInst(tech().m2m3(),
m3.getTrackCenter(),
m2R.getTrackCenter(),
DEF_SIZE, DEF_SIZE, 0, parent);
// vertical m3
LayoutLib.newArcInst(tech().m3(), config.signalWid,
m2m3a.getOnlyPortInst(),
m2m3b.getOnlyPortInst());
// right horizontal m2
newM2SignalWire(m2m3b.getOnlyPortInst(), m2PortB);
} else {
newM2SignalWire(m2PortA, m2PortB);
}
}
public void newM2SignalWire(PortInst p1, PortInst p2) {
PortInst pL, pR;
if (p1.getCenter().getX()<p2.getCenter().getX()) {
pL=p1; pR=p2;
} else {
pL=p2; pR=p1;
}
Cell parent = pL.getNodeInst().getParent();
double y = p1.getCenter().getY();
double yR = p2.getCenter().getY();
error(y!=yR, "M2 must be horizontal");
double xL = pL.getCenter().getX();
double xR = pR.getCenter().getX();
double len = xR-xL;
double extend = config.minM2Len - (len + config.signalWid);
if (extend > 0) {
// round extention to tenths of a lambda
double halfExt = Math.ceil(10*extend/2)/10;
//prln("halfExt: "+halfExt);
// add additional m2 to this wire
NodeInst pin1 = LayoutLib.newNodeInst(tech().m2pin(), xL-halfExt, y,
DEF_SIZE, DEF_SIZE, 0,
parent);
NodeInst pin2 = LayoutLib.newNodeInst(tech().m2pin(), xR+halfExt, y,
DEF_SIZE, DEF_SIZE, 0,
parent);
LayoutLib.newArcInst(tech().m2(), config.signalWid,
pin1.getOnlyPortInst(), pL);
LayoutLib.newArcInst(tech().m2(), config.signalWid,
pR, pin2.getOnlyPortInst());
}
LayoutLib.newArcInst(tech().m2(), config.signalWid, pL, pR);
}
private boolean connectsToM1(PortProto pp) {
return pp.connectsTo(tech().m1());
}
private boolean connectsToM1(PortInst pi) {
return connectsToM1(pi.getPortProto());
}
private boolean connectsToM2(PortProto pp) {
return pp.connectsTo(tech().m2());
}
public boolean connectsToM2(PortInst pi) {
return connectsToM2(pi.getPortProto());
}
private boolean connectsToM3(PortProto pp) {
return pp.connectsTo(tech().m3());
}
public boolean connectsToM3(PortInst pi) {
return connectsToM3(pi.getPortProto());
}
private boolean hasM2Pin(ToConnect toConn) {
for (PortInst pi : toConn.getPortInsts()) {
if (connectsToM2(pi)) return true;
}
return false;
}
private boolean hasM3Pin(ToConnect toConn) {
for (PortInst pi : toConn.getPortInsts()) {
if (connectsToM3(pi)) return true;
}
return false;
}
public void connectPwrGnd(List<NodeInst> nodeInsts) {
List<ArcProto> vertLayers = new ArrayList<ArcProto>();
vertLayers.add(tech().m3());
NodeInst prev = null;
for (NodeInst ni : nodeInsts) {
if (prev!=null) {
AbutRouter.abutRouteBotTop(prev, ni, 0, vertLayers);
}
prev = ni;
}
}
public Router(FlagConfig config, Scan scan) {
this.config = config; this.scan = scan;
}
public PortInst raiseToM3(PortInst pi) {
if (connectsToM3(pi)) return pi;
if (connectsToM2(pi)) {
double x = pi.getBounds().getCenterX();
double y = pi.getBounds().getCenterY();
Cell parent = pi.getNodeInst().getParent();
NodeInst via =
LayoutLib.newNodeInst(tech().m2m3(), x, y,
FlagDesign.DEF_SIZE, FlagDesign.DEF_SIZE, 0, parent);
newM2SignalWire(pi, via.getOnlyPortInst());
return via.getOnlyPortInst();
}
Utils.error(true, "scan port on other than m2 or m3?");
return null;
}
/** Find which PortInsts are already connected. Stick connected PortInsts
* into a list. Return a list of such lists. */
private List<List<PortInst>> groupConnectedPorts(ToConnect tc) {
PortInst firstPi = tc.getPortInsts().get(0);
Cell parent = firstPi.getNodeInst().getParent();
Netlist nl = parent.getNetlist(ShortResistors.PARASITIC);
Map<Network, List<PortInst>> netToPorts =
new HashMap<Network, List<PortInst>>();
for (PortInst pi : tc.getPortInsts()) {
Network n = nl.getNetwork(pi);
List<PortInst> ports = netToPorts.get(n);
if (ports==null) {
ports = new ArrayList<PortInst>();
netToPorts.put(n, ports);
}
ports.add(pi);
}
List<List<PortInst>> groupedPorts = new ArrayList<List<PortInst>>();
for (Network n : netToPorts.keySet()) {
groupedPorts.add(netToPorts.get(n));
}
return groupedPorts;
}
private double manhDist(PortInst pi1, PortInst pi2) {
return Math.abs(pi1.getCenter().getX()-pi2.getCenter().getX()) +
Math.abs(pi1.getCenter().getY()-pi2.getCenter().getY());
}
private static class PortPair {
public PortInst p1, p2;
public double dist;
}
private PortPair findClosest(List<PortInst> pl1, List<PortInst> pl2) {
PortPair closest = new PortPair();
closest.dist = Double.MAX_VALUE;
for (PortInst p1 : pl1) {
for (PortInst p2 : pl2) {
double d = manhDist(p1, p2);
if (d<closest.dist) {
closest.dist = d;
closest.p1 = p1;
closest.p2 = p2;
}
}
}
error(closest.dist==Double.MAX_VALUE,
"empty port lists?");
return closest;
}
private static class ClosestClusters {
public int ndx1, ndx2;
public PortPair pair = new PortPair();
}
private ClosestClusters findClosest(List<List<PortInst>> portLists) {
ClosestClusters closest = new ClosestClusters();
closest.pair.dist = Double.MAX_VALUE;
for (int i=0; i<portLists.size(); i++) {
for (int j=i+1; j<portLists.size(); j++) {
PortPair pair = findClosest(portLists.get(i), portLists.get(j));
if (pair.dist<closest.pair.dist) {
closest.pair = pair;
closest.ndx1 = i;
closest.ndx2 = j;
}
}
}
return closest;
}
private void dumpConnPorts(List<List<PortInst>> connPorts) {
prln("Clustered port connections:");
for (List<PortInst> ports : connPorts) {
pr(" cluster: ");
for (PortInst port : ports) pr(port.toString()+" ");
prln("");
}
}
// return true if ok
private boolean isSimple(List<List<PortInst>> connPorts) {
// if no cluster then nothing to connect
// if one cluster then everything already connected
if (connPorts.size()==0 || connPorts.size()==1) return true;
if (connPorts.size()==2 || connPorts.size()==3) {
for (List<PortInst> ports : connPorts) {
if (ports.size()!=1) {
prln("Can't handle pre-connected PortInsts");
dumpConnPorts(connPorts);
return false;
}
}
return true;
}
prln("Can't handle Nets that connect more than three PortInsts:");
dumpConnPorts(connPorts);
return false;
}
private List<ToConnect> reduceToTwoOrThreePin(List<ToConnect> toConns) {
List<ToConnect> twoOrThreePin = new ArrayList<ToConnect>();
for (ToConnect tc : toConns) {
// Skip Exported net that touches no stage PortInsts
if (tc.numPortInsts()==0) continue;
// Some PortInsts on a ToConnect may already be connected in
// schematic by abut router or by scan chain stitcher
List<List<PortInst>> connPorts = groupConnectedPorts(tc);
if (connPorts.size()==2) connPorts = makeTwoClusterSimple(connPorts);
// make sure this routing problem is simple
if (!isSimple(connPorts)) continue;
if (connPorts.size()==2 || connPorts.size()==3) {
ToConnect tcX = new ToConnect();
for (List<PortInst> ports : connPorts) {
error(ports.size()!=1, "We only allow one port per cluster");
tcX.addPortInst(ports.get(0));
}
twoOrThreePin.add(tcX);
}
}
return twoOrThreePin;
}
/** Special case. If a net has exactly two clusters, it only needs one connection
* between two PortInsts. Return those two PortInsts. */
private List<List<PortInst>> makeTwoClusterSimple(List<List<PortInst>> portLists) {
error(portLists.size()!=2, "only handle 2 clusters");
ClosestClusters cc = findClosest(portLists);
List<List<PortInst>> pls = new ArrayList<List<PortInst>>();
List<PortInst> pl = new ArrayList<PortInst>();
pl.add(cc.pair.p1);
pls.add(pl);
pl = new ArrayList<PortInst>();
pl.add(cc.pair.p2);
pls.add(pl);
return pls;
}
private void getM3PwrGndExports(Map<Double, PortInst> pwr, Map<Double, PortInst> gnd,
NodeInst ni, double y) {
for (Iterator piIt=ni.getPortInsts(); piIt.hasNext();) {
PortInst pi = (PortInst) piIt.next();
if (pi.getCenter().getY()!=y) continue;
if (!connectsToM3(pi)) continue;
double x = pi.getCenter().getX();
if (Utils.isPwr(pi)) pwr.put(x, pi);
else if (Utils.isGnd(pi)) gnd.put(x, pi);
}
}
private void route(List<ToConnect> toConns, LayerChannels m2Chan,
LayerChannels m3Chan) {
// Connect m3 pins using vertical m3
// for (ToConnect toConn : toConns) {
// if (hasM3Pin(toConn)) connect2PinM3(toConn);
// }
// We must route nets with m2 pins first because m2 pins allow us no
// choice of m2 track.
for (ToConnect toConn : toConns) {
if (hasM2Pin(toConn)) routeTwoOrThreePinNet(toConn, m2Chan, m3Chan);
}
for (ToConnect toConn : toConns) {
if (!hasM2Pin(toConn) && !hasM3Pin(toConn))
routeTwoOrThreePinNet(toConn, m2Chan, m3Chan);
}
}
public void routeSignals(List<ToConnect> toConns, LayoutNetlist layNets) {
List<NodeInst> layInsts = layNets.getLayoutInstancesSortedBySchematicPosition();
if (layInsts.size()==0) return;
List<ToConnect> twoOrThreePins = reduceToTwoOrThreePin(toConns);
LayerChannels m2chan = new LayerChannels();
LayerChannels m3chan = new LayerChannels();
findChannels(m2chan, m3chan, layInsts);
// // debug
// prln("Metal 2 channels");
// prln(m2chan.toString());
//
// prln("Metal 3 channels");
// prln(m3chan.toString());
route(twoOrThreePins, m2chan, m3chan);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?