📄 schemtolay.java
字号:
return true; } return false; } } // ----------------------------- private data ----------------------------- static final PortFilter SKIP_WIRE_PORTINSTS = new SkipWirePortInsts(); private static void error(boolean pred, String msg) { LayoutLib.error(pred, msg); } private static double getNumericVal(Object val) { if (val==null) { System.out.println("null value detected, using 40"); return 40; } if (val instanceof Number) { return ((Number)val).doubleValue(); } error(true, "not a numeric value: "+val); return 0; } private static Cell getPurpleLay(NodeInst iconInst, VarContext context, StdCellParams stdCell) { TechType tech = stdCell.getTechType(); NodeProto prot = iconInst.getProto(); String pNm = prot.getName(); // we actually generate layout for two primitive nodes: Power and Ground if (!iconInst.isCellInstance()) { if (pNm.equals("Power")) { return TieHi.makePart(stdCell); } else if (pNm.equals("Ground")) { //return TieLo.makePart(stdCell); } error(true, "can't generate layout for PrimitiveNode: "+pNm); } // Keepers require special handling because they don't have sizes // attached to them. Instead, the components making up keepers // have sizes attached. We need to pass the schematic // implementing the keeper to the keeper generator. if (pNm.equals("keeper_high{ic}")) { NodeProto npe = ((Cell)iconInst.getProto()).getEquivalent(); return KeeperHigh.makePart((Cell)npe, context.push(iconInst), stdCell); } else if (pNm.equals("keeper_low{ic}")) { NodeProto npe = ((Cell)iconInst.getProto()).getEquivalent(); return KeeperLow.makePart((Cell)npe, context.push(iconInst), stdCell); } Variable var = iconInst.getParameterOrVariable(tech.getAttrS()); if (var==null) var = iconInst.getParameterOrVariable(tech.getAttrSP()); if (var==null) var = iconInst.getParameterOrVariable(tech.getAttrSN()); if (var==null) var = iconInst.getParameterOrVariable(tech.getAttrX()); double x = getNumericVal(context.evalVar(var)); //System.out.println("Gate Type: " + pNm + ", Gate Size: " + x); // Daniel StdCellParams sc = stdCell; if (pNm.equals("nms1{ic}")) return Nms1.makePart(x, sc); else if (pNm.equals("nms1K{ic}")) return Nms1.makePart(x, sc); else if (pNm.equals("nms2{ic}")) return Nms2.makePart(x, sc); else if (pNm.equals("nms2_sy{ic}")) return Nms2_sy.makePart(x, sc); else if (pNm.equals("nms3_sy3{ic}")) return Nms3_sy3.makePart(x, sc); else if (pNm.equals("pms1{ic}")) return Pms1.makePart(x, sc); else if (pNm.equals("pms1K{ic}")) return Pms1.makePart(x, sc); else if (pNm.equals("pms2{ic}")) return Pms2.makePart(x, sc); else if (pNm.equals("pms2_sy{ic}")) return Pms2_sy.makePart(x, sc); else if (pNm.equals("inv{ic}")) return Inv.makePart(x, sc); else if (pNm.equals("invCTLn{ic}")) return InvCTLn.makePart(x, sc); // for Daniel else if (pNm.equals("inv_ll{ic}")) return Inv.makePart(x, sc); else if (pNm.equals("inv_passgate{ic}")) return Inv_passgate.makePart(x, sc); else if (pNm.equals("inv2i{ic}")) return Inv2i.makePart(x, sc); else if (pNm.equals("inv2iKp{ic}")) return Inv2iKp.makePart(x, sc); else if (pNm.equals("inv2iKn{ic}")) return Inv2iKn.makePart(x, sc); else if (pNm.equals("invLT{ic}")) return InvLT.makePart(x, sc); else if (pNm.equals("invHT{ic}")) return InvHT.makePart(x, sc); else if (pNm.equals("nand2{ic}")) return Nand2.makePart(x, sc); else if (pNm.equals("nand2k{ic}")) return Nand2.makePart(x, sc); else if (pNm.equals("nand2en{ic}")) return Nand2en.makePart(x, sc); else if (pNm.equals("nand2en_sy{ic}")) return Nand2en_sy.makePart(x, sc); else if (pNm.equals("nand2HLT{ic}")) return Nand2HLT.makePart(x, sc); else if (pNm.equals("nand2LT{ic}")) return Nand2LT.makePart(x, sc); else if (pNm.equals("nand2_sy{ic}")) return Nand2_sy.makePart(x, sc); else if (pNm.equals("nand2HLT_sy{ic}")) return Nand2HLT_sy.makePart(x, sc); else if (pNm.equals("nand2LT_sy{ic}")) return Nand2LT_sy.makePart(x, sc); else if (pNm.equals("nand2PH{ic}")) return Nand2PH.makePart(x, sc); else if (pNm.equals("nand2PHfk{ic}")) return Nand2PHfk.makePart(x, sc); else if (pNm.equals("nand3{ic}")) return Nand3.makePart(x, sc); else if (pNm.equals("nand3MLT{ic}")) return Nand3MLT.makePart(x, sc); else if (pNm.equals("nand3LT{ic}")) return Nand3LT.makePart(x, sc); else if (pNm.equals("nand3_sy3{ic}")) return Nand3_sy3.makePart(x, sc); else if (pNm.equals("nand3en_sy{ic}")) return Nand3en_sy.makePart(x, sc); else if (pNm.equals("nand3LT_sy3{ic}")) return Nand3LT_sy3.makePart(x, sc); else if (pNm.equals("nand3en_sy3{ic}")) return Nand3en_sy3.makePart(x, sc); else if (pNm.equals("nor2{ic}")) return Nor2.makePart(x, sc); else if (pNm.equals("nor2LT{ic}")) return Nor2LT.makePart(x, sc); else if (pNm.equals("nor2kresetV{ic}")) return Nor2kresetV.makePart(x, sc); // patch for Robert Drost else if (pNm.equals("invK{ic}")) return Inv.makePart(x, sc); else { error(true, "Don't know how to generate layout for schematic icon: "+ pNm); return null; } } private static boolean isNstkNm(String nm) { return nm.startsWith("nms1") || nm.startsWith("nms2") || nm.startsWith("NmosWellTie"); } private static boolean isPstkNm(String nm) { return nm.startsWith("pms1") || nm.startsWith("pms2") || nm.startsWith("PmosWellTie"); }// private static boolean isNstk(Cell c) {// return isNstkNm(c.getName());// }// private static boolean isPstk(Cell c) {// return isPstkNm(c.getName());// } private static boolean isNstk(NodeInst ni) { return isNstkNm(ni.getProto().getName()); } private static boolean isPstk(NodeInst ni) { return isPstkNm(ni.getProto().getName()); } private static boolean isUsefulIconInst(NodeInst ni, Cell schematic) { if (ni.isIconOfParent()) return false; NodeProto np = ni.getProto(); if (!ni.isCellInstance()) { // Power and Ground symbols mean we need to connect this net to // vdd or gnd. if (np.getName().equals("Power") || np.getName().equals("Ground")) return true; // skip all other primitive drawing nodes such as wire pins, // off-page. return false; } Cell c = (Cell) np; // skip anything that's not an Icon View if (!c.getView().getFullName().equals("icon")) return false; if (c.getName().equals("wire{ic}")) return false; return true; } // Return layout instances. iconToLay maps from the icon instance to // the layout instance. private static void makeLayoutInsts(ArrayList<NodeInst> layInsts, HashMap<NodeInst,NodeInst> iconToLay, Cell schematic, Cell gasp, VarContext context, StdCellParams stdCell) { Iterator<NodeInst> iconInsts = schematic.getNodes(); while (iconInsts.hasNext()) { NodeInst iconInst = iconInsts.next(); if (!isUsefulIconInst(iconInst, schematic)) continue; Cell lay = getPurpleLay(iconInst, context, stdCell); NodeInst layInst = LayoutLib.newNodeInst(lay, 0, 0, 1, 1, 0, gasp); iconToLay.put(iconInst, layInst); layInsts.add(layInst); } } // Sort nets to reduce non-determinism. This isn't totally // satisfactory because only nets with names will be ordered. private static ArrayList<Network> sortNets(Iterator<Network> nets) { ArrayList<Network> sortedNets = new ArrayList<Network>(); while (nets.hasNext()) {sortedNets.add(nets.next());} Comparator<Network> netNmComp = new Comparator<Network>() { public int compare(Network n1, Network n2) { Iterator<String> nms1 = n1.getNames(); Iterator<String> nms2 = n2.getNames(); if (!nms1.hasNext() && !nms2.hasNext()) { // neither net has a name return 0; } else if (!nms1.hasNext()) { return 1; } else if (!nms2.hasNext()) { return -1; } String nm1 = nms1.next(); String nm2 = nms2.next(); return nm1.compareTo(nm2); } }; Collections.sort(sortedNets, netNmComp); return sortedNets; } // Build route segments and sort them into two groups. // // 1) stkSegs: segments with N-stacks but no P-stacks and segments // with P-stacks but no N-stacks // // 2) noStkSegs: segments with neither N-stacks nor P-stacks. // // Nets with both N-stacks and P-stacks are divided into two // segments, one N-stack only, and one P-stack only. If nets of // this type don't have at least one non-stack device then we need // to generate an additional part that contains a vertical routing // channel for connecting the two segments. private static void buildRouteSegs(ArrayList<RouteSeg> stkSegs, ArrayList<RouteSeg> noStkSegs, ArrayList<NodeInst> vertTracks, Iterator<Network> nets, HashMap<NodeInst,NodeInst> iconToLay, HashMap<String,Object> expTrkAsgn, StdCellParams stdCell, Cell gasp) { ArrayList<Network> sortedNets = sortNets(nets); for (int i=0; i<sortedNets.size(); i++) { Network net = sortedNets.get(i); RouteSeg r = new RouteSeg(net, iconToLay, expTrkAsgn); if (r.getAllPorts().size()==0) { // Schematic net had nothing useful attached to it } else if (r.hasNstk() && r.hasPstk()) { RouteSeg pr = r.splitOffPstkRouteSeg(vertTracks, stdCell, gasp); stkSegs.add(r); stkSegs.add(pr); } else if (r.hasNstk() || r.hasPstk()) { stkSegs.add(r); } else { noStkSegs.add(r); } } } private static void sortPortsLeftToRight(ArrayList<PortInst> ports) { Comparator<PortInst> compare = new Comparator<PortInst>() { public int compare(PortInst p1, PortInst p2) { double diff = LayoutLib.roundCenterX(p1) - LayoutLib.roundCenterX(p2); if (diff<0) return -1; if (diff==0) return 0; return 1; } }; Collections.sort(ports, compare); } private static void metal1route(PortInst prev, PortInst port, TechType tech) { NodeInst prevInst = prev.getNodeInst(); // If one gate is half height and the other full height then we // must route horizontally from the half height gate first because // the half height gate doesn't have a full vertical metal-1 // channel. if (isNstk(prevInst) || isPstk(prevInst)) { LayoutLib.newArcInst(tech.m1(), 4, prev, port); } else { // prev is full height so route vertically from prev LayoutLib.newArcInst(tech.m1(), 4, port, prev); } } // Try to route physically adjacent ports in metal-1. If we connect // a pair of ports in metal-1, then remove the first of the two // ports from the port list so the Track FillRouter doesn't connect them // also. // // The list of ports must be sorted in X from lowest to hightest. private static void metal1route(ArrayList<PortInst> ports, TechType tech) { final double ADJACENT_DIST = 7; for (int i=1; i<ports.size(); i++) { PortInst prev = ports.get(i-1); PortInst port = ports.get(i); double dx = LayoutLib.roundCenterX(port) - LayoutLib.roundCenterX(prev); error(dx<=0, "metal1route: ports not sorted left to right!"); if (dx<=ADJACENT_DIST) { metal1route(prev, port, tech); // Remove prev and back up so we consider the port that moves // into index i as a result of the deletion. ports.remove(--i); } prev = port; } } private static void connectSegment(RouteSeg r, TrackAllocator trackAlloc, StdCellParams stdCell, Cell gasp) { TechType tech = stdCell.getTechType(); ArrayList<PortInst> ports = r.getAllPorts(); sortPortsLeftToRight(ports); // first route physically adjacent ports in metal-1 metal1route(ports, tech); // Don't allocate a metal-2 track if the net is internal and there // is nothing left to connect in metal-2. if (ports.size()<=1 && !r.hasExports()) return; double trackY = r.hasExpTrk() ? ( stdCell.getPhysTrackY(r.getExpTrk()) ) : ( trackAlloc.getTrackY(r, 4.0) ); //if (r.hasExpTrk()) { //System.out.println("Using assigned track: "+trackY); //} TrackRouter route = new TrackRouterH(tech.m2(), 4.0, trackY, tech, gasp); // connect RouteSeg's exports Iterator<Export> expIt = r.findExports(); while (expIt.hasNext()) { Export exp = expIt.next(); String expNm = exp.getName(); // Align the export with left most port // RKao debug error(ports.size()==0, "No device ports on this net?: "+expNm); double x = LayoutLib.roundCenterX(ports.get(0)); LayoutLib.newExport(gasp, expNm, exp.getCharacteristic(), tech.m2(), 4, x, trackY); route.connect(gasp.findExport(expNm)); } // connect RouteSeg's ports route.connect(ports); } private static void connectSegments(TrackAllocator trackAlloc, ArrayList<RouteSeg> segs, boolean exports,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -