/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Gates.java
*
* Copyright (c) 2003, 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.layout;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.HierarchyEnumerator;
import com.sun.electric.database.hierarchy.HierarchyEnumerator.CellInfo;
import com.sun.electric.database.hierarchy.Library;
import com.sun.electric.database.hierarchy.Nodable;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.variable.EditWindow_;
import com.sun.electric.database.variable.UserInterface;
import com.sun.electric.database.variable.VarContext;
import com.sun.electric.database.variable.Variable;
import com.sun.electric.technology.Technology;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.JobException;
import com.sun.electric.tool.generator.layout.gates.Inv350;
import com.sun.electric.tool.generator.layout.gates.MoCMOSGenerator;
import com.sun.electric.tool.logicaleffort.LEInst;
import com.sun.electric.tool.user.User;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/*
* Regression test for gate generators
*/
public class GateLayoutGenerator {
// specify which gates shouldn't be surrounded by DRC rings
private static final DrcRings.Filter FILTER = new DrcRings.Filter() {
@Override
public boolean skip(NodeInst ni) {
// well tie cells don't pass DRC with DrcRings
return ni.getProto().getName().indexOf("mosWellTie_") != -1;
}
};
// private static void error(boolean pred, String msg) {
// LayoutLib.error(pred, msg);
// }
// private Cell findCell(Library lib, String cellName) {
// Cell c = lib.findNodeProto(cellName);
// LayoutLib.error(c==null, "can't find: "+lib+":"+cellName);
// return c;
// }
public static Cell generateCell(Library outputLib, StdCellParams stdCell,
String type, double Xstrength) {
if (outputLib == null) return null;
TechType tech = stdCell.getTechType();
stdCell.setOutputLibrary(outputLib);
if (Xstrength<0) return null;
int pwr = type.indexOf("_pwr");
if (pwr!=-1) type = type.substring(0, pwr);
Cell c = null;
if (tech.getTechnology()==Technology.getCMOS90Technology())
{
try
{
Class<?> cmos90GeneratorClass = Class.forName("com.sun.electric.plugins.tsmc.gates90nm.CMOS90Generator");
Class<?> [] parameterTypes = new Class[] {String.class, Double.class, StdCellParams.class};
Method makeGateMethod = cmos90GeneratorClass.getDeclaredMethod("makeGate", parameterTypes);
c = (Cell)makeGateMethod.invoke(null, new Object[] {type, new Double(Xstrength), stdCell});
} catch (Exception e)
{
System.out.println("ERROR invoking the CMOS90 gate generator");
}
// c = CMOS90Generator.makeGate(pNm, x, stdCell);
} else if (tech.getTechnology().getTechName().equals("MIMOS_035"))
{
if (type.equals("inv")) {
c = Inv350.makePart(Xstrength, "", stdCell);
} else {
System.out.println("Can't generate cell " + type + " for technology " + tech.name());
}
} else
{
c = MoCMOSGenerator.makeGate(type, Xstrength, stdCell);
}
return c;
}
/**
* Generate layout cells from a hierarchical traversal of the
* schematic cell
* @param outLib the output library
* @param cell the schematic cell
* @param context the context of the schematic cell
* @param stdCell the standard cell parameters
* @param topLevelOnly true to generate gates in the top level only,
* so it does not generate standard cells in sub cells.
* @return a map of cells generated
*/
public static Map<Nodable,Cell> generateLayoutFromSchematics(Library outLib,
Cell cell, VarContext context,
StdCellParams stdCell, boolean topLevelOnly) {
stdCell.setOutputLibrary(outLib);
GenerateLayoutForGatesInSchematic visitor =
new GenerateLayoutForGatesInSchematic(stdCell, topLevelOnly);
HierarchyEnumerator.enumerateCell(cell, context, visitor);
// HierarchyEnumerator.enumerateCell(cell, context, null, visitor);
Map<Nodable,Cell> result = visitor.getGeneratedCells();
if (result.size() > 0)
{
Cell gallery = Gallery.makeGallery(outLib);
DrcRings.addDrcRings(gallery, FILTER, stdCell);
}
return result;
}
public static void generateFromSchematicsJob(Technology technology) {
GenerateFromSchematicsJob job = new GenerateFromSchematicsJob(technology);
job.startJob();
}
public static StdCellParams locoParams() {
StdCellParams stdCell = new StdCellParams(Technology.getMocmosTechnology());
stdCell.enableNCC("purpleFour");
stdCell.setSizeQuantizationError(0);
stdCell.setMaxMosWidth(1000);
stdCell.setVddY(21);
stdCell.setGndY(-21);
stdCell.setNmosWellHeight(42);
stdCell.setPmosWellHeight(42);
stdCell.setSimpleName(true);
return stdCell;
}
public static StdCellParams sportParams() {
return sportParams(true);
}
public static StdCellParams sportParams(boolean enableNCC) {
StdCellParams stdCell = new StdCellParams(Technology.getCMOS90Technology());
if (enableNCC) stdCell.enableNCC("purpleFour");
stdCell.setSizeQuantizationError(0);
stdCell.setMaxMosWidth(1000);
stdCell.setVddY(24.5);
stdCell.setGndY(-24.5);
stdCell.setNmosWellHeight(84);
stdCell.setPmosWellHeight(84);
stdCell.setSimpleName(true);
return stdCell;
}
public static StdCellParams dividerParams(Technology technology) {
return dividerParams(technology, true);
}
public static StdCellParams dividerParams(Technology technology, boolean enableNCC) {
StdCellParams stdCell = new StdCellParams(technology);
if (enableNCC) stdCell.enableNCC("purpleFour");
stdCell.setSizeQuantizationError(0);
stdCell.setMaxMosWidth(1000);
stdCell.setVddY(21);
stdCell.setGndY(-21);
stdCell.setNmosWellHeight(84);
stdCell.setPmosWellHeight(84);
stdCell.setSimpleName(true);
return stdCell;
}
public static StdCellParams fastProxParams(Technology technology) {
StdCellParams stdCell = new StdCellParams(technology);
stdCell.enableNCC("purpleFour");
stdCell.setSizeQuantizationError(0);
stdCell.setMaxMosWidth(1000);
stdCell.setVddY(24);
stdCell.setGndY(-24);
stdCell.setVddWidth(9);
stdCell.setGndWidth(9);
stdCell.setNmosWellHeight(60);
stdCell.setPmosWellHeight(60);
stdCell.setSimpleName(true);
return stdCell;
}
public static StdCellParams justinParams(Technology technology) {
StdCellParams stdCell = new StdCellParams(technology);
stdCell.enableNCC("purpleFour");
stdCell.setSizeQuantizationError(0);
stdCell.setMaxMosWidth(1000);
stdCell.setVddY(21);
stdCell.setGndY(-21);
stdCell.setNmosWellHeight(42);
stdCell.setPmosWellHeight(42);
stdCell.setSimpleName(true);
return stdCell;
}
public static class GenerateFromSchematicsJob extends Job {
static final long serialVersionUID = 0;
private Technology technology;
private Cell cell;
private VarContext context;
public GenerateFromSchematicsJob(Technology technology) {
super("Generate gate layouts", User.getUserTool(), Job.Type.CHANGE,
null, null, Job.Priority.ANALYSIS);
this.technology = technology;
UserInterface ui = Job.getUserInterface();
EditWindow_ wnd = ui.needCurrentEditWindow_();
if (wnd == null) return;
cell = wnd.getCell();
context = wnd.getVarContext();
}
@Override
public boolean doIt() throws JobException {
String outLibNm = "autoGenLib"+technology;
Library outLib = LayoutLib.openLibForWrite(outLibNm);
StdCellParams stdCell;
if (technology == Technology.getCMOS90Technology()) {
stdCell = sportParams();
} else if (technology.getTechName().equals("MIMOS_035")) {
stdCell = StdCellParams350.invParams(technology);
} else {
//stdCell = locoParams(outLib);
stdCell = dividerParams(technology);
//stdCell = justinParams(outLib, technology);
}
if (cell==null) {
System.out.println("Please open the schematic for which you " +
"want to generate gate layouts.");
return false;
}
if (!cell.isSchematic()) {
System.out.println("The current cell isn't a schematic. This " +
"command only works on schematics.");
return false;
}
System.out.println("Generating layouts for gates in the schematic: "+
cell.getName()+" and its descendents");
System.out.println("Output goes to library: " + outLibNm);
//Library outLib = cell.getLibrary();
GateLayoutGenerator.generateLayoutFromSchematics(outLib, cell, context, stdCell, false);
System.out.println("done.");
return true;
}
}
}
/** Traverse a schematic hierarchy and generate Cells that we recognize. */
class GenerateLayoutForGatesInSchematic extends HierarchyEnumerator.Visitor {
private final StdCellParams stdCell;
private final boolean DEBUG = false;
private final boolean topLevelOnly;
private final Variable.Key ATTR_X;
private Map<Nodable,Cell> generatedCells;
private void trace(String s) {
if (DEBUG) System.out.println(s);
}
private void traceln(String s) {
trace(s);
trace("\n");
}
/**
* Construct a Visitor that will walk a schematic and generate layout for Cells.
* param libraryName the name of the library that contains the Cells for
* which we want to generate layout. For example: "redFour" or "purpleFour".
* param cellNames the names of the Cells for which we want to generate layout
*/
public GenerateLayoutForGatesInSchematic(StdCellParams stdCell, boolean topLevelOnly) {
this.stdCell = stdCell;
this.topLevelOnly = topLevelOnly;
this.generatedCells = new HashMap<Nodable,Cell>();
this.ATTR_X = stdCell.getTechType().getAttrX();
}
/** @return value of strength attribute "ATTR_X" or -1 if no such
* attribute or -2 if attribute exists but has no value. */
private double getStrength(Nodable no, VarContext context) {
Variable var = no.getParameterOrVariable(ATTR_X);
if (var==null) return -1;
Object val = context.evalVar(var, no);
if (val==null) return -2;
//LayoutLib.error(val==null, "strength is null?");
Job.error(!(val instanceof Number),
"strength not number?");
return ((Number)val).doubleValue();
}
private Cell generateCell(Nodable iconInst, CellInfo info) {
VarContext context = info.getContext();
String pNm = iconInst.getProto().getName();
double x = getStrength(iconInst, context);
if (x==-2) {
System.out.println("no value for strength attribute for Cell: "+
pNm+" instance: "+
info.getUniqueNodableName(iconInst, "/"));
}
// System.out.println("Try : "+pNm+" X="+x+" for instance: "+
// info.getUniqueNodableName(iconInst, "/"));
Cell c = GateLayoutGenerator.generateCell(stdCell.getOutputLibrary(), stdCell, pNm, x);
if (c!=null) {
// record defining schematic cell if it is sizable
if (LEInst.getType(iconInst, context) == LEInst.Type.LEGATE) {
c.newVar(LEInst.ATTR_LEGATE, c.libDescribe());
}
if (LEInst.getType(iconInst, context) == LEInst.Type.LEKEEPER) {
c.newVar(LEInst.ATTR_LEKEEPER, c.libDescribe());
}
System.out.println("Use: "+pNm+" X="+x+" for instance: "+
info.getUniqueNodableName(iconInst, "/"));
}
return c;
}
@Override
public boolean enterCell(CellInfo info) {
VarContext ctxt = info.getContext();
traceln("Entering Cell instance: "+ctxt.getInstPath("/"));
return true;
}
@Override
public void exitCell(CellInfo info) {
VarContext ctxt = info.getContext();
traceln("Leaving Cell instance: "+ctxt.getInstPath("/"));
}
@Override
public boolean visitNodeInst(Nodable no, CellInfo info) {
// we never generate layout for PrimitiveNodes
if (no instanceof NodeInst) return false;
trace("considering instance: "+
info.getUniqueNodableName(no, "/")+" ... ");
Cell cell = (Cell) no.getProto();
Library lib = cell.getLibrary();
String libNm = lib.getName();
if (libNm.equals("redFour") || libNm.equals("purpleFour") ||
libNm.equals("power2_gates")) {
traceln("generate");
Cell c = generateCell(no, info);
if (c != null) generatedCells.put(no, c);
return false;
}
traceln("descend");
if (topLevelOnly) return false;
return true;
}
public Map<Nodable,Cell> getGeneratedCells() { return generatedCells; }
}