/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: PLA.java
* MOSIS CMOS PLA Generator.
* Originally written by Wallace Kroeker at the University of Calgary
* Translated to Java by Steven Rubin, Sun Microsystems.
*
* Copyright (c) 2005, 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.generator.cmosPLA;
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.prototype.PortProto;
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.Variable;
import com.sun.electric.lib.LibFile;
import com.sun.electric.technology.ArcProto;
import com.sun.electric.technology.PrimitiveNode;
import com.sun.electric.technology.Technology;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.JobException;
import com.sun.electric.tool.io.FileType;
import com.sun.electric.tool.io.input.LibraryFiles;
import com.sun.electric.tool.user.User;
import com.sun.electric.tool.user.dialogs.EDialog;
import com.sun.electric.tool.user.dialogs.OpenFile;
import com.sun.electric.tool.user.ui.WindowFrame;
import com.sun.electric.util.math.Orientation;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.net.URL;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JTextField;
/**
* Class to generate MOSIS CMOS PLAs from personality files.
*/
public class PLA
{
/** maximum number of columns */ static final int MAX_COL_SIZE = 500;
/** Lambda seperation between grid lines in array */ static final int X_SEP = 10;
/** Lambda seperation between grid line */ static final int Y_MIR_SEP = 10;
/** Lambda seperation between grid lines in array */ static final int Y_SEP = 10;
static class UCItem
{
int value;
NodeInst nodeInst;
UCItem rightItem;
UCItem bottomItem;
};
/**
* Row and column pointers
*/
static class UCRow
{
UCItem firstItem;
UCItem lastitem;
UCRow()
{
firstItem = new UCItem();
lastitem = new UCItem();
}
};
/** the cells in the pla_mocmos library */ Cell nmosOne, pmosOne, decoderInv, ioInv4, pullUps;
/** the generated cells */ private Cell pmosCell, nmosCell, orCell, decodeCell, orPlaneCell;
/** primitives in the mocmos technology */ PrimitiveNode m1Pin, m2Pin, m12Con, mpCon, maCon, mwBut, msBut, pwNode;
/** arcs in the mocmos technology */ ArcProto m1Arc, m2Arc, pArc, aArc;
UCRow [] columnList;
UCRow [][] rowList;
private NGrid ng;
private PGrid pg;
private Decode dec;
private String cellName;
private String andFileName;
private String orFileName;
private boolean inputsOnTop;
private boolean outputsOnBottom;
/**
* Method called to generate a CMOS PLA.
* Invokes a dialog to ask for options.
*/
public static void generate()
{
// prompt the user for some information
SetupPLAGen dialog = new SetupPLAGen();
if (dialog.failed()) return;
generate(Library.getCurrent(), dialog.getCellName(), dialog.getAndFileName(), dialog.getOrFileName(),
dialog.isInputsOnTop(), dialog.isOutputsOnBottom(), false);
}
/**
* Method called to generate a CMOS PLA, given all options.
* @param destLib library where create PLA cells.
* @param cellName the name of the PLA cell to generate.
* @param andFileName the disk file with the AND plane.
* @param orFileName the disk file with the OR plane.
* @param inputsOnTop true to place inputs on the top of the plane.
* @param outputsOnBottom true to place outputs on the bottom of the plane.
* @param doItNow true if already in a Job and so do not start another.
*/
public static void generate(Library destLib, String cellName, String andFileName, String orFileName,
boolean inputsOnTop, boolean outputsOnBottom, boolean doItNow)
{
new GeneratePLAJob(destLib, cellName, andFileName, orFileName, inputsOnTop, outputsOnBottom, doItNow);
}
/**
* Class to build a CMOS PLA in a new Job.
*/
private static class GeneratePLAJob extends Job
{
private Library destLib;
private String cellName;
private String andFileName;
private String orFileName;
private boolean inputsOnTop;
private boolean outputsOnBottom;
private Cell newCell;
private boolean doItNow; // for regression
protected GeneratePLAJob(Library destLib, String cellName, String andFileName, String orFileName,
boolean inputsOnTop, boolean outputsOnBottom, boolean doItNow)
{
super("Generate MOSIS CMOS PLA", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER);
this.destLib = destLib;
this.cellName = cellName;
this.andFileName = andFileName;
this.orFileName = orFileName;
this.inputsOnTop = inputsOnTop;
this.outputsOnBottom = outputsOnBottom;
this.doItNow = doItNow;
if (doItNow)
{
try {doIt();} catch (Exception e) { e.printStackTrace();}
} else
{
startJob();
}
}
public boolean doIt() throws JobException
{
String libName = "pla_mocmos";
if (Library.findLibrary(libName) == null)
{
// start a job to read the PLA support library
URL fileURL = LibFile.getLibFile(libName + ".jelib");
LibraryFiles.readLibrary(fileURL, libName, FileType.JELIB, true);
}
PLA pla = new PLA(cellName, andFileName, orFileName, inputsOnTop, outputsOnBottom);
newCell = pla.doStep(destLib);
if (!doItNow)
fieldVariableChanged("newCell");
return true;
}
public void terminateOK()
{
if (newCell != null)
{
WindowFrame wf = WindowFrame.getCurrentWindowFrame();
if (User.isShowCellsInNewWindow()) wf = null;
if (wf == null) wf = WindowFrame.createEditWindow(newCell);
wf.setCellWindow(newCell, null);
}
}
}
private PLA(String cellName, String andFileName, String orFileName, boolean inputsOnTop, boolean outputsOnBottom)
{
this.cellName = cellName;
this.andFileName = andFileName;
this.orFileName = orFileName;
this.inputsOnTop = inputsOnTop;
this.outputsOnBottom = outputsOnBottom;
pg = new PGrid(this);
ng = new NGrid(this);
dec = new Decode(this);
}
private Cell doStep(Library lib)
throws JobException
{
initialize();
// generate the AND plane (Decode unit of a ROM)
String thisCellName = cellName + "_p_cell{lay}";
pmosCell = pg.pmosGrid(lib, andFileName, thisCellName);
if (pmosCell == null) return null;
thisCellName = cellName + "_n_cell{lay}";
nmosCell = ng.nmosGrid(lib, andFileName, thisCellName);
if (nmosCell == null) return null;
thisCellName = cellName + "_decode{lay}";
decodeCell = dec.decodeGen(lib, pmosCell, nmosCell, thisCellName, inputsOnTop);
if (decodeCell == null) return null;
// Generate the OR plane
thisCellName = cellName + "_or_cell{lay}";
orCell = ng.nmosGrid(lib, orFileName, thisCellName);
if (orCell == null) return null;
thisCellName = cellName + "_or_plane{lay}";
orPlaneCell = makeOrPlane(lib, thisCellName, outputsOnBottom);
if (orPlaneCell == null) return null;
Cell plaCell = makePLA(lib, cellName + "{lay}");
return plaCell;
}
private void initialize()
throws JobException
{
// get the right technology and all its nodes and arcs
Technology theTech = Technology.getMocmosTechnology();
if (theTech == null) throw new JobException("Cannot find technology 'mocmos'");
m1Pin = theTech.findNodeProto("Metal-1-Pin");
if (m1Pin == null) throw new JobException("Cannot find Metal-1-Pin primitive");
m2Pin = theTech.findNodeProto("Metal-2-Pin");
if (m2Pin == null) throw new JobException("Cannot find Metal-2-Pin primitive");
m12Con = theTech.findNodeProto("Metal-1-Metal-2-Con");
if (m12Con == null) throw new JobException("Cannot find Metal-1-Metal-2-Con primitive");
mpCon = theTech.findNodeProto("Metal-1-Polysilicon-1-Con");
if (mpCon == null) throw new JobException("Cannot find Metal-1-Polysilicon-1-Con primitive");
maCon = theTech.findNodeProto("Metal-1-N-Active-Con");
if (maCon == null) throw new JobException("Cannot find Metal-1-N-Active-Con primitive");
mwBut = theTech.findNodeProto("Metal-1-P-Well-Con");
if (mwBut == null) throw new JobException("Cannot find Metal-1-P-Well-Con primitive");
msBut = theTech.findNodeProto("Metal-1-N-Well-Con");
if (msBut == null) throw new JobException("Cannot find Metal-1-N-Well-Con primitive");
pwNode = theTech.findNodeProto("P-Well-Node");
if (pwNode == null) throw new JobException("Cannot find P-Well-Node primitive");
m1Arc = theTech.findArcProto("Metal-1");
if (msBut == null) throw new JobException("Cannot find Metal-1 arc");
m2Arc = theTech.findArcProto("Metal-2");
if (msBut == null) throw new JobException("Cannot find Metal-2 arc");
pArc = theTech.findArcProto("Polysilicon-1");
if (msBut == null) throw new JobException("Cannot find Polysilicon-1 arc");
aArc = theTech.findArcProto("N-Active");
if (msBut == null) throw new JobException("Cannot find N-Active arc");
// make sure the standard cell library is read in
String libName = "pla_mocmos";
Library cellLib = Library.findLibrary(libName);
if (cellLib == null) throw new JobException("Cannot find the 'pla_mocmos' support library");
// find required cells in the library
nmosOne = cellLib.findNodeProto("nmos_one");
if (nmosOne == null) throw new JobException("Unable to find cell 'nmos_one'");
pmosOne = cellLib.findNodeProto("pmos_one");
if (pmosOne == null) throw new JobException("Unable to find cell 'pmos_one'");
decoderInv = cellLib.findNodeProto("decoder_inv1");
if (decoderInv == null) throw new JobException("Unable to find cell 'decoder_inv1'");
ioInv4 = cellLib.findNodeProto("io-inv-4");
if (ioInv4 == null) throw new JobException("Unable to find cell 'io-inv-4'");
pullUps = cellLib.findNodeProto("pullups");
if (pullUps == null) throw new JobException("Unable to find cell 'pullups'");
// initialize the global tables
columnList = new UCRow[MAX_COL_SIZE];
rowList = new UCRow[MAX_COL_SIZE][3];
for(int i=0; i<MAX_COL_SIZE; i++)
{
columnList[i] = new UCRow();
rowList[i][0] = new UCRow();
rowList[i][1] = new UCRow();
rowList[i][2] = new UCRow();
}
}
/**
* This class displays a dialog to setup PLA generation.
*/
private static class SetupPLAGen extends EDialog
{
private JTextField andPlaneFile, orPlaneFile, cellName;
private JCheckBox inputs, outputs;
private boolean good;
/** Creates new form to setup PLA generation */
private SetupPLAGen()
{
super(null, true);
good = false;
initComponents();
setVisible(true);
}
protected void escapePressed() { exit(false); }
public boolean failed() { return !good; }
public String getAndFileName() { return andPlaneFile.getText(); }
public String getOrFileName() { return orPlaneFile.getText(); }
public boolean isInputsOnTop() { return inputs.isSelected(); }
public boolean isOutputsOnBottom() { return outputs.isSelected(); }
public String getCellName() { return cellName.getText(); }
// Call this method when the user clicks the OK button
private void exit(boolean goodButton)
{
good = goodButton;
setVisible(false);
}
private void browse(boolean andPlane)
{
String fileName = OpenFile.chooseInputFile(FileType.ANY,
(andPlane ? "AND Plane File:" : "OR Plane File:"));
if (fileName == null) return;
if (andPlane) andPlaneFile.setText(fileName); else
orPlaneFile.setText(fileName);
}
private void initComponents()
{
getContentPane().setLayout(new GridBagLayout());
setTitle("MOSIS CMOS PLA Generation Control");
setName("");
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent evt) { exit(false); }
});
// the AND plane
JLabel lab1 = new JLabel("AND Plane File:");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0; gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(lab1, gbc);
andPlaneFile = new JTextField();
andPlaneFile.setColumns(35);
gbc = new GridBagConstraints();
gbc.gridx = 1; gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1; gbc.weighty = 0.5;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(andPlaneFile, gbc);
JButton andPlaneBrowse = new JButton("Browse");
gbc = new GridBagConstraints();
gbc.gridx = 2; gbc.gridy = 0;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(andPlaneBrowse, gbc);
andPlaneBrowse.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt) { browse(true); }
});
// the OR plane
JLabel lab2 = new JLabel("OR Plane File:");
gbc = new GridBagConstraints();
gbc.gridx = 0; gbc.gridy = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(lab2, gbc);
orPlaneFile = new JTextField();
orPlaneFile.setColumns(35);
gbc = new GridBagConstraints();
gbc.gridx = 1; gbc.gridy = 1;
gbc.weightx = 1; gbc.weighty = 0.5;
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(orPlaneFile, gbc);
JButton orPlaneBrowse = new JButton("Browse");
gbc = new GridBagConstraints();
gbc.gridx = 2; gbc.gridy = 1;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(orPlaneBrowse, gbc);
orPlaneBrowse.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt) { browse(false); }
});
// other questions
inputs = new JCheckBox("Input to the Top of the AND plane");
inputs.setSelected(true);
gbc = new GridBagConstraints();
gbc.gridx = 0; gbc.gridy = 2;
gbc.gridwidth = 3;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(inputs, gbc);
outputs = new JCheckBox("Outputs from the Bottom of the OR plane");
outputs.setSelected(true);
gbc = new GridBagConstraints();
gbc.gridx = 0; gbc.gridy = 3;
gbc.gridwidth = 3;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(outputs, gbc);
JLabel lab3 = new JLabel("Cell name:");
gbc = new GridBagConstraints();
gbc.gridx = 0; gbc.gridy = 4;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(lab3, gbc);
cellName = new JTextField();
cellName.setText("pla");
gbc = new GridBagConstraints();
gbc.gridx = 1; gbc.gridy = 4;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(cellName, gbc);
// OK and Cancel
JButton cancel = new JButton("Cancel");
gbc = new GridBagConstraints();
gbc.gridx = 0; gbc.gridy = 5;
gbc.anchor = GridBagConstraints.CENTER;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(cancel, gbc);
cancel.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt) { exit(false); }
});
JButton ok = new JButton("OK");
getRootPane().setDefaultButton(ok);
gbc = new java.awt.GridBagConstraints();
gbc.gridx = 1; gbc.gridy = 5;
gbc.gridwidth = 2;
gbc.anchor = GridBagConstraints.CENTER;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(ok, gbc);
ok.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt) { exit(true); }
});
pack();
}
}
/**
* Plus Output options eg. column decode etc.
*/
private Cell makeOrPlane(Library library, String cellName, boolean outputsOnBottom)
{
Cell cell = Cell.makeInstance(library, cellName);
NodeInst orNode = makeInstance(cell, orCell, 0, 0, false);
if (orNode == null) return null;
NodeInst newNode = null;
NodeInst lastNode = null;
int columns = 2;
Variable var = orCell.getVar("PLA_data_cols");
if (var != null) columns = ((Integer)var.getObject()).intValue(); else
System.out.println("DATA_cols defaulting to 2");
NodeInst gndNode2 = null, pwrNode1 = null;
char side = 'n';
if (outputsOnBottom) side = 's';
int limit = columns / 4;
Rectangle2D nodeBounds = orNode.getBounds();
double lowX = nodeBounds.getMinX(); double highX = nodeBounds.getMaxX();
double lowY = nodeBounds.getMinY(); double highY = nodeBounds.getMaxY();
Rectangle2D cellBounds = ioInv4.getBounds();
double diff = cellBounds.getHeight();
if (diff < 0) diff = -diff;
if (limit == 0 || (columns % 4) != 0) limit++;
int invCnt = 0;
double invY = highY;
if (outputsOnBottom) invY = lowY - diff;
invY -= 5;
double invXOffset = lowX + 17;
PortProto invPwrW = ioInv4.findExport("PWR.m-2.w");
PortProto invPwrE = ioInv4.findExport("PWR.m-2.e");
PortProto invGnd1W = ioInv4.findExport("GND.m-2.sw");
PortProto invGnd1E = ioInv4.findExport("GND.m-2.se");
PortProto invGnd2W = ioInv4.findExport("GND.m-2.nw");
PortProto invGnd2E = ioInv4.findExport("GND.m-2.ne");
for (int i = 0; i < limit; i++)
{
newNode = makeInstance(cell, ioInv4, i*50 + invXOffset, invY, !outputsOnBottom);
if (newNode == null) return null;
if (lastNode == null)
{
Export.newInstance(cell, newNode.findPortInstFromProto(invPwrW), "PWR.m-2.w");
Export.newInstance(cell, newNode.findPortInstFromProto(invGnd1W), "GND.m-2.w");
// Put in GND bar pin (metal-2)
Poly poly = newNode.findPortInstFromProto(invGnd1W).getPoly();
double pwrY = poly.getCenterY();
NodeInst gndNode1 = makePin(cell, lowX-13, pwrY, 6, m12Con);
if (gndNode1 == null) return null;
makeWire(m2Arc, 14, newNode, invGnd1W, gndNode1, gndNode1.getProto().getPort(0), cell);
poly = newNode.findPortInstFromProto(invGnd2W).getPoly();
pwrY = poly.getCenterY();
gndNode2 = makePin(cell, lowX-13, pwrY, 6, m12Con);
if (gndNode2 == null) return null;
makeWire(m2Arc, 14, newNode, invGnd2W, gndNode2, gndNode2.getProto().getPort(0), cell);
makeWire(m2Arc, 14, gndNode1, gndNode1.getProto().getPort(0), gndNode2,
gndNode2.getProto().getPort(0), cell);
} else
{
// get wired
if (invPwrW != null && invPwrE != null)
makeWire(m2Arc, 14, lastNode, invPwrE, newNode, invPwrW, cell);
if (invGnd1W != null && invGnd1E != null)
makeWire(m2Arc, 14, lastNode, invGnd1E, newNode, invGnd1W, cell);
if (invGnd2W != null && invGnd2E != null)
makeWire(m2Arc, 14, lastNode, invGnd2E, newNode, invGnd2W, cell);
}
lastNode = newNode;
for (int x = invCnt; x < invCnt+4; x++)
{
Export pPort = orCell.findExport("DATA" + x + ".m-1." + side);
Export nPort = ioInv4.findExport("in" + (x%4) + ".m-1.n");
Export outPort = ioInv4.findExport("out" + (x % 4) + "-bar.m-1.s");
if (outPort != null)
Export.newInstance(cell, newNode.findPortInstFromProto(outPort), "out" + (invCnt + (x % 4)) + ".m-1." + side);
if (pPort != null && nPort != null)
makeWire(m1Arc, 4, orNode, pPort, newNode, nPort, cell);
}
invCnt += 4;
}
if (invPwrE != null)
{
Poly poly = lastNode.findPortInstFromProto(invPwrE).getPoly();
double pwrY = poly.getCenterY();
pwrNode1 = makePin(cell, highX+13, pwrY, 14, m2Pin);
if (pwrNode1 == null) return null;
makeWire(m2Arc, 14, lastNode, invPwrE, pwrNode1, pwrNode1.getProto().getPort(0), cell);
Export.newInstance(cell, lastNode.findPortInstFromProto(invPwrE), "PWR.m-2.e");
}
if (invGnd1W != null)
Export.newInstance(cell, lastNode.findPortInstFromProto(invGnd1E), "GND.m-2.e");
// OK PUT in the PULLUPS
newNode = null;
lastNode = null;
side = 's';
if (outputsOnBottom) side = 'n';
Rectangle2D pullUpsBounds = pullUps.getBounds();
double pullUpsDiff = pullUpsBounds.getHeight();
if (pullUpsDiff < 0) pullUpsDiff = -pullUpsDiff;
int pullUpsCnt = 0;
double pullUpsY = highY;
if (!outputsOnBottom) pullUpsY = lowY - pullUpsDiff;
pullUpsY += 16;
double pullUpsXOffset = lowX + 27;
Export pullUpsPwrW = pullUps.findExport("PWR.m-2w");
if (pullUpsPwrW == null)
{
System.out.println("Cannot find port PWR.m-2w in "+pullUps);
return null;
}
Export pullUpsPwrE = pullUps.findExport("PWR.m-2e");
if (pullUpsPwrE == null)
{
System.out.println("Cannot find port PWR.m-2e in "+pullUps);
return null;
}
Export pullUpsGnd1W = pullUps.findExport("GND.m-1.sw");
if (pullUpsGnd1W == null)
{
System.out.println("Cannot find port GND.m-1.sw in "+pullUps);
return null;
}
Export pullUpsGnd1E = pullUps.findExport("GND.m-1.se");
if (pullUpsGnd1E == null)
{
System.out.println("Cannot find port GND.m-1.se in "+pullUps);
return null;
}
for (int i = 0; i < limit; i++)
{
newNode = makeInstance(cell, pullUps, i*50 + pullUpsXOffset, pullUpsY, !outputsOnBottom);
if (newNode == null) return null;
if (lastNode == null)
{
Export.newInstance(cell, newNode.findPortInstFromProto(pullUpsPwrW), "PWR0.m-2.w");
Export.newInstance(cell, newNode.findPortInstFromProto(pullUpsGnd1W), "GND0.m-1.w");
PortInst pi = newNode.findPortInstFromProto(pullUpsGnd1W);
Poly poly = pi.getPoly();
double pwrY = poly.getCenterY();
NodeInst gndNode1 = makePin(cell, lowX-13, pwrY, 6, m12Con);
if (gndNode1 == null) return null;
makeWire(m1Arc, 4, newNode, pullUpsGnd1W, gndNode1, gndNode1.getProto().getPort(0), cell);
makeWire(m2Arc, 14, gndNode1, gndNode1.getProto().getPort(0), gndNode2,
gndNode2.getProto().getPort(0), cell);
Export pullUpsGnd2W = orCell.findExport("GND" + i + ".m-1." + side);
Export pullUpsGnd2E = orCell.findExport("GND" + (i+1) + ".m-1." + side);
if (pullUpsGnd1W != null && pullUpsGnd2W != null)
makeWire(m1Arc, 4, newNode, pullUpsGnd1W, orNode, pullUpsGnd2W, cell);
if (pullUpsGnd2W != null && pullUpsGnd2E != null)
makeWire(m1Arc, 4, newNode, pullUpsGnd1E, orNode, pullUpsGnd2E, cell);
} else
{
// get wired
if (pullUpsPwrW != null && pullUpsPwrE != null)
makeWire(m2Arc, 14, lastNode, pullUpsPwrE, newNode, pullUpsPwrW, cell);
Export pullUpsGnd2W = orCell.findExport("GND" + i + ".m-1." + side);
Export pullUpsGnd2E = orCell.findExport("GND" + (i+1) + ".m-1." + side);
if (pullUpsGnd1W != null && pullUpsGnd2W != null)
makeWire(m1Arc, 4, newNode, pullUpsGnd1W, orNode, pullUpsGnd2W, cell);
if (pullUpsGnd1E != null && pullUpsGnd2E != null)
makeWire(m1Arc, 4, newNode, pullUpsGnd1E, orNode, pullUpsGnd2E, cell);
}
lastNode = newNode;
for (int x = pullUpsCnt; x < pullUpsCnt+4; x++)
{
Export pPort = orCell.findExport("DATA" + x + ".m-1." + side);
Export nPort = pullUps.findExport("PULLUP" + (x%4) + ".m-1.s");
if (pPort != null && nPort != null)
makeWire(m1Arc, 4, orNode, pPort, newNode, nPort, cell);
}
pullUpsCnt += 4;
}
if (pullUpsPwrE != null)
{
PortInst pi = lastNode.findPortInstFromProto(pullUpsPwrE);
Poly poly = pi.getPoly();
double pwrY = poly.getCenterY();
NodeInst pwrNode2 = makePin(cell, highX+13, pwrY, 14, m2Pin);
if (pwrNode2 == null) return null;
makeWire(m2Arc, 14, lastNode, pullUpsPwrE, pwrNode2, pwrNode2.getProto().getPort(0), cell);
makeWire(m2Arc, 14, pwrNode1, pwrNode1.getProto().getPort(0), pwrNode2,
pwrNode2.getProto().getPort(0), cell);
Export.newInstance(cell, lastNode.findPortInstFromProto(pullUpsPwrE), "PWR0.m-2.e");
}
if (pullUpsGnd1E != null)
Export.newInstance(cell, lastNode.findPortInstFromProto(pullUpsGnd1E), "GND0.m-1.e");
int x = 0;
String aName = "ACCESS" + x + ".p.w";
PortProto pPort = orCell.findPortProto(aName);
while (pPort != null)
{
Export.newInstance(cell, orNode.findPortInstFromProto(pPort), aName);
x++;
aName = "ACCESS" + x + ".p.w";
pPort = orCell.findPortProto(aName);
}
return cell;
}
private Cell makePLA(Library library, String name)
{
Cell cell = Cell.makeInstance(library, name);
NodeInst decodeNode = makeInstance(cell, decodeCell, 0, 0, false);
if (decodeNode == null) return null;
Rectangle2D decodeBounds = decodeNode.getBounds();
NodeInst orNode = makeInstance(cell, orPlaneCell, decodeBounds.getMaxX()+27, 0, false);
if (orNode == null) return null;
Export orPort = orPlaneCell.findExport("ACCESS0.p.w");
Poly orPoly = orNode.findPortInstFromProto(orPort).getPoly();
double orY = orPoly.getCenterY();
Export decodePort = decodeCell.findExport("DATA0.m-1.n");
Poly decodePoly = decodeNode.findPortInstFromProto(decodePort).getPoly();
double decodeY = decodePoly.getCenterY();
double dY = decodeY - orY;
if (orY != decodeY) orNode.move(0, dY);
int x = 0;
while (orPort != null && decodePort != null)
{
makeWire(m1Arc, 4, orNode, orPort, decodeNode, decodePort, cell);
x++;
orPort = orPlaneCell.findExport("ACCESS" + x + ".p.w");
decodePort = decodeCell.findExport("DATA" + x + ".m-1.n");
}
return cell;
}
NodeInst makePin(Cell cell, double x, double y, double size, PrimitiveNode node)
{
double xS = node.getDefWidth();
double yS = node.getDefHeight();
if (size < xS) size = xS;
if (size < yS) size = yS;
NodeInst ni = NodeInst.makeInstance(node, new Point2D.Double(x, y), size, size, cell);
if (ni == null)
System.out.println("Unable to create " + node + " in " + cell);
return ni;
}
void makeWire(ArcProto typ, double width, NodeInst fromNodeInst,
PortProto fromPortProto, NodeInst toNodeInst, PortProto toPortProto, Cell cell)
{
PortInst fromPi = fromNodeInst.findPortInstFromProto(fromPortProto);
PortInst toPi = toNodeInst.findPortInstFromProto(toPortProto);
if (typ == null)
{
System.out.println("Attempting to wire with unknown arc layer");
return;
}
double wid = typ.getDefaultLambdaBaseWidth();
// double wid = typ.getDefaultLambdaFullWidth();
// w = us_widestarcinst(typ, fromnodeinst, fromportproto);
// if (w > wid) wid = w;
// w = us_widestarcinst(typ, tonodeinst, toportproto);
// if (w > wid) wid = w;
if (width > wid) wid = width;
ArcInst ai = ArcInst.makeInstanceBase(typ, wid, fromPi, toPi);
// ArcInst ai = ArcInst.makeInstanceFull(typ, wid, fromPi, toPi);
if (ai == null)
{
System.out.println("Unable to run " + typ + " from " + fromNodeInst +
", " + fromPortProto + " to " + toNodeInst + ", " +
toPortProto + " in " + cell);
}
}
NodeInst makeInstance(Cell cell, Cell instProto, double x, double y, boolean mirror)
{
Rectangle2D protoBounds = instProto.getBounds();
double sX = protoBounds.getWidth();
double sY = protoBounds.getHeight();
Orientation orient = Orientation.IDENT;
if (mirror)
{
orient = Orientation.Y;
double y1 = protoBounds.getMinY() + y;
double y2 = protoBounds.getMaxY() + y;
y = y2 + y1 - y;
}
NodeInst ni = NodeInst.makeInstance(instProto, new Point2D.Double(x, y), sX, sY, cell, orient, null);
return ni;
}
}