📄 sue.java
字号:
String arg = pt.substring(argStart, ptPos++); // parse the argument into key and value int argPos = 0; int argLen = arg.length(); if (argPos < argLen && arg.charAt(argPos) == '{') { argPos++; if (arg.endsWith("}")) arg = arg.substring(0, --argLen); } int keyStart = argPos; while (argPos < argLen && arg.charAt(argPos) != ' ') argPos++; String key = arg.substring(keyStart, argPos); while (argPos < argLen && arg.charAt(argPos) == ' ') argPos++; String value = arg.substring(argPos); if (value.startsWith("{")) { value = value.substring(1); if (value.endsWith("}")) value = value.substring(0, value.length()-1); } argumentKey.add(key); argumentValue.add(value); } continue; } // handle "icon_property" for defining icon strings if (keyword0.equalsIgnoreCase("icon_property")) { // extract parameters ParseParameters parP = new ParseParameters(keywords, 1); if (parP.theLabel == null) continue; // substitute parameters StringBuffer infstr = new StringBuffer(); for(int i=0; i<parP.theLabel.length(); i++) { char chr = parP.theLabel.charAt(i); if (chr == '$') { String partial = parP.theLabel.substring(i+1); int j = 0; for( ; j<argumentKey.size(); j++) { String key = argumentKey.get(j); if (partial.startsWith(key)) break; } if (j < argumentKey.size()) { infstr.append(argumentValue.get(j)); i += argumentKey.get(j).length(); continue; } } infstr.append(chr); } parP.theLabel = infstr.toString(); NodeInst ni = NodeInst.makeInstance(Generic.tech().invisiblePinNode, parP.pt, 0, 0, cell); if (ni == null) continue; ni.newDisplayVar(Artwork.ART_MESSAGE, parP.theLabel); continue; } // handle "make_text" for placing strings if (keyword0.equalsIgnoreCase("make_text")) { // extract parameters ParseParameters parP = new ParseParameters(keywords, 1); if (parP.theText == null) continue; NodeInst ni = NodeInst.makeInstance(Generic.tech().invisiblePinNode, parP.pt, 0, 0, cell); if (ni == null) continue; if (parP.theText.startsWith("^")) { ni.newVar(Spice.SPICE_CARD_KEY, parP.theText.substring(1), TextDescriptor.getAnnotationTextDescriptor().withColorIndex(EGraphics.BLUE)); } else { ni.newDisplayVar(Artwork.ART_MESSAGE, parP.theText); } continue; } // ignore known keywords if (keyword0.equalsIgnoreCase("icon_title") || keyword0.equalsIgnoreCase("make_line") || keyword0.equalsIgnoreCase("}")) { continue; } System.out.println("Cell " + cellName + ", line " + lr.getLineNumber() + ": unknown keyword (" + keyword0 + "): " + lastLineRead); } // place an icon instance in the schematic if requested if (placeIcon && schemCell != null && iconCell != null) { Rectangle2D bounds = iconCell.getBounds(); double wid = bounds.getWidth(); double hei = bounds.getHeight(); NodeInst ni = NodeInst.makeInstance(iconCell, iconPt, wid, hei, schemCell); if (ni != null) ni.setExpanded(); } // make warnings about duplicate names for(String name : duplicateNames.keySet()) { List<NodeInst> dups = duplicateNames.get(name); System.out.print("Cell " + cell.getName() + " has multiple nodes with the same Sue name (" + name + "):"); for(NodeInst ni : dups) System.out.print(" " + ni.describe(false)); System.out.println(); } // cleanup the current cell if (cell != null) { placeWires(sueWires, sueNets, cell, invertNodeOutput); placeNets(sueNets, cell); } // return the cell if (schemCell != null) return schemCell; return iconCell; } /** * Method to create a port called "thename" on port "pp" of node "ni" in cell "cell". * The name is modified if it already exists. */ private Export newExport(Cell cell, PortInst pi, String theName, PortCharacteristic pc) { String portName = theName; for(int i=0; ; i++) { Export ppt = (Export)cell.findPortProto(portName); if (ppt == null) { return Export.newInstance(cell, pi, portName, pc); } // make space for modified name int openPos = theName.indexOf('['); if (openPos < 0) portName = theName + "-" + i; else { portName = theName.substring(0, openPos) + "-" + i + theName.substring(openPos); } } } /** * Method to find the pin at (x, y) and return it. */ private PortInst findPinNode(double x, double y, Cell cell) { Rectangle2D searchBounds = new Rectangle2D.Double(x, y, 0, 0); for(Iterator<RTBounds> sea = cell.searchIterator(searchBounds); sea.hasNext(); ) { RTBounds geom = sea.next(); if (!(geom instanceof NodeInst)) continue; NodeInst ni = (NodeInst)geom; // find closest port for(Iterator<PortInst> it = ni.getPortInsts(); it.hasNext(); ) { PortInst pi = it.next(); Poly poly = pi.getPoly(); if (poly.getCenterX() == x && poly.getCenterY() == y) return pi; } } return null; } /** * Method to find the SUE file "name" on disk, and read it into library "lib". * Returns NONODEPROTO if the file is not found or not read properly. */ private NodeProto readFromDisk(Library lib, String name) { // look for another "sue" file that describes this cell for(String directory : sueDirectories) { // get the directory String subFileName = directory + name + ".sue"; // see if the file exists in the directory LineNumberReader lr = null; try { FileInputStream fis = new FileInputStream(subFileName); InputStreamReader is = new InputStreamReader(fis); lr = new LineNumberReader(is); } catch (FileNotFoundException e) { continue; } if (lr == null) continue; // read the file try { String saveLastLine = sueLastLine; sueLastLine = null; readFile(lib, name, lr); sueLastLine = saveLastLine; Cell cell = lib.findNodeProto(name); if (cell != null) return cell; } catch (IOException e) { System.out.println("ERROR reading Sue libraries"); } } return null; } /** * Method to find cell "protoname" in library "lib". */ private NodeProto getNodeProto(Library lib, String protoname) { for(Iterator<Cell> it = lib.getCells(); it.hasNext(); ) { Cell cell = it.next(); if (cell.getName().equalsIgnoreCase(protoname)) { Cell icon = cell.iconView(); if (icon != null) return icon; return cell; } } return null; } private static class ParseParameters { int count; Point2D pt; int rot; boolean trn; PortCharacteristic type; String theName; String theLabel; String theText; /** * Method to parse the "count" parameters in "keywords" and fill in the values * that are found. Fills in: * "-origin" placed into "x" and "y" * "-orient" placed into "rot" and "trn" * "-type" placed into "type" * "-name" placed into "thename". * "-label" placed into "thelabel". * "-text" placed into "thetext". */ private ParseParameters(List<String> keywords, int start) { rot = 0; pt = null; trn = false; type = PortCharacteristic.UNKNOWN; theName = null; theLabel = null; theText = null; for(int i=start; i<keywords.size(); i += 2) { String keyword = keywords.get(i); String param = ""; if (i+1 < keywords.size()) param = keywords.get(i+1); if (keyword.equalsIgnoreCase("-origin")) { int j = 0; if (param.charAt(j) == '{') j++; double x = TextUtils.atof(param.substring(j)); while (j < param.length()-1 && !Character.isWhitespace(param.charAt(j))) j++; while (j < param.length()-1 && Character.isWhitespace(param.charAt(j))) j++; double y = TextUtils.atof(param.substring(j)); pt = new Point2D.Double(convertXCoord(x), convertYCoord(y)); } if (keyword.equalsIgnoreCase("-orient")) { if (param.equalsIgnoreCase("R90")) { rot = 900; } else if (param.equalsIgnoreCase("R270")) { rot = 2700; } else if (param.equalsIgnoreCase("RXY")) { rot = 1800; } else if (param.equalsIgnoreCase("RY")) { rot = 900; trn = true; } else if (param.equalsIgnoreCase("R90X")) { rot = 0; trn = true; } else if (param.equalsIgnoreCase("R90Y")) { rot = 1800; trn = true; } else if (param.equalsIgnoreCase("RX")) { rot = 2700; trn = true; } rot = (3600 - rot) % 3600; } if (keyword.equalsIgnoreCase("-type")) { if (param.equalsIgnoreCase("input")) type = PortCharacteristic.IN; else if (param.equalsIgnoreCase("output")) type = PortCharacteristic.OUT; else if (param.equalsIgnoreCase("inout")) type = PortCharacteristic.BIDIR; } if (keyword.equalsIgnoreCase("-name") || keyword.equalsIgnoreCase("-label") || keyword.equalsIgnoreCase("-text")) { String infstr = param; if (infstr.startsWith("{") && infstr.endsWith("}")) { int len = infstr.length(); infstr = infstr.substring(1, len-1); } if (keyword.equalsIgnoreCase("-name")) theName = infstr; else if (keyword.equalsIgnoreCase("-label")) theLabel = infstr; else if (keyword.equalsIgnoreCase("-text")) theText = infstr; } } } } /** * Method to place all SUE wires into the cell. */ private void placeWires(List<SueWire> sueWires, List<SueNet> sueNets, Cell cell, Set invertNodeOutput) { // mark all wire ends as "unassigned", all wire types as unknown for(SueWire sw : sueWires) { sw.pi[0] = sw.pi[1] = null; sw.proto = null; } // examine all network names and assign wire types appropriately for(SueNet sn : sueNets) { for(SueWire sw : sueWires) { for(int i=0; i<2; i++) { if (sw.pt[i].getX() == sn.pt.getX() && sw.pt[i].getY() == sn.pt.getY()) { Name snName = Name.findName(sn.label); if (snName != null && snName.busWidth() > 1) sw.proto = Schematics.tech().bus_arc; else sw.proto = Schematics.tech().wire_arc; } } } } // find connections that are exactly on existing nodes for(SueWire sw : sueWires) { for(int i=0; i<2; i++) { if (sw.pi[i] != null) continue; for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); PortInst pi = wiredPort(ni, sw.pt[i], sw.pt[1-i]); if (pi == null) continue; sw.pi[i] = pi; // determine whether this port is a bus boolean isBus = false; PortOriginal fp = new PortOriginal(pi); PortInst bottomPort = fp.getBottomPort(); NodeInst bottomNi = bottomPort.getNodeInst(); if (bottomNi.getProto() == Schematics.tech().wireConNode) continue; if (!isBus && ni.getProto() == Schematics.tech().offpageNode) { // see if there is a bus port on this primitive for(Iterator<Export> eIt = ni.getExports(); eIt.hasNext(); ) { Export e = eIt.next(); Name eName = Name.findName(e.getName()); if (eName.busWidth() > 1) isBus = true; } } if (isBus) { sw.proto = Schematics.tech().bus_arc; } else { if (sw.proto == null) sw.proto = Schematics.tech().wire_arc; } } } } // now iteratively extend bus wires to connections with others boolean propagatedBus = true; while (propagatedBus) { propagatedBus = false; for(SueWire sw : sueWires) { if (sw.proto != Schematics.tech().bus_arc) continue; for(SueWire oSw : sueWires) { if (oSw.proto != null) continue; for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { if (sw.pt[i].getX() == oSw.pt[j].getX() && sw.pt[i].getY() == oSw.pt[j].getY()) { // common point found: continue the bus request oSw.proto = Schematics.tech().bus_arc; propagatedBus = true; } } } } } } // now make pins where wires meet for(SueWire sw : sueWires) { for(int i=0; i<2; i++) { if (sw.pi[i] != null) continue; NodeProto proto = Schematics.tech().wirePinNode; if (sw.proto == Schematics.tech().bus_arc) proto = Schematics.tech().busPinNode; // look at all other wires at this point and figure out type of pin to make for(SueWire oSw : sueWires) { if (oSw == sw) continue; for(int j=0; j<2; j++) { if (sw.pt[i].getX() != oSw.pt[j].getX() || sw.pt[i].getY() != oSw.pt[j].getY()) continue; if (oSw.pi[j] != null) { sw.pi[i] = oSw.pi[j]; break; } if (oSw.proto == Schematics.tech().bus_arc) proto = Schematics.tech().busPinNode; } if (sw.pi[i] != null) break; } // make the pin if it doesn't exist if (sw.pi[i] == null) { // common point found: make a pin NodeInst ni = NodeInst.makeInstance(proto, sw.pt[i], proto.getDefWidth(), proto.getDefHeight(), cell); sw.pi[i] = ni.getOnlyPortInst(); } // put that node in all appropriate locations for(SueWire oSw : sueWires) { if (oSw == sw) continue; for(int j=0; j<2; j++) { if (sw.pt[i].getX() != oSw.pt[j].getX() || sw.pt[i].getY() != oSw.pt[j].getY()) continue; if (oSw.pi[j] != null) continue; oSw.pi[j] = sw.pi[i]; } } } } // make pins at all of the remaining wire ends for(SueWire sw : sueWires) { for(int i=0; i<2; i++) { if (sw.pi[i] != null) continue; sw.pi[i] = findNode(sw.pt[i], sw.pt[1-i], cell, sw.pi[1-i]); if (sw.pi[i] == null)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -