📄 def.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: DEF.java * Input/output tool: DEF (Design Exchange Format) reader * Written by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2004 Sun Microsystems and Static Free Software * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */package com.sun.electric.tool.io.input;import com.sun.electric.database.geometry.Orientation;import com.sun.electric.database.geometry.Poly;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.hierarchy.Library;import com.sun.electric.database.hierarchy.View;import com.sun.electric.database.prototype.NodeProto;import com.sun.electric.database.prototype.PortCharacteristic;import com.sun.electric.database.prototype.PortProto;import com.sun.electric.database.text.CellName;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.topology.ArcInst;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.topology.PortInst;import com.sun.electric.database.variable.Variable;import com.sun.electric.technology.ArcProto;import com.sun.electric.technology.PrimitiveNode;import com.sun.electric.technology.SizeOffset;import com.sun.electric.technology.Technology;import com.sun.electric.technology.technologies.Generic;import com.sun.electric.tool.io.IOTool;import java.awt.geom.AffineTransform;import java.awt.geom.Point2D;import java.io.IOException;import java.util.ArrayList;import java.util.Enumeration;import java.util.Hashtable;import java.util.Iterator;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * This class reads files in DEF files. * <BR> * Note that this reader was built by examining DEF files and reverse-engineering them. * It does not claim to be compliant with the DEF specification, but it also does not * claim to define a new specification. It is merely incomplete. * * R. Reese (RBR) - modified Spring 2007 to be able to import a DEF file to a currently * opened View. The intended use is for the Views to either be layout or schematic. * If the view is layout, then all geometry is input and unrouted net connections * are used to maintain connectivity between logical nets and physical geometries. * At some point in the future, these unrouted nets need to be cleaned up, but for * now, the use of unrouted nets allows the layout to pass DRC and to be simulated. * Can also import to a schematic view - this creates a hodgepodge of icons in the * schematic view but net connections are correct so NCC can be used to check * layout vs schematic. This is useful in a hierarchical design where part of the * design is imported DEF (say, a standard cell layout), and the rest of the design * is manual layout. Having a schematic view for the imported DEF allows NCC to * complain less when checking the design. */public class DEF extends LEFDEF{ private double scaleUnits; private ViaDef firstViaDef; private Hashtable<String,PortInst> specialNetsHT = null; private Hashtable<String,PortInst> normalNetsHT = null; private Hashtable<Double,List<NodeInst>> PortHT = null; private boolean schImport = false; private Pattern pat_starleftbracket = Pattern.compile(".*\\\\"+ "\\["); private Pattern pat_leftbracket = Pattern.compile("\\\\"+ "\\["); private Pattern pat_starrightbracket = Pattern.compile(".*\\\\"+ "\\]"); private Pattern pat_rightbracket = Pattern.compile("\\\\"+ "\\]"); /** * Method to import a library from disk. * @param lib the library to fill * @return the created library (null on error). */ protected Library importALibrary(Library lib) { initKeywordParsing(); scaleUnits = 1000; firstViaDef = null; // read the file try { if (!readFile(lib)) return null; // error during reading } catch (IOException e) { System.out.println("ERROR reading DEF libraries"); } return lib; } private boolean ignoreToSemicolon(String command) throws IOException { // ignore up to the next semicolon for(;;) { String key = mustGetKeyword(command); if (key == null) return true; if (key.equals(";")) break; } return false; } private String mustGetKeyword(String where) throws IOException { String key = getAKeyword(); if (key == null) reportError("EOF parsing " + where); return key; } private double convertDEFString(String key) { double v = TextUtils.atof(key) / scaleUnits; return TextUtils.convertFromDistance(v, Technology.getCurrent(), TextUtils.UnitScale.MICRO); } private void reportError(String command) { System.out.println("File " + filePath + ", line " + lineReader.getLineNumber() + ": " + command); } /** * Method to read the DEF file. */ private boolean readFile(Library lib) throws IOException { Cell cell = null; for(;;) { // get the next keyword String key = getAKeyword(); if (key == null) break; if (key.equalsIgnoreCase("VERSION") || key.equalsIgnoreCase("NAMESCASESENSITIVE") || key.equalsIgnoreCase("DIVIDERCHAR") || key.equalsIgnoreCase("BUSBITCHARS") || key.equalsIgnoreCase("DIEAREA") || key.equalsIgnoreCase("ROW") || key.equalsIgnoreCase("TRACKS") || key.equalsIgnoreCase("GCELLGRID") || key.equalsIgnoreCase("HISTORY") || key.equalsIgnoreCase("TECHNOLOGY")) { if (ignoreToSemicolon(key)) return true; continue; } if (key.equalsIgnoreCase("DEFAULTCAP") || key.equalsIgnoreCase("REGIONS")) { if (ignoreBlock(key)) return true; continue; } if (key.equalsIgnoreCase("DESIGN")) { String cellName = mustGetKeyword("DESIGN"); if (cellName == null) return true; /* RBR - first, see if Cell name is equal to current cells * it exists then read into cell */ cell = lib.getCurCell(); if (Input.isNewLibraryCreated()== false) { // reading into current cell, current library if (cell == null) { reportError("A cell must be currently opened for this operation, aborting."); return true; } if (!cell.getCellName().getName().equals(cellName)) { reportError("Cell name in DEF file '" + cellName + "' does not equal current cell name '" + cell.getCellName().getName() + "', aborting."); return true; } View cellView = cell.getCellName().getView(); if (cellView.getAbbreviation().equals("sch")) { schImport = true; // special flag when importing into schematic view } } else if (cell == null || !cell.getCellName().getName().equals(cellName)) { // does not equal current cell, so lets cell = Cell.makeInstance(lib, cellName); } if (cell == null) { reportError("Cannot create cell '" + cellName + "'"); return true; } if (ignoreToSemicolon("DESIGN")) return true; continue; } if (key.equalsIgnoreCase("UNITS")) { if (readUnits()) return true; continue; } if (key.equalsIgnoreCase("PROPERTYDEFINITIONS")) { if (readPropertyDefinitions()) return true; continue; } if (key.equalsIgnoreCase("VIAS")) { if (readVias(cell)) return true; continue; } if (key.equalsIgnoreCase("COMPONENTS")) { if (readComponents(cell)) return true; continue; } if (key.equalsIgnoreCase("PINS")) { if (readPins(cell)) return true; continue; } if (key.equalsIgnoreCase("SPECIALNETS")) { if (readNets(cell, true)) return true; continue; } if (key.equalsIgnoreCase("NETS")) { if (readNets(cell, false)) return true; continue; } if (key.equalsIgnoreCase("END")) { key = getAKeyword(); break; } } return false; } private boolean ignoreBlock(String command) throws IOException { for(;;) { // get the next keyword String key = mustGetKeyword(command); if (key == null) return true; if (key.equalsIgnoreCase("END")) { getAKeyword(); break; } } return false; } private Point2D readCoordinate() throws IOException { // get "(" String key = mustGetKeyword("coordinate"); if (key == null) return null; if (!key.equals("(")) { reportError("Expected '(' in coordinate"); return null; } // get X key = mustGetKeyword("coordinate"); if (key == null) return null; double x = convertDEFString(key); // get Y key = mustGetKeyword("coordinate"); if (key == null) return null; double y = convertDEFString(key); // get ")" key = mustGetKeyword("coordinate"); if (key == null) return null; if (!key.equals(")")) { reportError("Expected ')' in coordinate"); return null; } return new Point2D.Double(x, y); } /** * Find nodeProto with same view as the parent cell */ private Cell getNodeProto(String name, Library curlib, Cell parent) { // first see if this cell is in the current library CellName cn; if (schImport) { cn = CellName.newName(name,View.ICON,0); } else { cn = CellName.newName(name,parent.getView(),0); } Cell cell = curlib.findNodeProto(cn.toString()); if (cell != null) return cell; // now look in other libraries for(Iterator<Library> it = Library.getLibraries(); it.hasNext(); ) { Library lib = it.next(); if (lib.isHidden()) continue; if (lib == curlib) continue; cell = lib.findNodeProto(name); if (cell != null) { // must copy the cell// Cell newCell = copyrecursively(cell, cell->protoname, curlib, cell->cellview,// FALSE, FALSE, "", FALSE, FALSE, TRUE, new HashSet());// return newCell; return cell; } } return null; } private Cell getNodeProto(String name, Library curlib) { // first see if this cell is in the current library Cell cell = curlib.findNodeProto(name); if (cell != null) return cell; // now look in other libraries for(Iterator<Library> it = Library.getLibraries(); it.hasNext(); ) { Library lib = it.next(); if (lib.isHidden()) continue; if (lib == curlib) continue; cell = lib.findNodeProto(name); if (cell != null) { // must copy the cell// Cell newCell = copyrecursively(cell, cell->protoname, curlib, cell->cellview,// FALSE, FALSE, "", FALSE, FALSE, TRUE, new HashSet());// return newCell; return cell; } } return null; } //RBR - temp method until I figure out //why in Java 6.0 my use of GetOrientation //generates a compile error private Orientation FetchOrientation() throws IOException { String key = mustGetKeyword("orientation"); if (key == null) return null; int angle; boolean transpose = false; if (key.equalsIgnoreCase("N")) { angle = 0; } else if (key.equalsIgnoreCase("S")) { angle = 1800; } else if (key.equalsIgnoreCase("E")) { angle = 2700; } else if (key.equalsIgnoreCase("W")) { angle = 900; } else if (key.equalsIgnoreCase("FN")) { angle = 900; transpose = true; } else if (key.equalsIgnoreCase("FS")) { angle = 2700; transpose = true; } else if (key.equalsIgnoreCase("FE")) { angle = 1800; transpose = true; } else if (key.equalsIgnoreCase("FW")) { angle = 0; transpose = true; } else { reportError("Unknown orientation (" + key + ")"); return null; } return (Orientation.fromC(angle, transpose)); } private class GetOrientation { private Orientation orient; private GetOrientation() throws IOException { String key = mustGetKeyword("orientation"); if (key == null) return; int angle; boolean transpose = false; if (key.equalsIgnoreCase("N")) { angle = 0; } else if (key.equalsIgnoreCase("S")) { angle = 1800; } else if (key.equalsIgnoreCase("E")) { angle = 2700; } else if (key.equalsIgnoreCase("W")) { angle = 900; } else if (key.equalsIgnoreCase("FN")) { angle = 900; transpose = true; } else if (key.equalsIgnoreCase("FS")) { angle = 2700; transpose = true; } else if (key.equalsIgnoreCase("FE")) { angle = 1800; transpose = true; } else if (key.equalsIgnoreCase("FW")) { angle = 0; transpose = true; } else { reportError("Unknown orientation (" + key + ")"); return; } orient = Orientation.fromC(angle, transpose); } } /** * Method to look for a connection to arcs of type "ap" in cell "cell" * at (x, y). The connection can not be on "not" (if it is not null). * If found, return the PortInst. * * This function became too slow as the number of nets in cell increased. * Replaced by function below. RBR Mar 2007 */// private PortInst findConnection(double x, double y, ArcProto ap, Cell cell, NodeInst noti)// {// Rectangle2D bound = new Rectangle2D.Double(x, y, 0, 0);// Point2D pt = new Point2D.Double(x, y);// for(Iterator<RTBounds> sea = cell.searchIterator(bound); sea.hasNext(); )// {// RTBounds geom = sea.next();// if (!(geom instanceof NodeInst)) continue;// NodeInst ni = (NodeInst)geom;// if (ni == noti) continue;// for(Iterator<PortInst> it = ni.getPortInsts(); it.hasNext(); )// {// PortInst pi = (PortInst)it.next();// if (!pi.getPortProto().connectsTo(ap)) continue;// Poly poly = pi.getPoly();// if (poly.isInside(pt)) return pi;// }// }// return null;// } private PortInst findConnection(double x, double y, ArcProto ap, Cell cell, NodeInst noti) { if (PortHT.containsKey(x+y)) { List<NodeInst> pl = PortHT.get(x+y); Point2D pt = new Point2D.Double(x, y); for (int i=0; i < pl.size(); i++) { NodeInst ni = pl.get(i); if (ni == noti) continue; for(Iterator<PortInst> it = ni.getPortInsts(); it.hasNext(); ) { PortInst pi = it.next(); if (!pi.getPortProto().connectsTo(ap)) continue; Poly poly = pi.getPoly(); if (poly.isInside(pt)) return pi; } } } return null; } /** * Method to look for a connection to arcs of type "ap" in cell "cell" * at (x, y). If nothing is found, create a pin. In any case, return * the PortInst. Returns null on error. */ private PortInst getPin(double x, double y, ArcProto ap, Cell cell) { // if there is an existing connection, return it PortInst pi = findConnection(x, y, ap, cell, null); if (pi != null) return pi; // nothing found at this location: create a pin NodeProto pin = ap.findPinProto(); double sX = pin.getDefWidth(); double sY = pin.getDefHeight(); NodeInst ni = NodeInst.makeInstance(pin, new Point2D.Double(x, y), sX, sY, cell); if (ni == null) { reportError("Unable to create net pin"); return null; } List<NodeInst> pl; if (PortHT.containsKey(x+y)) { pl = PortHT.get(x+y); } else { pl = new ArrayList<NodeInst>(); PortHT.put(x+y, pl); } pl.add(ni); return ni.getOnlyPortInst(); } /*************** PINS ***************/ private boolean readPins(Cell cell) throws IOException { if (ignoreToSemicolon("PINS")) return true; for(;;) { // get the next keyword String key = mustGetKeyword("PINs"); if (key == null) return true; if (key.equals("-")) { if (readPin(cell)) return true; continue; } if (key.equalsIgnoreCase("END")) { key = getAKeyword(); break; } // ignore the keyword if (ignoreToSemicolon(key)) return true; } return false; } private String translateDefName (String name) { Matcher m_starleftbracket = pat_starleftbracket.matcher(name); Matcher m_starrightbracket = pat_starrightbracket.matcher(name); if ( m_starleftbracket.matches() || m_starrightbracket.matches()) { String tmpa, tmpb; Matcher m_leftbracket = pat_leftbracket.matcher(name); tmpa = m_leftbracket.replaceAll("["); Matcher m_rightbracket = pat_rightbracket.matcher(tmpa); tmpb = m_rightbracket.replaceAll("]");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -