/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: KeeperHigh.java * * Copyright (c) 2003 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.layout; import java.util.ArrayList; import java.util.Iterator; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.hierarchy.Export; import com.sun.electric.database.network.Netlist; import com.sun.electric.database.network.Network; import com.sun.electric.database.prototype.NodeProto; import com.sun.electric.database.prototype.PortCharacteristic; 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.tool.generator.layout.gates.Inv; import com.sun.electric.tool.generator.layout.gates.Pms1; import com.sun.electric.tool.Job; public class KeeperHigh { private static void error(boolean pred, String msg) { Job.error(pred, msg); } public static Cell makePart(Cell schem, VarContext context, StdCellParams stdCell) { TechType tech = stdCell.getTechType(); Netlist netlist = schem.getNetlist(); Iterator<NodeInst> nodes = schem.getNodes(); // extract size information double szMc = -1, szPmos = -1, szK = -1, szI = -1; while (nodes.hasNext()) { NodeInst ni = nodes.next(); String nm = ni.getProto().getName(); if (nm.equals("pms1K{ic}")) { szPmos = StdCellParams.getSize(ni, context); } else if (nm.equals("invK{ic}")) { szK = StdCellParams.getSize(ni, context); } else if (nm.equals("inv{ic}")) { Network net = netlist.getNetwork(ni.findPortInst("in")); if (net.hasName("mc")) { szMc = StdCellParams.getSize(ni, context); } else if (net.hasName("d")) { szI = StdCellParams.getSize(ni, context); } else { System.out.println("Unrecognized net: "); Iterator<String> it = net.getNames(); while (it.hasNext()) { System.out.println(it.next()); } error(true, "unrecognized net"); } } } error(szMc == -1, "KeeperHigh: inv bufferring mc not found"); error(szPmos == -1, "KeeperHigh: pmos not found"); error(szK == -1, "KeeperHigh: invK not found"); error(szI == -1, "KeeperHigh: inv driving invK not found"); double sz = stdCell.roundSize(szK); Cell keep = stdCell.findPart("keeper_high", sz); if (keep != null) return keep; keep = stdCell.newPart("keeper_high", sz); NodeProto invKProto = Inv.makePart(szK, stdCell); NodeInst invK = LayoutLib.newNodeInst(invKProto, 0, 0, 0, 0, 0, keep); NodeProto invIProto = Inv.makePart(szI, stdCell); NodeInst invI = LayoutLib.newNodeInst(invIProto, 0, 0, 0, 0, 0, keep); NodeProto pmosProto = Pms1.makePart(szPmos, stdCell); NodeInst pmos = LayoutLib.newNodeInst(pmosProto, 0, 0, 0, 0, 0, keep); NodeProto mcProto = Inv.makePart(szMc, stdCell); NodeInst mc = LayoutLib.newNodeInst(mcProto, 0, 0, 0, 0, 0, keep); ArrayList<NodeInst> l = new ArrayList<NodeInst>(); l.add(mc); l.add(pmos); l.add(invK); l.add(invI); LayoutLib.abutLeftRight(l); /* doesn't work, either it never worked or it stopped working // Mirror invK left to right so I don't have to use a metal-2 track. invK.mirrorLeftToRight(); */ // connect up power and ground TrackRouter vdd = new TrackRouterH(tech.m2(), 10, tech, keep); vdd.connect(new NodeInst[] { mc, pmos, invK, invI }, "vdd"); TrackRouter gnd = new TrackRouterH(tech.m2(), 10, tech, keep); gnd.connect(new NodeInst[] { mc, invK, invI }, "gnd"); // connect up signal wires TrackRouter d = new TrackRouterH(tech.m2(), 4, LayoutLib.roundCenterY(pmos.findPortInst("d")), tech, keep); d.connect(new PortInst[] {pmos.findPortInst("d"), invK.findPortInst("out"), invI.findPortInst("in")}); /* Use this when I finally get mirroring to work (again?) //double trackY = -11; */ double trackY = stdCell.getTrackY(-1); TrackRouter d_bar = new TrackRouterH(tech.m2(), 4, trackY, tech, keep); d_bar.connect(new PortInst[] {invK.findPortInst("in"), invI.findPortInst("out")}); TrackRouter mc_bar = new TrackRouterH(tech.m1(), 4, LayoutLib.roundCenterY(pmos.findPortInst("g")), tech, keep); mc_bar.connect(new PortInst[] {mc.findPortInst("out"), pmos.findPortInst("g")}); // exports Export.newInstance(keep, mc.findPortInst("in"), "mc") .setCharacteristic(PortCharacteristic.IN); Export.newInstance(keep, pmos.findPortInst("d"), "d") .setCharacteristic(PortCharacteristic.BIDIR); Export.newInstance(keep, invK.findPortInst("vdd"), "vdd") .setCharacteristic(PortCharacteristic.PWR); Export.newInstance(keep, invK.findPortInst("gnd"), "gnd") .setCharacteristic(PortCharacteristic.GND); // patch well over pullup stdCell.addNmosWell( mc.getBounds().getWidth(), mc.getBounds().getWidth() + pmos.getBounds().getWidth(), keep); // add essential bounds stdCell.addEssentialBounds(0, invI.getBounds().getMaxX(), keep); // Compare schematic to layout /* if (stdCell.nccEnabled()) { NccOptions options = new NccOptions(); options.checkExportNames = true; options.hierarchical = true; options.mergeParallel = true; boolean mismatch = Electric.networkConsistencyCheck(schem, context, keep, options); error(mismatch, "KeeperHigh topological mismatch"); } */ return keep; } }