SaguaroImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Written by gbb, March 31, 1987 5:37:59 pm PST
gbb April 2, 1987 1:17:47 pm PST
Saguaro is an extractor just for transistors. The code is very similar to the one now in Spinifex and much simpler than the original approach based on corner stitching.
DIRECTORY
CD USING [Layer, NewLayer, Number, Object, Position, Rect],
CDAtomicObjects USING [AtomicObsSpecific, DrawList],
CDBasics USING [highposition, minposition, NonEmpty],
CMosB USING [lambda, ndif, nwell, pdif, pol, pwell],
Rope USING [ROPE],
Saguaro;
SaguaroImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CMosB
EXPORTS Saguaro ~ BEGIN OPEN Saguaro;
Types
gate: PUBLIC CD.Layer ~ CD.NewLayer [NIL, $gate];
pol: CD.Layer ~ CMosB.pol;
ndif: CD.Layer ~ CMosB.ndif;
pdif: CD.Layer ~ CMosB.pdif;
nwell: CD.Layer ~ CMosB.nwell;
pwell: CD.Layer ~ CMosB.pwell;
lambda: CD.Number ~ CMosB.lambda;
invalidTransistor: PUBLIC SIGNAL [msg: Rope.ROPE] ~ CODE;
ExtractedTransistor: TYPE ~ REF exXtr;
ExXtr: TYPE ~ RECORD [ch1, ch2, gate, bulk: Geom, width, length: CD.Number];
Geom: TYPE ~ RECORD [layout: DrawList, area, perimeter: INT];
DrawList: TYPE ~ CDAtomicObjects.DrawList;
DrawList: TYPE ~ LIST OF DrawRec;
DrawRec: TYPE ~ RECORD [r: CD.Rect, layer: CD.Layer ← CD.errorLayer];
Operation
ExtractTransistor: PUBLIC PROC [obj: CD.Object] RETURNS [et: ExtractedTransistor] ~ BEGIN
Interim version. Technology dependent !!!
tClass: ATOM ~ obj.class.objectType;
isNType: BOOL ~ (obj.layer = ndif); -- fix
isNWell: BOOL;
sep: CD.Number ~ lambda;
extensionLength: CD.Number ~ 3 * lambda; -- ch1/ch2 extension [rule 6.3.18]
rect, wellRect: CD.Rect;
polList, difList, chList, difListSouth: LIST OF CD.Rect ← NIL;
extL, extW: CD.Number;
Get the geometry. Streching information has already been procesed by ChipNDale.
IF ISTYPE [obj.specific, CDAtomicObjects.AtomicObsSpecific] THEN
FOR geom: CDAtomicObjects.DrawList ← NARROW [obj.specific, CDAtomicObjects.AtomicObsSpecific].rList, geom.rest WHILE geom # NIL DO
SELECT geom.first.layer FROM
pol => polList ← CONS [geom.first.r, polList];
ndif, pdif => difList ← CONS [geom.first.r, difList];
nwell, pwell => {wellRect ← geom.first.r; isNWell ← (geom.first.layer = nwell)};
ENDCASE => SIGNAL invalidTransistor ["Unknown transistor geometry"]
ENDLOOP
ELSE SIGNAL invalidTransistor ["Replace this old Chipmonk transistor"];
Process the geometry according to the transistor class. The ChipNDale transistors are fully supported for p substrate.
et ← NEW [ExXtr];
SELECT tClass FROM
$C2Trans, $C2WellTrans => BEGIN-- straight transistors
difRect, polRect, chRect, difExtRectNorth, difExtRectSouth, polExtEast, polExtWest: CD.Rect;
difRect ← difList.first; polRect ← polList.first;
chRect ← [difRect.x1, polRect.y1, difRect.x2, polRect.y2];
difExtRectNorth ← difExtRectSouth ← difRect;
difExtRectNorth.y1 ← polRect.y2; difExtRectSouth. y2 ← polRect.y1;
polExtWest ← [polRect.x1, polRect.y1, difRect.x1, polRect.y2];
polExtEast ← [difRect.x2, polRect.y1, polRect.x2, polRect.y2];
et.length ← polRect.y2 - polRect.y1; et.width ← difRect.x2 - difRect.x1;
extL ← polRect.y1 - difRect.y1; extW ← difRect.x1 - polRect.x1;
et.gate.area ← (et.width + 2*extW) * et.length;
et.gate.perimeter ← (et.width + 2*extW + et.length) * 2;
et.ch1.area ← et.ch2.area ← extL * et.width;
et.ch1.perimeter ← et.ch2.perimeter ← 2 * extL + et.width;
IF (extL < extensionLength) THEN SIGNAL invalidTransistor ["Extension length too small"];
et.gate.layout ← LIST [[polExtEast, pol], [polExtWest, pol], [chRect, gate]];
et.ch1.layout ← LIST [[difExtRectNorth, obj.layer]];
et.ch2.layout ← LIST [[difExtRectSouth, obj.layer]];
et.length ← polRect.y2 - polRect.y1; et.width ← difRect.x2 - difRect.x1;
IF tClass = $C2WellTrans THEN BEGIN
l: CD.Layer ~ (IF isNWell THEN nwell ELSE pwell); -- fix
IF NOT CDBasics.NonEmpty[wellRect] THEN SIGNAL invalidTransistor ["Well transistor must have a well"];
et.bulk.layout ← LIST [[wellRect, l]]
END
END; -- case $CTrans
$C2LTrans, $C2LWellTrans => BEGIN-- angle transistors
diffNE: CD.Position ← CDBasics.minposition;
diffSW, polSW: CD.Position ← CDBasics.highposition;
polHor, polVert, polExtWest, polExtNorth, chRectH, chRectV: CD.Rect;
IF ((polList.first.y2-polList.first.y1) < (polList.rest.first.y2-polList.rest.first.y1)) THEN
{polHor ← polList.first; polVert ← polList.rest.first}
ELSE {polHor ← polList.rest.first; polVert ← polList.first};
FOR diff: LIST OF CD.Rect ← difList, diff.rest WHILE diff # NIL DO
IF (diff.first.x1 <= diffSW.x) AND (diff.first.y1 <= diffSW.y) THEN
diffSW ← [diff.first.x1, diff.first.y1];
IF (diff.first.x2 >= diffNE.x) AND (diff.first.y2 >= diffNE.y) THEN
diffNE ← [diff.first.x2, diff.first.y2];
ENDLOOP;
polSW ← [polHor.x1, polHor.y1];
extW ← diffSW.x - polSW.x;
extL ← polSW.y - diffSW.y;
et.length ← polHor.y2 - polHor.y1;
et.width ← ((polHor.x2 - polHor.x1) - extW) + ((polVert.y2 - polVert.y1) - extW) - (et.length*3/2);
et.gate.area ← ((et.width+et.length/2) + 2*extW) * et.length;
et.gate.perimeter ← ((polHor.x2 - polHor.x1) + (polVert.y2 - polVert.y1)) * 2;
et.ch1.area ← ((diffNE.x - diffSW.x) + (diffNE.y - diffSW.y - extL)) * extL;
et.ch1.perimeter ← 2 * extL + (diffNE.x - diffSW.x) + (diffNE.y - diffSW.y);
et.ch2.perimeter ← diffNE.x + diffNE.y - diffSW.x - diffSW.y - 2 * (extL + et.length);
et.ch2.area ← et.ch2.perimeter * extL;
IF (extL < extensionLength) THEN SIGNAL invalidTransistor ["Extension length too small"];
polExtWest ← [polSW.x, polSW.y, diffSW.x, polHor.y2];
polExtNorth ← [diffNE.x-extL-et.length, diffNE.y, diffNE.x-extL, polHor.y2];
chRectH ← polHor; chRectH.x1 ← chRectH.x1 + extW;
chRectV ← polVert;
chRectV.y1 ← chRectV.y1 + et.length; chRectV.y2 ← chRectV.y2 - extW;
et.gate.layout ← LIST [[polExtWest, pol], [polExtNorth, pol], [chRectH, gate], [chRectV, gate]];
Process gate lead-in
BEGIN-- Bogus but first approx. for a fast impl.
d: CD.Number ← extL + et.length + sep;
rect ← [x1: diffSW.x, y1: diffSW.y+extL+et.length, x2: diffNE.x-extL-et.length, y2: diffSW.y+d];
et.ch1.layout ← LIST [[rect, obj.layer]]; -- North
rect ← [x1: diffNE.x-d, y1: diffSW.y+extL+et.length, x2: diffNE.x-extL-et.length, y2: diffNE.y];
et.ch1.layout ← CONS [[rect, obj.layer], et.ch1.layout]; -- West
d ← extL - sep;
rect ← [x1: diffSW.x, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffSW.y+extL];
et.ch2.layout ← LIST [[rect, obj.layer]]; -- South
rect ← [x1: diffNE.x-extL, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffNE.y];
et.ch2.layout ← CONS [[rect, obj.layer], et.ch2.layout] -- East
END; -- gate lead-in
Process well.
IF tClass = $C2WellTrans THEN BEGIN
l: CD.Layer ~ (IF isNWell THEN nwell ELSE pwell); -- fix
IF NOT CDBasics.NonEmpty[wellRect] THEN SIGNAL invalidTransistor ["Well transistor must have a well"];
et.bulk.layout ← LIST [[wellRect, l]]
END
END; -- case $C2LTrans, $C2LWellTrans
ENDCASE => SIGNAL invalidTransistor ["Unknown or antique transistor class"];
state.attributes.PutGeometry [cell.public[0], et.gate.layout];
state.attributes.PutGeometry [cell.public[1], et.ch1.layout];
state.attributes.PutGeometry [cell.public[2], et.ch2.layout]
END; -- MakeTransistor
Initialisation
END.