/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: PAL.java
* Input/output tool: PAL Netlist 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.hierarchy.Cell;
import com.sun.electric.database.hierarchy.HierarchyEnumerator;
import com.sun.electric.database.hierarchy.Nodable;
import com.sun.electric.database.network.Netlist;
import com.sun.electric.database.network.Network;
import com.sun.electric.database.topology.ArcInst;
import com.sun.electric.database.topology.Connection;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.database.variable.VarContext;
import com.sun.electric.technology.PrimitiveNode;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* This is the netlister for PAL.
*/
public class PAL extends Output
{
private Cell topCell;
private List<String> equations;
private Set<String> internalSymbols;
private Set<String> externalSymbols;
// private PALPreferences localPrefs;
public static class PALPreferences extends OutputPreferences
{
public PALPreferences(boolean factory) { super(factory); }
public Output doOutput(Cell cell, VarContext context, String filePath)
{
PAL out = new PAL(this);
if (out.openTextOutputStream(filePath)) return out.finishWrite();
out.initialize(cell);
PALNetlister netlister = new PALNetlister(out);
HierarchyEnumerator.enumerateCell(cell, context, netlister, Netlist.ShortResistors.ALL);
out.terminate(cell);
if (out.closeTextOutputStream()) return out.finishWrite();
System.out.println(filePath + " written");
return out.finishWrite();
}
}
/**
* Creates a new instance of the PAL netlister.
*/
PAL(PALPreferences pp) { /* localPrefs = pp; */ }
private void initialize(Cell cell)
{
topCell = cell;
equations = new ArrayList<String>();
internalSymbols = new TreeSet<String>();
externalSymbols = new TreeSet<String>();
}
private void terminate(Cell cell)
{
// initialize the deck
printWriter.println("module " + cell.getName());
printWriter.println("title 'generated by Electric'");
// write the external and internal symbols
int pinNumber = 1;
for(String symbol : externalSymbols)
{
printWriter.println(" " + symbol + " pin " + pinNumber + ";");
pinNumber++;
}
for(String symbol : internalSymbols)
printWriter.println(" " + symbol + " = 0,1;");
// write the equations
printWriter.println("");
printWriter.println("equations");
for(String eq : equations)
printWriter.println(" " + eq + ";");
// end of deck
printWriter.println("");
printWriter.println("end " + cell.describe(false));
}
/** PAL Netlister */
private static class PALNetlister extends HierarchyEnumerator.Visitor
{
private PAL pal;
PALNetlister(PAL pal)
{
super();
this.pal = pal;
}
public boolean enterCell(HierarchyEnumerator.CellInfo info) { return true; }
public void exitCell(HierarchyEnumerator.CellInfo info) {}
public boolean visitNodeInst(Nodable no, HierarchyEnumerator.CellInfo info)
{
// if this is a cell instance, keep recursing down
if (no.isCellInstance()) return true;
// Nodable is NodeInst because it is primitive node
NodeInst ni = (NodeInst)no;
// must be a logic gate
PrimitiveNode.Function fun = ni.getFunction();
if (fun != PrimitiveNode.Function.GATEAND && fun != PrimitiveNode.Function.GATEOR &&
fun != PrimitiveNode.Function.GATEXOR && fun != PrimitiveNode.Function.BUFFER) return false;
String funName = "";
if (fun == PrimitiveNode.Function.GATEAND) funName = "&"; else
if (fun == PrimitiveNode.Function.GATEOR) funName = "#"; else
if (fun == PrimitiveNode.Function.GATEXOR) funName = "$";
// find output
Connection outputCon = null;
for(Iterator<Connection> it = ni.getConnections(); it.hasNext(); )
{
Connection con = it.next();
PortInst pi = con.getPortInst();
if (pi.getPortProto().getName().equals("y")) { outputCon = con; break; }
}
if (outputCon == null)
{
pal.reportError("ERROR: output port is not connected on " + ni + " in " + ni.getParent());
return false;
}
Netlist netlist = info.getNetlist();
StringBuffer sb = new StringBuffer();
if (outputCon.isNegated()) sb.append("!");
Network oNet = netlist.getNetwork(outputCon.getPortInst());
sb.append(getNetName(oNet, info) + " =");
int count = 0;
for(Iterator<Connection> it = ni.getConnections(); it.hasNext(); )
{
Connection con = it.next();
PortInst pi = con.getPortInst();
if (!pi.getPortProto().getName().equals("a")) continue;
if (count == 1) sb.append(" " + funName);
count++;
sb.append(" ");
ArcInst ai = con.getArc();
if (con.isNegated()) sb.append("!");
Network net = netlist.getNetwork(ai, 0);
if (net == null) continue;
sb.append(getNetName(net, info));
}
pal.equations.add(sb.toString());
return false;
}
private String getNetName(Network net, HierarchyEnumerator.CellInfo info)
{
for(;;)
{
Network higher = info.getNetworkInParent(net);
if (higher == null) break;
net = higher;
info = info.getParentInfo();
}
if (net.isExported() && info.getCell() == pal.topCell)
{
String exportName = net.describe(false);
pal.externalSymbols.add(exportName);
return exportName;
}
String internalName = info.getUniqueNetName(net, ".");
pal.internalSymbols.add(internalName);
return internalName;
}
}
}