/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: ReadableDump.java * Input/output tool: "Readable Dump" Library input * Written by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2003 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.ImmutableExport; import com.sun.electric.database.geometry.EPoint; 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.id.ArcProtoId; import com.sun.electric.database.id.CellId; import com.sun.electric.database.id.ExportId; import com.sun.electric.database.id.LibId; import com.sun.electric.database.id.NodeProtoId; import com.sun.electric.database.id.PrimitiveNodeId; import com.sun.electric.database.id.TechId; import com.sun.electric.technology.ArcProto; 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.Name; import com.sun.electric.database.text.TextUtils; import com.sun.electric.database.text.Version; 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.CodeExpression; import com.sun.electric.database.variable.TextDescriptor; import com.sun.electric.database.variable.Variable; import com.sun.electric.technology.PrimitiveNode; import com.sun.electric.technology.Technology; import com.sun.electric.technology.technologies.Artwork; import com.sun.electric.technology.technologies.Generic; import com.sun.electric.tool.Tool; import com.sun.electric.tool.io.ELIBConstants; import com.sun.electric.tool.io.FileType; import java.awt.geom.Point2D; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeSet; /** * This class reads files in readable-dump (.txt) format. */ public class ReadableDump extends LibraryFiles { // ------------------------- private data ---------------------------- private static class ArcInstList { private ArcInst [] arcList; private String [] arcProtoName; private ArcProto [] arcProto; private String [] arcInstName; private TextDescriptor[] arcNameDescriptor; private int [] arcWidth; private int [] arcHeadNode; private String [] arcHeadPort; private int [] arcHeadX; private int [] arcHeadY; private int [] arcTailNode; private String [] arcTailPort; private int [] arcTailX; private int [] arcTailY; private int [] arcUserBits; private Variable[][] arcVars; }; private static class ExportList { private Export [] exportList; private String [] exportName; private TextDescriptor[] exportNameDescriptor; private int [] exportSubNode; private String [] exportSubPort; private int [] exportUserBits; private Variable[][] exportVars; }; // /** The current position in the file. */ private int filePosition; /** The state of reading the file. */ private int textLevel; /** A counter for reading multiple Tools, Technologies, etc. */ private int bitCount; // /** The current Cell in the Library. */ private int mainCell; /** The current ArcInst end being processed. */ private int curArcEnd; /** The current object type being processed. */ private int varPos; /** The index of the current Cell being processed. */ private int curCellNumber; /** The index of the current NodeInst being processed. */ private int curNodeInstIndex; /** The index of the current ArcInst being processed. */ private int curArcInstIndex; /** The index of the current Export being processed. */ private int curExportIndex; /** Offset values for cells being read. */ private double [] nodeProtoOffX, nodeProtoOffY; /** Proto strings for NodeInsts in each Cell. */ private String [][] nodeProtoTypeList; /** All data for NodeInsts in each Cell. */ private LibraryFiles.NodeInstList[] nodeInstList; /** All data for ArcInsts in each Cell. */ private ArcInstList[] arcInstList; /** All data for Exports in each Cell. */ private ExportList [] exportList; /** The maximum characters in a keyword. */ private int keywordArrayLen; /** An array of keyword data. */ private char [] keywordArray = null; /** The current keyword from the file. */ private String keyWord; /** Flags on the Library */ private int libBits; /** Variables on the Library */ private Variable[] libVars; /** All Tools found in the file. */ private Tool [] toolList; /** The current Tool being processed. */ private Tool curTool; /** All Technologies found in the file. */ private Technology [] techList; /** The current Technology being processed. */ private Technology curTech; /** The values of Lambda for each Technology. */ private int [] lambdaValues; /** The group numbers of the Cells being processed. */ private int [] cellGroups; /** The CellNames of the Cells being processed. */ private CellName [] cellNames; /** The creation dates of Cells being processed. */ private int [] cellCreationDates; /** The revision dates of the Cells being processed. */ private int [] cellRevisionDates; /** The technologies of the Cells being processed. */ private String [] cellTechNames; /** The userbits of the Cells being processed. */ private int [] cellUserbits; /** The variables of the Cells being processed. */ private Variable [][] cellVars; /** The low X bounds of the Cells being processed. */ private int [] cellLowX; /** The high X bounds of the Cells being processed. */ private int [] cellHighX; /** The low Y bounds of the Cells being processed. */ private int [] cellLowY; /** The high Y bounds of the Cells being processed. */ private int [] cellHighY; /** Library paths of the external Cells being processed. */ private String [] cellLibPaths; /** cells being processed from this or external libraries. */ private Cell [] allCellsArray; // state of input (value of "textLevel") /** Currently reading Library information. */ private static final int INLIB = 1; /** Currently reading Cell information. */ private static final int INCELL = 2; /** Currently reading Export information. */ private static final int INPORTPROTO = 3; /** Currently reading NodeInst information. */ private static final int INNODEINST = 4; /** Currently reading PortInst information. */ private static final int INPOR = 5; /** Currently reading ArcInst information. */ private static final int INARCINST = 6; /** Currently reading ArcInst end information. */ private static final int INARCEND = 7; // state of variable reading (value of "varPos") /** Currently reading a Tool. */ private static final int INVTOOL = 1; /** Currently reading a Technology. */ private static final int INVTECHNOLOGY = 2; /** Currently reading a Library. */ private static final int INVLIBRARY = 3; /** Currently reading a Cell. */ private static final int INVNODEPROTO = 4; /** Currently reading a NodeInst. */ private static final int INVNODEINST = 5; /** Currently reading a Export. */ private static final int INVPORTPROTO = 6; /** Currently reading a ArcInst. */ private static final int INVARCINST = 7; ReadableDump() { } // ----------------------- public methods ------------------------------- @Override protected boolean readProjectSettings() { try { textLevel = INLIB; for(;;) { // get keyword from file if (getKeyword()) break; String thisKey = keyWord; // get argument to keyword if (getKeyword()) break; // determine which keyword table to use if (textLevel != INLIB || varPos != 0 && varPos != INVTOOL && varPos != INVTECHNOLOGY) break; if (thisKey.equals("****library:")) { keywordNewLib(); continue; } if (thisKey.equals("lambda:")) { keywordLambda(); continue; } if (thisKey.equals("version:")) { keywordVersn(); continue; } if (thisKey.equals("aids:")) { keywordLibKno(); continue; } if (thisKey.equals("aidname:")) { keywordLibAiN(); continue; } if (thisKey.equals("aidbits:")) { keywordLibAiB(); continue; } if (thisKey.equals("techcount:")) { keywordLibTe(); continue; } if (thisKey.equals("techname:")) { keywordLibTeN(); continue; } if (thisKey.equals("cellcount:")) { keywordLibCC(); continue; } if (thisKey.equals("variables:")) { keywordGetVar(); continue; } } return false; } catch (IOException e) { System.out.println("End of file reached while reading " + filePath); return true; } } /** * Method to read the .elib file. * Returns true on error. */ @Override boolean readTheLibrary(boolean onlyProjectSettings, LibraryStatistics.FileContents fc) throws IOException { textLevel = INLIB; // filePosition = 0; for(;;) { // get keyword from file if (getKeyword()) break; String thisKey = keyWord; // get argument to keyword if (getKeyword()) break; // determine which keyword table to use switch (textLevel) { case INLIB: if (thisKey.equals("****library:")) { keywordNewLib(); break; } if (thisKey.equals("bits:")) { keywordLibBit(); break; } if (thisKey.equals("lambda:")) { keywordLambda(); break; } if (thisKey.equals("version:")) { keywordVersn(); break; } if (thisKey.equals("aids:")) { keywordLibKno(); break; } if (thisKey.equals("aidname:")) { keywordLibAiN(); break; } if (thisKey.equals("aidbits:")) { keywordLibAiB(); break; } if (thisKey.equals("userbits:")) { keywordLibUsb(); break; } if (thisKey.equals("techcount:")) { keywordLibTe(); break; } if (thisKey.equals("techname:")) { keywordLibTeN(); break; } if (thisKey.equals("cellcount:")) { keywordLibCC(); break; } if (thisKey.equals("maincell:")) { keywordLibMS(); break; } if (thisKey.equals("view:")) { keywordLibVie(); break; } if (thisKey.equals("***cell:")) { keywordNewCel(); break; } if (thisKey.equals("variables:")) { keywordGetVar(); break; } break; case INCELL: if (thisKey.equals("bits:")) { keywordCelBit(); break; } if (thisKey.equals("userbits:")) { keywordCelUsb(); break; } if (thisKey.equals("name:")) { keywordCelNam(); break; } if (thisKey.equals("version:")) { keywordCelVer(); break; } if (thisKey.equals("creationdate:")) { keywordCelCre(); break; } if (thisKey.equals("revisiondate:")) { keywordCelRev(); break; } if (thisKey.equals("externallibrary:")) { keywordCelExt(); break; } if (thisKey.equals("lowx:")) { keywordCelLX(); break; } if (thisKey.equals("highx:")) { keywordCelHX(); break; } if (thisKey.equals("lowy:")) { keywordCelLY(); break; } if (thisKey.equals("highy:")) { keywordCelHY(); break; } if (thisKey.equals("nodes:")) { keywordCelNoC(); break; } if (thisKey.equals("arcs:")) { keywordCelArC(); break; } if (thisKey.equals("porttypes:")) { keywordCelPtC(); break; } if (thisKey.equals("technology:")) { keywordTech(); break; } if (thisKey.equals("**node:")) { keywordNewNo(); break; } if (thisKey.equals("**arc:")) { keywordNewAr(); break; } if (thisKey.equals("***cell:")) { keywordNewCel(); break; } if (thisKey.equals("variables:")) { keywordGetVar(); break; } break; case INPORTPROTO: if (thisKey.equals("bits:")) { keywordPtBit(); break; } if (thisKey.equals("userbits:")) { keywordPtUsb(); break; } if (thisKey.equals("subnode:")) { keywordPtSNo(); break; } if (thisKey.equals("subport:")) { keywordPtSPt(); break; } if (thisKey.equals("name:")) { keywordPtNam(); break; } if (thisKey.equals("descript:")) { keywordPtDes(); break; } if (thisKey.equals("aseen:")) { keywordPtKse(); break; } if (thisKey.equals("**porttype:")) { keywordNewPt(); break; } if (thisKey.equals("**arc:")) { keywordNewAr(); break; } if (thisKey.equals("**node:")) { keywordNewNo(); break; } if (thisKey.equals("***cell:")) { keywordNewCel(); break; } if (thisKey.equals("variables:")) { keywordGetVar(); break; } break; case INNODEINST: if (thisKey.equals("bits:")) { keywordNodBit(); break; } if (thisKey.equals("userbits:")) { keywordNodUsb(); break; } if (thisKey.equals("type:")) { keywordNodTyp(); break; } if (thisKey.equals("lowx:")) { keywordNodLX(); break; } if (thisKey.equals("highx:")) { keywordNodHX(); break; } if (thisKey.equals("lowy:")) { keywordNodLY(); break; } if (thisKey.equals("highy:")) { keywordNodHY(); break; } if (thisKey.equals("rotation:")) { keywordNodRot(); break; } if (thisKey.equals("transpose:")) { keywordNodTra(); break; } if (thisKey.equals("aseen:")) { keywordNodKse(); break; } if (thisKey.equals("name:")) { keywordNodNam(); break; } if (thisKey.equals("descript:")) { keywordNodDes(); break; } if (thisKey.equals("*port:")) { keywordNewPor(); break; } if (thisKey.equals("**node:")) { keywordNewNo(); break; } if (thisKey.equals("**porttype:")) { keywordNewPt(); break; } if (thisKey.equals("**arc:")) { keywordNewAr(); break; } if (thisKey.equals("variables:")) { keywordGetVar(); break; } if (thisKey.equals("***cell:")) { keywordNewCel(); break; } if (thisKey.equals("ports:")) { keywordNodPoC(); break; } break; case INPOR: if (thisKey.equals("*port:")) { keywordNewPor(); break; } if (thisKey.equals("**node:")) { keywordNewNo(); break; } if (thisKey.equals("**porttype:")) { keywordNewPt(); break; } if (thisKey.equals("**arc:")) { keywordNewAr(); break; } if (thisKey.equals("variables:")) { keywordGetVar(); break; } if (thisKey.equals("***cell:")) { keywordNewCel(); break; } break; case INARCINST: if (thisKey.equals("bits:")) { keywordArcBit(); break; } if (thisKey.equals("userbits:")) { keywordArcUsb(); break; } if (thisKey.equals("type:")) { keywordArcTyp(); break; } if (thisKey.equals("width:")) { keywordArcWid(); break; } if (thisKey.equals("aseen:")) { keywordArcKse(); break; } if (thisKey.equals("name:")) { keywordArcNam(); break; } if (thisKey.equals("*end:")) { keywordNewEnd(); break; } if (thisKey.equals("**arc:")) { keywordNewAr(); break; } if (thisKey.equals("**node:")) { keywordNewNo(); break; } if (thisKey.equals("variables:")) { keywordGetVar(); break; } if (thisKey.equals("***cell:")) { keywordNewCel(); break; } break; case INARCEND: if (thisKey.equals("node:")) { keywordEndNod(); break; } if (thisKey.equals("nodeport:")) { keywordEndPt(); break; } if (thisKey.equals("xpos:")) { keywordEndXP(); break; } if (thisKey.equals("ypos:")) { keywordEndYP(); break; } if (thisKey.equals("*end:")) { keywordNewEnd(); break; } if (thisKey.equals("**arc:")) { keywordNewAr(); break; } if (thisKey.equals("**node:")) { keywordNewNo(); break; } if (thisKey.equals("variables:")) { keywordGetVar(); break; } if (thisKey.equals("***cell:")) { keywordNewCel(); break; } break; } } // see if cellgroup information was included // for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto) // if (np->temp1 == -1) break; // if (np != NONODEPROTO) // { // // missing cellgroup information, construct it from names // if (emajor > 7 || // (emajor == 7 && eminor > 0) || // (emajor == 7 && eminor == 0 && edetail > 11)) // { // ttyputmsg(M_("Unusual! Version %s library has no cellgroup information"), version); // } // buildcellgrouppointersfromnames(lib); // } else if (lib->firstnodeproto != NONODEPROTO) // { // // convert numbers to cellgroup pointers // if (emajor < 7 || // (emajor == 7 && eminor == 0 && edetail <= 11)) // { // ttyputmsg(M_("Unusual! Version %s library has cellgroup information"), version); // } // for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto) // np->nextcellgrp = NONODEPROTO; // for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto) // { // if (np->nextcellgrp != NONODEPROTO) continue; // prevmatch = np; // for(onp = np->nextnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto) // { // if (onp->temp1 != prevmatch->temp1) continue; // prevmatch->nextcellgrp = onp; // prevmatch = onp; // } // prevmatch->nextcellgrp = np; // } // } if (allCellsArray == null) return true; // error // if (mainCell >= 0) // Job.getUserInterface().setCurrentCell(lib, allCellsArray[mainCell]); return false; } //************************************* in library @Override Map<Cell,Variable[]> createLibraryCells(boolean onlyProjectSettings) { lib.erase(); lib.lowLevelSetUserBits(TextUtils.atoi(keyWord)); // this library came as readable dump, so don't automatically save it to disk lib.clearFromDisk(); realizeVariables(lib, libVars); HashMap<Cell,Variable[]> originalVars = new HashMap<Cell,Variable[]>(); for (int cellNumber = 0; cellNumber < nodeProtoCount; cellNumber++) { if (cellLibPaths[cellNumber] == null) finishCellInitialization(cellNumber, originalVars); else findExtCell(cellNumber); } return originalVars; } private void findExtCell(int cellNumber) { // get the library associated with that name String libPath = cellLibPaths[cellNumber]; Library elib = readExternalLibraryFromFilename(libPath, FileType.ELIB, null); // find the requested cell in the external library Cell cell = null; CellName curCellName = cellNames[cellNumber]; if (elib != null) { // find this cell in the external library cell = elib.findNodeProto(curCellName.toString()); if (cell != null) { // cell found: make sure it is valid if (cell.getRevisionDate().compareTo(ELIBConstants.secondsToDate(cellRevisionDates[cellNumber])) != 0) { System.out.println("Warning: " + cell + " in " + elib + " has been modified since its use in " + lib); } } } // see if a cell was found if (cell != null) { // cell found in external library: remember the external reference allCellsArray[cellNumber] = cell; nodeProtoList[cellNumber] = null; } else { // cell not found in external library: figure out the library name String elibName = null; if (elib != null) elibName = elib.getName(); else { File libFile = new File(libPath); elibName = libFile.getName(); int lastDotPos = elibName.lastIndexOf('.'); if (lastDotPos > 0) elibName = elibName.substring(0, lastDotPos); } // cell not found in library: issue warning System.out.println("Cannot find cell " + curCellName.toString() + " in library " + elibName + "...creating dummy version"); // rename the cell //curCellName.setName(curCellName.getName() + "FROM" + elibName); if (curCellName.getVersion() != 0) curCellName = CellName.parseName(curCellName.getName() + "FROM" + elibName + ";" + curCellName.getVersion() + curCellName.getView().getAbbreviationExtension()); else curCellName = CellName.parseName(curCellName.getName() + "FROM" + elibName + curCellName.getView().getAbbreviationExtension()); cellNames[cellNumber] = curCellName; finishCellInitialization(cellNumber, null); // schedule the cell to have two nodes (cell center and big "X") LibraryFiles.NodeInstList nil = new LibraryFiles.NodeInstList(2, false); nodeInstList[cellNumber] = nil; // create a cell-center node nil.protoType[0] = Generic.tech().cellCenterNode; nil.name[0] = null; nil.lowX[0] = 0; nil.highX[0] = 0; nil.lowY[0] = 0; nil.highY[0] = 0; nil.rotation[0] = 0; nil.transpose[0] = 0; // create an artwork "Crossed box" to define the cell size nil.protoType[1] = Artwork.tech().crossedBoxNode; nil.name[1] = null; nil.lowX[1] = cellLowX[cellNumber]; nil.highX[1] = cellHighX[cellNumber]; nil.lowY[1] = cellLowY[cellNumber]; nil.highY[1] = cellHighY[cellNumber]; nil.rotation[1] = 0; nil.transpose[1] = 0; } } private void finishCellInitialization(int cellNumber, HashMap<Cell,Variable[]> originalVars) { Cell curCell = Cell.newInstance(lib, cellNames[cellNumber].toString()); allCellsArray[cellNumber] = nodeProtoList[cellNumber] = curCell; curCell.setTempInt(cellGroups[cellNumber]); // curCell.lowLevelPopulate(curCellName.toString()); String techName = cellTechNames[cellNumber]; Technology tech = techName != null ? findTechnologyName(techName) : null; if (tech != null) curCell.setTechnology(tech); // curCell.lowLevelLink(); curCell.lowLevelSetCreationDate(ELIBConstants.secondsToDate(cellCreationDates[cellNumber])); curCell.lowLevelSetRevisionDate(ELIBConstants.secondsToDate(cellRevisionDates[cellNumber])); curCell.lowLevelSetUserbits(cellUserbits[cellNumber]); if (originalVars != null) originalVars.put(curCell, cellVars[cellNumber]); for (int nodeInstIndex = 0; nodeInstIndex < nodeInstList[cellNumber].protoType.length; nodeInstIndex++) findNodeProto(cellNumber, nodeInstIndex); for (int arcInstIndex = 0; arcInstIndex < arcInstList[cellNumber].arcProto.length; arcInstIndex++) findArcProto(cellNumber, arcInstIndex); } private void findNodeProto(int cellNumber, int nodeInstIndex) { String nodeProtoType = nodeProtoTypeList[cellNumber][nodeInstIndex]; NodeProto curNodeInstProto = null; int openSquare = nodeProtoType.indexOf('['); if (openSquare >= 0) { curNodeInstProto = allCellsArray[TextUtils.atoi(nodeProtoType, openSquare+1)]; } else { int colonPos = nodeProtoType.indexOf(':'); Technology tech = Technology.findTechnology(nodeProtoType.substring(0, colonPos)); if (tech == null) return; curNodeInstProto = tech.findNodeProto(nodeProtoType.substring(colonPos + 1)); if (curNodeInstProto == null) { // get the technology // Technology tech = null; // int colonPos = keyWord.indexOf(':'); // if (colonPos >= 0) // { // tech = Technology.findTechnology(keyWord.substring(0, colonPos)); // } // if (tech != null) // { // convert "Active-Node" to "P-Active-Node" (MOSIS CMOS) if (nodeProtoType.equals("Active-Node")) { curNodeInstProto = tech.findNodeProto("P-Active-Node"); if (curNodeInstProto == null) { // convert "message" and "cell-center" nodes curNodeInstProto = tech.convertOldNodeName(nodeProtoType); } } // } } } if (curNodeInstProto == null) System.out.println("Error on line "+lineReader.getLineNumber()+": unknown node type: "+nodeProtoType); nodeInstList[cellNumber].protoType[nodeInstIndex] = curNodeInstProto; } private void findArcProto(int cellNumber, int arcInstIndex) { String arcProtoName = arcInstList[cellNumber].arcProtoName[arcInstIndex]; ArcProto curArcInstProto = null; curArcInstProto = ArcProto.findArcProto(keyWord); if (curArcInstProto == null) { // get the technology Technology tech = null; int colonPos = keyWord.indexOf(':'); if (colonPos >= 0) { tech = Technology.findTechnology(keyWord.substring(0, colonPos)); } if (tech != null) { // convert old arcs curArcInstProto = tech.convertOldArcName(keyWord); } } if (curArcInstProto == null) System.out.println("Error on line "+lineReader.getLineNumber()+": unknown arc type: "+keyWord); arcInstList[cellNumber].arcProto[arcInstIndex] = curArcInstProto; } @Override Variable[] findVarsOnExampleIcon(Cell parentCell, Cell iconCell) { // get information about this cell int cellIndex; for (cellIndex = 0; cellIndex < nodeProtoList.length; cellIndex++) { if (nodeProtoList[cellIndex] == parentCell) break; } if (cellIndex >= nodeInstList.length) return null; LibraryFiles.NodeInstList nil = nodeInstList[cellIndex]; for (int i = 0; i < nil.protoType.length; i++) { findNodeProto(cellIndex, i); NodeProto np = nodeInstList[cellIndex].protoType[i]; if (np == iconCell) return nil.vars[i]; } return null; } //************************************* recursive /** * Method to recursively create the contents of each cell in the library. */ protected void realizeCellsRecursively(Cell cell, HashSet<Cell> markCellForNodes, String scaledCellName, double scale) { // do not realize cross-library references if (cell.getLibrary() != lib) return; // cannot do scaling yet if (scaledCellName != null) return; // recursively scan the nodes to the bottom and only proceed when everything below is built int cellIndex = cell.getTempInt(); if (nodeInstList == null) return; // error LibraryFiles.NodeInstList nil = nodeInstList[cellIndex]; int numNodes = 0; NodeProto [] nodePrototypes = null; if (nil != null) { nodePrototypes = nil.protoType; numNodes = nodePrototypes.length; } scanNodesForRecursion(cell, markCellForNodes, nodePrototypes, 0, numNodes); // report progress if (LibraryFiles.VERBOSE) System.out.println("Text: Doing contents of " + cell + " in " + lib); cellsConstructed++; setProgressValue(cellsConstructed * 100 / totalCells); // now fill in the nodes double lambda = cellLambda[cellIndex]; Point2D offset = realizeNodes(cell, nil, lambda); nodeProtoOffX[cellIndex] = offset.getX(); nodeProtoOffY[cellIndex] = offset.getY(); // do the exports now realizeExports(cell, cellIndex); // do the arcs now realizeArcs(cell, cellIndex); // cell.loadExpandStatus(); } protected boolean spreadLambda(Cell cell, int cellIndex) { boolean changed = false; LibraryFiles.NodeInstList nil = nodeInstList[cellIndex]; int numNodes = 0; if (nil != null) numNodes = nil.protoType.length; double thisLambda = cellLambda[cellIndex]; for(int i=0; i<numNodes; i++) { NodeProto np = nil.protoType[i]; if (np == null) continue; if (np instanceof PrimitiveNode) continue; Cell subCell = (Cell)np; LibraryFiles reader = this; if (subCell.getLibrary() != lib) { reader = getReaderForLib(subCell.getLibrary()); if (reader == null) continue; } int subCellIndex = subCell.getTempInt(); double subLambda = reader.cellLambda[subCellIndex]; if (subLambda != thisLambda) { reader.cellLambda[subCellIndex] = thisLambda; changed = true; } } return changed; } protected void computeTech(Cell cell, Set uncomputedCells) { uncomputedCells.remove(cell); int cellIndex = 0; for(; cellIndex<nodeProtoCount && nodeProtoList[cellIndex] != cell; cellIndex++); if (cellIndex >= nodeProtoCount || nodeInstList == null) return; // error LibraryFiles.NodeInstList nil = nodeInstList[cellIndex]; int numNodes = 0; NodeProto [] nodePrototypes = null; if (nil != null) { nodePrototypes = nil.protoType; numNodes = nodePrototypes.length; } // recursively ensure that subcells's technologies are computed for(int i=0; i<numNodes; i++) { NodeProto np = nodePrototypes[i]; if (!uncomputedCells.contains(np)) continue; Cell subCell = (Cell)np; LibraryFiles reader = getReaderForLib(subCell.getLibrary()); if (reader != null) reader.computeTech(subCell, uncomputedCells); } ArcInstList ail = arcInstList[cellIndex]; int numArcs = 0; ArcProto [] arcPrototypes = null; if (ail != null) { arcPrototypes = ail.arcProto; numArcs = arcPrototypes.length; } Technology cellTech = Technology.whatTechnology(cell, nodePrototypes, 0, numNodes, arcPrototypes); cell.setTechnology(cellTech); } protected double computeLambda(Cell cell, int cellIndex) { // LibraryFiles.NodeInstList nil = nodeInstList[cellIndex]; // int numNodes = 0; // NodeProto [] nodePrototypes = null; // if (nil != null) // { // nodePrototypes = nil.protoType; // numNodes = nodePrototypes.length; // } // ArcInstList ail = arcInstList[cellIndex]; // int numArcs = 0; // ArcProto [] arcPrototypes = null; // if (ail != null) // { // arcPrototypes = ail.arcProto; // numArcs = arcPrototypes.length; // } // Technology cellTech = Technology.whatTechnology(cell, nodePrototypes, 0, numNodes, // arcPrototypes, 0, numArcs); // cell.setTechnology(cellTech); Technology cellTech = cell.getTechnology(); double lambda = 1.0; if (cellTech != null) { for(int i=0; i<techList.length; i++) { if (techList[i] != cellTech) continue; lambda = lambdaValues[i]; break; } } return lambda; } private Point2D realizeNodes(Cell cell, LibraryFiles.NodeInstList nil, double lambda) { // find the "cell center" node and place it first int xoff = 0, yoff = 0; int numNodes = 0; if (nil != null) numNodes = nil.protoType.length; for(int j=0; j<numNodes; j++) { // convert to new style NodeProto np = nil.protoType[j]; if (np == Generic.tech().cellCenterNode) { realizeNode(nil, j, xoff, yoff, lambda, cell, np); xoff = (nil.lowX[j] + nil.highX[j]) / 2; yoff = (nil.lowY[j] + nil.highY[j]) / 2; break; } } Point2D offset = new Point2D.Double(xoff, yoff); // create the rest of the nodes for(int j=0; j<numNodes; j++) { NodeProto np = nil.protoType[j]; if (np == null) continue; if (np == Generic.tech().cellCenterNode) continue; realizeNode(nil, j, xoff, yoff, lambda, cell, np); } return offset; } private void realizeExports(Cell cell, int cellIndex) { ExportList el = exportList[cellIndex]; int numExports = 0; if (el != null) numExports = el.exportList.length; CellId cellId = cell.getId(); // Try to create ExportIds in alphanumeric order TreeSet<String> exportNames = new TreeSet<String>(TextUtils.STRING_NUMBER_ORDER); for (int j = 0; j < numExports; j++) exportNames.add(el.exportName[j]); for (String exportName: exportNames) cell.getId().newPortId(exportName); for(int j=0; j<numExports; j++) { NodeInst subNi = nodeInstList[cellIndex].theNode[el.exportSubNode[j]]; PortInst pi = findProperPortInst(subNi, el.exportSubPort[j]); int userBits = el.exportUserBits[j]; boolean alwaysDrawn = ImmutableExport.alwaysDrawnFromElib(userBits); boolean bodyOnly = ImmutableExport.bodyOnlyFromElib(userBits); PortCharacteristic characteristic = ImmutableExport.portCharacteristicFromElib(userBits); ExportId exportId = cellId.newPortId(Name.findName(el.exportName[j]).toString()); Export pp = Export.newInstance(cell, exportId, null, el.exportNameDescriptor[j], pi, alwaysDrawn, bodyOnly, characteristic, errorLogger); el.exportList[j] = pp; if (pp == null) continue; realizeVariables(pp, el.exportVars[j]); } } /** * Method to find the PortInst associated with a named port on a NodeInst. * Does the proper conversion of old port names if necessary. * @param ni the NodeInst to explore. * @param portName the name of the port on that NodeInst. * @return the PortInst, null if not found. */ private PortInst findProperPortInst(NodeInst ni, String portName) { NodeProto np = ni.getProto(); PortProto pp = findPortProto(np, portName); // PortProto pp = np.findPortProto(portName); // convert special port names if (pp == null && !ni.isCellInstance()) { Technology tech = np.getTechnology(); pp = tech.convertOldPortName(portName, (PrimitiveNode)np); } if (pp == null) return null; return ni.findPortInstFromProto(pp); } private void realizeArcs(Cell cell, int cellIndex) { ArcInstList ail = arcInstList[cellIndex]; int numArcs = 0; if (ail != null) numArcs = ail.arcProto.length; double lambda = cellLambda[cellIndex]; double xoff = nodeProtoOffX[cellIndex]; double yoff = nodeProtoOffY[cellIndex]; // create the arcs for(int j=0; j<numArcs; j++) { ArcProto ap = ail.arcProto[j]; String name = ail.arcInstName[j]; long gridExtendOverMin = getSizeCorrector(ap.getTechnology()).getExtendFromDisk(ap, ail.arcWidth[j] / lambda); NodeInst arcHeadNode = nodeInstList[cellIndex].theNode[ail.arcHeadNode[j]]; NodeInst arcTailNode = nodeInstList[cellIndex].theNode[ail.arcTailNode[j]]; if (!arcHeadNode.isLinked() || !arcTailNode.isLinked()) continue; PortInst headPortInst = findProperPortInst(arcHeadNode, ail.arcHeadPort[j]); PortInst tailPortInst = findProperPortInst(arcTailNode, ail.arcTailPort[j]); if (ap == null || headPortInst == null || tailPortInst == null) continue; double headX = (ail.arcHeadX[j]-xoff) / lambda; double headY = (ail.arcHeadY[j]-yoff) / lambda; double tailX = (ail.arcTailX[j]-xoff) / lambda; double tailY = (ail.arcTailY[j]-yoff) / lambda; EPoint headPt = new EPoint(headX, headY); EPoint tailPt = new EPoint(tailX, tailY); int userBits = ail.arcUserBits[j]; // make checks Poly poly = headPortInst.getPoly(); if (!poly.isInside(headPt)) System.out.println("Cell " + cell.describe(true) + ", " + ap + " head at (" + ail.arcHeadX[j] + "," + ail.arcHeadY[j] + ") not in port"); poly = tailPortInst.getPoly(); if (!poly.isInside(tailPt)) System.out.println("Cell " + cell.describe(true) + ", " + ap + " tail at (" + ail.arcTailX[j] + "," + ail.arcTailY[j] + ") not in port"); ArcInst ai = ArcInst.newInstance(cell, ap, name, ail.arcNameDescriptor[j], headPortInst, tailPortInst, headPt, tailPt, gridExtendOverMin, ImmutableArcInst.angleFromElib(userBits), ImmutableArcInst.flagsFromElib(userBits)); ail.arcList[j] = ai; // ELIBConstants.applyELIBArcBits(ai, userBits); if (ai == null) { String msg = "ERROR: "+cell + ": arc " + name + " could not be created"; System.out.println(msg); Input.errorLogger.logError(msg, cell, 1); continue; } // if (gridExtendOverMin < 0) { // String msg = "WARNING: "+cell + ": arc " + ai.getName() + " width is less than minimum by " + DBMath.gridToLambda(-2*gridExtendOverMin); // System.out.println(msg); // Input.errorLogger.logWarning(msg, ai, cell, null, 2); // } realizeVariables(ai, ail.arcVars[j]); } } private boolean getKeyword() throws IOException { int filePostionDelta = 0; // get only delta in file since byteCount exists // skip leading blanks int c = 0; for(;;) { c = lineReader.read(); if (c == -1) return true; filePostionDelta++; if (c != ' ') break; } // collect the word int cindex = 0; boolean inQuote = false; if (c == '"') inQuote = true; if (keywordArray == null) { keywordArrayLen = 500; keywordArray = new char[keywordArrayLen]; } keywordArray[cindex++] = (char)c; for(;;) { c = lineReader.read(); if (c == -1) return true; filePostionDelta++; if (c == '\n' || (c == ' ' && !inQuote)) break; if (c == '"' && (cindex == 0 || keywordArray[cindex-1] != '^')) inQuote = !inQuote; if (cindex >= keywordArrayLen) { int newKeywordArrayLen = keywordArrayLen * 2; char [] newKeywordArray = new char[newKeywordArrayLen]; for(int i=0; i<keywordArrayLen; i++) newKeywordArray[i] = keywordArray[i]; keywordArray = newKeywordArray; keywordArrayLen = newKeywordArrayLen; } keywordArray[cindex++] = (char)c; } keyWord = new String(keywordArray, 0, cindex); updateProgressDialog(filePostionDelta); // if (progress != null && fileLength > 0) // { // progress.setProgress((int)(filePosition * 100 / fileLength)); // } return false; } // --------------------------------- LIBRARY PARSING METHODS --------------------------------- /** * a new library is introduced (keyword "****library") * This should be the first keyword in the file */ private void keywordNewLib() { // set defaults // mainCell = -1; varPos = INVTOOL; curTech = null; textLevel = INLIB; } /** * get the file's Electric version number (keyword "version") */ private void keywordVersn() { version = Version.parseVersion(keyWord); // emajor = version.getMajor(); // eminor = version.getMinor(); // edetail = version.getDetail(); // for versions before 6.03q, convert MOSIS CMOS technology names convertMosisCmosTechnologies = version.compareTo(Version.parseVersion("6.03q")) < 0; // convertMosisCmosTechnologies = false; // if (emajor < 6 || // (emajor == 6 && eminor < 3) || // (emajor == 6 && eminor == 3 && edetail < 17)) // { // convertMosisCmosTechnologies = true; // System.out.println(" Converting MOSIS CMOS technologies (mocmossub => mocmos)"); // } // for Electric version 4 or earlier, scale lambda by 20 scaleLambdaBy20 = version.compareTo(Version.parseVersion("5")) < 0; // if (emajor <= 4) lambda *= 20; // mirror bits rotationMirrorBits = version.compareTo(Version.parseVersion("7.01")) >= 0; // if (emajor > 7 || (emajor == 7 && eminor >= 1)) } /** * get the number of tools (keyword "aids") */ private void keywordLibKno() { bitCount = 0; toolList = new Tool[Integer.parseInt(keyWord)]; } /** * get the name of the tool (keyword "aidname") */ private void keywordLibAiN() { curTool = Tool.findTool(keyWord); toolList[bitCount++] = curTool; } /** * get the number of toolbits (keyword "aidbits") */ private void keywordLibAiB() { bitCount = 0; } /** * get tool information for the library (keyword "bits") */ private void keywordLibBit() { if (bitCount == 0) libBits = TextUtils.atoi(keyWord); bitCount++; } /** * get the number of toolbits (keyword "userbits") */ private void keywordLibUsb() { libBits = TextUtils.atoi(keyWord); } /** * get the number of technologies (keyword "techcount") */ private void keywordLibTe() { varPos = INVTECHNOLOGY; bitCount = 0; int numTechs = Integer.parseInt(keyWord); techList = new Technology[numTechs]; lambdaValues = new int[numTechs]; } /** * get the name of the technology (keyword "techname") */ private void keywordLibTeN() { curTech = Technology.findTechnology(keyWord); techList[bitCount++] = curTech; } /** * get lambda values for each technology in library (keyword "lambda") */ private void keywordLambda() { int lam = Integer.parseInt(keyWord); // for version 4.0 and earlier, scale lambda by 20 if (scaleLambdaBy20) lam *= 20; // if (emajor <= 4) lam *= 20; lambdaValues[bitCount-1] = lam; } /** * get the number of cells in this library (keyword "cellcount") */ private void keywordLibCC() { varPos = INVLIBRARY; nodeProtoCount = Integer.parseInt(keyWord); if (nodeProtoCount == 0) return; // allocate a list of node prototypes for this library nodeProtoList = new Cell[nodeProtoCount]; allCellsArray = new Cell[nodeProtoCount]; cellLambda = new double[nodeProtoCount]; nodeProtoOffX = new double[nodeProtoCount]; nodeProtoOffY = new double[nodeProtoCount]; cellLowX = new int[nodeProtoCount]; cellHighX = new int[nodeProtoCount]; cellLowY = new int[nodeProtoCount]; cellHighY = new int[nodeProtoCount]; nodeProtoTypeList = new String[nodeProtoCount][]; nodeInstList = new LibraryFiles.NodeInstList[nodeProtoCount]; arcInstList = new ArcInstList[nodeProtoCount]; exportList = new ExportList[nodeProtoCount]; cellNames = new CellName[nodeProtoCount]; cellGroups = new int[nodeProtoCount]; cellTechNames = new String[nodeProtoCount]; cellCreationDates = new int[nodeProtoCount]; cellRevisionDates = new int[nodeProtoCount]; cellUserbits = new int[nodeProtoCount]; cellVars = new Variable[nodeProtoCount][]; cellLibPaths = new String[nodeProtoCount]; } /** * get the main cell of this library (keyword "maincell") */ private void keywordLibMS() { // mainCell = Integer.parseInt(keyWord); } /** * get a view (keyword "view") */ private void keywordLibVie() { int openCurly = keyWord.indexOf('{'); if (openCurly < 0) { System.out.println("Error on line "+lineReader.getLineNumber()+": missing '{' in view name: " + keyWord); return; } String fullName = keyWord.substring(0, openCurly); String abbrev = keyWord.substring(openCurly+1); int closeCurly = abbrev.indexOf('}'); if (closeCurly < 0) { System.out.println("Error on line "+lineReader.getLineNumber()+": missing '}' in view name: " + keyWord); return; } abbrev = abbrev.substring(0, closeCurly); View v = View.findView(fullName); if (v == null) { v = findOldViewName(fullName); if (v != null) abbrev = v.getAbbreviation(); } if (v == null) { v = View.newInstance(fullName, abbrev); } else { if (!v.getAbbreviation().equals(abbrev)) { System.out.println("Error on line " + lineReader.getLineNumber() + ": view " + fullName + " has abbreviation '" + abbrev + "' which does not match the existing abbreviation '" + v.getAbbreviation() + "'"); return; } } } // --------------------------------- CELL PARSING METHODS --------------------------------- /** * initialize for a new cell (keyword "***cell") */ private void keywordNewCel() { curCellNumber = TextUtils.atoi(keyWord); // curCell = nodeProtoList[curCellNumber]; int curCellGroup = -1; int slashPos = keyWord.indexOf('/'); if (slashPos >= 0) curCellGroup = TextUtils.atoi(keyWord.substring(slashPos+1)); cellGroups[curCellNumber] = curCellGroup; textLevel = INCELL; varPos = INVNODEPROTO; } /** * get the name of the current cell (keyword "name") */ private void keywordCelNam() { cellNames[curCellNumber] = CellName.parseName(convertCellName(keyWord)); } /** * get the version of the current cell (keyword "version") */ private void keywordCelVer() { CellName curCellName = cellNames[curCellNumber]; cellNames[curCellNumber] = CellName.newName(curCellName.getName(), curCellName.getView(), TextUtils.atoi(keyWord)); //curCellName.setVersion(TextUtils.atoi(keyWord)); } /** * get the creation date of the current cell (keyword "creationdate") */ private void keywordCelCre() { cellCreationDates[curCellNumber] = TextUtils.atoi(keyWord); } /** * get the revision date of the current cell (keyword "revisiondate") */ private void keywordCelRev() { cellRevisionDates[curCellNumber] = TextUtils.atoi(keyWord); } /** * get the low X of the current cell (keyword "lowx") */ private void keywordCelLX() { cellLowX[curCellNumber] = TextUtils.atoi(keyWord); } /** * get the high X of the current cell (keyword "highx") */ private void keywordCelHX() { cellHighX[curCellNumber] = TextUtils.atoi(keyWord); } /** * get the low Y of the current cell (keyword "lowy") */ private void keywordCelLY() { cellLowY[curCellNumber] = TextUtils.atoi(keyWord); } /** * get the high Y of the current cell (keyword "highy") */ private void keywordCelHY() { cellHighY[curCellNumber] = TextUtils.atoi(keyWord); } /** * get tool information for current cell (keyword "bits") */ private void keywordCelBit() { cellUserbits[curCellNumber] = TextUtils.atoi(keyWord); } /** * get tool information for current cell (keyword "userbits") */ private void keywordCelUsb() { cellUserbits[curCellNumber] = TextUtils.atoi(keyWord); } /** * get the external library file (keyword "externallibrary") */ private void keywordCelExt() { // get the path to the library file String withoutQuotes = keyWord; if (withoutQuotes.charAt(0) == '"') { withoutQuotes = withoutQuotes.substring(1); if (withoutQuotes.endsWith("\"")) withoutQuotes = withoutQuotes.substring(0, withoutQuotes.length()-1); } cellLibPaths[curCellNumber] = withoutQuotes; } /** * get the default technology for objects in this cell (keyword "technology") */ private void keywordTech() { cellTechNames[curCellNumber] = keyWord; } /** * get the number of node instances in the current cell (keyword "nodes") */ private void keywordCelNoC() { // // this keyword indicates that the cell is NOT external, so establish it now // finishCellInitialization(); // handle the NodeInst count in the cell int nodeInstCount = Integer.parseInt(keyWord); if (nodeInstCount == 0) return; nodeProtoTypeList[curCellNumber] = new String[nodeInstCount]; nodeInstList[curCellNumber] = new LibraryFiles.NodeInstList(nodeInstCount, false); } /** * get the number of arc instances in the current cell (keyword "arcs") */ private void keywordCelArC() { int arcInstCount = Integer.parseInt(keyWord); ArcInstList ail = new ArcInstList(); arcInstList[curCellNumber] = ail; ail.arcList = new ArcInst[arcInstCount]; ail.arcProtoName = new String[arcInstCount]; ail.arcProto = new ArcProto[arcInstCount]; ail.arcInstName = new String[arcInstCount]; ail.arcNameDescriptor = new TextDescriptor[arcInstCount]; ail.arcWidth = new int[arcInstCount]; ail.arcHeadNode = new int[arcInstCount]; ail.arcHeadPort = new String[arcInstCount]; ail.arcHeadX = new int[arcInstCount]; ail.arcHeadY = new int[arcInstCount]; ail.arcTailNode = new int[arcInstCount]; ail.arcTailPort = new String[arcInstCount]; ail.arcTailX = new int[arcInstCount]; ail.arcTailY = new int[arcInstCount]; ail.arcUserBits = new int[arcInstCount]; ail.arcVars = new Variable[arcInstCount][]; } /** * get the number of port prototypes in the current cell (keyword "porttypes") */ private void keywordCelPtC() { int exportCount = Integer.parseInt(keyWord); ExportList el = new ExportList(); exportList[curCellNumber] = el; el.exportList = new Export[exportCount]; el.exportName = new String[exportCount]; el.exportNameDescriptor = new TextDescriptor[exportCount]; el.exportSubNode = new int[exportCount]; el.exportSubPort = new String[exportCount]; el.exportUserBits = new int[exportCount]; el.exportVars = new Variable[exportCount][]; } // --------------------------------- NODE INSTANCE PARSING METHODS --------------------------------- /** * initialize for a new node instance (keyword "**node") */ private void keywordNewNo() { curNodeInstIndex = Integer.parseInt(keyWord); textLevel = INNODEINST; varPos = INVNODEINST; } /** * get the type of the current nodeinst (keyword "type") */ private void keywordNodTyp() { nodeProtoTypeList[curCellNumber][curNodeInstIndex] = keyWord; } /** * get the bounding box information for the current node instance */ private void keywordNodLX() { nodeInstList[curCellNumber].lowX[curNodeInstIndex] = TextUtils.atoi(keyWord); } private void keywordNodHX() { nodeInstList[curCellNumber].highX[curNodeInstIndex] = TextUtils.atoi(keyWord); } private void keywordNodLY() { nodeInstList[curCellNumber].lowY[curNodeInstIndex] = TextUtils.atoi(keyWord); } private void keywordNodHY() { nodeInstList[curCellNumber].highY[curNodeInstIndex] = TextUtils.atoi(keyWord); } /** * get the instance name of the current node instance (keyword "name") */ private void keywordNodNam() { nodeInstList[curCellNumber].name[curNodeInstIndex] = keyWord; } /** * get the text descriptor of the current node instance (keyword "descript") */ private void keywordNodDes() { int td0 = TextUtils.atoi(keyWord); int td1 = 0; int slashPos = keyWord.indexOf('/'); if (slashPos >= 0) td1 = TextUtils.atoi(keyWord.substring(slashPos+1)); nodeInstList[curCellNumber].protoTextDescriptor[curNodeInstIndex] = makeDescriptor(td0, td1); // mtd.setCBits(td0, td1); // nodeInstList[curCellNumber].theNode[curNodeInstIndex].setTextDescriptor(NodeInst.NODE_PROTO_TD, mtd); } /** * get the rotation for the current nodeinst (keyword "rotation"); */ private void keywordNodRot() { nodeInstList[curCellNumber].rotation[curNodeInstIndex] = (short)Integer.parseInt(keyWord); } /** * get the transposition for the current nodeinst (keyword "transpose") */ private void keywordNodTra() { nodeInstList[curCellNumber].transpose[curNodeInstIndex] = Integer.parseInt(keyWord); } /** * get the tool seen bits for the current nodeinst (keyword "aseen") */ private void keywordNodKse() { bitCount = 0; } /** * get the port count for the current nodeinst (keyword "ports") */ private void keywordNodPoC() {} /** * get tool information for current nodeinst (keyword "bits") */ private void keywordNodBit() { if (bitCount == 0) nodeInstList[curCellNumber].userBits[curNodeInstIndex] = TextUtils.atoi(keyWord); bitCount++; } /** * get tool information for current nodeinst (keyword "userbits") */ private void keywordNodUsb() { nodeInstList[curCellNumber].userBits[curNodeInstIndex] = TextUtils.atoi(keyWord); } /** * initialize for a new portinst on the current nodeinst (keyword "*port") */ private void keywordNewPor() { textLevel = INPOR; } // --------------------------------- ARC INSTANCE PARSING METHODS --------------------------------- /** * initialize for a new arc instance (keyword "**arc") */ private void keywordNewAr() { curArcInstIndex = Integer.parseInt(keyWord); textLevel = INARCINST; varPos = INVARCINST; } /** * get the type of the current arc instance (keyword "type") */ private void keywordArcTyp() { arcInstList[curCellNumber].arcProtoName[curArcInstIndex] = keyWord; } /** * get the instance name of the current arc instance (keyword "name") */ private void keywordArcNam() { arcInstList[curCellNumber].arcInstName[curArcInstIndex] = keyWord; } /** * get the width of the current arc instance (keyword "width") */ private void keywordArcWid() { arcInstList[curCellNumber].arcWidth[curArcInstIndex] = TextUtils.atoi(keyWord); } /** * initialize for an end of the current arcinst (keyword "*end") */ private void keywordNewEnd() { curArcEnd = Integer.parseInt(keyWord); textLevel = INARCEND; } /** * get the node at the current end of the current arcinst (keyword "node") */ private void keywordEndNod() { int endIndex = TextUtils.atoi(keyWord); if (curArcEnd == ArcInst.HEADEND) { arcInstList[curCellNumber].arcHeadNode[curArcInstIndex] = endIndex; // arcInstList[curCellNumber].arcHeadNode[curArcInstIndex] = nodeInstList[curCellNumber].theNode[endIndex]; } else { arcInstList[curCellNumber].arcTailNode[curArcInstIndex] = endIndex; // arcInstList[curCellNumber].arcTailNode[curArcInstIndex] = nodeInstList[curCellNumber].theNode[endIndex]; } } /** * get the porttype at the current end of current arcinst (keyword "nodeport") */ private void keywordEndPt() { if (curArcEnd == ArcInst.HEADEND) { arcInstList[curCellNumber].arcHeadPort[curArcInstIndex] = keyWord; } else { arcInstList[curCellNumber].arcTailPort[curArcInstIndex] = keyWord; } } /** * get the coordinates of the current end of the current arcinst */ private void keywordEndXP() { int x = TextUtils.atoi(keyWord); if (curArcEnd == ArcInst.HEADEND) { arcInstList[curCellNumber].arcHeadX[curArcInstIndex] = x; } else { arcInstList[curCellNumber].arcTailX[curArcInstIndex] = x; } } private void keywordEndYP() { int y = TextUtils.atoi(keyWord); if (curArcEnd == ArcInst.HEADEND) { arcInstList[curCellNumber].arcHeadY[curArcInstIndex] = y; } else { arcInstList[curCellNumber].arcTailY[curArcInstIndex] = y; } } /** * get the tool information for the current arcinst (keyword "aseen") */ private void keywordArcKse() { bitCount = 0; } /** * get tool information for current arcinst (keyword "bits") */ private void keywordArcBit() { if (bitCount == 0) arcInstList[curCellNumber].arcUserBits[curArcInstIndex] = TextUtils.atoi(keyWord); bitCount++; } /** * get tool information for current arcinst (keyword "userbits") */ private void keywordArcUsb() { arcInstList[curCellNumber].arcUserBits[curArcInstIndex] = TextUtils.atoi(keyWord); } // --------------------------------- PORT PROTOTYPE PARSING METHODS --------------------------------- /** * initialize for a new port prototype (keyword "**porttype") */ private void keywordNewPt() { curExportIndex = Integer.parseInt(keyWord); textLevel = INPORTPROTO; varPos = INVPORTPROTO; } /** * get the name for the current port prototype (keyword "name") */ private void keywordPtNam() { exportList[curCellNumber].exportName[curExportIndex] = keyWord; } /** * get the text descriptor for the current port prototype (keyword "descript") */ private void keywordPtDes() { int td0 = TextUtils.atoi(keyWord); int td1 = 0; int slashPos = keyWord.indexOf('/'); if (slashPos >= 0) td1 = TextUtils.atoi(keyWord, slashPos+1); exportList[curCellNumber].exportNameDescriptor[curExportIndex] = makeDescriptor(td0, td1); } /** * get the sub-nodeinst for the current port prototype (keyword "subnode") */ private void keywordPtSNo() { int index = Integer.parseInt(keyWord); exportList[curCellNumber].exportSubNode[curExportIndex] = index; // exportList[curCellNumber].exportSubNode[curExportIndex] = nodeInstList[curCellNumber].theNode[index]; } /** * get the sub-portproto for the current port prototype (keyword "subport") */ private void keywordPtSPt() { exportList[curCellNumber].exportSubPort[curExportIndex] = keyWord; } /** * get the tool seen for the current port prototype (keyword "aseen") */ private void keywordPtKse() { bitCount = 0; } /** * get the tool data for the current port prototype (keyword "bits") */ private void keywordPtBit() { if (bitCount == 0) exportList[curCellNumber].exportUserBits[curExportIndex] = TextUtils.atoi(keyWord); bitCount++; } /** * get the tool data for the current port prototype (keyword "userbits") */ private void keywordPtUsb() { exportList[curCellNumber].exportUserBits[curExportIndex] = TextUtils.atoi(keyWord); } // --------------------------------- VARIABLE PARSING METHODS --------------------------------- /** * get variables on current object (keyword "variables") */ private void keywordGetVar() throws IOException { Variable[] vars = parseVars(); switch (varPos) { case INVNODEINST: // keyword applies to nodeinst nodeInstList[curCellNumber].vars[curNodeInstIndex] = vars; for (int i = 0; i < vars.length; i++) { Variable var = vars[i]; if (var == null || var.getKey() != NodeInst.NODE_NAME) continue; Object value = var.getObject(); if (!(value instanceof String)) continue; nodeInstList[curCellNumber].name[curNodeInstIndex] = convertGeomName(value, var.isDisplay()); nodeInstList[curCellNumber].nameTextDescriptor[curNodeInstIndex] = var.getTextDescriptor(); vars[i] = null; } break; case INVPORTPROTO: // keyword applies to portproto exportList[curCellNumber].exportVars[curExportIndex] = vars; break; case INVARCINST: // keyword applies to arcinst arcInstList[curCellNumber].arcVars[curArcInstIndex] = vars; for (int i = 0; i < vars.length; i++) { Variable var = vars[i]; if (var == null || var.getKey() != ArcInst.ARC_NAME) continue; Object value = var.getObject(); if (!(value instanceof String)) continue; arcInstList[curCellNumber].arcInstName[curArcInstIndex] = convertGeomName(value, var.isDisplay()); arcInstList[curCellNumber].arcNameDescriptor[curArcInstIndex] = var.getTextDescriptor(); vars[i] = null; } break; case INVTOOL: // keyword applies to tools realizeMeaningPrefs(curTool, vars); break; case INVTECHNOLOGY: // keyword applies to technologies realizeMeaningPrefs(curTech, vars); break; case INVLIBRARY: // keyword applies to library for (int i = 0; i < vars.length; i++) { Variable var = vars[i]; if (var == null || var.getKey() != Library.FONT_ASSOCIATIONS) continue; Object value = var.getObject(); if (!(value instanceof String[])) continue; setFontNames((String[])value); vars[i] = null; } libVars = vars; break; case INVNODEPROTO: // keyword applies to nodeproto cellVars[curCellNumber] = vars; break; } } /** * get variables on current object (keyword "variables") */ private Variable[] parseVars() throws IOException { // find out how many variables to read int count = Integer.parseInt(keyWord); if (count <= 0) return Variable.NULL_ARRAY; Variable[] vars = new Variable[count]; for(int i=0; i<count; i++) { // read the first keyword with the name, type, and descriptor if (getKeyword()) { System.out.println("EOF too soon"); return vars; } // get the variable name String varName = ""; int len = keyWord.length(); if (keyWord.charAt(len-1) != ':') { System.out.println("Error on line "+lineReader.getLineNumber()+": missing colon in variable specification: "+keyWord); return vars; } for(int j=0; j<len; j++) { char cat = keyWord.charAt(j); if (cat == '^' && j < len-1) { j++; varName += keyWord.charAt(j); continue; } if (cat == '(' || cat == '[' || cat == ':') break; varName += cat; } // Variable.Key varKey = ElectricObject.newKey(varName); // see if the variable is valid // get type int openSquarePos = keyWord.lastIndexOf('['); // lastIndex, because LE variables may contain '[' if (openSquarePos < 0) { System.out.println("Error on line "+lineReader.getLineNumber()+": missing type information in variable: " + keyWord); return vars; } int type = TextUtils.atoi(keyWord, openSquarePos+1); // get the descriptor int commaPos = keyWord.indexOf(','); int td0 = 0; int td1 = 0; if (commaPos >= 0) { td0 = TextUtils.atoi(keyWord, commaPos+1); td1 = 0; int slashPos = keyWord.indexOf('/'); if (slashPos >= 0) td1 = TextUtils.atoi(keyWord, slashPos+1); } TextDescriptor td = makeDescriptor(td0, td1, type); CodeExpression.Code code = CodeExpression.Code.getByCBits(type); // get value if (getKeyword()) { System.out.println("EOF too soon"); return vars; } Object value = null; if ((type&ELIBConstants.VISARRAY) == 0) { value = variableDecode(keyWord, type); } else { if (keyWord.charAt(0) != '[') { System.out.println("Error on line "+lineReader.getLineNumber()+": missing '[' in list of variable values: " + keyWord); return vars; } ArrayList<Object> al = new ArrayList<Object>(); int pos = 1; len = keyWord.length(); for(;;) { // string arrays must be handled specially int start = pos; if ((type&ELIBConstants.VTYPE) == ELIBConstants.VSTRING) { while (keyWord.charAt(pos) != '"' && pos < len-1) pos++; start = pos; if (pos < len) { pos++; for(;;) { if (keyWord.charAt(pos) == '^' && pos < len-1) { pos += 2; continue; } if (keyWord.charAt(pos) == '"' || pos == len-1) break; pos++; } if (pos < len) pos++; } } else { while (keyWord.charAt(pos) != ',' && keyWord.charAt(pos) != ']' && pos < len) pos++; } if (pos >= len) { System.out.println("Error on line "+lineReader.getLineNumber()+": array too short in variable values: " + keyWord); return vars; } String entry = keyWord.substring(start, pos); al.add(variableDecode(entry, type)); if (keyWord.charAt(pos) == ']') break; if (keyWord.charAt(pos) != ',') { System.out.println("Error on line "+lineReader.getLineNumber()+": missing comma between array entries: " + keyWord); return vars; } pos++; } int arrayLen = al.size(); switch (type&ELIBConstants.VTYPE) { case ELIBConstants.VADDRESS: case ELIBConstants.VINTEGER: value = new Integer[arrayLen]; break; case ELIBConstants.VFRACT: case ELIBConstants.VFLOAT: value = new Float[arrayLen]; break; case ELIBConstants.VDOUBLE: value = new Double[arrayLen]; break; case ELIBConstants.VSHORT: value = new Short[arrayLen]; break; case ELIBConstants.VBOOLEAN: value = new Boolean[arrayLen]; break; case ELIBConstants.VCHAR: value = new Byte[arrayLen]; break; case ELIBConstants.VSTRING: value = new String[arrayLen]; break; case ELIBConstants.VNODEPROTO: value = new NodeProtoId[arrayLen]; break; case ELIBConstants.VARCPROTO: value = new ArcProtoId[arrayLen]; break; case ELIBConstants.VPORTPROTO: value = new ExportId[arrayLen]; break; case ELIBConstants.VTECHNOLOGY: value = new TechId[arrayLen]; break; case ELIBConstants.VLIBRARY: value = new LibId[arrayLen]; break; case ELIBConstants.VTOOL: value = new Tool[arrayLen]; break; } if (value != null) { for(int j=0; j<arrayLen; j++) { ((Object [])value)[j] = al.get(j); } } if (value instanceof NodeProtoId[]) { NodeProtoId[] newAddrArray = (NodeProtoId[])value; int numCells = 0, numPrims = 0; for (int j = 0; j < newAddrArray.length; j++) { if (newAddrArray[j] == null) continue; if (newAddrArray[j] instanceof CellId) numCells++; if (newAddrArray[j] instanceof PrimitiveNodeId) numPrims++; } if (numCells >= numPrims) { CellId[] cellArray = new CellId[newAddrArray.length]; for (int j = 0; j < cellArray.length; j++) if (newAddrArray[j] instanceof CellId) cellArray[j] = (CellId)newAddrArray[j]; value = cellArray; } else { PrimitiveNodeId[] primArray = new PrimitiveNodeId[newAddrArray.length]; for (int j = 0; j < primArray.length; j++) if (newAddrArray[j] instanceof PrimitiveNodeId) primArray[j] = (PrimitiveNodeId)newAddrArray[j]; value = primArray; } } } if (value == null) continue; value = Variable.withCode(value, code); vars[i] = Variable.newInstance(Variable.newKey(varName), value, td); } return vars; } private Object variableDecode(String name, int type) { int thistype = type; if ((thistype&(ELIBConstants.VCODE1|ELIBConstants.VCODE2)) != 0) thistype = ELIBConstants.VSTRING; switch (thistype&ELIBConstants.VTYPE) { case ELIBConstants.VINTEGER: case ELIBConstants.VADDRESS: return new Integer(TextUtils.atoi(name)); case ELIBConstants.VSHORT: return new Short((short)TextUtils.atoi(name)); case ELIBConstants.VBOOLEAN: return new Boolean(TextUtils.atoi(name) != 0); case ELIBConstants.VFRACT: return new Float(TextUtils.atoi(name) / 120.0f); case ELIBConstants.VCHAR: return new Byte((byte)name.charAt(0)); case ELIBConstants.VSTRING: char [] letters = new char[name.length()]; int outpos = 0; int inpos = 0; if (name.charAt(inpos) == '"') inpos++; for( ; inpos < name.length(); inpos++) { if (name.charAt(inpos) == '^' && inpos < name.length()-1) { inpos++; letters[outpos++] = name.charAt(inpos); continue; } if (name.charAt(inpos) == '"') break; letters[outpos++] = name.charAt(inpos); } return new String(letters, 0, outpos); case ELIBConstants.VFLOAT: return new Float(Float.parseFloat(name)); case ELIBConstants.VDOUBLE: return new Double(Double.parseDouble(name)); case ELIBConstants.VLIBRARY: if (name.length() == 0) return null; if (name.charAt(0) == '"') name = name.substring(1, name.length() - 1); return idManager.newLibId(name); case ELIBConstants.VNODEPROTO: int colonPos = name.indexOf(':'); if (colonPos < 0) { // just an integer specification int cindex = Integer.parseInt(name); return allCellsArray[cindex] != null ? allCellsArray[cindex].getId() : null; } return idManager.newTechId(name.substring(0, colonPos)).newPrimitiveNodeId(name.substring(colonPos + 1)); case ELIBConstants.VPORTPROTO: int ppIndex = TextUtils.atoi(name); PortProto pp = exportList[curCellNumber].exportList[ppIndex]; if (!(pp instanceof Export)) return null; return ((Export)pp).getId(); case ELIBConstants.VARCPROTO: int colon = name.indexOf(':'); if (colon < 0) { System.out.println("Error on line "+lineReader.getLineNumber()+": cannot find arc " + name); return null; } return idManager.newTechId(name.substring(0, colon)).newArcProtoId(name.substring(colon + 1)); case ELIBConstants.VTECHNOLOGY: return idManager.newTechId(name); case ELIBConstants.VTOOL: return Tool.findTool(name); } return null; } }