/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: PGrid.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 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.generator.cmosPLA; 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.NodeInst; import com.sun.electric.database.topology.PortInst; /** * Class to generate the P grid part of MOSIS CMOS PLAs. */ public class PGrid { private PLA pla; PGrid(PLA pla) { this.pla = pla; } Cell pmosGrid(Library library, String fileName, String cellName) { int y = 0; int x = 3; int xOffset = PLA.X_SEP; int yOffset = PLA.Y_SEP; int yMOffset = PLA.Y_MIR_SEP; Cell cell = Cell.makeInstance(library, cellName); IO perFile = new IO(); if (!perFile.readHeader(fileName)) { System.out.println("Error reading height and width"); return null; } int width = perFile.getWidth(); int height = perFile.getHeight(); int widthIn = perFile.getWidthIn(); int heightIn = perFile.getHeightIn(); cell.newVar("PLA_data_cols", new Integer(widthIn)); cell.newVar("PLA_access_rows", new Integer(heightIn)); cell.newVar("PLA_cols", new Integer(width)); cell.newVar("PLA_rows", new Integer(height)); // initialize the columns if (pmosInitColumns(width, x, y, xOffset, cell)) return null; // initialize the rows if (pmosInitRows(heightIn, x, y, yOffset, yMOffset, cell)) return null; y = 3 - yOffset; x = xOffset + 4; int row = 0; int readRows = 0; while (readRows < heightIn) { // read in the two rows first int [] row1 = null, row2 = null; if (readRows < heightIn) { row1 = perFile.readRow(); if (row1 == null) return null; readRows++; } if (readRows < heightIn) { row2 = perFile.readRow(); if (row2 == null) return null; readRows++; } for(int i = 0; i < width; i++) { // place a pmos_one cell and connect to power, and cell up above if (((i % 5) == 0) && (i != 0)) // put in power strap { if (pwrStrap(i, ((xOffset*i)+3), y, cell)) return null; } else { // put in bits -- make an instance of a pmos_one if ((row1[i] == 1) && (row1[0] != -1)) { // make an instance of a pmos_one if (pmosMakeOne(i, ((i*xOffset)+6), y, 0, row, cell)) return null; } if ((row2[i] == 1) && (row2[0] != -1)) { // make an instance of a pmos_one if (pmosMakeOne(i, ((i*xOffset)+6), y-yMOffset, 2, row, cell)) return null; } } } // Now put the poly metal contact at on the other side of the row if (pmosCompleteRow(row, ((xOffset*width)+0), y, cell)) return null; if ((readRows % 4) == 0) y -= yOffset; row++; y -= 2*yOffset; } x = 3; if ((readRows % 4) == 0) y += 2*yOffset-3; else y += yOffset-3; if (pmosFinishColumns(width, x, y, xOffset, cell)) return null; perFile.done(); return cell; } private boolean pmosInitColumns(int width, int x, int y, int xOffset, Cell arrayCell) { int pwrCnt = 0; for (int i = 0; i < width; i++) { pla.columnList[i].firstItem = new PLA.UCItem(); pla.columnList[i].lastitem = pla.columnList[i].firstItem; String name; if ((i % 5) == 0) { // put in a Power pin every 5th position name = "PWR" + pwrCnt + ".m-1.n"; pla.columnList[i].firstItem.nodeInst = pla.makePin(arrayCell, xOffset * i + x, y, 14, pla.msBut); if (pla.columnList[i].firstItem.nodeInst == null) return true; pwrCnt++; } else { // must be a data pin, don't count power pins name = "DATA" + (i - pwrCnt) + ".m-1.n"; pla.columnList[i].firstItem.nodeInst = pla.makePin(arrayCell, xOffset * i + x, y, 4, pla.m1Pin); if (pla.columnList[i].firstItem.nodeInst == null) return true; } PortProto pp = pla.columnList[i].firstItem.nodeInst.getProto().getPort(0); PortInst pi = pla.columnList[i].firstItem.nodeInst.findPortInstFromProto(pp); Export.newInstance(arrayCell, pi, name); } return false; } private boolean pmosInitRows(int heightIn, int x, int y, int yOffset, int yMOffset, Cell arrayCell) { int limit = (heightIn/2) + (heightIn % 2); for (int i = 0; i < limit; i++) { PLA.UCItem newItem = new PLA.UCItem(); if (((i % 2) == 0) && (i != 0)) y -= yOffset; // put in Substrate contact first newItem.nodeInst = pla.makePin(arrayCell, x, y-yMOffset+10, 14, pla.msBut); if (newItem.nodeInst == null) return true; // wire in the first power strap // connect to last column object // only put this in a column list PortProto nodeColPort = newItem.nodeInst.getProto().getPort(0); PortProto lastColPort = pla.columnList[0].lastitem.nodeInst.getProto().getPort(0); pla.makeWire(pla.m1Arc, 4, pla.columnList[0].lastitem.nodeInst, lastColPort, newItem.nodeInst, nodeColPort, arrayCell); pla.columnList[0].lastitem.bottomItem = newItem; pla.columnList[0].lastitem = pla.columnList[0].lastitem.bottomItem; pla.rowList[i][0].firstItem = new PLA.UCItem(); pla.rowList[i][0].lastitem = pla.rowList[i][0].firstItem; pla.rowList[i][2].firstItem = new PLA.UCItem(); pla.rowList[i][2].lastitem = pla.rowList[i][2].firstItem; pla.rowList[i][0].firstItem.nodeInst = pla.makePin(arrayCell, x-7, y-5, 6, pla.mpCon); if (pla.rowList[i][0].firstItem.nodeInst == null) return true; pla.rowList[i][2].firstItem.nodeInst = pla.makePin(arrayCell, x-7, y-15, 6, pla.mpCon); if (pla.rowList[i][2].firstItem.nodeInst == null) return true; y -= 2*yOffset; } return false; } private boolean pwrStrap(int i, int x, int y, Cell arrayCell) { PLA.UCItem newItem = new PLA.UCItem(); // put in Substrate contact first newItem.nodeInst = pla.makePin(arrayCell, x, y+7, 14, pla.msBut); if (newItem.nodeInst == null) return true; // wire in the first power strap and connect to last column object PortProto nodeColPort = newItem.nodeInst.getProto().getPort(0); PortProto lastColPort = pla.columnList[i].lastitem.nodeInst.getProto().getPort(0); pla.makeWire(pla.m1Arc, 4, pla.columnList[i].lastitem.nodeInst, lastColPort, newItem.nodeInst, nodeColPort, arrayCell); // only put this in a column list pla.columnList[i].lastitem.bottomItem = newItem; pla.columnList[i].lastitem = pla.columnList[i].lastitem.bottomItem; return false; } private boolean pmosMakeOne(int i, int x, int y, int rowPos, int row, Cell arrayCell) { NodeInst ni = pla.makeInstance(arrayCell, pla.pmosOne, x, y, false); if (ni == null) return true; // find ports that need to be connected and connect to last column object PortProto nodeColPort = ni.getProto().findPortProto("IN.m-1.n"); PortProto lastColPort; if (pla.columnList[i].lastitem.nodeInst.getProto() != pla.pmosOne) // a Metal pin lastColPort = pla.columnList[i].firstItem.nodeInst.getProto().getPort(0); else lastColPort = pla.columnList[i].lastitem.nodeInst.getProto().findPortProto("OUT.m-1.s"); pla.makeWire(pla.m1Arc, 4, pla.columnList[i].lastitem.nodeInst, lastColPort, ni, nodeColPort, arrayCell); // connect to last GATE object if (pla.rowList[row][rowPos].lastitem.nodeInst.getProto() != pla.pmosOne) lastColPort = pla.rowList[row][rowPos].lastitem.nodeInst.getProto().getPort(0); else lastColPort = pla.rowList[row][rowPos].lastitem.nodeInst.getProto().findPortProto("GATE.p.e"); nodeColPort = ni.getProto().findPortProto("GATE.p.w"); pla.makeWire(pla.pArc, 0, pla.rowList[row][rowPos].lastitem.nodeInst, lastColPort, ni, nodeColPort, arrayCell); // put in column list pla.columnList[i].lastitem.bottomItem = new PLA.UCItem(); pla.columnList[i].lastitem = pla.columnList[i].lastitem.bottomItem; pla.columnList[i].lastitem.nodeInst = ni; // put in row list pla.rowList[row][rowPos].lastitem.rightItem = pla.columnList[i].lastitem; pla.rowList[row][rowPos].lastitem = pla.rowList[row][rowPos].lastitem.rightItem; return false; } private boolean pmosCompleteRow(int row, int x, int y, Cell arrayCell) { PLA.UCItem newItem = new PLA.UCItem(); newItem.nodeInst = pla.makePin(arrayCell, x, y+2, 6, pla.mpCon); if (newItem.nodeInst == null) return true; // connect to last GATE object PortProto lastColPort; if (pla.rowList[row][0].lastitem.nodeInst.getProto() != pla.pmosOne) lastColPort = pla.rowList[row][0].lastitem.nodeInst.getProto().getPort(0); else lastColPort = pla.rowList[row][0].lastitem.nodeInst.getProto().findPortProto("GATE.p.e"); PortProto nodeColPort = newItem.nodeInst.getProto().getPort(0); pla.makeWire(pla.pArc, 0, pla.rowList[row][0].lastitem.nodeInst, lastColPort, newItem.nodeInst, nodeColPort, arrayCell); pla.rowList[row][0].lastitem = newItem; // Now export port at the beginning and end of this half of row grouping PortProto pp = pla.rowList[row][0].firstItem.nodeInst.getProto().getPort(0); PortInst pi = pla.rowList[row][0].firstItem.nodeInst.findPortInstFromProto(pp); Export.newInstance(arrayCell, pi, "ACCESS" + (row * 2) + ".m-1.w"); pp = pla.rowList[row][0].lastitem.nodeInst.getProto().getPort(0); pi = pla.rowList[row][0].lastitem.nodeInst.findPortInstFromProto(pp); Export.newInstance(arrayCell, pi, "ACCESS" + (row * 2) + ".m-1.e"); pp = pla.rowList[row][0].firstItem.nodeInst.getProto().getPort(0); pi = pla.rowList[row][0].firstItem.nodeInst.findPortInstFromProto(pp); Export.newInstance(arrayCell, pi, "ACCESS" + (row * 2) + ".p.w"); pp = pla.rowList[row][0].lastitem.nodeInst.getProto().getPort(0); pi = pla.rowList[row][0].lastitem.nodeInst.findPortInstFromProto(pp); Export.newInstance(arrayCell, pi, "ACCESS" + (row * 2) + ".p.e"); newItem = new PLA.UCItem(); newItem.nodeInst = pla.makePin(arrayCell, x, y-8, 6, pla.mpCon); if (newItem.nodeInst == null) return true; // connect to last GATE object if (pla.rowList[row][2].lastitem.nodeInst.getProto() != pla.pmosOne) lastColPort = pla.rowList[row][2].lastitem.nodeInst.getProto().getPort(0); else lastColPort = pla.rowList[row][2].lastitem.nodeInst.getProto().findPortProto("GATE.p.e"); nodeColPort = newItem.nodeInst.getProto().getPort(0); pla.makeWire(pla.pArc, 0, pla.rowList[row][2].lastitem.nodeInst, lastColPort, newItem.nodeInst, nodeColPort, arrayCell); pla.rowList[row][2].lastitem = newItem; pp = pla.rowList[row][2].firstItem.nodeInst.getProto().getPort(0); pi = pla.rowList[row][2].firstItem.nodeInst.findPortInstFromProto(pp); Export.newInstance(arrayCell, pi, "ACCESS" + (row * 2 + 1) + ".m-1.w"); pp = pla.rowList[row][2].lastitem.nodeInst.getProto().getPort(0); pi = pla.rowList[row][2].lastitem.nodeInst.findPortInstFromProto(pp); Export.newInstance(arrayCell, pi, "ACCESS" + (row * 2 + 1) + ".m-1.e"); pp = pla.rowList[row][2].firstItem.nodeInst.getProto().getPort(0); pi = pla.rowList[row][2].firstItem.nodeInst.findPortInstFromProto(pp); Export.newInstance(arrayCell, pi, "ACCESS" + (row * 2 + 1) + ".p1.w"); pp = pla.rowList[row][2].lastitem.nodeInst.getProto().getPort(0); pi = pla.rowList[row][2].lastitem.nodeInst.findPortInstFromProto(pp); Export.newInstance(arrayCell, pi, "ACCESS" + (row * 2 + 1) + ".p.e"); return false; } private boolean pmosFinishColumns(int width, int x, int y, int xOffset, Cell arrayCell) { int pwrCnt = 0; for (int i = 0; i < width; i++) { PLA.UCItem newItem = new PLA.UCItem(); String name; PortProto lastColPort; if ((i % 5) == 0) // put in a power pin every 5th position { name = "PWR" + pwrCnt + ".m-1.s"; newItem.nodeInst = pla.makePin(arrayCell, xOffset * i + x, y, 14, pla.msBut); if (newItem.nodeInst == null) return true; lastColPort = pla.columnList[i].lastitem.nodeInst.getProto().getPort(0); pwrCnt++; } else { // must be a data pin, don't count power pins name = "DATA" + (i - pwrCnt) + ".m-1.s"; newItem.nodeInst = pla.makePin(arrayCell, xOffset * i + x, y, 4, pla.m1Pin); if (newItem.nodeInst == null) return true; if (pla.columnList[i].lastitem.nodeInst.getProto() != pla.pmosOne) lastColPort = pla.columnList[i].lastitem.nodeInst.getProto().getPort(0); else lastColPort = pla.columnList[i].lastitem.nodeInst.getProto().findPortProto("OUT.m-1.s"); } // wire in the first power strap PortProto nodeColPort = newItem.nodeInst.getProto().getPort(0); // connect to last column object pla.makeWire(pla.m1Arc, 4, pla.columnList[i].lastitem.nodeInst, lastColPort, newItem.nodeInst, nodeColPort, arrayCell); // only put this in a column list pla.columnList[i].lastitem.bottomItem = newItem; pla.columnList[i].lastitem = pla.columnList[i].lastitem.bottomItem; PortInst pi = newItem.nodeInst.findPortInstFromProto(newItem.nodeInst.getProto().getPort(0)); Export.newInstance(arrayCell, pi, name); } return false; } }