/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: WellTie.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.gates;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.Export;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.tool.generator.layout.LayoutLib;
import com.sun.electric.tool.generator.layout.StdCellParams;
import com.sun.electric.tool.generator.layout.TechType;
import com.sun.electric.tool.generator.layout.TrackRouterH;
import com.sun.electric.tool.Job;
// Well Ties now serve two roles.
//
// 1) First, they are inserted between abutted cells. In this case the
// cells must be moved apart to make room for the tie. The ties are
// chosen to be as narrow as possible because they increase the GasP
// cell width.
//
// 2) Second, they are inserted in half height gaps. In this case the
// ties are also serving as well patches. These well ties are made as
// wide as the gap. A contact is included on the left and right of the
// cell because additional contacts can decrease the width of the GasP
// cell by reducing the need to insert
//
// Well contacts are allocated on a pitch: WELL_CONT_PITCH that
// guarantees that there are no select errors from adjacent
// contacts. There are two reasons well contacts can be adjacent.
// First, a single WellTie can have multiple contacts. Second, when
// cells are concatenated, a well tie from one cell might be adjacent
// to a well tie from another cell.
public class WellTie {
private static final double DEF_SIZE = LayoutLib.DEF_SIZE;
// diff_cont_width + select_surround + select_space
private static final double WELL_CONT_PITCH = 5 + 4 + 2;
private static void error(boolean pred, String msg) {
Job.error(pred, msg);
}
/** The maximum distance from an internal well contact to the right
edge of the WellTie. */
public static double edgeToContDist() {return WELL_CONT_PITCH*1.5;}
/** Create a well tie
* @param nmos should this well tie include nmos well contacts
* @param pmos should this well tie include pmos well contacts
* @param wid desired width of well tie. 0 means produce minimum
* width contact */
public static Cell makePart(boolean nmos, boolean
pmos, double wid, StdCellParams stdCell) {
TechType tech = stdCell.getTechType();
if (wid==0) wid=WELL_CONT_PITCH;
String nm = (nmos?"Nmos":"") + (pmos?"Pmos":"") + "WellTie";
nm = stdCell.parameterizedName(nm)+"_W"+wid+"{lay}";
Cell tie = stdCell.findPart(nm);
if (tie!=null) return tie;
tie = stdCell.newPart(nm);
// Leave half a pitch distance from any contact to the right and
// left edges of WellTie.
double leftWellContX = WELL_CONT_PITCH/2;
double rightWellContX = wid - WELL_CONT_PITCH/2;
// Well width must be at least 12 to avoid DRC errors This cell is
// one of the rare cases where the cell's essential bounds are
// narrower than the well
//
// On second thought, I just noticed that Electric's well contact
// is asymmetric! It sticks out an extra .5 lambda on top and
// right. Jon Lexau asked me to completely cover it.
double wellMinX = leftWellContX - 6.5;
double wellMaxX = Math.max(leftWellContX, rightWellContX) + 6.5;
// add well contacts
if (wid<WELL_CONT_PITCH) {
// This well tie has no room for a contact. It can only being
// used as a well patch.
} else {
if (nmos) {
// export
String portNm = stdCell.getNmosWellTieName();
Export e =
LayoutLib.newExport(tie, portNm,
stdCell.getNmosWellTieRole(), tech.m2(),
4, leftWellContX,
stdCell.getNmosWellTieY());
// left well contact
PortInst left =
LayoutLib.newNodeInst(tech.pwm1(), leftWellContX, stdCell.getNmosWellTieY(),
DEF_SIZE,
DEF_SIZE,
0, tie).getOnlyPortInst();
// connect them
TrackRouterH tr =
new TrackRouterH(tech.m2(),
stdCell.getNmosWellTieWidth(),
stdCell.getNmosWellTieY(), tech, tie);
tr.connect(e);
tr.connect(left);
// Insert right contact if there's room.
if (wid>=WELL_CONT_PITCH*2) {
PortInst right =
LayoutLib.newNodeInst(tech.pwm1(), rightWellContX, stdCell.getNmosWellTieY(),
DEF_SIZE,
DEF_SIZE, 0, tie
).getOnlyPortInst();
tr.connect(right);
}
}
if (pmos) {
// export
String portNm = stdCell.getPmosWellTieName();
Export e =
LayoutLib.newExport(tie, portNm,
stdCell.getPmosWellTieRole(), tech.m2(),
4, leftWellContX,
stdCell.getPmosWellTieY());
TrackRouterH tr =
new TrackRouterH(tech.m2(),
stdCell.getPmosWellTieWidth(),
stdCell.getPmosWellTieY(), tech, tie);
// left well contact
PortInst left =
LayoutLib.newNodeInst(tech.nwm1(), leftWellContX, stdCell.getPmosWellTieY(),
DEF_SIZE,
DEF_SIZE, 0, tie
).getOnlyPortInst();
// connect them
tr.connect(e);
tr.connect(left);
// Insert right contact if there's room.
if (wid>=WELL_CONT_PITCH*2) {
PortInst right =
LayoutLib.newNodeInst(tech.nwm1(), rightWellContX, stdCell.getPmosWellTieY(),
DEF_SIZE,
DEF_SIZE, 0, tie
).getOnlyPortInst();
tr.connect(right);
}
}
}
// add wells
if (nmos) stdCell.addNmosWell(wellMinX, wellMaxX, tie);
if (pmos) stdCell.addPmosWell(wellMinX, wellMaxX, tie);
// add essential bounds
if (nmos) {
if (pmos) {
stdCell.addEssentialBounds(0, wid, tie);
} else {
stdCell.addNstackEssentialBounds(0, wid, tie);
}
} else {
error(!pmos, "WellTie must be for at least one well");
stdCell.addPstackEssentialBounds(0, wid, tie);
}
return tie;
}
}