📄 lef.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: LEF.java * Input/output tool: LEF (Library 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.DBMath;import com.sun.electric.database.geometry.Orientation;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.prototype.NodeProto;import com.sun.electric.database.prototype.PortCharacteristic;import com.sun.electric.database.prototype.PortProto;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.topology.RTBounds;import com.sun.electric.technology.ArcProto;import com.sun.electric.technology.Layer;import com.sun.electric.technology.PrimitiveNode;import com.sun.electric.technology.Technology;import com.sun.electric.technology.technologies.Generic;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.io.IOException;import java.util.HashMap;import java.util.Iterator;import java.util.Map;/** * This class reads files in LEF files. * <BR> * Note that this reader was built by examining LEF files and reverse-engineering them. * It does not claim to be compliant with the LEF specification, but it also does not * claim to define a new specification. It is merely incomplete. */public class LEF extends LEFDEF{ /*************** LEF PATHS ***************/ private static class LEFPath { private Point2D [] pt; private NodeInst [] ni; private double width; private ArcProto arc; private LEFPath nextLEFPath; private LEFPath() { pt = new Point2D[2]; ni = new NodeInst[2]; } } /** * 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) { // remove any vias in the globals firstViaDefFromLEF = null; widthsFromLEF = new HashMap<ArcProto,Double>(); knownLayers = new HashMap<String,GetLayerInformation>(); initKeywordParsing(); try { if (!readFile(lib)) return null; // error during reading } catch (IOException e) { System.out.println("ERROR reading LEF libraries"); } return lib; } /** * Helper method for keyword processing which removes comments. * @param line a line of text just read. * @return the line after comments have been removed. */ protected String preprocessLine(String line) { int sharpPos = line.indexOf('#'); if (sharpPos >= 0) return line.substring(0, sharpPos); return line; } /** * Method to read the LEF file. */ private boolean readFile(Library lib) throws IOException { for(;;) { // get the next keyword String key = getAKeyword(); if (key == null) break; if (key.equalsIgnoreCase("LAYER")) { if (readLayer(lib)) return true; } if (key.equalsIgnoreCase("MACRO")) { if (readMacro(lib)) return true; } if (key.equalsIgnoreCase("VIA")) { if (readVia(lib)) return true; } if (key.equalsIgnoreCase("VIARULE") || key.equalsIgnoreCase("SITE") || key.equalsIgnoreCase("ARRAY")) { String name = getAKeyword(); ignoreToEnd(name); continue; } if (key.equalsIgnoreCase("SPACING")) { ignoreToEnd(key); continue; } if (key.equalsIgnoreCase("MINFEATURE")) { ignoreToSemicolon(key); continue; } } return false; } private boolean readVia(Library lib) throws IOException { // get the via name String viaName = getAKeyword(); if (viaName == null) return true; // create a new via definition ViaDef vd = new ViaDef(); vd.viaName = viaName; vd.sX = vd.sY = 0; vd.via = null; vd.lay1 = vd.lay2 = null; vd.nextViaDef = firstViaDefFromLEF; firstViaDefFromLEF = vd; boolean ignoreDefault = true; for(;;) { // get the next keyword String key = getAKeyword(); if (key == null) return true; if (ignoreDefault) { ignoreDefault = false; if (key.equalsIgnoreCase("DEFAULT")) continue; } if (key.equalsIgnoreCase("END")) { key = getAKeyword(); break; } if (key.equalsIgnoreCase("RESISTANCE")) { if (ignoreToSemicolon(key)) return true; continue; } if (key.equalsIgnoreCase("LAYER")) { key = getAKeyword(); if (key == null) return true; GetLayerInformation li = getLayerInformation(key); if (li.arc != null) { if (vd.lay1 == null) vd.lay1 = li.arc; else vd.lay2 = li.arc; } if (ignoreToSemicolon("LAYER")) return true; continue; } if (key.equalsIgnoreCase("RECT")) { // handle definition of a via rectangle key = getAKeyword(); if (key == null) return true; double lX = convertLEFString(key); key = getAKeyword(); if (key == null) return true; double lY = convertLEFString(key); key = getAKeyword(); if (key == null) return true; double hX = convertLEFString(key); key = getAKeyword(); if (key == null) return true; double hY = convertLEFString(key); // accumulate largest layer size if (hX-lX > vd.sX) vd.sX = hX - lX; if (hY-lY > vd.sY) vd.sY = hY - lY; if (ignoreToSemicolon("RECT")) return true; continue; } } if (vd.lay1 != null && vd.lay2 != null) { for(Iterator<PrimitiveNode> it = Technology.getCurrent().getNodes(); it.hasNext(); ) { PrimitiveNode np = it.next(); if (np.getFunction() != PrimitiveNode.Function.CONTACT) continue; PortProto pp = np.getPort(0); if (pp.connectsTo(vd.lay1) && pp.connectsTo(vd.lay2)) { vd.via = np; break; } } } return false; } private boolean readMacro(Library lib) throws IOException { String cellName = getAKeyword(); if (cellName == null) { System.out.println("EOF parsing MACRO header"); return true; } cellName = cellName + "{lay.sk}"; Cell cell = Cell.makeInstance(lib, cellName); if (cell == null) { System.out.println("Cannot create cell '" + cellName + "'"); return true; } for(;;) { // get the next keyword String key = getAKeyword(); if (key == null) { System.out.println("EOF parsing MACRO"); return true; } if (key.equalsIgnoreCase("END")) { key = getAKeyword(); break; } if (key.equalsIgnoreCase("SOURCE") || key.equalsIgnoreCase("FOREIGN") || key.equalsIgnoreCase("SYMMETRY") || key.equalsIgnoreCase("SITE") || key.equalsIgnoreCase("CLASS") || key.equalsIgnoreCase("LEQ") || key.equalsIgnoreCase("POWER")) { if (ignoreToSemicolon(key)) return true; continue; } if (key.equalsIgnoreCase("ORIGIN")) { key = getAKeyword(); if (key == null) { System.out.println("EOF reading ORIGIN X"); return true; } double oX = convertLEFString(key); key = getAKeyword(); if (key == null) { System.out.println("EOF reading ORIGIN Y"); return true; } double oY = convertLEFString(key); if (ignoreToSemicolon("ORIGIN")) return true; // create or move the cell-center node NodeInst ccNi = null; for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (ni.getProto() == Generic.tech().cellCenterNode) { ccNi = ni; break; } } if (ccNi == null) { double sX = Generic.tech().cellCenterNode.getDefWidth(); double sY = Generic.tech().cellCenterNode.getDefHeight(); ccNi = NodeInst.makeInstance(Generic.tech().cellCenterNode, new Point2D.Double(oX, oY), sX, sY, cell); if (ccNi == null) { System.out.println("Line " + lineReader.getLineNumber() + ": Cannot create cell center node"); return true; } ccNi.setHardSelect(); ccNi.setVisInside(); } else { double dX = oX - ccNi.getTrueCenterX(); double dY = oY - ccNi.getTrueCenterY(); ccNi.move(dX, dY); } continue; } if (key.equalsIgnoreCase("SIZE")) { key = getAKeyword(); if (key == null) { System.out.println("EOF reading SIZE X"); return true; } double wid = convertLEFString(key); // get width key = getAKeyword(); if (key == null) { System.out.println("EOF reading SIZE 'BY'"); return true; } if (!key.equalsIgnoreCase("BY")) { System.out.println("Line " + lineReader.getLineNumber() + ": Expected 'by' in SIZE"); return true; } key = getAKeyword(); if (key == null) { System.out.println("EOF reading SIZE Y"); return true; } double hei = convertLEFString(key); // get height cell.newVar(prXkey, new Double(wid)); cell.newVar(prYkey, new Double(hei)); if (ignoreToSemicolon("SIZE")) return true; if (!PLACELEFGEOMETRY) { Point2D ctr = new Point2D.Double(wid/2, hei/2); NodeInst.makeInstance(Generic.tech().invisiblePinNode, ctr, wid, hei, cell); } continue; } if (key.equalsIgnoreCase("PIN")) { if (readPin(cell)) return true; continue; } if (key.equalsIgnoreCase("OBS")) { if (readObs(cell)) return true; continue; } System.out.println("Line " + lineReader.getLineNumber() + ": Unknown MACRO keyword (" + key + ")"); return true; } return false; } private boolean readObs(Cell cell) throws IOException { NodeProto np = null; for(;;) { String key = getAKeyword(); if (key == null) { System.out.println("EOF parsing OBS"); return true; } if (key.equalsIgnoreCase("END")) break; if (key.equalsIgnoreCase("LAYER")) { key = getAKeyword(); if (key == null) { System.out.println("EOF reading LAYER clause"); return true; } GetLayerInformation li = getLayerInformation(key); np = li.pure; if (li.layerFun == Layer.Function.UNKNOWN || np == null) { System.out.println("Line " + lineReader.getLineNumber() + ": Unknown layer name (" + key + ")"); return true; } if (ignoreToSemicolon("LAYER")) return true; continue; } if (key.equalsIgnoreCase("RECT")) { key = getAKeyword(); if (key == null) { System.out.println("EOF reading RECT low X"); return true; } double lX = convertLEFString(key); key = getAKeyword(); if (key == null) { System.out.println("EOF reading RECT low Y"); return true; } double lY = convertLEFString(key); key = getAKeyword(); if (key == null) { System.out.println("EOF reading RECT high X"); return true; } double hX = convertLEFString(key); key = getAKeyword(); if (key == null) { System.out.println("EOF reading RECT high Y"); return true; } double hY = convertLEFString(key); if (ignoreToSemicolon("RECT")) return true; // make the obstruction if (PLACELEFGEOMETRY) { if (np == null) { System.out.println("Line " + lineReader.getLineNumber() + ": No layers for RECT"); return true; } Point2D ctr = new Point2D.Double((lX+hX)/2, (lY+hY)/2); double sX = Math.abs(hX - lX); double sY = Math.abs(hY - lY); NodeInst ni = NodeInst.makeInstance(np, ctr, sX, sY, cell); if (ni == null) { System.out.println("Line " + lineReader.getLineNumber() + ": Cannot create node for RECT"); return true; } } continue; } } return false; } private boolean readPin(Cell cell) throws IOException { // get the pin name String key = getAKeyword(); if (key == null) { System.out.println("EOF parsing PIN name"); return true; } String pinName = key.replace('<', '[').replace('>', ']'); PortCharacteristic useCharacteristics = PortCharacteristic.UNKNOWN; PortCharacteristic portCharacteristics = PortCharacteristic.UNKNOWN; for(;;) { key = getAKeyword(); if (key == null) { System.out.println("EOF parsing PIN"); return true; } if (key.equalsIgnoreCase("END")) { key = getAKeyword(); break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -