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 August 14, 1985 10:57:54 am PDT
DIRECTORY
CD USING [Instance, lambda, Layer, Number, Position, Rect],
CDBasics USING [RectAt],
CDInstances USING [InstRectO],
CDProperties USING [GetPropFromInstance],
CDSimpleRules,
Core USING [CellType],
CoreOps USING [CreateRecordWire],
CDOrient USING [CreateTransform],
CoreProperties USING [PutProp],
CoreRecord USING [CellInstance, CellInstanceList, CellInstanceRec],
CoreTransistor USING [Create, Transistor, TransistorRec],
ImagerTransformation USING [Transformation],
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],
SXAtoms USING [cdCellHint, crystalAttr, instanceTransf],
SXNMosBasicRules,
SXOutput USING [LinkageHousekeeper, LinkagePrintProc],
SXOutputPrivate USING [coreCellInstance, coreDesign, coreNodeBuffer, GetANaming, InsertNode, 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, CDInstances, CDOrient, CDProperties, CDSimpleRules, CoreOps, CoreProperties, CoreTransistor, IO, NMos, Rope, SX, SXAtoms, SXOutputPrivate, SXTechnology, TerminalIO =
BEGIN
l: CD.Number ~ CD.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-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], 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-SXNMosBasicRules.difToPolSep > 0
THEN {
-- At the top
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt+p.length+SXNMosBasicRules.difToPolSep, size.x-polExt, size.y], inst~inst, 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], inst~inst, 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], inst~inst, 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], 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-SXNMosBasicRules.contactWidth)/2, size.y-6*l, (size.x+SXNMosBasicRules.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), 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[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];
};
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+SXNMosBasicRules.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+SXNMosBasicRules.difToPolSep, inst.ob.size.x, inst.ob.size.y], inst~inst, 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, 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-SXNMosBasicRules.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-SXNMosBasicRules.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-SXNMosBasicRules.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-SXNMosBasicRules.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-SXNMosBasicRules.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-SXNMosBasicRules.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;
};
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
];
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.GetPropFromInstance [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[ "];"]
};
MakeCoreNMOSTransistor:
PUBLIC SXOutput.LinkagePrintProc ~
BEGIN
[desWDir: Rope.ROPE, dfStream, cellStream: IO.STREAM, linkage: REF SX.NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc]
t: CoreTransistor.Transistor ← NEW [CoreTransistor.TransistorRec];
tInstance: CoreRecord.CellInstance ← NEW [CoreRecord.CellInstanceRec];
o: Core.CellType;
cm: NMosTransistors.TransistorPtr ~ NARROW [linkage.source.ob.specificRef];
InsertAttachment:
PROCEDURE [key:
ATOM] ~
BEGIN
FOR a:
LIST
OF
REF SX.AttachedNode ← linkage.nodes, a.rest
WHILE a #
NIL
DO
IF a.first.attachmentType = key
THEN
BEGIN
SXOutputPrivate.InsertNode [a.first.node];
RETURN
END
ENDLOOP;
END; -- InsertAttachment
t.type ←
IF cm.pullup
THEN nD
--
WRONG (no provision for NMos in Core as yet)
ELSE SELECT cm.implant FROM
NMosTransistors.enhancement => nE,
NMosTransistors.strongDepletion => pE,
ENDCASE => nD;
t.length ← linkage.l/l; t.width ← linkage.w/l;
o ← CoreTransistor.Create [SXOutputPrivate.coreDesign, t];
-- coreNodeBuffer was niled out in SXOutputImplA just before this code is executed.
InsertAttachment [$Gate]; InsertAttachment [$Source]; InsertAttachment [$Drain];
tInstance.actualWire ← CoreOps.CreateRecordWire [name: "attachements", components: SXOutputPrivate.coreNodeBuffer];
SXOutputPrivate.coreNodeBuffer ← NIL;
tInstance.name ← name;
tInstance.type ← o;
BEGIN
-- properties
t: ImagerTransformation.Transformation;
pos, size: CD.Position; ir: CD.Rect; propertyValue: REF;
ir ← CDInstances.InstRectO [linkage.source];
pos ← [x: ir.x1, y: ir.y1]; size ← [x: ir.x2 - ir.x1, y: ir.y2 - ir.y1];
t ← CDOrient.CreateTransform [cellSize: size, cellInstOrient: linkage.source.orientation, cellInstPos: pos];
tInstance.properties ← CoreProperties.PutProp [on: tInstance.properties, prop: SXAtoms.cdCellHint, value: linkage.source];
tInstance.properties ← CoreProperties.PutProp [on: tInstance.properties, prop: SXAtoms.instanceTransf, value: t];
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 => tInstance.properties ← CoreProperties.PutProp [tInstance.properties, SXAtoms.crystalAttr, crystalHack];
ENDCASE => IF propertyValue # NIL THEN TerminalIO.WriteRope [" Crystal property must be a rope./n"]
END;
SXOutputPrivate.coreCellInstance.instances ← CONS [tInstance, SXOutputPrivate.coreCellInstance.instances]
END; -- MakeCoreNMosTransistor
-- 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;
TriggerMap: TYPE ~ PACKED ARRAY SX.ConstraintIndex OF BOOLEAN ← ALL[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,SXNMosBasicRules.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~SXNMosBasicRules.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*CD.lambda, message: "Buried Contact Cut Spacing", okIfConnected: FALSE, trigger1~bcSpaceTrigger, trigger2~bcSpaceTrigger]];
bcMetalCutSpacingRuleA ← NEW[ GeometricRule ← [extent: 3*CD.lambda/2, message: "Buried Contact Cut/Metal Cut Spacing[debug: A]", okIfConnected: FALSE, trigger1~bcMetalCutSpacingTriggerA, trigger2~bcMetalCutSpacingTriggerB]];
bcMetalCutSpacingRuleB ← NEW[ GeometricRule ← [extent: 3*CD.lambda/2, message: "Buried Contact Cut/Metal Cut Separation[debug: B]", okIfConnected: FALSE, trigger1~bcMetalCutSpacingTriggerB, trigger2~bcMetalCutSpacingTriggerA]];
polBuriedSpacingRuleA ← NEW[ GeometricRule ← [extent: CD.lambda/2, message: "Buried Contact Cut/Unrelated Poly Spacing[debug:A]", okIfConnected: TRUE, trigger1~polBuriedSpaceTriggerA, trigger2~polBuriedSpaceTriggerB]];
polBuriedSpacingRuleB ← NEW[ GeometricRule ← [extent: CD.lambda/2, message: "Buried Contact Cut/Unrelated Poly Spacing[debug:B]", okIfConnected: TRUE, trigger1~polBuriedSpaceTriggerB, trigger2~polBuriedSpaceTriggerA]];
nMosHandle.rules[ difSpinifex] ← LIST[difSpacingRule, difWidthRule];
nMosHandle.rules[ polSpinifex] ← LIST[polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule, polBuriedSpacingRuleA, polBuriedSpacingRuleB];
nMosHandle.rules[ metSpinifex] ← LIST[metSpacingRule, metWidthRule, bcCutSpacingRule, bcMetalCutSpacingRuleA, bcMetalCutSpacingRuleB];
-- 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, core~MakeCoreNMOSTransistor, fini~SXOutputPrivate.UnNameTransType];
SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosATransistor, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor, core~MakeCoreNMOSTransistor];
SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosPullUp, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor, core~MakeCoreNMOSTransistor];
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