📄 jelibparser.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: JelibParser.java * Input/output tool: JELIB Library input * 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.ImmutableArcInst;import com.sun.electric.database.ImmutableNodeInst;import com.sun.electric.database.Snapshot;import com.sun.electric.database.geometry.EPoint;import com.sun.electric.database.geometry.Orientation;import com.sun.electric.database.hierarchy.View;import com.sun.electric.database.id.ArcProtoId;import com.sun.electric.database.id.CellId;import com.sun.electric.database.id.ExportId;import com.sun.electric.database.id.IdManager;import com.sun.electric.database.id.LibId;import com.sun.electric.database.id.NodeProtoId;import com.sun.electric.database.id.PortProtoId;import com.sun.electric.database.id.PrimitiveNodeId;import com.sun.electric.database.id.PrimitivePortId;import com.sun.electric.database.id.TechId;import com.sun.electric.database.prototype.PortCharacteristic;import com.sun.electric.database.text.CellName;import com.sun.electric.database.text.Name;import com.sun.electric.database.text.Version;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.variable.CodeExpression;import com.sun.electric.database.variable.MutableTextDescriptor;import com.sun.electric.database.variable.TextDescriptor;import com.sun.electric.database.variable.Variable;import com.sun.electric.tool.Tool;import com.sun.electric.tool.io.FileType;import com.sun.electric.tool.ncc.basic.TransitiveRelation;import com.sun.electric.tool.user.ErrorLogger;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.LineNumberReader;import java.net.URL;import java.net.URLConnection;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.LinkedHashSet;import java.util.List;import java.util.Set;/** * This class reads files in new library file (.jelib) format. */public class JelibParser{ class CellContents { final Version version; boolean filledIn; String fileName; int lineNumber; CellId cellId; CellName groupName; long creationDate; long revisionDate; TechId techId; boolean expanded; boolean allLocked; boolean instLocked; boolean cellLib; boolean techLib; Variable[] vars; List<NodeContents> nodes = new ArrayList<NodeContents>(); List<ExportContents> exports = new ArrayList<ExportContents>(); List<ArcContents> arcs = new ArrayList<ArcContents>(); // map disk node names (duplicate node names written "sig"1 and "sig"2) HashMap<String,NodeContents> diskName = new HashMap<String,NodeContents>(); CellContents(Version version) { this.version = version; filledIn = false; } } static class NodeContents { int line; NodeProtoId protoId; String nodeName; TextDescriptor nameTextDescriptor; EPoint anchor; Orientation orient; EPoint size; TextDescriptor protoTextDescriptor; int flags; int techBits; Variable[] vars; NodeInst ni; } static class ExportContents { int line; ExportId exportId; String exportUserName; NodeContents originalNode; PortProtoId originalPort; TextDescriptor nameTextDescriptor; PortCharacteristic ch; boolean alwaysDrawn; boolean bodyOnly; Variable[] vars; Point2D pos; } static class ArcContents { int line; ArcProtoId arcProtoId; String arcName; TextDescriptor nameTextDescriptor; double diskWidth; NodeContents headNode; PortProtoId headPort; EPoint headPoint; NodeContents tailNode; PortProtoId tailPort; EPoint tailPoint; int angle; int flags; Variable[] vars; } // The parsing result Version version; Variable[] libVars; final LinkedHashMap<LibId,String> externalLibIds = new LinkedHashMap<LibId,String>(); final LinkedHashMap<CellId,Rectangle2D> externalCells = new LinkedHashMap<CellId,Rectangle2D>(); final LinkedHashMap<ExportId,EPoint> externalExports = new LinkedHashMap<ExportId,EPoint>(); final LinkedHashMap<TechId,Variable[]> techIds = new LinkedHashMap<TechId,Variable[]>(); final LinkedHashMap<PrimitiveNodeId,Variable[]> primitiveNodeIds = new LinkedHashMap<PrimitiveNodeId,Variable[]>(); final LinkedHashMap<PrimitivePortId,Variable[]> primitivePortIds = new LinkedHashMap<PrimitivePortId,Variable[]>(); final LinkedHashMap<ArcProtoId,Variable[]> arcProtoIds = new LinkedHashMap<ArcProtoId,Variable[]>(); final LinkedHashMap<String,Variable[]> tools = new LinkedHashMap<String,Variable[]>(); final LinkedHashMap<CellId,CellContents> allCells = new LinkedHashMap<CellId,CellContents>(); final LinkedHashSet<String> delibCellFiles = new LinkedHashSet<String>(); /*---------------------------------------------------------------------*/ private static String[] revisions = { // Revision 1 "8.01aw", // Revision 2 "8.04l", }; private static final Version newDelibHeaderVersion = Version.parseVersion("8.04n"); private static int defaultArcFlags; static { defaultArcFlags = ImmutableArcInst.DEFAULT_FLAGS; defaultArcFlags = ImmutableArcInst.HARD_SELECT.set(defaultArcFlags, false); // A defaultArcFlags = ImmutableArcInst.BODY_ARROWED.set(defaultArcFlags, false); // B defaultArcFlags = ImmutableArcInst.FIXED_ANGLE.set(defaultArcFlags, true); // F defaultArcFlags = ImmutableArcInst.HEAD_NEGATED.set(defaultArcFlags, false); // G defaultArcFlags = ImmutableArcInst.HEAD_EXTENDED.set(defaultArcFlags, true); // I defaultArcFlags = ImmutableArcInst.TAIL_EXTENDED.set(defaultArcFlags, true); // J defaultArcFlags = ImmutableArcInst.TAIL_NEGATED.set(defaultArcFlags, false); // N defaultArcFlags = ImmutableArcInst.RIGID.set(defaultArcFlags, false); // R defaultArcFlags = ImmutableArcInst.SLIDABLE.set(defaultArcFlags, false); // S defaultArcFlags = ImmutableArcInst.HEAD_ARROWED.set(defaultArcFlags, false); // X defaultArcFlags = ImmutableArcInst.TAIL_ARROWED.set(defaultArcFlags, false); // Y } // Were in LibraryFiles final URL fileURL; private final FileType fileType; private final IdManager idManager; private final LibId libId; private final String filePath; private LineNumberReader lineReader; private final LineNumberReader delibHeaderReader; private int revision = revisions.length; private final ErrorLogger errorLogger; private final MutableTextDescriptor mtd = new MutableTextDescriptor(); /** buffer for reading Variables. */ private final ArrayList<Variable> variablesBuf = new ArrayList<Variable>(); // collect the cells by common protoName and by "groupLines" relation private final HashMap<String,ArrayList<CellContents>> cellsWithProtoName = new HashMap<String,ArrayList<CellContents>>(); private final TransitiveRelation<String> transitiveProtoNames = new TransitiveRelation<String>(); private HashMap<String,TextDescriptorAndCode> parsedDescriptorsF = new HashMap<String,TextDescriptorAndCode>(); private HashMap<String,TextDescriptorAndCode> parsedDescriptorsT = new HashMap<String,TextDescriptorAndCode>();// private Version version; private char escapeChar = '\\'; private String curLibName; private String curReadFile; private static class TextDescriptorAndCode { private final TextDescriptor td; private final CodeExpression.Code code; TextDescriptorAndCode(TextDescriptor td, CodeExpression.Code code) { this.td = td; this.code = code; } } private LibId curExternalLibId = null; private CellId curExternalCellId = null; private TechId curTechId = null; private PrimitiveNodeId curPrimId = null; private JelibParser(LibId libId, URL fileURL, FileType fileType, boolean onlyProjectSettings, ErrorLogger errorLogger) throws IOException { idManager = libId.idManager; this.libId = libId; this.fileURL = fileURL; this.fileType = fileType; filePath = fileURL.getFile(); this.errorLogger = errorLogger; InputStream inputStream; if (fileType == FileType.JELIB) { URLConnection urlCon = fileURL.openConnection(); urlCon.setConnectTimeout(10000); urlCon.setReadTimeout(1000); curReadFile = filePath; inputStream = urlCon.getInputStream(); } else if (fileType == FileType.DELIB) { curReadFile = filePath + File.separator + "header"; inputStream = new FileInputStream(curReadFile); } else { throw new IllegalArgumentException("fileType"); } InputStreamReader is = new InputStreamReader(inputStream, "UTF-8"); this.lineReader = new LineNumberReader(is); delibHeaderReader = fileType == FileType.DELIB ? lineReader : null; try { readFromFile(onlyProjectSettings); collectCellGroups(); } catch (Exception e) { logError("Exception " + e.getMessage()); } finally { lineReader.close(); } } private void collectCellGroups() { for (Iterator<Set<String>> git = transitiveProtoNames.getSetsOfRelatives(); git.hasNext(); ) { Set<String> protoNames = git.next(); // Collect cells in this group ArrayList<CellContents> cellsInGroup = new ArrayList<CellContents>(); for (String protoName: protoNames) { ArrayList<CellContents> list = cellsWithProtoName.get(protoName); if (list == null) { logError("No cells for group name " + protoName); continue; } cellsInGroup.addAll(list); } // Make cell group name ArrayList<CellName> cellNamesInGroup = new ArrayList<CellName>(); for (CellContents cc: cellsInGroup) cellNamesInGroup.add(cc.cellId.cellName); CellName groupName = Snapshot.makeCellGroupName(cellNamesInGroup); // Set cell group name for each cell for (CellContents cc: cellsInGroup) cc.groupName = groupName; } } public static JelibParser parse(LibId libId, URL fileURL, FileType fileType, boolean onlyProjectSettings, ErrorLogger errorLogger) throws IOException { return new JelibParser(libId, fileURL, fileType, onlyProjectSettings, errorLogger); } private void readFromFile(boolean onlyProjectSettings) throws IOException { boolean ignoreCvsMergedContent = false; for(;;) { // get keyword from file String line = lineReader.readLine(); if (line == null) break; // ignore blanks and comments if (line.length() == 0) continue; char first = line.charAt(0); if (first == '#') continue; if (line.startsWith("<<<<<<<")) { // This marks start of stuff merged from CVS, ignore this stuff ignoreCvsMergedContent = true; logError("CVS conflicts found: " + line); continue; } if (ignoreCvsMergedContent && line.startsWith("=======")) { // This marks start of local stuff merged, use this stuff ignoreCvsMergedContent = false; continue; } if (line.startsWith(">>>>>>>")) { // This marks end of cvs merging continue; } if (ignoreCvsMergedContent) continue; if (onlyProjectSettings && first != 'H' && first != 'O' && first != 'T') continue; if (first == 'C') { if (lineReader == delibHeaderReader) { readDelibCell(line); } else { readCell(line); } continue; } if (first == 'L') { // cross-library reference List<String> pieces = parseLine(line); if (pieces.size() != 2) { logError("External library declaration needs 2 fields: " + line); continue; } String libName = unQuote(pieces.get(0)); curExternalLibId = idManager.newLibId(libName); String libFileName = unQuote(pieces.get(1)); // recurse if (!externalLibIds.containsKey(curExternalLibId)) externalLibIds.put(curExternalLibId, libFileName); continue; } if (first == 'R') { // cross-library cell information List<String> pieces = parseLine(line); int numPieces = revision == 1 ? 7 : 5; if (pieces.size() != numPieces) { logError("External cell declaration needs " + numPieces + " fields: " + line); continue; } double lowX = readDouble(pieces.get(1)); double highX = readDouble(pieces.get(2)); double lowY = readDouble(pieces.get(3)); double highY = readDouble(pieces.get(4)); if (revision == 1) { Long.parseLong(pieces.get(5)); // ignore cdate Long.parseLong(pieces.get(6)); // ignore rdate } Rectangle2D bounds = new Rectangle2D.Double(lowX, lowY, highX-lowX, highY-lowY); String cellName = unQuote(pieces.get(0)); curExternalCellId = curExternalLibId.newCellId(CellName.parseName(cellName)); if (!externalCells.containsKey(curExternalCellId)) externalCells.put(curExternalCellId, bounds); continue; } if (first == 'F') { // cross-library export information List<String> pieces = parseLine(line); if (pieces.size() != 3) { logError("External export declaration needs 3 fields: " + line); continue; } String exportName = unQuote(pieces.get(0)); double posX = readDouble(pieces.get(1)); double posY = readDouble(pieces.get(1)); ExportId exportId = curExternalCellId.newPortId(exportName); externalExports.put(exportId, EPoint.fromLambda(posX, posY)); continue; } if (first == 'H') { // parse header List<String> pieces = parseLine(line); if (pieces.size() < 2) { logError("Library declaration needs 2 fields: " + line); continue; } version = Version.parseVersion(pieces.get(1)); if (version == null) { logError("Badly formed version: " + pieces.get(1)); continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -