SXNMos.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Written by Shand, September 12, 1983 11:40 pm
Last Edited by: Shand, March 12, 1985 4:23:50 pm PST
Last Edited by: Spreitzer, January 14, 1985 10:35:35 pm PST
Last Edited by: Jacobi, December 18, 1984 4:49:59 pm PST
Last Edited by: Beretta, June 18, 1985 4:57:52 pm PDT
DIRECTORY
CD USING [ApplicationPtr, DesignNumber, DesignPosition, DesignRect, lambda, Layer, Rect],
CDBasics USING [RectAt],
CDProperties USING [GetPropFromApplication],
IO USING [char, int, Put, PutF, PutRope, rope],
NMos USING [nmos, dif, pol, met, ovg, cut],
NMosContacts USING [ContactPtr],
NMosTransistors USING [enhancement, strongDepletion, TransistorPtr, weakDepletion, zeroTresh],
Rope USING [Cat, ROPE],
SX USING [AddBox, AddRect, AdjustNode, AttachedNode, Circuit, CircuitNode, Constraint, ConstraintArray, ConstraintIndex, ConstraintResolution, ConversionProc, CreateLinkage, GeometricRule, IllegalConstruct, LinkageAttach, MapRec, MergeNode, nodeIndex, NodeLinkage, spaceIndex, SpinifexLayerIndex, techCIndexBase, TechHandle],
SXNMosBasicRules USING [contactWidth, difSep, difSpacing, difToPolExtSep, difToPolSep, difWidth, metSep, metSpacing, metWidth, polDifSep, polOverDif, polSep, polSpacing, polWidth],
SXOutput USING [LinkageHousekeeper, LinkagePrintProc],
SXOutputPrivate USING [GetANaming, NameTransType, Naming, PrintNaming, PrintRoseInstantiationTransformation, UnNameTransType],
SXQuadTree USING [RectDelta],
SXTechnology USING [ESWGrow, NESGrow, PerDrawRectProc, ProcessMosTransistor, RegisterSpinifexObjectProcs, RegisterTechnologyHandle, ReportDifProc, ResolutionTable, SetUpResolution, SWNGrow, WNEGrow],
TerminalIO USING [WriteRope]
;
SXNMos: CEDAR PROGRAM
IMPORTS CDBasics, CDProperties, IO, NMos, Rope, SX, SXOutputPrivate, SXTechnology, TerminalIO =
BEGIN
l: CD.DesignNumber ~ CD.lambda;
-- New Regime Transistor converters (IE the Shand unified xstr representaion)
ConvertNMosTransistor: SX.ConversionProc -- [appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, cir: REF ] -- ~ {
p: NMosTransistors.TransistorPtr = NARROW[appl.ob.specificRef];
size: CD.DesignPosition ← appl.ob.size;
xstr: REF SX.NodeLinkage;
gateNode, sourceNode, drainNode, metNode: REF SX.CircuitNode;
polExt: CD.DesignNumber ~ IF p.pullup THEN MIN[ (size.x-SXNMosBasicRules.contactWidth)/2, p.wExt] ELSE p.wExt;
IF p.bendList = NIL THEN { -- Oh this is easy!
IF ~ p.angle THEN { -- Oh this is easy!
-- Add poly boxes
gateNode ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[0, p.lExt, polExt, p.lExt+p.length], appl~appl, pos~ pos, orient~ orient, interestBloat~SXTechnology.SWNGrow[SXNMosBasicRules.polSep]];
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt, size.x-polExt, p.lExt+p.length], appl~appl, pos~ pos, orient~ orient, value~gateNode];
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[size.x-polExt, p.lExt, size.x, p.lExt+p.length], appl~appl, pos~ pos, orient~ orient, interestBloat~SXTechnology.NESGrow[SXNMosBasicRules.polSep], value~gateNode];
-- Add rects for poly exclusion
IF p.lExt-SXNMosBasicRules.difToPolSep > 0 THEN {
-- At the top
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt+p.length+SXNMosBasicRules.difToPolSep, size.x-polExt, size.y], appl~appl, pos~ pos, orient~ orient,
interestBloat~SXTechnology.WNEGrow[ SXNMosBasicRules.difToPolExtSep],
value~pCnstr[pExcl]];
-- ... and the bottom
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, 0, size.x-p.wExt, p.lExt-SXNMosBasicRules.difToPolSep], appl~appl, pos~ pos, orient~ orient, interestBloat~SXTechnology.ESWGrow[ SXNMosBasicRules.difToPolExtSep],
value~pCnstr[pExcl]]
};
-- Add rects for channel lead-in.
-- At the top
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt+p.length, size.x-polExt, p.lExt+p.length+SXNMosBasicRules.difToPolSep], appl~appl, pos~ pos, orient~ orient, value~pCnstr[pChE]];
-- ... and the bottom
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, p.lExt-SXNMosBasicRules.difToPolSep, size.x-p.wExt, p.lExt], appl~appl, pos~ pos, orient~ orient, value~pCnstr[pChE]];
-- Fill channel gap
[] ← cir.AddBox[ spinifexLayer~difSpinifex, dim~[p.wExt, p.lExt, size.x-p.wExt, p.lExt+p.length], appl~appl, pos~ pos, orient~ orient, interestBloat~[dx1~ SXNMosBasicRules.difSep, dy1~ 0, dx2~ SXNMosBasicRules.difSep, dy2~ 0], value~dCnstr[dCh]];
IF polExt < p.wExt THEN [] ← cir.AddBox[ spinifexLayer~difSpinifex, dim~[polExt, p.lExt+p.length-l, size.x-polExt, p.lExt+p.length], appl~appl, pos~ pos, orient~ orient, interestBloat~[dx1~ SXNMosBasicRules.difSep, dy1~ 0, dx2~ SXNMosBasicRules.difSep, dy2~ SXNMosBasicRules.difSep], value~dCnstr[dCh]];
-- Add rects for diff width spacing and connection
sourceNode ← cir.AddBox[ spinifexLayer~difSpinifex, dim~[polExt, p.lExt+p.length, size.x-polExt, size.y], appl~appl, pos~ pos, orient~ orient, interestBloat~SXTechnology.WNEGrow[SXNMosBasicRules.difSep]];
drainNode ← cir.AddBox[ spinifexLayer~difSpinifex, dim~[p.wExt, 0, size.x-p.wExt, p.lExt], appl~appl, pos~ pos, orient~ orient, interestBloat~SXTechnology.ESWGrow[SXNMosBasicRules.difSep]];
IF p.pullup THEN {
metNode ← cir.AddRect[ lev~NMos.met, dim~[ (size.x-SXNMosBasicRules.contactWidth)/2, size.y-6*l, (size.x+SXNMosBasicRules.contactWidth)/2, size.y], appl~appl, pos~ pos, orient~ orient];
}
ELSE metNode ← NIL
}
ELSE { -- Oh no not a bent transistor yetcchh!
sourceDrainList: LIST OF REF SX.CircuitNode;
sourceDrainCount: INTEGER;
sourceHint: REF SX.CircuitNode ← NIL;
NoteSourceHint: SXTechnology.ReportDifProc ~ {
sourceHint ← difNode
};
[gateNode, sourceDrainList, sourceDrainCount] ← SXTechnology.ProcessMosTransistor[appl, pos, orient, cir, difSpinifex, polSpinifex, dCnstr[dCh], pCnstr[pChE], SXNMosBasicRules.difSep, SXNMosBasicRules.difToPolSep, MapMaterial, cir, NoteSourceHint];
IF sourceDrainCount = 2 THEN {
sourceNode ← sourceDrainList.first;
drainNode ← sourceDrainList.rest.first;
IF p.pullup THEN {
SELECT sourceHint FROM
sourceNode => NULL;
drainNode => {
drainNode ← sourceNode;
sourceNode ← sourceHint
};
ENDCASE => ERROR -- Including case when sourceHint = NIL
}
}
ELSE {
TerminalIO.WriteRope[ Rope.Cat["Xstr with ", (SELECT sourceDrainCount FROM 0 => "no", 1 => "only 1", ENDCASE => "more than 2"), " sources/drains not included in circuit description\n"]];
RETURN
}
};
-- Add Linkages for transistor.
xstr ← cir.CreateLinkage[appl];
-- We're a lot smarter than this program, so let's adjust the area and perim values its got.
SX.AdjustNode[ gateNode, polSpinifex, size.y*p.length, (size.y+p.length)*2, absolute];
SX.AdjustNode[ sourceNode, difSpinifex, (size.y-(p.lExt+p.length))*(size.x-2*polExt), (size.y-(p.lExt+p.length))*2 + size.x-2*polExt, absolute]; -- Ignore perim leading into channel.
SX.AdjustNode[ drainNode, difSpinifex, p.lExt*p.width, 2*p.lExt + p.width, absolute]; -- Ignore perim leading into channel.
IF p.pullup THEN {
cir.MergeNode[ gateNode, sourceNode]; sourceNode ← gateNode;
cir.MergeNode[ gateNode, metNode]; metNode ← gateNode;
};
SX.LinkageAttach[link~xstr, attachType~$Gate, node~gateNode];
SX.LinkageAttach[link~xstr, attachType~$Source, node~sourceNode];
SX.LinkageAttach[link~xstr, attachType~$Drain, node~drainNode];
};
MapMaterial: SXTechnology.PerDrawRectProc -- [r: CD.DesignRect, l: CD.Layer, data: REF ANY] RETURNS [TransistorMaterial] -- ~ {
cir: REF SX.Circuit ~ NARROW[ data, REF SX.Circuit];
SELECT l FROM
NMos.dif => RETURN [diffusion];
NMos.pol => RETURN [polysilicon];
NMos.met => {
[] ← cir.AddRect[ lev~ NMos.met, dim~ r];
RETURN [nothing];
};
NMos.cut => {
RETURN [postProcess];
};
ENDCASE => RETURN [nothing];
};
-- Contact converters
ConvertNMosContactDifAndPol: SX.ConversionProc -- [appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, cir: REF SX.Circuit] -- ~ {
box: CD.Rect ← CDBasics.RectAt[pos~[0,0], size~appl.ob.size];
node: REF SX.CircuitNode;
Attach two rectangles to the same node.
node ← cir.AddRect[ lev~NMos.met, dim~box, appl~appl, pos~ pos, orient~ orient];
[] ← cir.AddRect[ lev~appl.ob.layer, dim~box, appl~appl, pos~ pos, orient~ orient, value~node];
IF appl.ob.layer = NMos.dif THEN
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~box, appl~appl, pos~ pos, orient~ orient, value~pCnstr[pExCon]];
};
ConvertNMosButtingContact: SX.ConversionProc -- [appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, cir: REF SX.Circuit] -- ~ {
rimWidth: CD.DesignNumber ~ l;
polSize: CD.DesignNumber ~ appl.ob.size.y/2;
box: CD.Rect ← CDBasics.RectAt[pos~[0,0], size~appl.ob.size];
node: REF SX.CircuitNode;
node ← cir.AddRect[ lev~NMos.met, dim~box, appl~appl, pos~ pos, orient~ orient];
[] ← cir.AddRect[ lev~NMos.pol, dim~[0,0, appl.ob.size.x, polSize], appl~appl, pos~ pos, orient~ orient, value~node];
-- Add rect for poly exclusion
[] ← cir.AddBox[ spinifexLayer~polSpinifex,
dim~[-rimWidth,polSize, appl.ob.size.x+rimWidth, polSize+SXNMosBasicRules.difToPolSep], appl~appl, pos~ pos, orient~ orient, value~pCnstr[pChE]];
[] ← cir.AddBox[ spinifexLayer~polSpinifex,
dim~[-rimWidth,polSize-rimWidth, 0, polSize], appl~appl, pos~ pos, orient~ orient, value~pCnstr[pDxorP]];
[] ← cir.AddBox[ spinifexLayer~polSpinifex,
dim~[appl.ob.size.x,polSize-rimWidth, appl.ob.size.x+rimWidth, polSize], appl~appl, pos~ pos, orient~ orient, value~pCnstr[pDxorP]];
[] ← cir.AddBox[ spinifexLayer~polSpinifex,
dim~[0,polSize+SXNMosBasicRules.difToPolSep, appl.ob.size.x, appl.ob.size.y], appl~appl, pos~ pos, orient~ orient,
interestBloat~SXTechnology.WNEGrow[ SXNMosBasicRules.difToPolExtSep],
value~pCnstr[pExCon]];
-- Add rect for diff width spacing and connection
[] ← cir.AddBox[ spinifexLayer~difSpinifex,
dim~[0,polSize, appl.ob.size.x, appl.ob.size.y], appl~appl, pos~ pos, orient~ orient,
interestBloat~[ SXNMosBasicRules.difSep, SXNMosBasicRules.difSep, SXNMosBasicRules.difSep, SXNMosBasicRules.difSep], value~node];
};
ConvertNMosBuriedContact: SX.ConversionProc -- [appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, cir: REF SX.Circuit] -- ~ {
Buried contacts come in three flavours, Pol-Surround, Dif-Surround and Crossing. The buried contacts in chipndale are parameterized by lExt and wExt, their interpretation is as follows: Diff always extends 1l to the left, material above/below and to the right is determined by lExt and wExt respectively. 2l is the pivotal value, below 2l the material is Pol, at 2l or above the material is Diff. (Note: some combinations give Diff on all four sides, it is assumed that such combinations will not be created.)
s: CD.DesignPosition ~ appl.ob.size;
cp: NMosContacts.ContactPtr ~ NARROW[appl.ob.specificRef];
node: REF SX.CircuitNode ~ cir.AddRect[ lev~NMos.pol, dim~[2*l, cp.lExt, s.x-cp.wExt, s.y-cp.lExt], appl~appl, pos~ pos, orient~ orient];
SELECT TRUE FROM
cp.lExt < 2*l AND cp.wExt < 2*l => {
Polysilicon Surround
wex: CD.DesignNumber ~ MAX[cp.wExt+l, 2*l];
lex: CD.DesignNumber ~ MAX[cp.lExt+l, 2*l];
[] ← cir.AddRect [
lev: appl.ob.layer,
dim: [l, lex, 2*l, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l-SXNMosBasicRules.difToPolSep, lex, 2*l, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l, lex, s.x-wex, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: pCnstr[pDandP]];
[] ← cir.AddBox [
spinifexLayer: difSpinifex,
dim: [2*l, lex, s.x-wex, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: node];
};
cp.lExt < 2*l AND cp.wExt >= 2*l => {
Polysilicon/Diffusion Crossing.
lex: CD.DesignNumber ~ MAX[cp.lExt+l, 2*l];
[] ← cir.AddBox [
spinifexLayer: difSpinifex,
dim: [2*l, lex, s.x-cp.wExt, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l, lex, s.x-cp.wExt, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: pCnstr[pDandP]];
Left side.
[] ← cir.AddRect [lev: appl.ob.layer,
dim: [l, lex, 2*l, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l-SXNMosBasicRules.difToPolSep, lex, 2*l, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
Right side.
[] ← cir.AddRect [
lev: appl.ob.layer,
dim: [s.x-cp.wExt, lex, s.x-(cp.wExt-l), s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [s.x-cp.wExt, lex, s.x-(cp.wExt-SXNMosBasicRules.difToPolSep), s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
};
cp.lExt >= 2*l AND cp.wExt < 2*l => {
Diffusion Surround
wex: CD.DesignNumber ~ MAX[cp.wExt+l, 2*l];
lex: CD.DesignNumber ~ cp.lExt-l;
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l, cp.lExt, s.x-wex, s.y-cp.lExt],
appl: appl,
pos: pos,
orient: orient,
value: pCnstr[pDandP]];
Left side.
[] ← cir.AddRect [
lev: appl.ob.layer,
dim: [l, lex, s.x-wex, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l-SXNMosBasicRules.difToPolSep, lex, 2*l, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
Top.
[] ← cir.AddRect [
lev: appl.ob.layer,
dim: [2*l, s.y-cp.lExt, s.x-wex, s.y-lex],
appl: appl,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l, s.y-cp.lExt, s.x-wex, s.y-(cp.lExt-SXNMosBasicRules.difToPolSep)],
appl: appl,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
Bottom.
[] ← cir.AddRect [
lev: appl.ob.layer,
dim: [2*l, lex, s.x-wex, cp.lExt],
appl: appl,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l, cp.lExt-SXNMosBasicRules.difToPolSep, s.x-wex, cp.lExt],
appl: appl,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
};
cp.lExt >= 2*l AND cp.wExt >= 2*l => {
Diffusion Surround ! on all sides ???
ERROR SX.IllegalConstruct [appl.ob.p.interestRect[appl.ob], "Polysilicon surrounded by diffusion or all sides in Buried Contact"];
};
ENDCASE => ERROR;
};
RoseNMosTransistor: 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[ "\"?\")"];
};
p: NMosTransistors.TransistorPtr ~ NARROW[ linkage.source.ob.specificRef];
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: $n,
mode: IF p.pullup THEN $D ELSE SELECT p.implant FROM
NMosTransistors.enhancement => $E,
NMosTransistors.strongDepletion => $D,
NMosTransistors.zeroTresh => $Z,
NMosTransistors.weakDepletion => $W,
ENDCASE => ERROR,
length: p.length,
width: p.width], "\""]
];
SXOutputPrivate.PrintRoseInstantiationTransformation[cellStream, linkage.source];
cellStream.PutRope[ " (CIC"];
PrintAttachment[ $Gate, "gate"];
PrintAttachment[ $Source, "in"];
PrintAttachment[ $Drain, "out"];
cellStream.PutRope[ "))"]
};
ThymeNMosTransistor: SXOutput.LinkagePrintProc -- [ desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, 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['?]];
};
p: NMosTransistors.TransistorPtr ~ NARROW[ linkage.source.ob.specificRef];
defaultL: INTEGER ~ 2*l;
propertyValue: REF;
cellStream.Put[ IO.rope[name], IO.rope[": "]];
cellStream.PutRope[ IF ~p.pullup THEN
SELECT p.implant FROM
NMosTransistors.enhancement => "ETran[",
NMosTransistors.strongDepletion => "DTran[",
NMosTransistors.zeroTresh => "ZTran[",
NMosTransistors.weakDepletion => "WTran",
ENDCASE => ERROR
ELSE
"DTran["
];
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[p.width/l]];
IF p.length # defaultL THEN cellStream.PutF[", L←%g", IO.int[p.length/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.GetPropFromApplication [from: linkage.source, prop: $Crystal];
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[ "];"]
};
-- Module Initialization
Global constants and variables.
nMosHandle: REF SX.TechHandle;
difSpinifex: SX.SpinifexLayerIndex ~ SX.SpinifexLayerIndex.FIRST;
polSpinifex: SX.SpinifexLayerIndex ~ difSpinifex.SUCC;
metSpinifex: SX.SpinifexLayerIndex ~ polSpinifex.SUCC;
Constraint: TYPE ~ SX.Constraint;
-- Diffusion layer
dCnstr: REF SX.ConstraintArray ← NEW[SX.ConstraintArray]; -- Diffusion constraints
dCh: SX.ConstraintIndex ~ SX.techCIndexBase; -- Diffusion channel
-- Poly layer
pCnstr: REF SX.ConstraintArray ← NEW[SX.ConstraintArray]; -- Poly constraints
pExcl: SX.ConstraintIndex ~ SX.techCIndexBase; -- Poly not allowed here.
pExCon: SX.ConstraintIndex ~ pExcl.SUCC; -- Poly not allowed here because of Contact to n-Diffusion.
pDPErr: SX.ConstraintIndex ~ pExCon.SUCC; -- Poly and Diffusion found together here.
pChE: SX.ConstraintIndex ~ pDPErr.SUCC; -- Close to Xstr Gate, (Channel Edge).
pDxorP: SX.ConstraintIndex ~ pChE.SUCC; -- Diffusion XOR Poly allowed here.
pDandP: SX.ConstraintIndex ~ pDxorP.SUCC; -- Diffusion AND Poly may appear together here.
Init: PROCEDURE ~ {
GeometricRule: TYPE ~ SX.GeometricRule;
difSpacingRule, difWidthRule: REF GeometricRule;
polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule: REF GeometricRule;
metSpacingRule, metWidthRule: REF GeometricRule;
TriggerMap: TYPE ~ PACKED ARRAY SX.ConstraintIndex OF BOOLEANALL[FALSE];
spaceRuleTrigger: TriggerMap;
widthRuleTrigger: TriggerMap;
polOverDifTrigger1, polOverDifTrigger2, polDifSepTriggerA, polDifSepTriggerB: TriggerMap;
difSpaceTrigger1: TriggerMap;
polWidthTrigger: TriggerMap;
difResolution: REF SX.ConstraintResolution;
polyResolution: REF SX.ConstraintResolution;
-- Construction of the Layer Constraints.
dCnstr[dCh] ← NEW[ Constraint ← [ $DifChannel, dCh]];
pCnstr[pExcl] ← NEW[ Constraint ← [ $ExcludePol, pExcl]];
pCnstr[pExCon] ← NEW[ Constraint ← [ $ExcludePolByContact, pExCon]];
pCnstr[pDPErr] ← NEW[ Constraint ← [ $PolDifError, pDPErr]];
pCnstr[pChE] ← NEW[ Constraint ← [ $ChannelEdge, pChE]];
pCnstr[pDxorP]← NEW[ Constraint ← [ $PolXorDif, pDxorP]];
pCnstr[pDandP] ← NEW[ Constraint ← [ $PolAndDif, pDandP, TRUE, polSpinifex]];
{
nd: SX.ConstraintIndex ~ SX.nodeIndex;
sp: SX.ConstraintIndex ~ SX.spaceIndex;
dResTab: SXTechnology.ResolutionTable ~ [
[ sp,  nd,  dCh, ,,,,,,,,,,,,],
[ nd,  nd,  dCh, ,,,,,,,,,,,,],
[ dCh, dCh, dCh, ,,,,,,,,,,,,],
,,,,,,,,,,,,
];
pResTab: SXTechnology.ResolutionTable ~ [
[ sp,   nd,   pExcl,  pExCon, pDPErr, pChE,  pDxorP, pDandP, ,,,,,,,],
[ nd,   nd,   pDPErr, pDPErr, pDPErr, pDPErr, nd,   pDandP, ,,,,,,,],
[ pExcl,  pDPErr, pExcl,  pExCon, pDPErr, pChE,  pChE,  pDandP, ,,,,,,,],
[ pExCon, pDPErr, pExCon, pExCon, pDPErr, pExCon, pExCon, pDandP, ,,,,,,,],
[ pDPErr, pDPErr, pDPErr, pDPErr, pDPErr, pDPErr, pDPErr, pDandP, ,,,,,,,],
[ pChE,  pDPErr, pChE,  pExCon, pDPErr, pChE,  pChE,  pDandP, ,,,,,,,],
[ pDxorP, nd,   pChE,  pExCon, pDPErr, pChE,  pDxorP, pDandP, ,,,,,,,],
[ pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, ,,,,,,,],
,,,,,,,
];
difResolution ← SXTechnology.SetUpResolution[ dCnstr, dResTab];
polyResolution ← SXTechnology.SetUpResolution[ pCnstr, pResTab]
};
-- Basic nMosHandle & cdLayerMappings.
nMosHandle ← NEW[SX.TechHandle ← [numSpinifexLayers~3, layerInterestBloat~[SXNMosBasicRules.difSep, SXNMosBasicRules.polSep, SXNMosBasicRules.metSep, ,,,,]] ];
nMosHandle.illegalLayer[NMos.dif] ← FALSE;
nMosHandle.illegalLayer[NMos.pol] ← FALSE;
nMosHandle.illegalLayer[NMos.met] ← FALSE;
nMosHandle.illegalLayer[NMos.ovg] ← FALSE;
nMosHandle.cdLayerMapping[NMos.dif] ← LIST[ [difSpinifex, SXNMosBasicRules.difSep], [polSpinifex,SXNMosBasicRules.difToPolExtSep,pCnstr[pExcl]]];
nMosHandle.cdLayerMapping[NMos.pol] ← LIST[ [polSpinifex,SXNMosBasicRules.polSep]];
nMosHandle.cdLayerMapping[NMos.met] ← LIST[ [metSpinifex,SXNMosBasicRules.metSep]];
-- Spinifex Layer Identification.
nMosHandle.spinifexLayerNames[difSpinifex].layerId ← $Diffusion;
nMosHandle.spinifexLayerNames[polSpinifex].layerId ← $Poly;
nMosHandle.spinifexLayerNames[metSpinifex].layerId ← $Metal;
-- Thyme stray capacitance layer names.
nMosHandle.spinifexLayerNames[difSpinifex].thymeName ← "D";
nMosHandle.spinifexLayerNames[polSpinifex].thymeName ← "P";
nMosHandle.spinifexLayerNames[metSpinifex].thymeName ← "M";
-- Set Constraint Resolutions for each layer into the TechHandle.
nMosHandle.constraintResolutions[difSpinifex] ← difResolution;
nMosHandle.constraintResolutions[polSpinifex] ← polyResolution;
-- Geometric rule triggers.
spaceRuleTrigger[SX.nodeIndex] ← TRUE;
widthRuleTrigger[SX.spaceIndex] ← TRUE;
Corners are defined by union of dif and gate, but checking only looks at dif
difSpaceTrigger1[SX.nodeIndex] ← TRUE;
difSpaceTrigger1[dCh] ← TRUE;
polWidthTrigger ← ALL[TRUE];
polWidthTrigger[ SX.nodeIndex] ← FALSE;
polWidthTrigger [pDandP] ← FALSE; -- newly added by gbb
polDifSepTriggerA[ SX.nodeIndex] ← TRUE;
polDifSepTriggerB[ pExcl] ← TRUE;
polDifSepTriggerB[ pExCon] ← TRUE;
-- Purely local errors are not handled in a natural manner by the corner-based scheme, so for every corner we find in pCnstr[pDPErr] we generate an error if there is anything on any layer nearby, of course there is always something so we get our error.
polOverDifTrigger1[ pDPErr] ← TRUE;
polOverDifTrigger2 ← ALL[TRUE];
-- The geometric rules.
difSpacingRule ← NEW[ GeometricRule ← [extent~SXNMosBasicRules.difSpacing, message~"Diffusion spacing", okIfConnected~TRUE, trigger1~difSpaceTrigger1, trigger2~spaceRuleTrigger]];
difWidthRule ← NEW[ GeometricRule ← [extent~SXNMosBasicRules.difWidth, message~"Diffusion width", trigger1~widthRuleTrigger, trigger2~widthRuleTrigger]];
polSpacingRule ← NEW[ GeometricRule ← [extent~SXNMosBasicRules.polSpacing, message~"Poly spacing", okIfConnected~TRUE, trigger1~spaceRuleTrigger, trigger2~spaceRuleTrigger]];
polWidthRule ← NEW[ GeometricRule ← [extent~SXNMosBasicRules.polWidth, message~"Poly width", trigger1~polWidthTrigger, trigger2~polWidthTrigger]];
polDifSepRuleA ← NEW[ GeometricRule ← [extent~SXNMosBasicRules.polDifSep, message~"Poly/Diffusion spacing[debug:A]", trigger1~polDifSepTriggerA, trigger2~polDifSepTriggerB]];
polDifSepRuleB ← NEW[ GeometricRule ← [extent~SXNMosBasicRules.polDifSep, message~"Poly/Diffusion spacing[debug:B]", trigger1~polDifSepTriggerB, trigger2~polDifSepTriggerA]];
polOverDifRule ← NEW[ GeometricRule ← [extent~SXNMosBasicRules.polOverDif, message~"Poly over Diffusion", trigger1~polOverDifTrigger1, trigger2~polOverDifTrigger2]];
metSpacingRule ← NEW[ GeometricRule ← [extent~SXNMosBasicRules.metSpacing, message~"Metal spacing", okIfConnected~TRUE, trigger1~spaceRuleTrigger, trigger2~spaceRuleTrigger]];
metWidthRule ← NEW[ GeometricRule ← [extent~SXNMosBasicRules.metWidth, message~"Metal width", trigger1~widthRuleTrigger, trigger2~widthRuleTrigger]];
nMosHandle.rules[ difSpinifex] ← LIST[difSpacingRule, difWidthRule];
nMosHandle.rules[ polSpinifex] ← LIST[polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule];
nMosHandle.rules[ metSpinifex] ← LIST[metSpacingRule, metWidthRule];
-- Technology handle is attached to the ChipNDale technology.
SXTechnology.RegisterTechnologyHandle[cdTech~ NMos.nmos, technologyHandle~ nMosHandle];
-- Technology specific objects.
SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosTransistor, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor, fini~SXOutputPrivate.UnNameTransType];
SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosATransistor, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor];
SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosPullUp, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor];
SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosContactDifAndPol, conv~ConvertNMosContactDifAndPol];
SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosContactBut, conv~ConvertNMosButtingContact];
SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosBurContact, conv~ConvertNMosBuriedContact];
};
Init[];
TerminalIO.WriteRope["nMos technology parameters Loaded\n"];
END.
Edited on March 7, 1985 1:28:12 am PST, by Shand
added interaction region around dCnstr[dCh] constraints, new parameter to SXTechnology.ProcessMosTransistor to handle channel constraint interest bloating. Also changed dCnstr[dCh].withNode so that dCnstr[dCh]+Node => $Conflict.
changes to: ConvertNMosTransistor contains creation of dCnstr[dCh] constraints and call of SXTechnology.ProcessMosTransistor, Init setting of dCnstr[dCh].withNode
Edited on March 7, 1985 4:25:39 pm PST, by Shand
Transistor Output changes: n*W multiplier for McCreight, ZTrans for Bowers.
Edited on March 9, 1985 2:01:08 pm PST, by Beretta & Shand
New Constraint Representation from SX and procedures to set it up.
changes to: ConvertNMosTransistor, ConvertNMosButtingContact, ConvertNMosBuriedContact, Constraint, dCnstr, pCnstr, Init, DIRECTORY
Edited on March 10, 1985 10:25:58 pm PST, by Shand
changes to: RoseNMosTransistor
Edited on March 12, 1985 4:23:50 pm PST, by Shand
Now uses registration mechanisms of SXTechnology.
changes to: DIRECTORY, NMosSpinifex, Init, pCnstr, Init, ConvertNMosContactDifAndPol, ConvertNMosButtingContact, pCnstr, Init, Init
Edited on March 19, 1985 12:44:28 pm PST, by Beretta
Thyme output change: substituted `n' coefficient for Ed McCreight by `N'
changes to: ThymeNMosTransistor
Edited on March 27, 1985 6:37:12 pm PST, by Beretta
Corrected bug in poly constraint resolution table
changes to: Init: pResTab[3,1] ← pDPErr
Edited on April 29, 1985 8:09:08 pm PDT, by Beretta
Fixed bug that flagged a poly width rule violation at the attachments of buried contacts "Polysilicon Surround" and "Diffusion Surround"
changes to: Init added polWidthTrigger [pDandP] ← FALSE;
Edited on May 2, 1985 10:45:08 am PDT, by Beretta
Added a quick hack to the Thyme output to allow John Ousterhout to test Crystal.
changes to: ThymeNMosTransistor: If a transistor has a property $Crystal, then its rope value is placed in the parameter list, preceded by a semicolon.
Edited on May 6, 1985 11:26:55 am PDT, by Beretta
Converted to ChipNDale CD20
Edited on May 20, 1985 2:38:11 pm PDT, by Beretta,
Created new interface SXNMosBasicRules.
Edited on June 18, 1985 4:56:52 pm PDT, by Beretta
Changed transistor types from FooTrans to FooTran, as Thyme expects.
changes to: ThymeNMosTransistor