/* -*- 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);
}
}
}