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 + -
显示快捷键?