/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: ReadableDump.java * Input/output tool: "Readable-Dump" Library output * Written by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * * 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.output; import com.sun.electric.database.CellBackup; import com.sun.electric.database.CellRevision; import com.sun.electric.database.ImmutableExport; import com.sun.electric.database.ImmutableNodeInst; 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.PortProtoId; import com.sun.electric.database.id.PrimitiveNodeId; import com.sun.electric.database.id.TechId; import com.sun.electric.database.text.Version; import com.sun.electric.database.variable.CodeExpression; import com.sun.electric.technology.Technology; import com.sun.electric.tool.Tool; import com.sun.electric.tool.io.ELIBConstants; import com.sun.electric.util.math.DBMath; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; /** * Class to write a library to disk in Readable Dump format. */ public class ReadableDump extends ELIB { private int portProtoError; private LinkedHashMap<CellId, Integer> cellOrdering = new LinkedHashMap<CellId, Integer>(); // private HashMap<CellId,Integer> cellGrouping = new HashMap<CellId,Integer>(); private HashMap<ExportId, Integer> portMap; ReadableDump() { write6Compatible(); } /** * Method to write the .elib file. * Returns true on error. */ @Override boolean writeTheLibrary() throws IOException { // clear error counters portProtoError = 0; // determine proper library order for (CellRevision cellRevision : externalCells) { cellOrdering.put(cellRevision.d.cellId, null); } for (CellRevision cellRevision : localCells) { CellId cellId = cellRevision.d.cellId; if (!cellOrdering.containsKey(cellId)) { textRecurse(theLibId, cellId); } } int cellNumber = 0; for (Map.Entry<CellId, Integer> e : cellOrdering.entrySet()) { e.setValue(new Integer(cellNumber++)); objInfo.put(e.getKey(), e.getValue()); } // write header information printWriter.println("****library: \"" + theLibId.libName + "\""); printWriter.println("version: " + Version.getVersion().toOldStyleString()); printWriter.println("aids: " + toolCount); for (Iterator<Tool> it = Tool.getTools(); it.hasNext();) { Tool tool = it.next(); if (!objInfo.containsKey(tool)) { continue; } printWriter.println("aidname: " + tool.getName()); writeMeaningPrefs(tool); } // printWriter.println("userbits: " + lib.lowLevelGetUserBits()); printWriter.println("techcount: " + technologies.size()); for (Technology tech : technologies) { printWriter.println("techname: " + tech.getTechName() + " lambda: " + gridCoordToElib(tech, DBMath.GRID)); // printWriter.println("techname: " + tech.getTechName() + " lambda: " + (int)(tech.getScale()*2)); writeMeaningPrefs(tech); } for (Iterator<View> it = View.getViews(); it.hasNext();) { View v = it.next(); if (!objInfo.containsKey(v)) { continue; } printWriter.println("view: " + v.getFullName() + v.getAbbreviationExtension()); } printWriter.println("cellcount: " + cellNumber); // write variables on the library writeVariables(snapshot.getLib(theLibId).d); // write the rest of the database writeExternalCells(); for (Map.Entry<CellId, Integer> entry : cellOrdering.entrySet()) { CellId cellId = entry.getKey(); if (cellId.libId != theLibId) { continue; } CellBackup cellBackup = snapshot.getCell(cellId); CellRevision cellRevision = cellBackup.cellRevision; startCell(cellRevision, 0); int groupIndex = groupRenumber[snapshot.getCellGroupIndex(cellId)]; printWriter.println("***cell: " + entry.getValue().intValue() + "/" + groupIndex); writeCellInfo(cellRevision); // write tool information printWriter.println("userbits: " + (cellRevision.d.flags & ELIBConstants.CELL_BITS)); // count and number the ports portMap = new HashMap<ExportId, Integer>(); int portCount = 0; for (int exportIndex = 0; exportIndex < cellRevision.exports.size(); exportIndex++) { ImmutableExport e = cellRevision.exports.get(exportIndex); portMap.put(e.exportId, new Integer(portCount++)); } printWriter.println("nodes: " + cellRevision.nodes.size() + " arcs: " + cellRevision.arcs.size() + " porttypes: " + cellRevision.exports.size()); // write variables on the cell writeVariables(cellRevision.d); // write the nodes in this cell writeNodes(cellBackup, 0); // write the portprotos in this cell writeExports(cellRevision); // write the arcs in this cell writeArcs(cellRevision); printWriter.println("celldone: " + cellId.cellName.getName()); } // print any variable-related error messages if (portProtoError != 0) { System.out.println("Warning: " + portProtoError + " export pointers point outside cell: not saved"); } return false; } @Override void writeOrientation(int angle, int transpose) throws IOException { printWriter.println("rotation: " + angle + " transpose: " + transpose); } @Override void writeConnection(PortProtoId portId, int arcIndex, int connIndex) throws IOException { printWriter.println("*port: " + portId.getName(snapshot) + " arc: " + arcIndex); } @Override void writeReExport(ImmutableExport e) throws IOException { Integer pIndex = portMap.get(e.exportId); if (pIndex == null) { pIndex = new Integer(-1); } printWriter.println("*port: " + e.originalPortId.getName(snapshot) + " exported: " + pIndex.intValue()); } /** * Method to help order the library for proper nonforward references * in the outout */ private void textRecurse(LibId libId, CellId cellId) { for (ImmutableNodeInst n : snapshot.getCellRevision(cellId).nodes) { if (!(n.protoId instanceof CellId)) { continue; } CellId subCellId = (CellId) n.protoId; if (subCellId.libId != libId) { continue; } if (!cellOrdering.containsKey(subCellId)) { textRecurse(libId, subCellId); } } // add this cell to the list cellOrdering.put(cellId, null); } /** * Method to write the value of variable. * @param obj value of variable. */ @Override void writeVarValue(Object varObj) { StringBuffer infstr = new StringBuffer(); if (varObj instanceof Object[]) { Object[] objArray = (Object[]) varObj; int len = objArray.length; for (int i = 0; i < len; i++) { Object oneObj = objArray[i]; if (i == 0) { infstr.append("["); } else { infstr.append(","); } if (oneObj != null) { makeStringVar(infstr, oneObj); } } infstr.append("]"); } else { makeStringVar(infstr, varObj); } printWriter.println(infstr); } /** * Method to make a string from the value in "addr" which has a type in * "type". */ private void makeStringVar(StringBuffer infstr, Object obj) { if (obj instanceof String) { infstr.append("\""); infstr.append(convertString((String) obj)); infstr.append("\""); return; } if (obj instanceof CodeExpression) { infstr.append("\""); infstr.append(convertString(((CodeExpression) obj).getExpr())); infstr.append("\""); return; } if (obj instanceof Double) { infstr.append(((Double) obj).floatValue()); return; } if (obj instanceof Float) { infstr.append(((Float) obj).floatValue()); return; } if (obj instanceof Long) { infstr.append(((Long) obj).intValue()); return; } if (obj instanceof Integer) { infstr.append(((Integer) obj).intValue()); return; } if (obj instanceof Short) { infstr.append(((Short) obj).shortValue()); return; } if (obj instanceof Byte) { infstr.append(((Byte) obj).byteValue()); return; } if (obj instanceof Boolean) { infstr.append(((Boolean) obj).booleanValue() ? 1 : 0); return; } if (obj instanceof Tool) { Tool tool = (Tool) obj; infstr.append(tool.getName()); return; } if (obj instanceof TechId) { TechId techId = (TechId) obj; infstr.append(techId.techName); return; } if (obj instanceof PrimitiveNodeId) { PrimitiveNodeId np = (PrimitiveNodeId) obj; infstr.append(np.fullName); return; } if (obj instanceof ArcProtoId) { ArcProtoId arcProtoId = (ArcProtoId) obj; infstr.append(arcProtoId.fullName); return; } if (obj instanceof LibId) { LibId libId = (LibId) obj; infstr.append("\"" + libId.libName + "\""); return; } if (obj instanceof CellId) { CellId cellId = (CellId) obj; Integer mi = cellOrdering.get(cellId); int cIndex = -1; if (mi != null) { cIndex = mi.intValue(); } infstr.append(Integer.toString(cIndex)); return; } if (obj instanceof ExportId) { ExportId exportId = (ExportId) obj; Integer portIndex = portMap.get(exportId); int cIndex = -1; if (portIndex == null) { portProtoError++; } else { cIndex = portIndex.intValue(); } infstr.append(Integer.toString(cIndex)); return; } assert false; } /** * Method to write a text descriptor (possibly with variable bits). * Face of text descriptor is mapped according to "faceMap". * @param varBits variableBits or -1. * @param td0 first word of TextDescriptor to write. * @param td1 first word of TextDescriptor to write. */ @Override void writeTextDescriptor(int varBits, int td0, int td1) throws IOException { if (varBits == -1) { printWriter.println("descript: " + td0 + "/" + td1); return; } if ((varBits & ELIBConstants.VISARRAY) != 0) { printWriter.print("(" + ((varBits & ELIBConstants.VLENGTH) >> ELIBConstants.VLENGTHSH) + ")"); } printWriter.print("[0" + Integer.toOctalString(varBits) + ","); printWriter.print(td0 != 0 ? "0" + Integer.toOctalString(td0) : "0"); printWriter.print("/"); printWriter.print(td1 != 0 ? "0" + Integer.toOctalString(td1) : "0"); printWriter.print("]: "); } /** * Method to write a disk index of Object. * Index is obtained fron objInfo map. * @param obj Object to write */ @Override void writeObj(Object obj) throws IOException { } /** * Method to write an integer (4 bytes) to the ouput stream. * @param keyword keywork fro ReadableDump * @parma i integer value. */ @Override void writeInt(String keyword, int i) throws IOException { if (keyword == null) { return; } printWriter.println(keyword + i); } /** * Method to write a text into ReadableDump stream. * @param txt a text to write into ReadableDump stream. */ @Override void writeTxt(String txt) throws IOException { printWriter.println(txt); } @Override void writeBigInteger(int i) throws IOException { } /** * Method to write a disk index of variable name. * Index is obtained from the nameSpace map. * @param name Variable Key to write */ @Override void writeVariableName(String name) throws IOException { printName(name); } /** * Method to add the string "str" to the infinite string and to quote the * special characters '[', ']', '"', and '^'. */ private String convertString(String str) { StringBuffer infstr = new StringBuffer(); int len = str.length(); for (int i = 0; i < len; i++) { char ch = str.charAt(i); if (ch == '[' || ch == ']' || ch == '"' || ch == '^') { infstr.append('^'); } infstr.append(ch); } return infstr.toString(); } /** * Method to print the variable name in "name" on file "file". The * conversion performed is to quote with a backslash any of the characters * '(', '[', or '^'. */ private void printName(String name) { int len = name.length(); for (int i = 0; i < len; i++) { char pt = name.charAt(i); if (pt == '^' || pt == '[' || pt == '(' || pt == ':') { printWriter.print("^"); } printWriter.print(pt); } } }