SXCMosBTransistorsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last edited by: gbb January 14, 1986 3:26:38 pm PST
Bowers, October 9, 1985 4:03:32 pm PDT
DIRECTORY
CD USING [Instance, InstanceList, Layer, Number, Orientation, Position, Rect],
CDAtomicObjects USING [AtomicObsPtr, DrawList],
CDBasics USING [empty, highposition, minposition, NonEmpty],
CDProperties USING [GetPropFromInstance],
CDSimpleRules USING [MinDist],
CMosB USING [lambda, ndif, nwell, pdif, pol, pwell, wndif, wpdif],
IO USING [char, int, Put, PutF, PutRope, rope],
Properties USING [PutProp],
Rope USING [Cat, ROPE],
SX USING [AddBox, AddRect, AdjustNode, AttachedNode, Circuit, CircuitNode, Constraint, ConversionProc, CreateLinkage, IllegalConstruct, LinkageAttach, NodeLinkage, SpinifexLayerIndex],
SXAtoms USING [crystalAttr],
SXCMosB USING [ndCh, ndCnstr, ndifSpinifex, pChE, pdCh, pdCnstr, pdifSpinifex, pExnD, pExpD, polCnstr, polSpinifex],
SXCMosBBasicRules USING [difToPolExtSep],
SXOutput USING [LinkagePrintProc],
SXOutputPrivate USING [GetANaming, NameTransType, Naming, PrintNaming, PrintRoseInstantiationTransformation],
SXTechnology USING [ESWGrow, NESGrow, PerDrawRectProc, WNEGrow, WNGrow],
TerminalIO USING [WriteRope];
SXCMosBTransistorsImpl: CEDAR PROGRAM
IMPORTS CDBasics, CDProperties, CDSimpleRules, CMosB, IO, Properties, Rope, SX, SXAtoms, SXCMosB, SXOutputPrivate, SXTechnology, TerminalIO
EXPORTS SXCMosB =
BEGIN
OPEN SXCMosB;
l: CD.Number ~ CMosB.lambda;
Nodes: TYPE = LIST OF REF SX.CircuitNode;
MapMaterial: SXTechnology.PerDrawRectProc -- [r: CD.Rect, l: CD.Layer, data: REF ANY] RETURNS [TransistorMaterial] -- ~ {
cir: REF SX.Circuit ~ NARROW [data, REF SX.Circuit];
SELECT l FROM
CMosB.ndif, CMosB.pdif => RETURN [diffusion];
CMosB.pol => RETURN [polysilicon];
CMosB.nwell => {
wellNode: REF SX.CircuitNode ← cir.AddRect [lev~ CMosB.nwell, dim~ r];
wellNode.properties ← Properties.PutProp [wellNode.properties, wellNode, wellNode];
RETURN [nothing];
};
ENDCASE => RETURN [nothing];
}; -- MapMaterial
ConvTransistor: PUBLIC SX.ConversionProc =
New transistor conversion procedure for ChipNDale 2.1
PROCEDURE [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF Circuit]
BEGIN
transistor: REF SX.NodeLinkage;
gateNode, sourceNode, drainNode, wellNode: REF SX.CircuitNode;
tClass: ATOM = inst.ob.class.objectType;
isNType: BOOL = (inst.ob.layer = CMosB.ndif);
isNWell: BOOL;
difSXLayer: SX.SpinifexLayerIndex;
difChannel, exclPol: REF SX.Constraint;
sep: CD.Number = CDSimpleRules.MinDist[CMosB.ndif, CMosB.pol];
extSep: CD.Number = SXCMosBBasicRules.difToPolExtSep;
rect, wellRect: CD.Rect;
polList, difList, chList, difListSouth: LIST OF CD.Rect ← NIL;
length, width, extL, extW: CD.Number;
gateA, gateP, sourceA, sourceP, drainA, drainP: INT; -- ignore perimeter leading into channel
errorRect: CD.Rect = inst.ob.class.oldInsideRect[inst.ob];
Determine diffusion layer and channel constraint
IF isNType THEN
{difSXLayer ← ndifSpinifex; difChannel ← ndCnstr[ndCh]; exclPol ← polCnstr[pExnD]}
ELSE
{difSXLayer ← pdifSpinifex; difChannel ← pdCnstr[pdCh]; exclPol ← polCnstr[pExpD]};
Get the geometry. Streching information has already been procesed by ChipNDale.
wellRect ← CDBasics.empty;
IF ISTYPE [inst.ob.specificRef, CDAtomicObjects.AtomicObsPtr] THEN
FOR geom: CDAtomicObjects.DrawList ← NARROW [inst.ob.specificRef, CDAtomicObjects.AtomicObsPtr].rList, geom.rest WHILE geom # NIL DO
SELECT geom.first.lev FROM
CMosB.pol => polList ← CONS [geom.first.r, polList];
CMosB.ndif, CMosB.pdif => difList ← CONS [geom.first.r, difList];
CMosB.nwell, CMosB.pwell => {wellRect ← geom.first.r; isNWell ← (geom.first.lev = CMosB.nwell)};
ENDCASE => ERROR SX.IllegalConstruct [geom.first.r, "Unknown transistor geometry"];
ENDLOOP
ELSE ERROR SX.IllegalConstruct [errorRect, "Replace this old Chipmonk transistor"];
Process the geometry according to the transistor class. The ChipNDale transistors are fully supported for p substrate.
SELECT tClass FROM
$C2Trans, $C2WellTrans => -- straight transistors
BEGIN
difRect, polRect, chRect, difExtRectNorth, difExtRectSouth: 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;
length ← polRect.y2 - polRect.y1; width ← difRect.x2 - difRect.x1;
extL ← polRect.y1 - difRect.y1; extW ← difRect.x1 - polRect.x1;
gateA ← (width + 2*extW) * length; gateP ← (width + 2*extW + length) * 2;
sourceA ← drainA ← extL * width; sourceP ← drainP ← 2 * extL + width;
Process poly layer
gateNode ← SX.AddRect [cir: cir, lev: CMosB.pol, dim: polRect, inst: inst, pos: pos, orient: orient];
IF extL > sep THEN-- Add rectangles for poly exclusion
BEGIN
rect ← difExtRectNorth; rect.y1 ← rect.y1 + sep;
[] ← SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.WNEGrow [extSep], exclPol];
rect ← difExtRectSouth; rect.y2 ← rect.y2 - sep;
[] ← SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.ESWGrow [extSep], exclPol];
END;
Process channel lead-in
rect ← difExtRectNorth; rect.y2 ← rect.y1+sep;
[] ← SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]];
rect ← difExtRectSouth; rect.y1 ← rect.y2-sep;
[] ← SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]];
Fill channel gap. NOTE: The DRC of channels is affected by the change made to CMosSpinifexInitImpl on April 2, 1985.
[] ← SX.AddBox [cir: cir, spinifexLayer: difSXLayer,
dim: chRect, inst: inst, pos: pos, orient: orient,
interestBloat: [dx1: (CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2), dy1: 0, dx2: (CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2), dy2: 0],
value: difChannel];
Add rectangles for diff width spacing and connection
sourceNode ← SX.AddBox[cir: cir, spinifexLayer: difSXLayer,
dim: difExtRectNorth, inst: inst, pos: pos, orient: orient,
interestBloat: SXTechnology.WNEGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)]];
drainNode ← SX.AddBox[cir: cir, spinifexLayer: difSXLayer,
dim: difExtRectSouth, inst: inst, pos: pos, orient: orient,
interestBloat: SXTechnology.ESWGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)]];
Process well.
IF tClass = $C2WellTrans THEN
BEGIN
l: CD.Layer = IF isNWell THEN CMosB.nwell ELSE CMosB.pwell;
IF NOT CDBasics.NonEmpty[wellRect] THEN ERROR SX.IllegalConstruct [errorRect, "Well transistor must have a well"];
wellNode ← SX.AddRect [cir: cir, lev: l, dim: wellRect, inst: inst, pos: pos, orient: orient];
wellNode.properties ← Properties.PutProp [propList: wellNode.properties, prop: wellNode, val: wellNode];
END;
END; -- case $CTrans
$C2LTrans, $CLWellTrans => -- angle transistors
BEGIN
diffNE: CD.Position ← CDBasics.minposition;
diffSW, polSW: CD.Position ← CDBasics.highposition;
polHor, polVert: 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;
length ← polHor.y2 - polHor.y1;
width ← ((polHor.x2 - polHor.x1) - extW) + ((polVert.y2 - polVert.y1) - extW) - (length*3/2);
gateA ← ((width+length/2) + 2*extW) * length;
gateP ← ((polHor.x2 - polHor.x1) + (polVert.y2 - polVert.y1)) * 2;
sourceA ← ((diffNE.x - diffSW.x) + (diffNE.y - diffSW.y - extL)) * extL;
sourceP ← 2 * extL + (diffNE.x - diffSW.x) + (diffNE.y - diffSW.y);
drainP ← diffNE.x + diffNE.y - diffSW.x - diffSW.y - 2 * (extL + length);
drainA ← drainP * extL;
Process poly layer
gateNode ← SX.AddRect [cir: cir, lev: CMosB.pol, dim: polHor, inst: inst, pos: pos, orient: orient];
[] ← SX.AddRect [cir: cir, lev: CMosB.pol, dim: polVert, inst: inst, pos: pos, orient: orient, value: gateNode];
IF extL > sep THEN-- Add rectangles for poly exclusion
BEGIN
d: CD.Number ← extL + length + sep;
rect ← [x1: diffSW.x, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffSW.y+length+2*extL];
[] ← SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.WNGrow [extSep], exclPol]; -- North
rect ← [x1: diffNE.x-length-2*extL, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffNE.y];
[] ← SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.WNGrow [extSep], exclPol]; -- West
d ← extL - sep;
rect ← [x1: diffSW.x, y1: diffSW.y, x2: diffNE.x, y2: diffSW.y+d];
[] ← SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.ESWGrow [extSep], exclPol]; -- South
rect ← [x1: diffNE.x-d, y1: diffSW.y, x2: diffNE.x, y2: diffNE.y];
[] ← SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.NESGrow [extSep], exclPol] -- East
END; -- poly excl
Process channel lead-in
BEGIN
d: CD.Number ← extL + length + sep;
rect ← [x1: diffSW.x, y1: diffSW.y+extL+length, x2: diffNE.x-extL-length, y2: diffSW.y+d];
[] ← SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]]; -- North
rect ← [x1: diffNE.x-d, y1: diffSW.y+extL+length, x2: diffNE.x-extL-length, y2: diffNE.y];
[] ← SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]]; -- West
d ← extL - sep;
rect ← [x1: diffSW.x, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffSW.y+extL];
[] ← SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]]; -- South
rect ← [x1: diffNE.x-extL, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffNE.y];
[] ← SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]] -- East
END; -- ch lead-in
Fill channel gap. NOTE: The DRC of channels is affected by the change made to CMosSpinifexInitImpl on April 2, 1985.
rect ← polHor; rect.x1 ← rect.x1 + extW;
[] ← SX.AddBox [cir: cir, spinifexLayer: difSXLayer,
dim: rect, inst: inst, pos: pos, orient: orient,
interestBloat: [dx1: (CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2), dy1: 0, dx2: 0, dy2: 0],
value: difChannel];
rect ← polVert; rect.y2 ← rect.y2 - extW;
[] ← SX.AddBox [cir: cir, spinifexLayer: difSXLayer,
dim: rect, inst: inst, pos: pos, orient: orient,
interestBloat: [dx1: 0, dy1: 0, dx2: 0, dy2: (CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)],
value: difChannel];
Add rectangles for diff width spacing and connection
rect ← [x1: diffSW.x, y1: diffSW.y+extL+length, x2: diffNE.x-extL-length, y2: diffSW.y+2*extL+length];
sourceNode ← SX.AddBox [cir: cir, spinifexLayer: difSXLayer,
dim: rect, inst: inst, pos: pos, orient: orient,
interestBloat: SXTechnology.WNGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)]];
IF difList.rest # NIL THEN -- supposed source is concave
BEGIN
rect ← [x1: diffNE.x-length-2*extL, y1: rect.y1, x2: rect.x2, y2: diffNE.y];
[] ← SX.AddBox [cir: cir, spinifexLayer: difSXLayer,
dim: rect, inst: inst, pos: pos, orient: orient,
interestBloat: SXTechnology.WNGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)],
value: sourceNode]
END;
rect ← [x1: diffSW.x, y1: diffSW.y, x2: diffNE.x, y2: diffSW.x+extL];
drainNode ← SX.AddBox[cir: cir, spinifexLayer: difSXLayer,
dim: rect, inst: inst, pos: pos, orient: orient,
interestBloat: SXTechnology.ESWGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)]];
rect ← [x1: diffNE.x-extL, y1: rect.y2, x2: diffNE.x, y2: diffNE.y];
[] ← SX.AddBox[cir: cir, spinifexLayer: difSXLayer,
dim: rect, inst: inst, pos: pos, orient: orient,
interestBloat: SXTechnology.NESGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)],
value: drainNode];
Process well.
IF tClass = $CWellTrans THEN
BEGIN
l: CD.Layer = IF isNWell THEN CMosB.nwell ELSE CMosB.pwell;
IF NOT CDBasics.NonEmpty[wellRect] THEN ERROR SX.IllegalConstruct [errorRect, "Well transistor must have a well"];
wellNode ← SX.AddRect [cir: cir, lev: l, dim: wellRect, inst: inst, pos: pos, orient: orient];
wellNode.properties ← Properties.PutProp [propList: wellNode.properties, prop: wellNode, val: wellNode];
END;
END; -- case $CTrans
ENDCASE => ERROR SX.IllegalConstruct [errorRect, "Unknown transistor class"];
transistor ← SX.CreateLinkage [cir, inst, length, width];
Adjust area and perimeter values
SX.AdjustNode [node: gateNode, layer: polSpinifex, area: gateA, perim: gateP, mode: absolute];
SX.AdjustNode [sourceNode, difSXLayer, sourceA, sourceP, absolute];
SX.AdjustNode [drainNode, difSXLayer, drainA, drainP, absolute];
SX.LinkageAttach [link: transistor, attachType: $Gate, node: gateNode];
SX.LinkageAttach [link: transistor, attachType: $Source, node: sourceNode];
SX.LinkageAttach [link: transistor, attachType: $Drain, node: drainNode]
END; -- ConvTransistor
RoseTransistor: PUBLIC SXOutput.LinkagePrintProc -- [desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc] -- ~ {
PrintAttachment: PROCEDURE [key: ATOM, portName: Rope.ROPE] ~ {
cellStream.Put [IO.rope[" (\""], IO.rope[portName], IO.rope["\" "]];
FOR attachments: LIST OF REF SX.AttachedNode ← linkage.nodes, attachments.rest WHILE attachments # NIL DO
IF attachments.first.attachmentType = key THEN {
PrintNode[cellStream, attachments.first.node];
cellStream.PutRope[")"];
RETURN
}
ENDLOOP;
cellStream.PutRope ["\"?\")"];
}; -- PrintAttachment
naming: SXOutputPrivate.Naming ← SXOutputPrivate.GetANaming [linkage.source];
cellStream.PutRope["(CI "];
SXOutputPrivate.PrintNaming[
cellStream,
naming,
Rope.Cat[" \"", SXOutputPrivate.NameTransType[
desWDir: desWDir,
obj: linkage.source.ob,
dfStream: dfStream,
type: SELECT linkage.source.ob.layer FROM
CMosB.ndif, CMosB.wndif => $n,
CMosB.pdif, CMosB.wpdif => $p,
ENDCASE => $funny,
mode: $E,
length: linkage.l,
width: linkage.w], "\""]
];
SXOutputPrivate.PrintRoseInstantiationTransformation[cellStream, linkage.source];
cellStream.PutRope [" (CIC"];
PrintAttachment [$Gate, "gate"];
PrintAttachment [$Source, "ch1"];
PrintAttachment [$Drain, "ch2"];
cellStream.PutRope ["))"]
}; -- RoseTransistor
ThymeTransistor: PUBLIC SXOutput.LinkagePrintProc -- [desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc] -- ~ {
PrintAttachment: PROCEDURE [key: ATOM] ~ {
FOR attachments: LIST OF REF SX.AttachedNode ← linkage.nodes, attachments.rest WHILE attachments # NIL DO
IF attachments.first.attachmentType = key THEN {
PrintNode[cellStream, attachments.first.node];
RETURN
}
ENDLOOP;
cellStream.Put [IO.char['?]];
}; -- PrintAttachment
defaultW: INTEGER = 4*lambda;
defaultL: INTEGER = 2*l;
propertyValue: REF;
cellStream.Put [IO.rope[name], IO.rope[": "]];
cellStream.PutRope [SELECT linkage.source.ob.layer FROM
CMosB.ndif, CMosB.wndif => "ETran[",
CMosB.pdif, CMosB.wpdif => "CTran[",
ENDCASE => "FunnyTran["
];
PrintAttachment [$Gate];
cellStream.Put [IO.char[',]];
PrintAttachment [$Source];
cellStream.Put [IO.char[',]];
PrintAttachment [$Drain];
cellStream.Put [IO.char['|]];
cellStream.PutF[" W←N*%g", IO.int[linkage.w/l]];
IF linkage.l # defaultL THEN cellStream.PutF[", L←%g", IO.int[linkage.l/l]];
The following is a quick hack to allow John Ousterhout to test Crystal. In a later stage, SX.AttachedNode shall receive an additional field for this info. At the moment it is not clear yet, how the user interface should be like.
propertyValue ← CDProperties.GetPropFromInstance [from: linkage.source, prop: SXAtoms.crystalAttr];
WITH propertyValue SELECT FROM
crystalHack: Rope.ROPE => IO.Put [stream: cellStream, v1: IO.rope["; "], v2: IO.rope[crystalHack]];
ENDCASE => IF propertyValue # NIL THEN TerminalIO.WriteRope [" $Crystal property must be a rope./n"];
cellStream.PutRope ["];"]
}; -- ThymeTransistor
END.