-- ChipExpandAtomic.mesa

-- A package to expand atomic Chipmonk cell geometries,
-- such as transistors and contacts, for circuit extraction.


-- modified by Dillon, March 14, 1984 7:53 PM
-- to change the buried contact geometry
-- last modified by E. McCreight, January 30, 1984 6:27 PM
-- written by E. McCreight, March 17, 1982 10:28 AM

DIRECTORY
ChipDRC,
ChipExpand,
ChipNetDefs,
ppdefs;

ChipExpandAtomic: PROGRAM
IMPORTS ChipDRC, ChipExpand, ChipNetDefs
EXPORTS ChipExpand SHARES ChipExpand =
BEGIN OPEN ppdefs, ChipNetDefs, ChipDRC, ChipExpand;


-- Procedures copied from Chipmonk and changed slightly
-- for design rule checking and circuit extraction. The main
-- difference here is that pol and dif are not allowed
-- to overlap at all.

exXstr0: PUBLIC drProc =
BEGIN
p: LONG POINTER TO xstr object = LOOPHOLE[ob];
IF p.l=pdif THEN
pr.orArea[x-p.surround+p.wExt, y-p.surround,
x+p.size[0]+p.surround-p.wExt, y+p.size[1]+p.surround,
nwel, @pr.r];

IF x > pr.r.x2 OR y > pr.r.y2 OR x + p.size[0] < pr.r.x1
OR y + p.size[1] < pr.r.y1 THEN RETURN;
-- IF p.lExt>0 THEN
BEGIN -- make 0-length source/drain terminals anyway
joinTo ← @xstrInst.map[drain];
pr.orArea[x + p.wExt, y, x + p.width + p.wExt, y + p.lExt,
p.l, @pr.r]; -- "drain" dif
joinTo ← @xstrInst.map[source];
pr.orArea[x + p.wExt, y + p.length + p.lExt,
x + p.width + p.wExt, y + p.size[1],
p.l, @pr.r]; -- "source" dif
END;
joinTo ← @xstrInst.map[gate];
pr.orArea[x, y + p.lExt, x + p.size[0], y + p.length + p.lExt,
pol, @pr.r]; -- gate
IF doingDRC THEN
BEGIN
ExtractorFeature.p[x+p.wExt, y+p.lExt,
x+p.width+p.wExt, y + p.length + p.lExt,
(IF p.l=dif THEN nGate ELSE pGate)];
IF p.wExt<polyGateOverlap THEN
BEGIN
ExtractorFeature.p[x-polyGateOverlap+p.wExt, y+p.lExt,
x, y + p.length + p.lExt, polyRequired];
ExtractorFeature.p[x+p.size[0], y+p.lExt,
x+p.size[0]+polyGateOverlap-p.wExt, y + p.length + p.lExt,
polyRequired];
END;
IF p.lExt<minTransistorDiffusionWidth THEN
BEGIN
ExtractorFeature.p[x+p.wExt,
y-minTransistorDiffusionWidth+p.lExt,
x+p.width+p.wExt, y,
(IF p.l=dif THEN nPlusRequired ELSE pPlusRequired)];
ExtractorFeature.p[x+p.wExt, y + p.size[1],
x+p.width+p.wExt,
y + p.length + p.lExt+minTransistorDiffusionWidth,
(IF p.l=dif THEN nPlusRequired ELSE pPlusRequired)];
END;
ExtractorFeature[x+p.wExt-depletionOverlap,
y+p.lExt-depletionOverlap,
x+p.width+p.wExt+depletionOverlap,
y + p.length + p.lExt+depletionOverlap,
(IF p.impl#enhancement THEN nDepletionRequired
ELSE nDepletionForbidden)];
END;
IF p.impl#enhancement THEN
pr.orArea[x+p.wExt-depletionOverlap,
y+p.lExt-depletionOverlap,
x + p.size[0]-p.wExt+depletionOverlap,
y + p.size[1]-p.lExt+depletionOverlap,
imp, @pr.r];
END;

exAXstr0: PUBLIC drProc =
BEGIN
p: LONG POINTER TO xstr object = LOOPHOLE[ob];
ele: locNum;
hPoly, vPoly, nDrain, eDrain, wSource, sSource: Rect;
IF x > pr.r.x2 OR y > pr.r.y2 OR x + p.size[0] < pr.r.x1
OR y + p.size[1] < pr.r.y1 THEN RETURN;

ele ← 2*p.lExt+p.length; -- length and two length extensions

-- The transistor makes a 90-degree bend, going eastward and
-- then southward. The diffusion on the outer side of the angle,
-- that is, on the northeast side, is arbitrarily called the drain.

hPoly ← [x1: x, y1: y+p.lExt,
x2: x+p.size[0]-p.lExt, y2: y+p.length+p.lExt];
vPoly ← [x1: x+p.size[0]-p.length-p.lExt,
y1: hPoly.y2, x2: hPoly.x2, y2: y+p.size[1]];
nDrain ← [x1: x+p.wExt, y1: y, x2: x+p.size[0],
y2: hPoly.y1];
eDrain ← [x1: vPoly.x2, y1: nDrain.y2,
x2: nDrain.x2, y2: y+p.size[1]-p.wExt];
wSource ← [
x1: x+p.size[0]-ele,
y1: hPoly.y2,
x2: vPoly.x1,
y2: y+p.size[1]-p.wExt];
sSource ← [x1: x+MIN[p.wExt, p.size[0]-ele],
y1: hPoly.y2,
x2: wSource.x1,
y2: y+MIN[ele, p.size[1]-p.wExt]];

-- We are willing to put out 0-width wires here
-- so that other conductors can join onto them,
-- and so that design rule checking can work.

joinTo ← @xstrInst.map[drain];
pr.orArea[nDrain.x1, nDrain.y1, nDrain.x2, nDrain.y2,
p.l, @pr.r]; -- north "drain" dif
pr.orArea[eDrain.x1, eDrain.y1, eDrain.x2, eDrain.y2,
p.l, @pr.r]; -- east "drain" dif
joinTo ← @xstrInst.map[source];
pr.orArea[wSource.x1, wSource.y1, wSource.x2, wSource.y2,
p.l, @pr.r]; -- west "source" dif
IF sSource.x1<sSource.x2 THEN
pr.orArea[sSource.x1, sSource.y1, sSource.x2, sSource.y2,
p.l,@pr.r]; -- south "source" dif

joinTo ← @xstrInst.map[gate];
pr.orArea[hPoly.x1, hPoly.y1, hPoly.x2, hPoly.y2, pol, @pr.r];
-- horizontal gate
IF vPoly.y1<vPoly.y2 THEN
pr.orArea[vPoly.x1, vPoly.y1, vPoly.x2, vPoly.y2, pol, @pr.r];
-- vertical gate

IF doingDRC THEN
BEGIN
reqLev: ExtractLevel ←
IF p.l=dif THEN nPlusRequired ELSE pPlusRequired;

ExtractorFeature.p[sSource.x1, hPoly.y1, hPoly.x2, hPoly.y2,
(IF p.l=dif THEN nGate ELSE pGate)]; -- horizontal
ExtractorFeature.p[vPoly.x1, vPoly.y1, vPoly.x2, wSource.y2,
(IF p.l=dif THEN nGate ELSE pGate)]; -- vertical

IF sSource.x1-hPoly.x1<polyGateOverlap THEN
ExtractorFeature.p[
sSource.x1-polyGateOverlap,
hPoly.y1,
hPoly.x1, hPoly.y2, polyRequired]; -- horizontal

IF vPoly.y2-wSource.y2<polyGateOverlap THEN
ExtractorFeature.p[vPoly.x1, vPoly.y2,
vPoly.x2, wSource.y2+polyGateOverlap,
polyRequired]; -- vertical

IF p.lExt<minTransistorDiffusionWidth THEN
BEGIN
ExtractorFeature.p[
nDrain.x1,
nDrain.y2-minTransistorDiffusionWidth,
eDrain.x1+minTransistorDiffusionWidth, nDrain.y1,
reqLev]; -- north drain
ExtractorFeature.p[
eDrain.x2,
eDrain.y1,
eDrain.x1+minTransistorDiffusionWidth,
eDrain.y2,
reqLev]; -- east drain
END;

IF wSource.x2-wSource.x1<minTransistorDiffusionWidth THEN
ExtractorFeature.p[
wSource.x2-minTransistorDiffusionWidth,
wSource.y1,
wSource.x1,
MAX[wSource.y2, wSource.y1+minTransistorDiffusionWidth],
reqLev]; -- west source

IF sSource.x1<sSource.x2 AND
sSource.y2-sSource.y1<minTransistorDiffusionWidth THEN
ExtractorFeature.p[
sSource.x1,
sSource.y2,
sSource.x2,
sSource.y1+minTransistorDiffusionWidth,
reqLev]; -- south source
END;

IF p.impl#enhancement THEN
BEGIN
pr.orArea[nDrain.x1-depletionOverlap,
hPoly.y1-depletionOverlap,
hPoly.x2+depletionOverlap,
hPoly.y2+depletionOverlap,
imp, @pr.r];
pr.orArea[vPoly.x1-depletionOverlap,
vPoly.y1-depletionOverlap,
vPoly.x2+depletionOverlap,
eDrain.y2+depletionOverlap,
imp, @pr.r];
END
ELSE IF doingDRC THEN
BEGIN
ExtractorFeature.p[
sSource.x1-depletionOverlap,
hPoly.y1-depletionOverlap,
hPoly.x2+depletionOverlap,
hPoly.y2+depletionOverlap,
nDepletionForbidden]; -- horizontal
ExtractorFeature.p[
vPoly.x1-depletionOverlap,
vPoly.y1-depletionOverlap,
vPoly.x2+depletionOverlap,
wSource.y2+depletionOverlap,
nDepletionForbidden]; -- vertical
END;
END; -- of exAXstr0

exPu0: PUBLIC drProc =
BEGIN
p: LONG POINTER TO xstr object = LOOPHOLE[ob];
xx, yy: INTEGER;
id: NormalNetIdPtr;
xstrInst.map[gate] ← xstrInst.map[source] ← NewNet[initRefs: 2];
id ← GetNormalNetId[@xstrInst.map[gate]];
id.source ← NearestCellInstance[xstrInst];
id.couldBeLogo ← FALSE;
IF x > pr.r.x2 OR y > pr.r.y2 OR x + p.size[0] < pr.r.x1
OR y + p.size[1] < pr.r.y1 THEN RETURN;
xx ← x + p.wExt;
yy ← y + p.lExt;
-- IF p.lExt>0 THEN
BEGIN
joinTo ← @xstrInst.map[drain];
pr.orArea[xx, y, xx + p.width, y + p.lExt, p.l, @pr.r];
-- "drain" dif
END;
joinTo ← @xstrInst.map[gate];
pr.orArea[x, yy, x + p.size[0], yy + p.length, pol, @pr.r];
pr.orArea[x, y, x + p.size[0], yy + p.length + p.lExt,
imp, @pr.r];
xx ← x + p.size[0]/2 - butconSX/2;
yy ← y + p.size[1];
joinTo ← @xstrInst.map[source];
pr.orArea[xx, y+p.lExt+p.length, xx + butconSX, yy,
p.l, @pr.r]; -- "source" dif
joinTo ← @xstrInst.map[gate];
pr.orArea[xx, yy - butconSY, xx + butconSX, yy, met, @pr.r];
xx ← xx + butconSX/4;
yy ← yy - butconSX/4;
pr.saveArea[xx, yy - butconSX, xx + butconSX/2, yy,
cut, @pr.r];
END;

exBC0: PUBLIC drProc =
BEGIN
p: LONG POINTER TO cont object = LOOPHOLE[ob];
IF x > pr.r.x2 OR y > pr.r.y2 OR x + p.size[0] < pr.r.x1
OR y + p.size[1] < pr.r.y1 THEN RETURN;
pr.orArea[x, y, x + p.size[0], y + p.size[1], met, @pr.r];
pr.orArea[x, y, x + p.size[0], y + p.size[1]/2, pol, @pr.r];
pr.orArea[x, y + p.size[1]/2, x + p.size[0], y + p.size[1],
p.l, @pr.r];
pr.saveArea[
x + p.magicN, y + p.magicN, x - p.magicN + p.size[0],
y + p.magicN + p.size[0], cut, @pr.r];
END;

exBuC0: PUBLIC drProc =
BEGIN
p: LONG POINTER TO cont object = LOOPHOLE[ob];
burAct: locNum = 2*lambda;
dBur: locNum = lambda/2;
difBur: Point;

IF x-p.surround > pr.r.x2 OR y-p.surround > pr.r.y2
OR x + p.size[0] +p.surround < pr.r.x1
OR y + p.size[1]+p.surround < pr.r.y1 THEN RETURN;

pr.saveArea[x+dBur, y+dBur, x+p.size[0]-dBur, y+p.size[1]-dBur, bur, @pr.r];
pr.orArea[x+burAct, y+p.lExt, x+p.size[0]-p.wExt, y+p.size[1]-p.lExt, pol, @pr.r];
difBur ← [
x: (IF p.wExt<burAct THEN MAX[p.wExt+lambda, burAct] ELSE (p.wExt-lambda)),
y: (IF p.lExt<burAct THEN MAX[p.lExt+lambda, burAct] ELSE (p.lExt-lambda))];
pr.orArea[x+lambda, y+difBur.y, x+p.size[0]-difBur.x, y+p.size[1]-difBur.y, p.l, @pr.r];
IF p.l=pdif THEN
pr.orArea[x+lambda-p.surround, y+difBur.y-p.surround, x + p.size[0]-difBur.x+p.surround,
y+p.size[1]-difBur.y+p.surround, nwel, @pr.r];
END;

END. -- of ChipExpandAtomic