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
Bowers, September 13, 1985 3:03:18 pm PDT
Last edited by: gbb March 26, 1986 2:52:33 pm PST
DIRECTORY
CD USING [Instance, Layer, Number, Position, Rect],
CDBasics USING [RectAt],
CDProperties USING [GetInstanceProp],
CDSimpleRules USING [MinDist, MinWidth],
IO USING [char, int, Put, PutF, PutRope, rope],
NMos USING [lambda, 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, violateIndex],
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, CDSimpleRules, IO, NMos, Rope, SX, SXOutputPrivate, SXTechnology, TerminalIO =
BEGIN
l: CD.Number ~ NMos.lambda;
Basic rules not provided by CDSimpleRules
polOverDif: CD.Number = NMos.lambda;
These numbers are halved (sorry about any confusion this may cause)
difToPolExtSep: CD.Number = 0;
polSep: CD.Number = NMos.lambda;
difToPolSep: CD.Number = difToPolExtSep + polSep; -- not halved!
contactWidth: CD.Number = 4 * NMos.lambda;
New Regime Transistor converters (IE the Shand unified xstr representaion)
ConvertNMosTransistor: SX.ConversionProc ~ {
[appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF]
p: NMosTransistors.TransistorPtr = NARROW[inst.ob.specificRef];
size: CD.Position ← inst.ob.size;
xstr: REF SX.NodeLinkage;
gateNode, sourceNode, drainNode, metNode: REF SX.CircuitNode;
polExt: CD.Number ~ IF p.pullup THEN MIN[ (size.x-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], inst~inst, pos~ pos, orient~ orient, interestBloat~SXTechnology.SWNGrow[(CDSimpleRules.MinDist[NMos.pol, NMos.pol]/2)]];
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt, size.x-polExt, p.lExt+p.length], inst~inst, pos~ pos, orient~ orient, value~gateNode];
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[size.x-polExt, p.lExt, size.x, p.lExt+p.length], inst~inst, pos~ pos, orient~ orient, interestBloat~SXTechnology.NESGrow[(CDSimpleRules.MinDist[NMos.pol, NMos.pol]/2)], value~gateNode];
Add rects for poly exclusion
IF p.lExt-difToPolSep > 0 THEN {
At the top
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt+p.length+difToPolSep, size.x-polExt, size.y], inst~inst, pos~ pos, orient~ orient,
interestBloat~SXTechnology.WNEGrow[difToPolExtSep],
value~pCnstr[pExcl]];
... and the bottom
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, 0, size.x-p.wExt, p.lExt-difToPolSep], inst~inst, pos~ pos, orient~ orient, interestBloat~SXTechnology.ESWGrow[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+difToPolSep], inst~inst, pos~ pos, orient~ orient, value~pCnstr[pChE]];
... and the bottom
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, p.lExt-difToPolSep, size.x-p.wExt, p.lExt], inst~inst, 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], inst~inst, pos~ pos, orient~ orient, interestBloat~[dx1~ (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), dy1~ 0, dx2~ (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), 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], inst~inst, pos~ pos, orient~ orient, interestBloat~[dx1~ (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), dy1~ 0, dx2~ (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), dy2~ (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)], 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], inst~inst, pos~ pos, orient~ orient, interestBloat~SXTechnology.WNEGrow[(CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)]];
drainNode ← cir.AddBox[ spinifexLayer~difSpinifex, dim~[p.wExt, 0, size.x-p.wExt, p.lExt], inst~inst, pos~ pos, orient~ orient, interestBloat~SXTechnology.ESWGrow[(CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)]];
IF p.pullup THEN {
metNode ← cir.AddRect [lev~NMos.met, dim~[(size.x-contactWidth)/2, size.y-6*l, (size.x+contactWidth)/2, size.y], inst~inst, 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[inst, pos, orient, cir, difSpinifex, polSpinifex, dCnstr[dCh], pCnstr[pChE], (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), 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[inst, p.length, p.width];
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];
};
Material mapping
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
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.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit]
box: CD.Rect ← CDBasics.RectAt [pos~[0,0], size~inst.ob.size];
node: REF SX.CircuitNode;
Attach two rectangles to the same node.
node ← cir.AddRect[ lev~NMos.met, dim~box, inst~inst, pos~ pos, orient~ orient];
[] ← cir.AddRect[ lev~inst.ob.layer, dim~box, inst~inst, pos~ pos, orient~ orient, value~node];
IF inst.ob.layer = NMos.dif THEN
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~box, inst~inst, pos~ pos, orient~ orient, value~pCnstr[pExCon]];
};
ConvertNMosMmContact: SX.ConversionProc ~ {
[appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit]
s: CD.Position = inst.ob.size;
[] ← cir.AddBox [
spinifexLayer: metSpinifex,
dim: [l/2, l/2, s.x-l/2, s.y-l/2], -- cut bloated by 1/2 lambda
inst: inst,
pos: pos,
orient: orient,
value: mCnstr[mCutEx]];
[] ← cir.AddBox [
spinifexLayer: metSpinifex,
dim: [l, l, s.x-l, s.y-l], -- cut unbloated
inst: inst,
pos: pos,
orient: orient,
value: mCnstr[mCut]];
};
ConvertNMosButtingContact: SX.ConversionProc ~ {
[appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit]
rimWidth: CD.Number ~ l;
polSize: CD.Number ~ inst.ob.size.y/2;
box: CD.Rect ← CDBasics.RectAt [pos~[0,0], size~inst.ob.size];
node: REF SX.CircuitNode;
node ← cir.AddRect[ lev~NMos.met, dim~box, inst~inst, pos~ pos, orient~ orient];
[] ← cir.AddRect[ lev~NMos.pol, dim~[0,0, inst.ob.size.x, polSize], inst~inst, pos~ pos, orient~ orient, value~node];
Add rect for poly exclusion
[] ← cir.AddBox[ spinifexLayer~polSpinifex,
dim~[-rimWidth,polSize, inst.ob.size.x+rimWidth, polSize+difToPolSep], inst~inst, pos~ pos, orient~ orient, value~pCnstr[pChE]];
[] ← cir.AddBox [spinifexLayer~polSpinifex,
dim~[-rimWidth,polSize-rimWidth, 0, polSize], inst~inst, pos~ pos, orient~ orient, value~pCnstr[pDxorP]];
[] ← cir.AddBox [spinifexLayer~polSpinifex,
dim~[inst.ob.size.x,polSize-rimWidth, inst.ob.size.x+rimWidth, polSize], inst~inst, pos~ pos, orient~ orient, value~pCnstr[pDxorP]];
[] ← cir.AddBox [spinifexLayer~polSpinifex,
dim~[0,polSize+difToPolSep, inst.ob.size.x, inst.ob.size.y], inst~inst, pos~ pos, orient~ orient,
interestBloat~SXTechnology.WNEGrow[difToPolExtSep],
value~pCnstr[pExCon]];
Add rect for diff width spacing and connection
[] ← cir.AddBox [spinifexLayer~difSpinifex,
dim~[0,polSize, inst.ob.size.x, inst.ob.size.y], inst~inst, pos~ pos, orient~ orient,
interestBloat~[(CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)], value~node];
};
ConvertNMosBuriedContact: SX.ConversionProc ~ {
[appl: CD.Instance, pos: CD.Position, 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.Position ~ inst.ob.size;
cp: NMosContacts.ContactPtr ~ NARROW[inst.ob.specificRef];
node: REF SX.CircuitNode ~ cir.AddRect[ lev~NMos.pol, dim~[2*l, cp.lExt, s.x-cp.wExt, s.y-cp.lExt], inst~inst, pos~ pos, orient~ orient];
Cut
[] ← cir.AddBox [
spinifexLayer: metSpinifex,
dim: [l/2, l/2, s.x-l/2, s.y-l/2], -- actual dimensions of cut
inst: inst,
pos: pos,
orient: orient,
value: mCnstr[mBCCut]];
[] ← cir.AddBox [
spinifexLayer: metSpinifex,
dim: [-l/2, -l/2, s.x+l/2, s.y+l/2], -- cut bloated by 1 lambda
inst: inst,
pos: pos,
orient: orient,
value: mCnstr[mBCEx]];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [l/2, l/2, s.x-l/2, s.y-l/2], -- actual dimensions of cut
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pBCCut]];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [0, 0, s.x, s.y], --cut Bloated by 1/2 lambda (poly is bloated by lambda)
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pBCExcl]];
SELECT TRUE FROM
cp.lExt < 2*l AND cp.wExt < 2*l => {
Polysilicon Surround
wex: CD.Number ~ MAX[cp.wExt+l, 2*l];
lex: CD.Number ~ MAX[cp.lExt+l, 2*l];
bcExclConstraint: SX.Constraint ← pCnstr[pBCExcl]^;
bcExclConstraint.specificCorrespondingNode ← node;
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [-l/2, -l/2, 0, s.y+l/2], -- buried contact poly exclude (left side)
inst: inst,
pos: pos,
orient: orient,
value: NEW[Constraint ← bcExclConstraint]];
[] ← cir.AddRect [
lev: inst.ob.layer,
dim: [l, lex, 2*l, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l-difToPolSep, lex, 2*l, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l, lex, s.x-wex, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pDandP]];
[] ← cir.AddBox [
spinifexLayer: difSpinifex,
dim: [2*l, lex, s.x-wex, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: node];
};
cp.lExt < 2*l AND cp.wExt >= 2*l => {
Polysilicon/Diffusion Crossing.
lex: CD.Number ~ MAX[cp.lExt+l, 2*l];
bcExclConstraint: SX.Constraint ← pCnstr[pBCExcl]^;
bcExclConstraint.specificCorrespondingNode ← node;
Cut
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [s.x, -l/2, s.x+l/2, s.y+l/2], -- buried contact poly exclude (right side)
inst: inst,
pos: pos,
orient: orient,
value: NEW[Constraint ← bcExclConstraint]];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [-l/2, -l/2, 0, s.y+l/2], -- buried contact poly exclude (left side)
inst: inst,
pos: pos,
orient: orient,
value: NEW[Constraint ← bcExclConstraint]];
[] ← cir.AddBox [
spinifexLayer: difSpinifex,
dim: [2*l, lex, s.x-cp.wExt, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l, lex, s.x-cp.wExt, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pDandP]];
Left side.
[] ← cir.AddRect [lev: inst.ob.layer,
dim: [l, lex, 2*l, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l-difToPolSep, lex, 2*l, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
Right side.
[] ← cir.AddRect [
lev: inst.ob.layer,
dim: [s.x-cp.wExt, lex, s.x-(cp.wExt-l), s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [s.x-cp.wExt, lex, s.x-(cp.wExt-difToPolSep), s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
};
cp.lExt >= 2*l AND cp.wExt < 2*l => {
Diffusion Surround
wex: CD.Number ~ MAX[cp.wExt+l, 2*l];
lex: CD.Number ~ cp.lExt-l;
bcExclConstraint: SX.Constraint ← pCnstr[pBCExcl]^;
bcExclConstraint.specificCorrespondingNode ← node;
Cut
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [-l/2, -l/2, l/2, s.y+l/2], -- buried contact poly exclude (left side)
inst: inst,
pos: pos,
orient: orient,
value: NEW[Constraint ← bcExclConstraint]];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [l/2, s.y, s.x+l/2, s.y+l/2], -- buried contact poly exclude (top side)
inst: inst,
pos: pos,
orient: orient,
value: NEW[Constraint ← bcExclConstraint]];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [l/2, -l/2, s.x, 0], -- buried contact poly exclude (bottom side)
inst: inst,
pos: pos,
orient: orient,
value: NEW[Constraint ← bcExclConstraint]];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l, cp.lExt, s.x-wex, s.y-cp.lExt],
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pDandP]];
Left side.
[] ← cir.AddRect [
lev: inst.ob.layer,
dim: [l, lex, s.x-wex, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l-difToPolSep, lex, 2*l, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
Top.
[] ← cir.AddRect [
lev: inst.ob.layer,
dim: [2*l, s.y-cp.lExt, s.x-wex, s.y-lex],
inst: inst,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l, s.y-cp.lExt, s.x-wex, s.y-(cp.lExt-difToPolSep)],
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
Bottom.
[] ← cir.AddRect [
lev: inst.ob.layer,
dim: [2*l, lex, s.x-wex, cp.lExt],
inst: inst,
pos: pos,
orient: orient,
value: node];
[] ← cir.AddBox [
spinifexLayer: polSpinifex,
dim: [2*l, cp.lExt-difToPolSep, s.x-wex, cp.lExt],
inst: inst,
pos: pos,
orient: orient,
value: pCnstr[pChE]];
};
cp.lExt >= 2*l AND cp.wExt >= 2*l => {
Diffusion Surround ! on all sides ???
ERROR SX.IllegalConstruct [inst.ob.class.interestRect[inst.ob], "Polysilicon surrounded by diffusion or all sides in Buried Contact"];
};
ENDCASE => ERROR;
};
Thyme and Rosemary
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.GetInstanceProp [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.
pBCExcl: SX.ConstraintIndex = pDandP.SUCC; -- Buried Contact Cut Exclusion
pBCErr: SX.ConstraintIndex = pBCExcl.SUCC; -- Buried Contact Cut Separation violation
pBCCut: SX.ConstraintIndex = pBCErr.SUCC; -- Buried Contact Cut
mCnstr: REF SX.ConstraintArray ← NEW[SX.ConstraintArray]; -- metal constraints
mBCEx: SX.ConstraintIndex = SX.techCIndexBase; -- Buried Contact Cut Bloated
mBCErr: SX.ConstraintIndex = mBCEx.SUCC; -- Buried Contact Cut Separation violation
mBCCut: SX.ConstraintIndex = mBCErr.SUCC; -- Buried Contact Cut Unbloated
mCutEx: SX.ConstraintIndex = mBCCut.SUCC; -- Metal Contact Cut Bloated
mCut: SX.ConstraintIndex = mCutEx.SUCC; -- Metal Contact Cut Unbloated
mBCExM: SX.ConstraintIndex = mCut.SUCC; -- Buried Contact Cut Bloated over metal
mBCErrM: SX.ConstraintIndex = mBCExM.SUCC; -- Buried Contact Cut Separation violation over metal
mBCCutM: SX.ConstraintIndex = mBCErrM.SUCC; -- Buried Contact Cut Unbloated over metal
mCutExM: SX.ConstraintIndex = mBCCutM.SUCC; -- Metal Contact Cut Bloated over metal
mCutM: SX.ConstraintIndex = mCutExM.SUCC; -- Metal Contact Cut Unbloated over metal
Init: PROCEDURE ~ {
GeometricRule: TYPE ~ SX.GeometricRule;
difSpacingRule, difWidthRule: REF GeometricRule;
polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule, polBuriedSpacingRuleA, polBuriedSpacingRuleB: REF GeometricRule;
metSpacingRule, metWidthRule, bcCutSpacingRule, bcMetalCutSpacingRuleA, bcMetalCutSpacingRuleB: REF GeometricRule;
detectOpaqueViolation: REF GeometricRule;
TriggerMap: TYPE ~ PACKED ARRAY SX.ConstraintIndex OF BOOLEANALL[FALSE];
spaceRuleTrigger: TriggerMap;
widthRuleTrigger: TriggerMap;
polOverDifTrigger1, polOverDifTrigger2, polDifSepTriggerA, polDifSepTriggerB: TriggerMap;
difSpaceTrigger1: TriggerMap;
polWidthTrigger: TriggerMap;
polBuriedSpaceTriggerA, polBuriedSpaceTriggerB, polSpaceTrigger, metSpaceTrigger, metWidthTrigger: TriggerMap;
bcSpaceTrigger, bcMetalCutSpacingTriggerA, bcMetalCutSpacingTriggerB: TriggerMap;
difResolution: REF SX.ConstraintResolution;
polyResolution: REF SX.ConstraintResolution;
metResolution: 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]];
pCnstr[pBCExcl] ← NEW[ Constraint ← [ $PolyBCExcl, pBCExcl, TRUE]];
pCnstr[pBCErr] ← NEW[ Constraint ← [ $PolyBCErr, pBCErr, TRUE]];
pCnstr[pBCCut] ← NEW[ Constraint ← [ $PolyBCCut, pBCCut]];
mCnstr[mBCEx] ← NEW[ Constraint ← [ $BCExclCut, mBCEx]];
mCnstr[mBCErr] ← NEW[ Constraint ← [ $BCErr, mBCErr]];
mCnstr[mBCCut] ← NEW[ Constraint ← [ $BCCut, mBCCut]];
mCnstr[mCutEx] ← NEW[ Constraint ← [ $CutExcl, mCutEx]];
mCnstr[mCut] ← NEW[ Constraint ← [ $Cut, mCut]];
mCnstr[mBCExM] ← NEW[ Constraint ← [ $BCExclCutM, mBCExM]];
mCnstr[mBCErrM] ← NEW[ Constraint ← [ $BCErrM, mBCErrM]];
mCnstr[mBCCutM] ← NEW[ Constraint ← [ $BCCutM, mBCCutM]];
mCnstr[mCutExM] ← NEW[ Constraint ← [ $CutExclM, mCutExM]];
mCnstr[mCutM] ← NEW[ Constraint ← [ $CutM, mCutM]];
{
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, pBCExcl, pBCErr, ,,,,,],
[ nd,   nd,   pDPErr, pDPErr, pDPErr, pDPErr, nd,   pDandP, pBCErr, pBCErr, ,,,,,],
[ pExcl,  pDPErr, pExcl,  pExCon, pDPErr, pChE,  pChE,  pDandP, pExcl,  pExcl,  ,,,,,],
[ pExCon, pDPErr, pExCon, pExCon, pDPErr, pExCon, pExCon, pDandP, pExCon, pExCon, ,,,,,],
[ pDPErr, pDPErr, pDPErr, pDPErr, pDPErr, pDPErr, pDPErr, pDandP, pDPErr, pDPErr, ,,,,,],
[ pChE,  pDPErr, pChE,  pExCon, pDPErr, pChE,  pChE,  pDandP, pChE,  pChE,  ,,,,,],
[ pDxorP, nd,   pChE,  pExCon, pDPErr, pChE,  pDxorP, pDandP, pDxorP, pDxorP, ,,,,,],
[ pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, ,,,,,],
[ pBCExcl, pBCErr, pExcl,  pExCon, pDPErr, pChE,  pDxorP, pDandP, pBCExcl, pBCErr, ,,,,,],
[ pBCErr, pBCErr, pExcl,  pExCon, pDPErr, pChE,  pDxorP, pDandP, pBCErr, pBCErr, ,,,,,],
,,,,,
];
mResTab: SXTechnology.ResolutionTable = [
[ sp,    nd,    mBCEx, mBCErr, mBCCut, mCutEx, mCut,  mBCExM, mBCErrM, mBCCutM, mCutExM, mCutM,,,,],
[ nd,    nd,    mBCExM, mBCErrM, mBCCutM, mCutExM, mCutM, mBCExM, mBCErrM, mBCCutM, mCutExM, mCutM,,,,],
[ mBCEx,  mBCExM,  mBCErr, mBCErr, mBCCut, mBCErr, mCut,  mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM,,,,],
[ mBCErr,  mBCErrM,  mBCErr, mBCErr, mBCCut, mBCErr, mCut,  mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM,,,,],
[ mBCCut,  mBCCutM,  mBCCut, mBCCut, mBCCut, mBCCut, mCut,  mBCCutM, mBCCutM, mBCCutM, mBCCutM, mCutM,,,,],
[ mCutEx,  mCutExM,  mBCErr, mBCErr, mBCCut, mCutEx, mCut,  mBCErrM, mBCErrM, mBCCutM, mCutExM, mCutM,,,,],
[ mCut,   mCutM,  mCut,  mCut,  mCut,  mCut,  mCut,  mCutM, mCutM, mCutM, mCutM, mCutM,,,,],
[ mBCExM,  mBCExM,  mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM, mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM,,,,],
[ mBCErrM,  mBCErrM,  mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM, mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM,,,,],
[ mBCCutM,  mBCCutM,  mBCCutM, mBCCutM, mBCCutM, mBCCutM, mCutM, mBCCutM, mBCCutM, mBCCutM, mBCCutM, mCutM,,,,],
[ mCutExM,  mCutExM,  mBCErrM, mBCErrM, mBCCutM, mCutExM, mCutM, mBCErrM, mBCErrM, mBCCutM, mBCExM, mCutM,,,,],
[ mCutM,  mCutM,  mCutM, mCutM, mCutM, mCutM, mCutM, mCutM, mCutM, mCutM, mCutM, mCutM,,,,],
,,,
];
difResolution ← SXTechnology.SetUpResolution[ dCnstr, dResTab];
polyResolution ← SXTechnology.SetUpResolution[ pCnstr, pResTab];
metResolution ← SXTechnology.SetUpResolution[ mCnstr, mResTab];
};
Basic nMosHandle & cdLayerMappings.
nMosHandle ← NEW[SX.TechHandle ← [numSpinifexLayers~3, layerInterestBloat~[(CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), (CDSimpleRules.MinDist[NMos.pol, NMos.pol]/2), (CDSimpleRules.MinDist[NMos.met, NMos.met]/2), ,,,,]] ];
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, (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)], [polSpinifex,difToPolExtSep,pCnstr[pExcl]]];
nMosHandle.cdLayerMapping[NMos.pol] ← LIST[ [polSpinifex,(CDSimpleRules.MinDist[NMos.pol, NMos.pol]/2)]];
nMosHandle.cdLayerMapping[NMos.met] ← LIST[ [metSpinifex,(CDSimpleRules.MinDist[NMos.met, NMos.met]/2)]];
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;
nMosHandle.constraintResolutions[metSpinifex] ← metResolution;
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
polWidthTrigger[pBCErr] ← FALSE; -- added by Bowers
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];
bcSpaceTrigger[mBCCut] ← TRUE;
bcMetalCutSpacingTriggerA[mCut] ← TRUE;
bcMetalCutSpacingTriggerB[mBCCut] ← TRUE;
polBuriedSpaceTriggerA[pBCErr] ← TRUE;
polBuriedSpaceTriggerA[pBCExcl] ← TRUE;
polBuriedSpaceTriggerB[SX.nodeIndex] ← TRUE;
polSpaceTrigger[SX.nodeIndex] ← TRUE;
polSpaceTrigger[pBCErr] ← TRUE;
metSpaceTrigger[SX.nodeIndex] ← TRUE;
metSpaceTrigger[mBCExM] ← TRUE;
metSpaceTrigger[mBCErrM] ← TRUE;
metSpaceTrigger[mBCCutM] ← TRUE;
metSpaceTrigger[mCutExM] ← TRUE;
metSpaceTrigger[mCutM] ← TRUE;
metWidthTrigger[SX.spaceIndex] ← TRUE;
metWidthTrigger[mBCEx] ← TRUE;
metWidthTrigger[mBCErr] ← TRUE;
metWidthTrigger[mBCCut] ← TRUE;
metWidthTrigger[mCutEx] ← TRUE;
metWidthTrigger[mCut] ← TRUE;
The geometric rules.
difSpacingRule ← NEW[ GeometricRule ← [extent~CDSimpleRules.MinDist[NMos.dif, NMos.dif], message~"Diffusion spacing", okIfConnected~TRUE, trigger1~difSpaceTrigger1, trigger2~spaceRuleTrigger]];
difWidthRule ← NEW[ GeometricRule ← [extent~CDSimpleRules.MinWidth[NMos.dif], message~"Diffusion width", trigger1~widthRuleTrigger, trigger2~widthRuleTrigger]];
polSpacingRule ← NEW[ GeometricRule ← [extent~CDSimpleRules.MinDist[NMos.pol, NMos.pol], message~"Poly spacing", okIfConnected~TRUE, trigger1~polSpaceTrigger, trigger2~polSpaceTrigger]];
polWidthRule ← NEW[ GeometricRule ← [extent~CDSimpleRules.MinWidth[NMos.pol], message~"Poly width", trigger1~polWidthTrigger, trigger2~polWidthTrigger]];
polDifSepRuleA ← NEW[ GeometricRule ← [extent~CDSimpleRules.MinDist[NMos.pol, NMos.dif], message~"Poly/Diffusion spacing[debug:A]", trigger1~polDifSepTriggerA, trigger2~polDifSepTriggerB]];
polDifSepRuleB ← NEW[ GeometricRule ← [extent~CDSimpleRules.MinDist[NMos.pol, NMos.dif], message~"Poly/Diffusion spacing[debug:B]", trigger1~polDifSepTriggerB, trigger2~polDifSepTriggerA]];
polOverDifRule ← NEW[ GeometricRule ← [extent~polOverDif, message~"Poly over Diffusion", trigger1~polOverDifTrigger1, trigger2~polOverDifTrigger2]];
metSpacingRule ← NEW[ GeometricRule ← [extent~CDSimpleRules.MinDist[NMos.met, NMos.met], message~"Metal spacing", okIfConnected~TRUE, trigger1~metSpaceTrigger, trigger2~metSpaceTrigger]];
metWidthRule ← NEW[ GeometricRule ← [extent~CDSimpleRules.MinWidth[NMos.met], message~"Metal width", trigger1~metWidthTrigger, trigger2~metWidthTrigger]];
bcCutSpacingRule ← NEW[ GeometricRule ← [extent: 2*l, message: "Buried Contact Cut Spacing", okIfConnected: FALSE, trigger1~bcSpaceTrigger, trigger2~bcSpaceTrigger]];
bcMetalCutSpacingRuleANEW[ GeometricRule ← [extent: 3*l/2, message: "Buried Contact Cut/Metal Cut Spacing[debug: A]", okIfConnected: FALSE, trigger1~bcMetalCutSpacingTriggerA, trigger2~bcMetalCutSpacingTriggerB]];
bcMetalCutSpacingRuleBNEW[ GeometricRule ← [extent: 3*l/2, message: "Buried Contact Cut/Metal Cut Separation[debug: B]", okIfConnected: FALSE, trigger1~bcMetalCutSpacingTriggerB, trigger2~bcMetalCutSpacingTriggerA]];
polBuriedSpacingRuleA ← NEW[ GeometricRule ← [extent: l/2, message: "Buried Contact Cut/Unrelated Poly Spacing[debug:A]", okIfConnected: TRUE, trigger1~polBuriedSpaceTriggerA, trigger2~polBuriedSpaceTriggerB]];
polBuriedSpacingRuleB ← NEW[ GeometricRule ← [extent: l/2, message: "Buried Contact Cut/Unrelated Poly Spacing[debug:B]", okIfConnected: TRUE, trigger1~polBuriedSpaceTriggerB, trigger2~polBuriedSpaceTriggerA]];
detectOpaqueViolation ← NEW[ GeometricRule ← [ extent~ l, message~ "Opaque cell boundary violated", trigger1~ ALL[TRUE], trigger2~ ALL[TRUE]]];
We set violateIndex = FALSE, ALL else TRUE so that corner checks face inward, which should result in more logically pleasing error reports.
detectOpaqueViolation.trigger1[SX.violateIndex] ← FALSE;
nMosHandle.rules[ difSpinifex] ← LIST[difSpacingRule, difWidthRule, detectOpaqueViolation];
nMosHandle.rules[ polSpinifex] ← LIST[polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule, polBuriedSpacingRuleA, polBuriedSpacingRuleB, detectOpaqueViolation];
nMosHandle.rules[ metSpinifex] ← LIST[metSpacingRule, metWidthRule, bcCutSpacingRule, bcMetalCutSpacingRuleA, bcMetalCutSpacingRuleB, detectOpaqueViolation];
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];
SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosMmContact, conv~ConvertNMosMmContact];
};
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
Last edited by: gbb July 18, 1985 4:47:07 pm PDT
Converted to ChipNDale 2.1.
changes to: ConvTransistor: Adapted by Christian, ConvertContact: Completely rewritten.
gbb August 13, 1985 6:15:20 pm PDT
Added creation of Core data structure.
changes to: DIRECTORY, SXNMos, MakeCoreNMOSTransistor: new; type is not correct because Core does not yet cater for NMos transistors, Init
gbb November 7, 1985 5:07:31 pm PST
Conversions for ChipNDale22
gbb November 24, 1985 4:21:44 pm PST
Removed creation of Core data structure.
changes to: DIRECTORY, SXNMos