DIRECTORY CD, CDAtomicObjects USING [AtomicObsSpecific, DrawList], CDBasics, CDProperties USING [GetInstanceProp], CMosB USING [bur, cmosB, cut, cut2, lambda, met, met2, ndif, nwell, nwellCont, pdif, pol, pwell, pwellCont, wellSurround, wndif, wpdif], DesignRules USING [GetRuleSet, MinSpace, MinWidth, Rules], IO USING [atom, char, int, Put, PutF, PutFR, PutRope, rope], Properties USING [GetProp, PutProp], Rope USING [Cat, ROPE], SX USING [AddBox, AddRect, AdjustNode, AttachedNode, BoxMapProc, CellPostProcessProc, Circuit, CircuitNode, CombineNodePropertyProc, Constraint, ConstraintArray, ConstraintIndex, ConstraintResolution, ConversionProc, CreateLinkage, FindRootNode, GeometricRule, IllegalConstruct, LinkageAttach, LookupNode, nodeIndex, NodeLinkage, spaceIndex, SpinifexLayerIndex, techCIndexBase, TechHandle, violateIndex], SXAccess USING [invocation, sxTech], SXAccessInternal USING [PutError], SXAtoms USING [crystalAttr], SXOutput USING [LinkageHousekeeper, LinkagePrintProc], SXOutputPrivate USING [GetANaming, NameTransType, Naming, PrintNaming, PrintRoseInstantiationTransformation, UnNameTransType], SXTechnology USING [ESWGrow, GetCircuitFromCDObject, NESGrow, PerDrawRectProc, RegisterSpinifexObjectProcs, RegisterTechnologyHandle, ResolutionTable, SetUpResolution, WNEGrow, WNGrow], TerminalIO USING [PutRope]; SXCMosBImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDProperties, CMosB, DesignRules, IO, Properties, Rope, SX, SXAccess, SXAccessInternal, SXAtoms, SXOutputPrivate, SXTechnology, TerminalIO ~ BEGIN ruleSet: ATOM ~ $VTI; l: CD.Number ~ CMosB.lambda; Nodes: TYPE = LIST OF REF SX.CircuitNode; ConstraintArray: TYPE ~ SX.ConstraintArray; CIndex: TYPE ~ SX.ConstraintIndex; Constraint: TYPE ~ SX.Constraint; saguaroRules: DesignRules.Rules ~ DesignRules.GetRuleSet [ruleSet]; ndifSpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.ndif, CMosB.ndif].s; ndifWidth: CD.Number = DesignRules.MinWidth [saguaroRules, CMosB.ndif].w; ndifUncSubtrContSpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.ndif, CMosB.pwellCont].s; ndifInnWell: CD.Number = 0 * l; ndifpSubstrCont: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.ndif, CMosB.pwellCont].s; pdifSpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.pdif, CMosB.pdif].s; pdifWidth: CD.Number = DesignRules.MinWidth [saguaroRules, CMosB.pdif].w; pdifUncnWellSpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.pdif, CMosB.nwellCont].s; pdifnWellCont: CD.Number = 0 * l; polSpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.pol, CMosB.pol].s; polWidth: CD.Number = DesignRules.MinWidth [saguaroRules, CMosB.pol].w; polUncDifSpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.pol, CMosB.ndif].s; polDiffUncPolySpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.ndif, CMosB.pol].s; polOverDiff: CD.Number = 0 * l; metSeparation: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.met, CMosB.met].s; metWidth: CD.Number = DesignRules.MinWidth [saguaroRules, CMosB.met].w; metCutCutSpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.cut, CMosB.cut].s; metViaViaSpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.cut2, CMosB.cut2].s; metCutViaSpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.cut, CMosB.cut2].s; met2Separation: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.met2, CMosB.met2].s; met2Width: CD.Number = DesignRules.MinWidth [saguaroRules, CMosB.met2].w; difSep: CD.Number = ndifSpacing / 2; wellSep: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.nwell, CMosB.nwell].s; wellWidth: CD.Number = DesignRules.MinWidth [saguaroRules, CMosB.nwell].w; nDifToWell: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.ndif, CMosB.nwell].s; pDifToWell: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.pdif, CMosB.pwell].s; nDifTopDif: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.ndif, CMosB.pdif].s; pdifUncSubtrContSpacing: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.pdif, CMosB.nwellCont].s; nDifToSubtrCont: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.ndif, CMosB.nwellCont].s; pDifToSubtrCont: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.pdif, CMosB.pwellCont].s; nDifLayerSep: CD.Number = MAX [difSep, nDifToWell - difSep]; extensionLength: CD.Number = 3 * l; -- source/drain extension [rule 6.3.18] difToPolExtSep: CD.Number = 0; -- polSpacing - extensionLength; ndifSpinifex: SX.SpinifexLayerIndex ~ SX.SpinifexLayerIndex.FIRST; pdifSpinifex: SX.SpinifexLayerIndex ~ ndifSpinifex.SUCC; polSpinifex: SX.SpinifexLayerIndex ~ pdifSpinifex.SUCC; metSpinifex: SX.SpinifexLayerIndex ~ polSpinifex.SUCC; m2Spinifex: SX.SpinifexLayerIndex ~ metSpinifex.SUCC; wellSpinifex: SX.SpinifexLayerIndex ~ m2Spinifex.SUCC; ndCnstr: REF ConstraintArray _ NEW [ConstraintArray]; ndCh: CIndex ~ SX.techCIndexBase; -- n-Diffusion channel ndInWel: CIndex ~ ndCh.SUCC; -- n-Diffusion in n-Well ndWel: CIndex ~ ndInWel.SUCC; -- Exclude n-Diffusion by n-Well ndCnt: CIndex ~ ndWel.SUCC; -- n-Diffusion contact here. ndPWct: CIndex ~ ndCnt.SUCC; -- p-Diffusion contact here. ndPdErr: CIndex ~ ndPWct.SUCC; -- n-Diffusion & p-Diffusion together => Error. pdCnstr: REF ConstraintArray _ NEW [ConstraintArray]; pdCh: CIndex ~ SX.techCIndexBase; -- p-Diffusion channel pdNdErr: CIndex ~ pdCh.SUCC; -- p-Diffusion & n-Diffusion together => Error. pdCnt: CIndex ~ pdNdErr.SUCC; -- p-Diffusion contact here. pdNWct: CIndex ~ pdCnt.SUCC; -- n-Diffusion contact here. polCnstr: REF ConstraintArray _ NEW [ConstraintArray]; pExnD: CIndex ~ SX.techCIndexBase; -- Poly not allowed here because of n-Diffusion. pExpD: CIndex ~ pExnD.SUCC; -- Poly not allowed here because of p-Diffusion. pExNdCon: CIndex ~ pExpD.SUCC; -- Poly not allowed here because of n-Diffusion Contact. pExPdCon: CIndex ~ pExNdCon.SUCC; -- Poly not allowed here because of p-Diffusion Contact. pChE: CIndex ~ pExPdCon.SUCC; -- Close to Xstr Gate, (Channel Edge). pDxorP: CIndex ~ pChE.SUCC; -- Diffusion XOR Poly allowed here. pDandP: CIndex ~ pDxorP.SUCC; -- Diffusion AND Poly may appear together here. pDErr: CIndex ~ pDandP.SUCC; -- Poly and Diffusion found together => Error. metCnstr: REF ConstraintArray _ NEW [ConstraintArray]; mCut: CIndex ~ SX.techCIndexBase; -- Cut from Metal to dif or pol (bloated). mVia: CIndex ~ mCut.SUCC; -- Via from Metal to Metal2 (bloated). mVC: CIndex ~ mVia.SUCC; -- Via and Cut seperated by less than 2 lambda. InitRules: PROCEDURE [cMosHandle: REF SX.TechHandle] ~ { Rule: TYPE ~ SX.GeometricRule; TrigMap: TYPE ~ PACKED ARRAY CIndex OF BOOLEAN _ ALL [FALSE]; spaceRuleTrig, widthRuleTrig, nDifWidRuleTrig, polOverDifTrig1, polDifSepTrig1, polDifSepTrig2, nDifSpaceTrig1A, nDifSpaceTrig1B, nDifSpaceTrig2, pDifSpaceTrig1A, pDifSpaceTrig1B, pDifSpaceTrig2A, pDifSpaceTrig2B, pDifWidTrig, polSpaceTrig, polWidTrig, nDifSepNWellTrig1, nDifSepNWellTrig2, nDifInWellDifTrig1, nDifAndPDifTrig1, pDifAndNDifTrig1, alwaysErrorTrig2, nDifChannelTrig, metViaViaTrig, metCutViaTrig, metCutCutTrig, metSpTrig, metWTrig: TrigMap; -- ALL[FALSE] detectOpaqueViolation: REF Rule; spaceRuleTrig[SX.nodeIndex] _ TRUE; widthRuleTrig _ ALL[TRUE]; widthRuleTrig[SX.nodeIndex] _ FALSE; nDifSpaceTrig1A[SX.nodeIndex] _ TRUE; nDifSpaceTrig1A[ndCh] _ TRUE; nDifSpaceTrig1A[ndCnt] _ TRUE; nDifSpaceTrig1B[ndPWct] _ TRUE; nDifSpaceTrig2[SX.nodeIndex] _ TRUE; nDifSpaceTrig2[ndCh] _ FALSE; -- there is no diff at channels nDifSpaceTrig2[ndCnt] _ TRUE; nDifSpaceTrig2[ndPWct] _ TRUE; nDifChannelTrig[ndCh] _ TRUE; nDifWidRuleTrig _ ALL[TRUE]; nDifWidRuleTrig[SX.nodeIndex] _ FALSE; nDifWidRuleTrig[ndCnt] _ FALSE; pDifSpaceTrig1A[SX.nodeIndex] _ TRUE; pDifSpaceTrig1A[pdCh] _ TRUE; pDifSpaceTrig1A[pdCnt] _ TRUE; pDifSpaceTrig2A[SX.nodeIndex] _ TRUE; pDifSpaceTrig2A[pdCh] _ FALSE; -- there is no diff at channels pDifSpaceTrig2A[pdCnt] _ TRUE; pDifSpaceTrig2A[pdNWct] _ TRUE; pDifSpaceTrig1B[pdNWct] _ TRUE; pDifSpaceTrig2B[SX.nodeIndex] _ TRUE; pDifSpaceTrig2B[pdCnt] _ TRUE; pDifWidTrig _ ALL[TRUE]; pDifWidTrig[SX.nodeIndex] _ FALSE; pDifWidTrig[pdCnt] _ FALSE; nDifSepNWellTrig1[SX.nodeIndex] _ TRUE; nDifSepNWellTrig2[ndWel] _ TRUE; polSpaceTrig[SX.nodeIndex] _ TRUE; polSpaceTrig[pDandP] _ TRUE; polWidTrig _ ALL[TRUE]; polWidTrig[SX.nodeIndex] _ FALSE; polWidTrig[pDandP] _ FALSE; polWidTrig[pDErr] _ FALSE; polDifSepTrig1 [SX.nodeIndex] _ TRUE; polDifSepTrig1 [pDandP] _ TRUE; polDifSepTrig2 [pExnD] _ TRUE; polDifSepTrig2 [pExpD] _ TRUE; polDifSepTrig2 [pExNdCon] _ TRUE; polDifSepTrig2 [pExPdCon] _ TRUE; metSpTrig [SX.nodeIndex] _ TRUE; metSpTrig [mCut] _ TRUE; metSpTrig [mVia] _ TRUE; metSpTrig [mVC] _ TRUE; metWTrig _ ALL [TRUE]; metWTrig [SX.nodeIndex] _ FALSE; metWTrig [mCut] _ FALSE; metWTrig [mVia] _ FALSE; metWTrig [mVC] _ FALSE; polOverDifTrig1 [pDErr] _ TRUE; nDifInWellDifTrig1 [ndInWel] _ TRUE; nDifAndPDifTrig1 [ndPdErr] _ TRUE; pDifAndNDifTrig1 [pdNdErr] _ TRUE; metCutCutTrig [mCut] _ TRUE; metCutViaTrig [mVC] _ TRUE; metCutViaTrig [mVia] _ TRUE; metViaViaTrig [mVia] _ TRUE; alwaysErrorTrig2 _ ALL[TRUE]; detectOpaqueViolation _ NEW[ Rule _ [ extent~ l, message~ "Opaque cell boundary violated", trigger1~ ALL[TRUE], trigger2~ ALL[TRUE]]]; detectOpaqueViolation.trigger1[SX.violateIndex] _ FALSE; cMosHandle.rules [ndifSpinifex] _ LIST[ NEW [Rule _ [message~ "n-Diffusion spacing", extent~ ndifSpacing, okIfConnected~ TRUE, trigger1~ nDifSpaceTrig1A, trigger2~ nDifSpaceTrig2]], NEW [Rule _ [message~ "n-Diffusion/unconnected p-substrate-contact spacing", extent~ ndifUncSubtrContSpacing, okIfConnected~ TRUE, trigger1~ nDifSpaceTrig1B, trigger2~ nDifSpaceTrig2]], NEW [Rule _ [message~ "n-Diffusion width", extent~ ndifWidth, trigger1~ nDifWidRuleTrig, trigger2~ nDifWidRuleTrig]], NEW [Rule _ [message~ "n-Diffusion/n-Well spacing", extent~ nDifToWell, trigger1~ nDifSepNWellTrig1, trigger2~ nDifSepNWellTrig2]], NEW [Rule _ [message~ "n-Well/n-Diffusion spacing", extent~ nDifToWell, trigger1~ nDifSepNWellTrig2, trigger2~ nDifSepNWellTrig1]], NEW [Rule _ [message~ "n-Diffusion in n-Well", extent~ ndifInnWell, trigger1~ nDifInWellDifTrig1, trigger2~ alwaysErrorTrig2]], NEW [Rule _ [message~ "n-Diffusion and p-substrate-contact", extent~ ndifpSubstrCont, trigger1~ nDifAndPDifTrig1, trigger2~ alwaysErrorTrig2]], detectOpaqueViolation ]; cMosHandle.rules [pdifSpinifex] _ LIST [ NEW [Rule _ [message~ "p-Diffusion spacing", extent~ pdifSpacing, okIfConnected~ TRUE, trigger1~ pDifSpaceTrig1A, trigger2~ pDifSpaceTrig2A]], NEW [Rule _ [message~ "p-Diffusion/unconnected n-Well-contact spacing", extent~ pdifUncnWellSpacing, okIfConnected~ TRUE, trigger1~ pDifSpaceTrig1B, trigger2~ pDifSpaceTrig2B]], NEW [Rule _ [message~ "p-Diffusion width", extent~ pdifWidth, trigger1~ pDifWidTrig, trigger2~ pDifWidTrig]], NEW [Rule _ [message~ "p-Diffusion and n-Well-contact", extent~ pdifnWellCont, trigger1~ pDifAndNDifTrig1, trigger2~ alwaysErrorTrig2]], detectOpaqueViolation ]; cMosHandle.rules [polSpinifex] _ LIST [ NEW [Rule _ [message~ "Poly spacing", extent~ polSpacing, okIfConnected~ TRUE, trigger1~ polSpaceTrig, trigger2~ polSpaceTrig]], NEW [Rule _ [message~ "Poly width", extent~ polWidth, trigger1~ polWidTrig, trigger2~ polWidTrig]], NEW [Rule _ [message~ "Poly/unconnected Diffusion spacing", extent~ polUncDifSpacing, okIfConnected~ TRUE, trigger1~ polDifSepTrig1, trigger2~ polDifSepTrig2]], NEW [Rule _ [message~ "Diffusion/unconnected Poly spacing", extent~ polDiffUncPolySpacing, okIfConnected~ TRUE, trigger1~ polDifSepTrig2, trigger2~ polDifSepTrig1]], NEW [Rule _ [message~ "Poly over Diffusion", extent~ polOverDiff, trigger1~ polOverDifTrig1, trigger2~ alwaysErrorTrig2]], detectOpaqueViolation ]; cMosHandle.rules [metSpinifex] _ LIST [ NEW [Rule _ [message~ "Metal spacing", extent~ metSeparation, okIfConnected~ TRUE, trigger1~ metSpTrig, trigger2~ metSpTrig]], NEW [Rule _ [message~ "Metal width", extent~ metWidth, trigger1~ metWTrig, trigger2~ metWTrig]], NEW [Rule _ [message~ "Cut to Cut spacing", extent~ metCutCutSpacing, trigger1~ metCutCutTrig, trigger2~ metCutCutTrig]], NEW [Rule _ [message~ "Via to Via spacing", extent~ metViaViaSpacing, trigger1~ metViaViaTrig, trigger2~ metViaViaTrig]], NEW [Rule _ [message~ "Cut to Via spacing", extent~ metCutViaSpacing, trigger1~ metCutCutTrig, trigger2~ metCutViaTrig]], detectOpaqueViolation ]; cMosHandle.rules [m2Spinifex] _ LIST[ NEW [Rule _ [message~ "Metal 2 spacing", extent~ met2Separation, okIfConnected~ TRUE, trigger1~ spaceRuleTrig, trigger2~ spaceRuleTrig]], NEW [Rule _ [message~ "Metal 2 width", extent~ met2Width, trigger1~ widthRuleTrig, trigger2~ widthRuleTrig]], detectOpaqueViolation ]; cMosHandle.rules [wellSpinifex] _ LIST[ NEW [Rule _ [message~ "Well spacing", extent~ wellSep, okIfConnected~ TRUE, trigger1~ spaceRuleTrig, trigger2~ spaceRuleTrig]], NEW [Rule _ [message~ "Well width", extent~ wellWidth, trigger1~ widthRuleTrig, trigger2~ widthRuleTrig]], detectOpaqueViolation ]; }; MapMaterial: SXTechnology.PerDrawRectProc ~ { cir: REF SX.Circuit ~ NARROW [data, REF SX.Circuit]; SELECT l FROM CMosB.ndif, CMosB.pdif => RETURN [diffusion]; CMosB.pol => RETURN [polysilicon]; CMosB.nwell => { wellNode: REF SX.CircuitNode _ cir.AddRect [lev~ CMosB.nwell, dim~ r]; wellNode.properties _ Properties.PutProp [wellNode.properties, wellNode, wellNode]; RETURN [nothing]; }; ENDCASE => RETURN [nothing]; }; -- MapMaterial ConvTransistor: PUBLIC SX.ConversionProc = BEGIN transistor: REF SX.NodeLinkage; gateNode, sourceNode, drainNode, wellNode: REF SX.CircuitNode; tClass: ATOM = ob.class.objectType; isNType: BOOL = (ob.layer = CMosB.ndif); isNWell: BOOL; difSXLayer: SX.SpinifexLayerIndex; difChannel, exclPol: REF SX.Constraint; sep: CD.Number = DesignRules.MinSpace [saguaroRules, CMosB.ndif, CMosB.pol].s; extSep: CD.Number = difToPolExtSep; rect, wellRect: CD.Rect; polList, difList, chList, difListSouth: LIST OF CD.Rect _ NIL; length, width, extL, extW: CD.Number; gateA, gateP, sourceA, sourceP, drainA, drainP: INT; -- ignore perimeter leading into channel errorRect: CD.Rect = CD.InterestRect [ob]; IF isNType THEN {difSXLayer _ ndifSpinifex; difChannel _ ndCnstr[ndCh]; exclPol _ polCnstr[pExnD]} ELSE {difSXLayer _ pdifSpinifex; difChannel _ pdCnstr[pdCh]; exclPol _ polCnstr[pExpD]}; wellRect _ CDBasics.empty; IF ISTYPE [ob.specific, CDAtomicObjects.AtomicObsSpecific] THEN FOR geom: CDAtomicObjects.DrawList _ NARROW [ob.specific, CDAtomicObjects.AtomicObsSpecific].rList, geom.rest WHILE geom # NIL DO SELECT geom.first.layer FROM CMosB.pol => polList _ CONS [geom.first.r, polList]; CMosB.ndif, CMosB.pdif => difList _ CONS [geom.first.r, difList]; CMosB.nwell, CMosB.pwell => {wellRect _ geom.first.r; isNWell _ (geom.first.layer = CMosB.nwell)}; ENDCASE => ERROR SX.IllegalConstruct [geom.first.r, "Unknown transistor geometry"]; ENDLOOP ELSE ERROR SX.IllegalConstruct [errorRect, "Replace this old Chipmonk transistor"]; SELECT tClass FROM $C2Trans, $C2WellTrans => -- straight transistors BEGIN difRect, polRect, chRect, difExtRectNorth, difExtRectSouth: CD.Rect; difRect _ difList.first; polRect _ polList.first; chRect _ [difRect.x1, polRect.y1, difRect.x2, polRect.y2]; difExtRectNorth _ difExtRectSouth _ difRect; difExtRectNorth.y1 _ polRect.y2; difExtRectSouth. y2 _ polRect.y1; length _ polRect.y2 - polRect.y1; width _ difRect.x2 - difRect.x1; extL _ polRect.y1 - difRect.y1; extW _ difRect.x1 - polRect.x1; gateA _ (width + 2*extW) * length; gateP _ (width + 2*extW + length) * 2; sourceA _ drainA _ extL * width; sourceP _ drainP _ 2 * extL + width; IF (extL < extensionLength) THEN ERROR SX.IllegalConstruct [errorRect, "Extension length too small"]; gateNode _ SX.AddRect [cir: cir, lev: CMosB.pol, dim: polRect, trans: trans]; IF extL > sep THEN -- Add rectangles for poly exclusion over extensions BEGIN rect _ difExtRectNorth; rect.y1 _ difExtRectNorth.y1 + sep; rect.y2 _ difExtRectNorth.y1 + polSpacing; [] _ SX.AddBox [cir, polSpinifex, rect, trans, SXTechnology.WNEGrow [extSep], exclPol]; rect _ difExtRectSouth; rect.y2 _ difExtRectSouth.y2 - sep; rect.y1 _ difExtRectSouth.y2 - polSpacing; [] _ SX.AddBox [cir, polSpinifex, rect, trans, SXTechnology.ESWGrow [extSep], exclPol]; END; rect _ difExtRectNorth; rect.y2 _ rect.y1 + sep; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, trans: trans, value: polCnstr[pChE]]; rect _ difExtRectSouth; rect.y1 _ rect.y2 - sep; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, trans: trans, value: polCnstr[pChE]]; [] _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: chRect, trans: trans, interestBloat: [dx1: (DesignRules.MinSpace[saguaroRules, CMosB.ndif, CMosB.ndif].s/2), dy1: 0, dx2: (DesignRules.MinSpace[saguaroRules, CMosB.ndif, CMosB.ndif].s/2), dy2: 0], value: difChannel]; sourceNode _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: difExtRectNorth, trans: trans, interestBloat: SXTechnology.WNEGrow[(DesignRules.MinSpace[saguaroRules, CMosB.ndif, CMosB.ndif].s/2)]]; drainNode _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: difExtRectSouth, trans: trans, interestBloat: SXTechnology.ESWGrow[(DesignRules.MinSpace[saguaroRules, CMosB.ndif, CMosB.ndif].s/2)]]; IF tClass = $C2WellTrans THEN BEGIN l: CD.Layer = IF isNWell THEN CMosB.nwell ELSE CMosB.pwell; IF NOT CDBasics.NonEmpty[wellRect] THEN ERROR SX.IllegalConstruct [errorRect, "Well transistor must have a well"]; wellNode _ SX.AddRect [cir: cir, lev: l, dim: wellRect, trans: trans]; wellNode.properties _ Properties.PutProp [propList: wellNode.properties, prop: wellNode, val: wellNode]; END; END; -- case $CTrans $C2LTrans, $C2LWellTrans => -- angle transistors BEGIN diffNE: CD.Position _ CDBasics.minposition; diffSW, polSW: CD.Position _ CDBasics.highposition; polHor, polVert: CD.Rect; IF ((polList.first.y2-polList.first.y1) < (polList.rest.first.y2-polList.rest.first.y1)) THEN {polHor _ polList.first; polVert _ polList.rest.first} ELSE {polHor _ polList.rest.first; polVert _ polList.first}; FOR diff: LIST OF CD.Rect _ difList, diff.rest WHILE diff # NIL DO IF (diff.first.x1 <= diffSW.x) AND (diff.first.y1 <= diffSW.y) THEN diffSW _ [diff.first.x1, diff.first.y1]; IF (diff.first.x2 >= diffNE.x) AND (diff.first.y2 >= diffNE.y) THEN diffNE _ [diff.first.x2, diff.first.y2]; ENDLOOP; polSW _ [polHor.x1, polHor.y1]; extW _ diffSW.x - polSW.x; extL _ polSW.y - diffSW.y; length _ polHor.y2 - polHor.y1; width _ ((polHor.x2 - polHor.x1) - extW) + ((polVert.y2 - polVert.y1) - extW) - (length*3/2); gateA _ ((width+length/2) + 2*extW) * length; gateP _ ((polHor.x2 - polHor.x1) + (polVert.y2 - polVert.y1)) * 2; sourceA _ ((diffNE.x - diffSW.x) + (diffNE.y - diffSW.y - extL)) * extL; sourceP _ 2 * extL + (diffNE.x - diffSW.x) + (diffNE.y - diffSW.y); drainP _ diffNE.x + diffNE.y - diffSW.x - diffSW.y - 2 * (extL + length); drainA _ drainP * extL; IF (extL < extensionLength) THEN ERROR SX.IllegalConstruct [errorRect, "Extension length too small"]; gateNode _ SX.AddRect [cir: cir, lev: CMosB.pol, dim: polHor, trans: trans]; [] _ SX.AddRect [cir: cir, lev: CMosB.pol, dim: polVert, trans: trans, value: gateNode]; IF extL > sep THEN BEGIN -- Add rectangles for poly exclusion over extensions d1: CD.Number _ extL + length + sep; d2: CD.Number _ extL + polSpacing; rect _ [x1: diffSW.x, y1: diffSW.y+d1, x2: diffNE.x-d1, y2: diffSW.y+length+d2]; [] _ SX.AddBox [cir, polSpinifex, rect, trans, SXTechnology.WNGrow [extSep], exclPol]; rect _ [x1: diffNE.x-length-d2, y1: diffSW.y+d1, x2: diffNE.x-d1, y2: diffNE.y]; [] _ SX.AddBox [cir, polSpinifex, rect, trans, SXTechnology.WNGrow [extSep], exclPol]; d1 _ extL - sep; d2 _ extL - polSpacing; rect _ [x1: diffSW.x, y1: diffSW.y+d2, x2: diffNE.x-d2, y2: diffSW.y+d1]; [] _ SX.AddBox [cir, polSpinifex, rect, trans, SXTechnology.ESWGrow [extSep], exclPol]; rect _ [x1: diffNE.x-d1, y1: diffSW.y, x2: diffNE.x-d2, y2: diffNE.y]; [] _ SX.AddBox [cir, polSpinifex, rect, trans, SXTechnology.NESGrow [extSep], exclPol] END; -- poly excl BEGIN d: CD.Number _ extL + length + sep; rect _ [x1: diffSW.x, y1: diffSW.y+extL+length, x2: diffNE.x-extL-length, y2: diffSW.y+d]; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, trans: trans, value: polCnstr[pChE]]; -- North rect _ [x1: diffNE.x-d, y1: diffSW.y+extL+length, x2: diffNE.x-extL-length, y2: diffNE.y]; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, trans: trans, value: polCnstr[pChE]]; -- West d _ extL - sep; rect _ [x1: diffSW.x, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffSW.y+extL]; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, trans: trans, value: polCnstr[pChE]]; -- South rect _ [x1: diffNE.x-extL, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffNE.y]; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, trans: trans, value: polCnstr[pChE]] -- East END; -- ch lead-in rect _ polHor; rect.x1 _ rect.x1 + extW; [] _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: rect, trans: trans, interestBloat: [dx1: (DesignRules.MinSpace[saguaroRules, CMosB.ndif, CMosB.ndif].s/2), dy1: 0, dx2: 0, dy2: 0], value: difChannel]; rect _ polVert; rect.y2 _ rect.y2 - extW; [] _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: rect, trans: trans, interestBloat: [dx1: 0, dy1: 0, dx2: 0, dy2: (DesignRules.MinSpace[saguaroRules, CMosB.ndif, CMosB.ndif].s/2)], value: difChannel]; rect _ [x1: diffSW.x, y1: diffSW.y+extL+length, x2: diffNE.x-extL-length, y2: diffSW.y+2*extL+length]; sourceNode _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: rect, trans: trans, interestBloat: SXTechnology.WNGrow[(DesignRules.MinSpace[saguaroRules, CMosB.ndif, CMosB.ndif].s/2)]]; IF difList.rest # NIL THEN -- supposed source is concave BEGIN rect _ [x1: diffNE.x-length-2*extL, y1: rect.y1, x2: rect.x2, y2: diffNE.y]; [] _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: rect, trans: trans, interestBloat: SXTechnology.WNGrow[(DesignRules.MinSpace[saguaroRules, CMosB.ndif, CMosB.ndif].s/2)], value: sourceNode] END; rect _ [x1: diffSW.x, y1: diffSW.y, x2: diffNE.x, y2: diffSW.x+extL]; drainNode _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: rect, trans: trans, interestBloat: SXTechnology.ESWGrow[(DesignRules.MinSpace[saguaroRules, CMosB.ndif, CMosB.ndif].s/2)]]; rect _ [x1: diffNE.x-extL, y1: rect.y2, x2: diffNE.x, y2: diffNE.y]; [] _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: rect, trans: trans, interestBloat: SXTechnology.NESGrow[(DesignRules.MinSpace[saguaroRules, CMosB.ndif, CMosB.ndif].s/2)], value: drainNode]; IF tClass = $C2LWellTrans THEN BEGIN l: CD.Layer = IF isNWell THEN CMosB.nwell ELSE CMosB.pwell; IF NOT CDBasics.NonEmpty[wellRect] THEN ERROR SX.IllegalConstruct [errorRect, "Well transistor must have a well"]; wellNode _ SX.AddRect [cir: cir, lev: l, dim: wellRect, trans: trans]; wellNode.properties _ Properties.PutProp [propList: wellNode.properties, prop: wellNode, val: wellNode]; END; END; -- case $C2LTrans, $C2LWellTrans $CLWellTrans => ERROR SX.IllegalConstruct [errorRect, "Antique transistor class $CLWellTrans is illegal"]; ENDCASE => ERROR SX.IllegalConstruct [errorRect, "Unknown or antique transistor class"]; transistor _ SX.CreateLinkage [cir, NEW[CD.InstanceRep_[ob: ob]], length, width]; SX.AdjustNode [node: gateNode, layer: polSpinifex, area: gateA, perim: gateP, mode: absolute]; SX.AdjustNode [sourceNode, difSXLayer, sourceA, sourceP, absolute]; SX.AdjustNode [drainNode, difSXLayer, drainA, drainP, absolute]; SX.LinkageAttach [link: transistor, attachType: $Gate, node: gateNode]; SX.LinkageAttach [link: transistor, attachType: $Source, node: sourceNode]; SX.LinkageAttach [link: transistor, attachType: $Drain, node: drainNode] END; -- ConvTransistor RoseTransistor: PUBLIC SXOutput.LinkagePrintProc ~ { PrintAttachment: PROCEDURE [key: ATOM, portName: Rope.ROPE] ~ { cellStream.Put [IO.rope[" (\""], IO.rope[portName], IO.rope["\" "]]; FOR attachments: LIST OF REF SX.AttachedNode _ linkage.nodes, attachments.rest WHILE attachments # NIL DO IF attachments.first.attachmentType = key THEN { PrintNode[cellStream, attachments.first.node]; cellStream.PutRope[")"]; RETURN } ENDLOOP; cellStream.PutRope ["\"?\")"]; }; -- PrintAttachment naming: SXOutputPrivate.Naming _ SXOutputPrivate.GetANaming [linkage.source]; cellStream.PutRope["(CI "]; SXOutputPrivate.PrintNaming[ cellStream, naming, Rope.Cat[" \"", SXOutputPrivate.NameTransType[ desWDir: desWDir, obj: linkage.source.ob, dfStream: dfStream, type: SELECT linkage.source.ob.layer FROM CMosB.ndif, CMosB.wndif => $n, CMosB.pdif, CMosB.wpdif => $p, ENDCASE => $funny, mode: $E, length: linkage.l, width: linkage.w], "\""] ]; SXOutputPrivate.PrintRoseInstantiationTransformation[cellStream, linkage.source]; cellStream.PutRope [" (CIC"]; PrintAttachment [$Gate, "gate"]; PrintAttachment [$Source, "ch1"]; PrintAttachment [$Drain, "ch2"]; cellStream.PutRope ["))"] }; -- RoseTransistor ThymeTransistor: PUBLIC SXOutput.LinkagePrintProc ~ { PrintAttachment: PROCEDURE [key: ATOM] ~ { FOR attachments: LIST OF REF SX.AttachedNode _ linkage.nodes, attachments.rest WHILE attachments # NIL DO IF attachments.first.attachmentType = key THEN { PrintNode[cellStream, attachments.first.node]; RETURN } ENDLOOP; cellStream.Put [IO.char['?]]; }; -- PrintAttachment defaultL: INTEGER = 2*l; propertyValue: REF; cellStream.Put [IO.rope[name], IO.rope[": "]]; cellStream.PutRope [SELECT linkage.source.ob.layer FROM CMosB.ndif, CMosB.wndif => "ETran[", CMosB.pdif, CMosB.wpdif => "CTran[", ENDCASE => "FunnyTran[" ]; PrintAttachment [$Gate]; cellStream.Put [IO.char[',]]; PrintAttachment [$Source]; cellStream.Put [IO.char[',]]; PrintAttachment [$Drain]; cellStream.Put [IO.char['|]]; cellStream.PutF[" W_N*%g", IO.int[linkage.w/l]]; IF linkage.l # defaultL THEN cellStream.PutF[", L_%g", IO.int[linkage.l/l]]; propertyValue _ CDProperties.GetInstanceProp [from: linkage.source, prop: SXAtoms.crystalAttr]; WITH propertyValue SELECT FROM crystalHack: Rope.ROPE => IO.Put [stream: cellStream, v1: IO.rope["; "], v2: IO.rope[crystalHack]]; ENDCASE => IF propertyValue # NIL THEN TerminalIO.PutRope [" $Crystal property must be a rope./n"]; cellStream.PutRope ["];"] }; -- ThymeTransistor wellConnection: ATOM ~ $SXCMosBWellConnection; wellNode: ATOM ~ $SXCMosBNWellNode; maxContSize: CD.Number ~ 5 * l; splitContWidth: CD.Number ~ 2 * l; splitContHeight: CD.Number ~ 6 * l; ConvertPDifRect: PUBLIC SX.ConversionProc = BEGIN wellNode: REF SX.CircuitNode; nWellBox: CD.Rect _ ob.bbox; pDifBox: CD.Rect _ CDBasics.Extend[nWellBox, -CMosB.wellSurround]; IF ~CDBasics.NonEmpty[pDifBox] THEN BEGIN TerminalIO.PutRope [" this cell contains a w-pDif object whose pDif rectangle is empty\n"]; ERROR END; [] _ cir.AddRect [lev~CMosB.pdif, dim~pDifBox, trans~trans]; wellNode _ cir.AddRect [lev~CMosB.nwell, dim~nWellBox, trans~trans]; wellNode.properties _ Properties.PutProp [wellNode.properties, wellNode, wellNode]; END; -- ConvertPDifRect ConvertContact: PUBLIC SX.ConversionProc = BEGIN Size: PROC [r: CD.Rect] RETURNS [s: CD.Position] ~ INLINE BEGIN s.x _ (r.x2 - r.x1); s.y _ (r.y2 - r.y1) END; -- Size classKey: ATOM = ob.class.objectType; r: CD.Rect = CD.InterestRect [ob]; node: REF SX.CircuitNode _ NIL; size: CD.Position; sizeExceeded: BOOL _ FALSE; SELECT classKey FROM $C2SimpleCon, $C2WellSimpleCon, $C2LargeSimpleCon, $C2LargeWellSimpleCon, $C2DiffShortCon, $C2DifShortCon, $C2WellDifShortCon, $C2Via, $C2LargeVia => FOR geom: CDAtomicObjects.DrawList _ NARROW [ob.specific, CDAtomicObjects.AtomicObsSpecific].rList, geom.rest WHILE geom # NIL DO SELECT geom.first.layer FROM CMosB.ndif, CMosB.pdif => { node _ SX.AddRect[cir: cir, lev: geom.first.layer, dim: geom.first.r, trans: trans, value: node]; [] _ SX.AddBox[cir: cir, spinifexLayer: polSpinifex, dim: geom.first.r, trans: trans, value: polCnstr[(IF geom.first.layer = CMosB.ndif THEN pExNdCon ELSE pExPdCon)]]; }; CMosB.nwell, CMosB.pwell => { bridge: REF SX.CircuitNode _ IF (classKey=$C2WellDifShortCon) THEN node ELSE NIL; wellNode: REF SX.CircuitNode _ SX.AddRect [cir: cir, lev: geom.first.layer, dim: geom.first.r, trans: trans, value: bridge]; wellNode.properties _ Properties.PutProp [wellNode.properties, wellNode, wellNode]; }; CMosB.nwellCont, CMosB.pwellCont => { node _ SX.AddRect[cir: cir, lev: geom.first.layer, dim: geom.first.r, trans: trans, value: node]; [] _ SX.AddBox[cir: cir, spinifexLayer: polSpinifex, dim: geom.first.r, trans: trans, value: polCnstr[(IF geom.first.layer = CMosB.nwellCont THEN pExNdCon ELSE pExPdCon)]]; }; CMosB.met, CMosB.met2, CMosB.pol => node _ SX.AddRect[cir: cir, lev: geom.first.layer, dim: geom.first.r, trans: trans, value: node]; CMosB.cut => { -- all but vias [] _ SX.AddBox[cir: cir, spinifexLayer: metSpinifex, dim: geom.first.r, trans: trans, value: metCnstr[mCut]]; size _ Size [geom.first.r]; SELECT classKey FROM $C2DifShortCon, $C2WellDifShortCon, $C2DiffShortCon => sizeExceeded _ sizeExceeded OR ((MIN[size.x, size.y]#splitContWidth) OR (MAX[size.x, size.y]#splitContHeight)); ENDCASE => sizeExceeded _ sizeExceeded OR (size.x>maxContSize OR size.y>maxContSize)}; CMosB.cut2 => { -- vias [] _ SX.AddBox[cir: cir, spinifexLayer: metSpinifex, dim: geom.first.r, trans: trans, value: metCnstr[mVia]]; size _ Size [geom.first.r]; sizeExceeded _ sizeExceeded OR (size.x>maxContSize OR size.y>maxContSize)}; ENDCASE => ERROR SX.IllegalConstruct [geom.first.r, "Unknown simple contact geometry"]; ENDLOOP ENDCASE => SX.IllegalConstruct [r, "Unknown CMos-B contact type"]; IF sizeExceeded THEN SX.IllegalConstruct [r, "Maximum contact size exceeded"] END; -- ConvertContact PointRect: PROC [p: CD.Position] RETURNS [r: CD.Rect] = BEGIN r _ CDBasics.Extend [CDBasics.ToRect[p, p], l] END; -- PointRect CopyWellConnections: PUBLIC SX.CombineNodePropertyProc ~ BEGIN fromConnections: Nodes _ NARROW [Properties.GetProp [propList: from, prop: wellConnection]]; toConnections: Nodes _ NARROW [Properties.GetProp [propList: to, prop: wellConnection]]; FOR fl: Nodes _ fromConnections, fl.rest WHILE fl # NIL DO fromNode: REF SX.CircuitNode; IF fromNesting = NIL THEN fromNode _ fl.first ELSE -- Side effect !!! May add fl.first to subcircuits ports. fromNode _ SX.FindRootNode [circuit: circuit, subcircuitNode: fl.first, qualifier: fromNesting, insertIfNotInCircuit: TRUE].node; FOR tl: Nodes _ toConnections, tl.rest WHILE tl # NIL DO IF SX.LookupNode [l: fromNode] = SX.LookupNode [l: tl.first] THEN EXIT; REPEAT FINISHED => toConnections _ CONS [fromNode, toConnections] ENDLOOP ENDLOOP; IF toConnections # NIL THEN to _ Properties.PutProp [propList: to, prop: wellConnection, val: toConnections]; IF (Properties.GetProp [propList: from, prop: wellNode] # NIL) AND (Properties.GetProp [propList: to, prop: wellNode] = NIL) THEN to _ Properties.PutProp [propList: to, prop: wellNode, val: wellNode]; RETURN [to] END; -- CopyWellConnections CheckWellConnections: PUBLIC SX.CellPostProcessProc = BEGIN isRoot: BOOL _ (cell.rootOnInvocation = SXAccess.invocation); hasNode, hasConnection, hasRoot: BOOL; wellConnects: Nodes; FOR scl: CD.InstanceList _ cell.circuit.subcircuits, scl.rest WHILE scl # NIL DO subcir: REF SX.Circuit ~ SXTechnology.GetCircuitFromCDObject [cdOb: scl.first.ob]; FOR nl: Nodes _ subcir.nodes, nl.rest WHILE nl # NIL DO hasNode _ (Properties.GetProp [propList: nl.first.properties, prop: wellNode] # NIL); hasConnection _ (Properties.GetProp [propList: nl.first.properties, prop: wellConnection] # NIL); IF hasNode AND ~ hasConnection THEN { hasRoot _ (SX.FindRootNode [circuit: cell.circuit, subcircuitNode: nl.first, qualifier: LIST[scl.first]].rootQualifier # NIL); IF hasRoot THEN { eLoc: CD.Position = CDBasics.MapPoint [pointInCell: nl.first.loc.xy, cellInWorld: scl.first.trans]; SXAccessInternal.PutError [ob: cell.cellObj, r: PointRect[eLoc], message: "floating n-well in subcell"]; } } -- if has unconnected node ENDLOOP -- for all nodes ENDLOOP; -- for all cells FOR nl: Nodes _ cell.circuit.nodes, nl.rest WHILE nl # NIL DO hasNode _ (Properties.GetProp[propList: nl.first.properties, prop: wellNode] # NIL); IF hasNode THEN { wellConnects _ NARROW [Properties.GetProp [propList: nl.first.properties, prop: wellConnection]]; FOR wl: Nodes _ wellConnects, wl.rest WHILE wl # NIL DO wl.first _ SX.LookupNode [l: wl.first]; FOR restOfWl: Nodes _ wl, restOfWl.rest WHILE restOfWl.rest # NIL DO IF wl.first = SX.LookupNode [l: restOfWl.rest.first] THEN restOfWl.rest _ restOfWl.rest.rest -- Drop this list element. ENDLOOP ENDLOOP; -- clean up IF (wellConnects = NIL AND isRoot) THEN { eLoc: CD.Position = nl.first.loc.xy; SXAccessInternal.PutError [ob: cell.cellObj, r: PointRect[eLoc], message: "floating n-well in root cell of analysis"]; } ELSE IF wellConnects # NIL AND wellConnects.rest # NIL THEN { eLoc: CD.Position = nl.first.loc.xy; SXAccessInternal.PutError [ob: cell.cellObj, r: PointRect[eLoc], message: "n-well connected to multiple nodes"]; FOR wc: Nodes _ wellConnects, wc.rest WHILE wc # NIL DO eLoc: CD.Position = wc.first.loc.xy; SXAccessInternal.PutError [ob: cell.cellObj, r: PointRect[eLoc], message: IO.PutFR ["node on %g connects to multiply connected n-Well", IO.atom[SXAccess.sxTech.spinifexLayerNames[wc.first.loc.layer].layerId]]]; ENDLOOP; } } -- has nWell node ENDLOOP -- for all nodes END; -- CheckWellConnections AttachNWellContact: PUBLIC SX.BoxMapProc = BEGIN wellCon: REF SX.CircuitNode _ SX.AddBox [cir: cir, spinifexLayer: wellSpinifex, dim: dim, trans: trans, interestBloat: [l, l, l, l]]; IF node = NIL THEN ERROR; wellCon.properties _ Properties.PutProp [propList: wellCon.properties, prop: wellConnection, val: NARROW[LIST[node], Nodes]] END; -- AttachNWellContact Init: PROCEDURE ~ { cMosHandle: REF SX.TechHandle; ndifResolution: REF SX.ConstraintResolution; pdifResolution: REF SX.ConstraintResolution; polyResolution: REF SX.ConstraintResolution; metalResolution: REF SX.ConstraintResolution; ndCnstr[ndCh] _ NEW [Constraint _ [$NDifChannel, ndCh, TRUE, polSpinifex]]; ndCnstr[ndInWel] _ NEW [Constraint _ [$NDifInWellError, ndInWel]]; ndCnstr[ndWel] _ NEW [Constraint _ [$ExcludeNDifByWell, ndWel]]; ndCnstr[ndCnt] _ NEW [Constraint _ [$ContactNDif, ndCnt, TRUE, ndifSpinifex]]; ndCnstr[ndPWct] _ NEW [Constraint _ [$ExcludeNDifByPWellCont, ndPWct, TRUE, pdifSpinifex]]; ndCnstr[ndPdErr] _ NEW [Constraint _ [$NDifAndPDifError, ndPdErr]]; pdCnstr[pdCh] _ NEW [Constraint _ [$PDifChannel, pdCh, TRUE, pdifSpinifex]]; pdCnstr[pdNdErr] _ NEW [Constraint _ [$PDifAndNDifError, pdNdErr]]; pdCnstr[pdCnt] _ NEW [Constraint _ [$ContactPDif, pdCnt, TRUE, pdifSpinifex]]; pdCnstr[pdNWct] _ NEW [Constraint _ [$ExcludePDifByNWellCont, pdNWct, TRUE, ndifSpinifex]]; polCnstr[pExnD] _ NEW [Constraint _ [$PolExcludeByNDif, pExnD, TRUE, ndifSpinifex]]; polCnstr[pExpD] _ NEW [Constraint _ [$PolExcludeByPDif, pExpD, TRUE, pdifSpinifex]]; polCnstr[pExNdCon] _ NEW [Constraint _ [$PolExcludeByNDifContact, pExNdCon, TRUE, ndifSpinifex]]; polCnstr[pExPdCon] _ NEW [Constraint _ [$PolExcludeByPDifContact, pExPdCon, TRUE, pdifSpinifex]]; polCnstr[pChE] _ NEW [Constraint _ [$PolChannelEdge, pChE]]; polCnstr[pDxorP] _ NEW [Constraint _ [$PolXorDif, pDxorP]]; polCnstr[pDandP] _ NEW [Constraint _ [$polAndDif, pDandP, TRUE, polSpinifex]]; polCnstr[pDErr] _ NEW [Constraint _ [$PolDifError, pDErr]]; metCnstr[mCut] _ NEW [Constraint _ [$MetCut, mCut, TRUE, metSpinifex]]; metCnstr[mVia] _ NEW [Constraint _ [$MetVia, mVia, TRUE, metSpinifex]]; metCnstr[mVC] _ NEW [Constraint _ [$MetViaAndCutError, mVC, TRUE, metSpinifex]]; { nd: SX.ConstraintIndex ~ SX.nodeIndex; sp: SX.ConstraintIndex ~ SX.spaceIndex; ndifResTab: SXTechnology.ResolutionTable ~ [ [ sp, nd, ndCh, ndInWel, ndWel, ndCnt, ndPWct, ndPdErr, ,,,,,,,], [ nd, nd, ndCh, ndInWel, ndInWel, ndCnt, ndPdErr, ndPdErr, ,,,,,,,], [ ndCh, ndCh, ndCh, ndInWel, ndInWel, ndCh, ndCh, ndPdErr, ,,,,,,,], [ ndInWel, ndInWel, ndInWel, ndInWel, ndInWel, ndCnt, ndPdErr, ndPdErr, ,,,,,,,], [ ndWel, ndInWel, ndInWel, ndInWel, ndWel, ndCnt, ndPWct, ndPdErr, ,,,,,,,], [ ndCnt, ndCnt, ndCh, ndCnt, ndCnt, ndCnt, ndPdErr, ndPdErr, ,,,,,,,], [ ndPWct, ndPdErr, ndCh, ndPdErr, ndPWct, ndPdErr, ndPWct, ndPdErr, ,,,,,,,], [ ndPdErr, ndPdErr, ndPdErr, ndPdErr, ndPdErr, ndPdErr, ndPdErr, ndPdErr, ,,,,,,,], ,,,,,,, ]; pdifResTab: SXTechnology.ResolutionTable ~ [ [ sp, nd, pdCh, pdNdErr, pdCnt, pdNWct, ,,,,,,,,,], [ nd, nd, pdCh, pdNdErr, pdCnt, pdNdErr, ,,,,,,,,,], [ pdCh, pdCh, pdCh, pdNdErr, pdCh, pdCh, ,,,,,,,,,], [ pdNdErr, pdNdErr, pdNdErr, pdNdErr, pdNdErr, pdNdErr, ,,,,,,,,,], [ pdCnt, pdCnt, pdCh, pdNdErr, pdCnt, pdNdErr, ,,,,,,,,,], [ pdNWct, pdNdErr, pdCh, pdNdErr, pdNdErr, pdNWct, ,,,,,,,,,], ,,,,,,,,, ]; polyResTab: SXTechnology.ResolutionTable ~ [ [ sp, nd, pExnD, pExpD, pExNdCon, pExPdCon, pChE, pDxorP, pDandP, pDErr, ,,,,,], [ nd, nd, pDErr, pDErr, pDErr, pDErr, pDErr, nd, pDandP, pDErr, ,,,,,], [ pExnD, pDErr, pExnD, pExpD, pExNdCon, pExPdCon, pChE, pChE, pDandP, pDErr, ,,,,,], [ pExpD, pDErr, pExpD, pExpD, pExPdCon, pExPdCon, pChE, pChE, pDandP, pDErr, ,,,,,], [ pExNdCon, pDErr, pExNdCon, pExPdCon, pExNdCon, pExPdCon, pChE, pChE, pDandP, pDErr, ,,,,,], [ pExPdCon, pDErr, pExPdCon, pExPdCon, pExPdCon, pExPdCon, pChE, pChE, pDandP, pDErr, ,,,,,], [ pChE, pDErr, pChE, pChE, pChE, pChE, pChE, pChE, pDandP, pDErr, ,,,,,], [ pDxorP, nd, pChE, pChE, pChE, pChE, pChE, pDxorP, pDandP, pDErr, ,,,,,], [ pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, ,,,,,], [ pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDandP, pDErr, ,,,,,], ,,,,, ]; metalResTab: SXTechnology.ResolutionTable ~ [ [ sp, nd, mCut, mVia, mVC, ,,,,,,,,,,], [ nd, nd, mCut, mVia, mVC, ,,,,,,,,,,], [ mCut, mCut, mCut, mVC, mVC, ,,,,,,,,,,], [ mVia, mVia, mVC, mVia, mVC, ,,,,,,,,,,], [ mVC, mVC, mVC, mVC, mVC, ,,,,,,,,,,], ,,,,,,,,,, ]; ndifResolution _ SXTechnology.SetUpResolution [ndCnstr, ndifResTab]; pdifResolution _ SXTechnology.SetUpResolution [pdCnstr, pdifResTab]; polyResolution _ SXTechnology.SetUpResolution [polCnstr, polyResTab]; metalResolution _ SXTechnology.SetUpResolution [metCnstr, metalResTab]; }; cMosHandle _ NEW [SX.TechHandle _ [ numSpinifexLayers~ 6, layerInterestBloat~ [nDifLayerSep, (ndifSpacing/2), (polSpacing/2), (metSeparation/2), (met2Separation/2), (wellSep/2),,], combineNodeProperties~ CopyWellConnections, cellPostProcess~ CheckWellConnections] ]; cMosHandle.illegalLayer[CMosB.nwellCont] _ FALSE; cMosHandle.illegalLayer[CMosB.pwellCont] _ FALSE; cMosHandle.illegalLayer[CMosB.ndif] _ FALSE; cMosHandle.illegalLayer[CMosB.pdif] _ FALSE; cMosHandle.illegalLayer[CMosB.nwell] _ FALSE; cMosHandle.illegalLayer[CMosB.pol] _ FALSE; cMosHandle.illegalLayer[CMosB.met] _ FALSE; cMosHandle.illegalLayer[CMosB.met2] _ FALSE; cMosHandle.cdLayerMapping[CMosB.nwellCont] _ LIST [[ndifSpinifex, (ndifSpacing/2)], [wellSpinifex, l, NEW [SX.BoxMapProc _ AttachNWellContact]], [pdifSpinifex, (pdifSpacing/2), pdCnstr[pdNWct]], [ndifSpinifex, (ndifSpacing/2), ndCnstr[ndCnt]], [polSpinifex, difToPolExtSep, polCnstr[pExnD]]]; cMosHandle.cdLayerMapping[CMosB.pwellCont] _ LIST [[pdifSpinifex, (pdifSpacing/2)], [ndifSpinifex, (ndifSpacing/2), ndCnstr[ndPWct]], [pdifSpinifex, (pdifSpinifex/2), pdCnstr[pdCnt]], [polSpinifex, difToPolExtSep, polCnstr[pExpD]]]; cMosHandle.cdLayerMapping[CMosB.ndif] _ LIST [[ndifSpinifex, (ndifSpacing/2)], [polSpinifex, polUncDifSpacing, polCnstr[pExnD]]]; cMosHandle.cdLayerMapping[CMosB.pdif] _ LIST [[pdifSpinifex, (pdifSpacing/2)], [polSpinifex, polUncDifSpacing, polCnstr[pExpD]]]; cMosHandle.cdLayerMapping[CMosB.nwell] _ LIST [[ndifSpinifex, nDifToWell-(ndifSpacing/2), ndCnstr[ndWel]], [wellSpinifex, (wellSep/2)]]; cMosHandle.cdLayerMapping[CMosB.pol] _ LIST [[polSpinifex, (polSpacing/2)]]; cMosHandle.cdLayerMapping[CMosB.met] _ LIST [[metSpinifex, (metSeparation/2)]]; cMosHandle.cdLayerMapping[CMosB.met2] _ LIST [[m2Spinifex, (met2Separation/2)]]; BEGIN conInfl: CD.Number ~ l; -- Influence distance of contacts. cMosHandle.cdLayerMapping[CMosB.cut] _ LIST [[ndifSpinifex, conInfl, $Opaque], [pdifSpinifex, conInfl, $Opaque], [polSpinifex, conInfl, $Opaque], [metSpinifex, conInfl, $Opaque]]; cMosHandle.cdLayerMapping[CMosB.cut2] _ LIST [[metSpinifex, conInfl, $Opaque], [m2Spinifex, conInfl, $Opaque]]; cMosHandle.cdLayerMapping[CMosB.bur] _ LIST [[ndifSpinifex, (met2Separation/2), $Opaque], [polSpinifex, conInfl, $Opaque]]; END; cMosHandle.spinifexLayerNames[ndifSpinifex].layerId _ $nDiffusion; cMosHandle.spinifexLayerNames[pdifSpinifex].layerId _ $pDiffusion; cMosHandle.spinifexLayerNames[polSpinifex].layerId _ $Poly; cMosHandle.spinifexLayerNames[metSpinifex].layerId _ $Metal; cMosHandle.spinifexLayerNames[m2Spinifex].layerId _ $Metal2; cMosHandle.spinifexLayerNames[wellSpinifex].layerId _ $NWell; cMosHandle.spinifexLayerNames[ndifSpinifex].thymeName _ "nD"; cMosHandle.spinifexLayerNames[pdifSpinifex].thymeName _ "pD"; cMosHandle.spinifexLayerNames[polSpinifex].thymeName _ "P"; cMosHandle.spinifexLayerNames[metSpinifex].thymeName _ "M"; cMosHandle.spinifexLayerNames[m2Spinifex].thymeName _ "M2"; cMosHandle.constraintResolutions[ndifSpinifex] _ ndifResolution; cMosHandle.constraintResolutions[pdifSpinifex] _ pdifResolution; cMosHandle.constraintResolutions[polSpinifex] _ polyResolution; cMosHandle.constraintResolutions[metSpinifex] _ metalResolution; InitRules [cMosHandle]; SXTechnology.RegisterTechnologyHandle[cdTech~ CMosB.cmosB, technologyHandle~ cMosHandle]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2Trans, conv~ ConvTransistor, thyme~ ThymeTransistor, rose~ RoseTransistor, fini~ SXOutputPrivate.UnNameTransType]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2WellTrans, conv~ ConvTransistor, thyme~ ThymeTransistor, rose~ RoseTransistor, fini~ SXOutputPrivate.UnNameTransType]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2LTrans, conv~ ConvTransistor, thyme~ ThymeTransistor, rose~ RoseTransistor, fini~ SXOutputPrivate.UnNameTransType]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2LWellTrans, conv~ ConvTransistor, thyme~ ThymeTransistor, rose~ RoseTransistor, fini~ SXOutputPrivate.UnNameTransType]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $CLWellTrans, conv~ ConvTransistor, thyme~ ThymeTransistor, rose~ RoseTransistor, fini~ SXOutputPrivate.UnNameTransType]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2PDifRect, conv~ ConvertPDifRect]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2NDifRect, conv~ ConvertPDifRect]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2SimpleCon, conv~ ConvertContact]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2WellSimpleCon, conv~ ConvertContact]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2LargeSimpleCon, conv~ ConvertContact]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2LargeWellSimpleCon, conv~ ConvertContact]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2DifShortCon, conv~ ConvertContact]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2DiffShortCon, conv~ ConvertContact]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2WellDifShortCon, conv~ ConvertContact]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2Via, conv~ ConvertContact]; SXTechnology.RegisterSpinifexObjectProcs [cdTech~ CMosB.cmosB, objectType~ $C2LargeVia, conv~ ConvertContact]; }; Init []; TerminalIO.PutRope [IO.PutFR ["\nCMOS technology parameters loaded with values for rule set %g as specified in Saguaro.\n", IO.atom [ruleSet]]] END. JSXCMosBImpl.mesa Copyright Ó 1984, 1986, 1987 by Xerox Corporation. All rights reserved. Written by gbb, November 25, 1985 6:36:23 pm PST Last edited by: gbb October 12, 1987 4:37:02 pm PDT Last edited by: Christian Jacobi, November 7, 1986 1:51:35 pm PST CDSimpleRules USING [MinSpace, MinWidth], Basic definitions and rules (Version with rules from Saguaro) ndif summary for Dragon rules (not VTI) N f P: MinSpace [ndif, pdif] / l => 10 N f N: MinSpace [ndif, ndif] / l => 3| P f P: MinSpace [pdif, pdif] / l => 3| N f N-well: MinSpace [ndif, nwell] / l => 5 P f P-well: MinSpace [pdif, pwell] / l => 5 N f P-well-contact: MinSpace [ndif, pwellCont] / l => 3| [rule 6.3.3] P f N-well-contact: MinSpace [pdif, nwellCont] / l => 3| [rule 6.3.3] N f N-well-contact: MinSpace [ndif, nwellCont] / l => 9 P f P-well-contact: MinSpace [pdif, pwellCont] / l => 9 N-well f P-well-contact: MinSpace [nwell, pwellCont] / l => 4 [rule 6.3.9] P-well f N-well-contact: MinSpace [pwell, nwellCont] / l => 4 [rule 6.3.9] N-well-contact f P-well-contact: MinSpace [nwellCont, pwellCont] / l => 8 [rule 6.3.6] ndif layer n-Diffusion/unconnected p-substrate-contact spacing n-Diffusion in n-Well n-Diffusion and p-substrate-contact pdif layer p-Diffusion/unconnected n-Well-contact spacing p-Diffusion and n-Well-contact pol layer Poly/unconnected Diffusion spacing Diffusion/unconnected Poly spacing Poly over Diffusion met layer Cut to Cut spacing Via to Via spacing Cut to Via spacing met2 layer Some of these numbers are half of the actual minimum distances we are checking for: this constant used to be zero and was used to control the separation between transistor gates, the separation of well and substrate contacts to unrelated diffusion. Grow terms are packed and may not be negative. Therefore unmade change. Layer indices Basic definitions and rules (Version with rules from CDSimpleRules) l: CD.Number ~ CMosB.lambda; Nodes: TYPE = LIST OF REF SX.CircuitNode; ConstraintArray: TYPE ~ SX.ConstraintArray; CIndex: TYPE ~ SX.ConstraintIndex; Constraint: TYPE ~ SX.Constraint; ndif summary N f P: MinSpace [ndif, pdif] / l => 10 N f N: MinSpace [ndif, ndif] / l => 3| P f P: MinSpace [pdif, pdif] / l => 3| N f N-well: MinSpace [ndif, nwell] / l => 5 P f P-well: MinSpace [pdif, pwell] / l => 5 N f P-well-contact: MinSpace [ndif, pwellCont] / l => 3| [rule 6.3.3] P f N-well-contact: MinSpace [pdif, nwellCont] / l => 3| [rule 6.3.3] N f N-well-contact: MinSpace [ndif, nwellCont] / l => 9 P f P-well-contact: MinSpace [pdif, pwellCont] / l => 9 N-well f P-well-contact: MinSpace [nwell, pwellCont] / l => 4 [rule 6.3.9] P-well f N-well-contact: MinSpace [pwell, nwellCont] / l => 4 [rule 6.3.9] N-well-contact f P-well-contact: MinSpace [nwellCont, pwellCont] / l => 8 [rule 6.3.6] ndif layer ndifSpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.ndif, CMosB.ndif]; -- (3| l) ndifWidth: CD.Number = CDSimpleRules.MinWidth [CMosB.cmosB.key, CMosB.ndif]; ndifUncSubtrContSpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.ndif, CMosB.pwellCont]; n-Diffusion/unconnected p-substrate-contact spacing (3| l) ndifInnWell: CD.Number = 0 * l; n-Diffusion in n-Well (0 l) ndifpSubstrCont: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.ndif, CMosB.pwellCont]; n-Diffusion and p-substrate-contact (3| l) pdif layer pdifSpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.pdif, CMosB.pdif]; -- (3| l) pdifWidth: CD.Number = CDSimpleRules.MinWidth [CMosB.cmosB.key, CMosB.pdif]; pdifUncnWellSpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.pdif, CMosB.nwellCont]; p-Diffusion/unconnected n-Well-contact spacing (3| l) pdifnWellCont: CD.Number = 0 * l; p-Diffusion and n-Well-contact pol layer polSpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.pol, CMosB.pol]; polWidth: CD.Number = CDSimpleRules.MinWidth [CMosB.cmosB.key, CMosB.pol]; polUncDifSpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.pol, CMosB.ndif]; Poly/unconnected Diffusion spacing (1 l) polDiffUncPolySpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.ndif, CMosB.pol]; Diffusion/unconnected Poly spacing (1 l) polOverDiff: CD.Number = 0 * l; Poly over Diffusion met layer metSeparation: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.met, CMosB.met]; metWidth: CD.Number = CDSimpleRules.MinWidth [CMosB.cmosB.key, CMosB.met]; metCutCutSpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.cut, CMosB.cut]; Cut to Cut spacing (3 l) metViaViaSpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.cut2, CMosB.cut2]; Via to Via spacing (4 l) metCutViaSpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.cut, CMosB.cut2]; Cut to Via spacing (2 l) met2 layer met2Separation: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.met2, CMosB.met2]; met2Width: CD.Number = CDSimpleRules.MinWidth [CMosB.cmosB.key, CMosB.met2]; Some of these numbers are half of the actual minimum distances we are checking for: difSep: CD.Number = ndifSpacing / 2; -- (3| l / 2) wellSep: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.nwell, CMosB.nwell]; -- (10 l) wellWidth: CD.Number = CDSimpleRules.MinWidth [CMosB.cmosB.key, CMosB.nwell]; -- (12 l) nDifToWell: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.ndif, CMosB.nwell]; -- (5 l) pDifToWell: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.pdif, CMosB.pwell]; -- (5 l) nDifTopDif: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.ndif, CMosB.pdif]; -- (10 l) pdifUncSubtrContSpacing: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.pdif, CMosB.nwellCont]; -- (3| l) nDifToSubtrCont: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.ndif, CMosB.nwellCont]; -- (9 l) pDifToSubtrCont: CD.Number = CDSimpleRules.MinSpace [CMosB.cmosB.key, CMosB.pdif, CMosB.pwellCont]; -- (9 l) nDifLayerSep: CD.Number = MAX [difSep, nDifToWell - difSep]; extensionLength: CD.Number = 3 * l; -- source/drain extension [rule 6.3.18] difToPolExtSep: CD.Number = 0; -- polSpacing - extensionLength; this constant used to be zero and was used to control the separation between transistor gates, the separation of well and substrate contacts to unrelated diffusion. Grow terms are packed and may not be negative. Therefore unmade change. Layer indices ndifSpinifex: SX.SpinifexLayerIndex ~ SX.SpinifexLayerIndex.FIRST; pdifSpinifex: SX.SpinifexLayerIndex ~ ndifSpinifex.SUCC; polSpinifex: SX.SpinifexLayerIndex ~ pdifSpinifex.SUCC; metSpinifex: SX.SpinifexLayerIndex ~ polSpinifex.SUCC; m2Spinifex: SX.SpinifexLayerIndex ~ metSpinifex.SUCC; wellSpinifex: SX.SpinifexLayerIndex ~ m2Spinifex.SUCC; Constraints n-Diffusion constraints. ndBur: CIndex ~ ndCh.SUCC; -- Buried window here. ndInWel: CIndex ~ ndBur.SUCC; -- n-Diffusion in n-Well p-Diffusion constraints Poly constraints pDExcl: CIndex ~ pChE.SUCC; -- No n-Diffusion permitted here due to buried contact. pBur: CIndex ~ pDExcl.SUCC; -- Buried window here. pBurErr: CIndex ~ pBur.SUCC; -- Buried Error, diffusion emerges from wrong side. Metal constraints Rule Initialisation Geometric rule triggers. Corners are defined by union of dif and gate nDifWidRuleTrig[ndCh] _ FALSE; Corners are defined by union of dif and gate Metal Purely local errors are not handled in a natural manner by my scheme, so for every corner we find in polCnstr[pDErr] we generate an error if there is anything on any layer nearby, of course there is always something so we get our error. The geometric rules. We set violateIndex = FALSE, ALL else TRUE so that corner checks face inward, which should result in more logically pleasing error reports. The above two rules are no longer applied to channels. Transistors [r: CD.Rect, l: CD.Layer, data: REF ANY] RETURNS [TransistorMaterial] New transistor conversion procedure for ChipNDale 2.1 PROCEDURE [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF Circuit] Determine diffusion layer and channel constraint Get the geometry. Streching information has already been procesed by ChipNDale. Process the geometry according to the transistor class. The ChipNDale transistors are fully supported for p substrate. Process poly layer Process channel lead-in Fill channel gap. NOTE: The DRC of channels is affected by the change made to CMosSpinifexInitImpl on April 2, 1985. Add rectangles for diff width spacing and connection Process well. Process poly layer North: West: South: East: Process channel lead-in Fill channel gap. NOTE: The DRC of channels is affected by the change made to CMosSpinifexInitImpl on April 2, 1985. Add rectangles for diff width spacing and connection Process well. Adjust area and perimeter values [desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc] [desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc] defaultW: INTEGER = 4*lambda; 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. Contacts [appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit] [appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit] [circuit: REF Circuit, to, from: Properties.PropList, fromNesting: LIST OF CD.Instance] RETURNS [Properties.PropList] PROC [cell: REF SX.LogicalCell] Process Subcells. Potential floating well in subcircuit, is it merged to some node in this cell? The well node of the subcircuit is not merged into this circuit, so it may be floating => VIOLATION Process the cell. In context of this cell floating n-well is only an error if this is a root cell for this particular invocation of Spinifex. Clean up list of well connections to eliminate REFs to superceded nodes. n-well unconnect in root cell => VIOLATION n-well connect multiple times => VIOLATION PROC [cir: REF Circuit, dim: CD.Rect, appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, node: REF CircuitNode] RETURNS [cirNode: REF CircuitNode _ NIL] Initialisation Construction of the Layer Constraints. Constraint: PUBLIC TYPE ~ RECORD [ name: ATOM, index: ConstraintIndex, -- index into the constraint array hasCorrespondingNode: BOOLEAN _ FALSE, -- used where connectivity affects the rule and there is a corresponding layer which has the node associated with this region. correspondingNodeLayer: SpinifexLayerIndex _ SpinifexLayerIndex.FIRST -- way to attach node values to constraints by looking at other layers. ]; ndCnstr[ndBur] _ NEW [Constraint _ [$BuriedNDifPol, ndBur]]; polCnstr[pBur] _ NEW [Constraint _ [$PolBuried, pBur]]; polCnstr[pDExcl] _ NEW [Constraint _ [$PolExcludeNDif, pDExcl]]; polCnstr[pBurErr] _ NEW [Constraint _ [$PolBuriedNDifError, pBurErr]]; metCnstr[mVC] _ NEW [Constraint _ [$MetViaAndCutError, mVC]]; Constraint priority: sp < ndBur < nd < ndCnt < ndCh < ndWel < ndInWel < ndPWct < ndPdErr. ndifResTab: SXTechnology.ResolutionTable ~ [ Constraint priority: sp < ndBur < nd < ndCnt < ndCh < ndWel < ndInWel < ndPWct < ndPdErr. [ sp, nd, ndCh, ndBur, ndInWel, ndWel, ndCnt, ndPWct, ndPdErr, ,,,,,,], [ nd, nd, ndCh, nd, ndInWel, ndInWel, ndCnt, ndPdErr, ndPdErr, ,,,,,,], [ ndCh, ndCh, ndCh, ndCh, ndInWel, ndInWel, ndCh, ndPdErr, ndPdErr, ,,,,,,], [ ndBur, nd, ndCh, ndBur, ndInWel, ndWel, ndCnt, ndPWct, ndPdErr, ,,,,,,], [ ndInWel, ndInWel, ndInWel, ndInWel, ndInWel, ndInWel, ndCnt, ndPdErr, ndPdErr, ,,,,,,], [ ndWel, ndInWel, ndInWel, ndWel, ndInWel, ndWel, ndCnt, ndPWct, ndPdErr, ,,,,,,], [ ndCnt, ndCnt, ndCh, ndCnt, ndCnt, ndCnt, ndCnt, ndPdErr, ndPdErr, ,,,,,,], [ ndPWct, ndPdErr, ndPdErr, ndPWct, ndPdErr, ndPWct, ndPdErr, ndPWct, ndPdErr, ,,,,,,], [ ndPdErr, ndPdErr, ndPdErr, ndPdErr, ndPdErr, ndPdErr, ndPdErr, ndPdErr, ndPdErr, ,,,,,,], ,,,,,, ]; Constraint priority: sp < nd < pdCnt < pdCh < pdNWct < pdNdErr Constraint priority: sp < pDxorP < pExnD < pExpD < pChE < pExNdCon < pExPdCon < pDExcl < pBur < nd < pBurErr < pDErr < pDandP polyResTab: SXTechnology.ResolutionTable ~ [ Constraint priority: sp < pDxorP < pExnD < pExpD < pChE < pExNdCon < pExPdCon < pDExcl < pBur < nd < pBurErr < pDErr < pDandP [ sp, nd, pExnD, pExpD, pExNdCon, pExPdCon, pChE, pDxorP, pDandP, pDErr, ,,,,,], [ nd, nd, pDErr, pDErr, pDErr, pDErr, pDErr, nd, pDandP, pDErr, ,,,,,], [ pExnD, pDErr, pExnD, pExpD, pExNdCon, pExPdCon, pChE, pChE, pDandP, pDErr, ,,,,,], [ pExpD, pDErr, pExpD, pExpD, pExPdCon, pExPdCon, pChE, pChE, pDandP, pDErr, ,,,,,], [ pExNdCon, pDErr, pExNdCon, pExPdCon, pExNdCon, pExPdCon, pExNdCon, pChE, pDandP, pDErr, ,,,,,], [ pExPdCon, pDErr, pExPdCon, pExPdCon, pExPdCon, pExPdCon, pExPdCon, pChE, pDandP, pDErr, ,,,,,], [ pChE, pDErr, pChE, pChE, pExNdCon, pExPdCon, pChE, pChE, pDandP, pDErr, ,,,,,], [ pDxorP, nd, pChE, pChE, pChE, pChE, pChE, pDxorP, pDandP, pDErr, ,,,,,], [ pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, ,,,,,], [ pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDandP, pDErr, ,,,,,], ,,,,, ]; polyResTab: SXTechnology.ResolutionTable ~ [ Constraint priority: sp < pDxorP < pExnD < pExpD < pChE < pExNdCon < pExPdCon < pDExcl < pBur < nd < pBurErr < pDErr < pDandP [ sp, nd, pExnD, pExpD, pExNdCon, pExPdCon, pChE, pDExcl, pBur, pBurErr, pDxorP, pDandP, pDErr, ,,], [ nd, nd, pDErr, pDErr, pDErr, pDErr, pDErr, nd, nd, pDErr, nd, pDandP, pDErr, ,,], [ pExnD, pDErr, pExnD, pExpD, pExNdCon, pExPdCon, pChE, pBurErr, pBur, pBurErr, pChE, pDandP, pDErr, ,,], [ pExpD, pDErr, pExpD, pExpD, pExPdCon, pExPdCon, pChE, pBurErr, pBur, pBurErr, pChE, pDandP, pDErr, ,,], [ pExNdCon, pDErr, pExNdCon, pExPdCon, pExNdCon, pExPdCon, pExNdCon, pBurErr, pBur, pBurErr, pChE, pDandP, pDErr, ,,], [ pExPdCon, pDErr, pExPdCon, pExPdCon, pExPdCon, pExPdCon, pExPdCon, pBurErr, pBur, pBurErr, pChE, pDandP, pDErr, ,,], [ pChE, pDErr, pChE, pChE, pExNdCon, pExPdCon, pChE, pBurErr, pBur, pBurErr, pChE, pDandP, pDErr, ,,], [ pDExcl, nd, pBurErr, pBurErr, pBurErr, pBurErr, pBurErr, pDExcl, pBur, pBurErr, pDExcl, pDandP, pDErr, ,,], [ pBur, nd, pBur, pBur, pBur, pBur, pBur, pBur, pBur, pBur, pBur, pDandP, pDErr, ,,], [ pBurErr, pDErr, pBurErr, pBurErr, pBurErr, pBurErr, pBurErr, pBurErr, pBur, pBurErr, pBurErr, pDandP, pDErr, ,,], [ pDxorP, nd, pChE, pChE, pChE, pChE, pChE, pDExcl, pBur, pBurErr, pDxorP, pDandP, pDErr, ,,], [ pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, ,,], [ pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDErr, pDandP, pDErr, ,,], ,, ]; Constraint priority: sp < nd < mCut < mVia < mVC Basic cMosHandle & cdLayerMappings. cMosHandle _ NEW[SX.TechHandle _ [ numSpinifexLayers~ 6, layerInterestBloat~ [nDifLayerSep, (ndifSpacing/2), (polSpacing/2), (metSeparation/2), (met2Separation/2), l,,], combineNodeProperties~ CopyWellConnections, cellPostProcess~ CheckWellConnections] ]; Order Important for well plugging, node is created in first mapping, and used in second. cMosHandle.cdLayerMapping[CMosB.nwell] _ LIST [[ndifSpinifex, nDifToWell-(ndifSpacing/2), ndCnstr[ndWel]], [wellSpinifex, l]]; -- INTERIM Translations for Opaque Cells. Using value $Opaque ensures we get an error if these are ever used as normal cdLayerMappings. Spinifex Layer Identification. Thyme stray capacitance layer names. Set Constraint Resolutions for each layer into the TechHandle. The geometric rules. Technology handle is attached to the ChipNDale technology. Technology specific objects. Main gbb January 14, 1986 2:56:00 pm PST Fixed some rules. gbb February 10, 1986 1:17:39 pm PST Fixed bug in the verification of cuts. gbb March 11, 1986 1:33:49 pm PST The contact class C2WellDifShortCon was only partially implemented changes to: ConvertContact: added as a valid contact, Init: added registration gbb March 15, 1986 1:03:26 pm PST Tracked change in design rules changes to: metCutViaSpacing: changed from 3l to 2l. gbb March 17, 1986 6:50:46 pm PST Made better use of CDSimpleRules. changes to: ndifSpacing, ndifUncSubtrContSpacing, ndifInnWell, ndifpSubstrCont, pdifUncnWellSpacing, pdifnWellCont, polUncDifSpacing, polDiffUncPolySpacing, polOverDiff, metCutCutSpacing, metViaViaSpacing, metCutViaSpacing, difSep, nDifToWell. gbb March 19, 1986 11:29:42 am PST Improved rules for diffusion changes to: ndifSpacing, ndifUncSubtrContSpacing, ndifpSubstrCont, pdifSpacing, pdifUncnWellSpacing, difSep, nDifToWell, pDifToWell, nDifTopDif, pdifUncSubtrContSpacing, nDifToSubtrCont, pDifToSubtrCont, ndifSpinifex, InitRules gbb June 2, 1986 2:24:48 pm PDT Bug fix in split contacts. changes to: ConvertContact: the well of split contacts no longer is a separate node. gbb June 10, 1986 6:41:58 pm PDT Tracked change of atom for p angle transistors and added a case for old classes changes to: ConvTransistor: fixed atoms and made new case for old classes, Init: registers with ChipNDale both the new and some old classes in oreder to provide clearer error messages. gbb October 13, 1986 6:20:26 pm PDT Tried to fix the separation between gates and between well and substrate contacts to unrelated diffusion. changes to: extensionLength: new, difToPolExtSep: used to be 0 gbb October 23, 1986 1:01:40 pm PDT Changed the way constraints are computed in order to allow local exceptions to rules. changes to: ConvTransistor gbb October 24, 1986 11:38:05 am PDT Allowed well/substrate contacts to be closer to diffusion than the rules requires, if it is across a gate. changes to: Init: constraint resolution ndPWct + ndCh = ndCh (was ndPdErr). Idem for p-diff gbb May 14, 1987 12:23:57 pm PDT Tracked new contact class $C2DiffShortCon. changes to: ConvertContact, Init gbb October 5, 1987 2:59:07 pm PDT Values for design rules are now taken from Saguaro instead of ChipNDale. changes to: DIRECTORY, IMPORTS, ndifSpacing, ndifWidth, ndifUncSubtrContSpacing, ndifInnWell, ndifpSubstrCont, pdifSpacing, pdifWidth, pdifUncnWellSpacing, polSpacing, polWidth, polUncDifSpacing, polDiffUncPolySpacing, metSeparation, metWidth, metCutCutSpacing, metViaViaSpacing, metCutViaSpacing, met2Separation, met2Width, difSep, wellSep, wellWidth, nDifToWell, pDifToWell, nDifTopDif, pdifUncSubtrContSpacing, nDifToSubtrCont, pDifToSubtrCont, ConvTransistor, TerminalIO gbb October 12, 1987 4:30:37 pm PDT Change constraint resolution PolExcludeByNDifContact o PolChannelEdge from PolExcludeByNDifContact to PolChannelEdge for both difusion sexes. This allows one to place diffusion contact guard rings at |l from a gate instead of what the di to poly rule says. changes to: Init Ê4–˜codešœ™KšœH™HK™0K™3K™A—code2šÏk ˜ Kšœ˜Kšœœ˜4Kšœ ˜ Kšœ œ˜%Kšœœ™)Kšœœ}˜ˆKšœ œ)˜:Kšœœ4˜™JšœœJ™^Kšœ&¡œ™(—šœœJ™cKšœ&¡œ™(—šœ œ¡œ™Kšœ™—M™ KšœœI™ZKšœ œ>™JšœœI™]Kšœ¡œ™—šœœK™_Kšœ¡œ™—šœœJ™^Kšœ¡œ™—M™ KšœœK™]Kšœ œ?™LMšœŸœ5™SKšœœ¥£¥Ðcg¥™2Kšœ œN¥§¥™bKšœ œF¥§¥™XKšœ œM¥§¥™cKšœ œM¥§¥™cKšœ œL¥§¥™cKšœœQ¥£¥§¥™uKšœœQ¥œ¥§¥™lKšœœQ¥œ¥§¥™lKšœœ œ™Kšœœ¥˜8Kšœœ¥˜9Kšœœ¥/˜N—Mšœ™šœ œœ˜5Nšœœ¥˜8Kšœœ¥/˜LKšœœ¥˜:Kšœœ¥˜9—Mšœ™šœ œœ˜6Nšœœ¥0˜SKšœœ¥0˜LKšœœ¥8˜WKšœœ¥8˜ZKšœœ¥&˜DKšœœ¥7™SKšœœ¥™2Kšœœ¥3™PKšœœ¥#˜?Kšœœ¥/˜MKšœœ¥.˜K—Mšœ™šœ œœ˜6Nšœœ¥*˜LKšœœ¥&˜@Kšœœ¥/˜I——™šž œ œœœ˜8Nšœœœ˜Nšœ œœœœœœœ˜=NšœÌœœ˜ÖNšœœ˜ šœ™Nšœœœ˜#Kšœœœ˜Kšœœœ˜$šœ,™,Kšœœœ˜%Kšœœ˜Kšœœ˜Kšœœ˜Kšœœœ˜$Kšœœ¥˜=Kšœœ˜Kšœœ˜Kšœœ˜Kšœœœ˜Kšœœœ˜&Kšœœ˜Kšœœ™—šœ,™,Kšœœœ˜%Kšœœ˜Kšœœ˜Kšœœœ˜%Kšœœ¥˜>Kšœœ˜Kšœœ˜Kšœœ˜Kšœœœ˜%Kšœœ˜Kšœœœ˜Kšœ œœ˜"Kšœœ˜Nšœœœ˜'Kšœœ˜ Nšœ œœ˜"Kšœœ˜Kšœ œœ˜Kšœ œœ˜!Kšœœ˜Kšœœ˜Kšœœœ˜%Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜!Kšœœ˜!—™Kšœ œœ˜ Kšœœ˜Kšœœ˜Kšœœ˜Kšœ œœ˜Kšœ œœ˜ Kšœœ˜Kšœœ˜Kšœœ˜—šœì™ìKšœœ˜Kšœœ˜$Kšœœ˜"Kšœœ˜"Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœœ˜——šœ™Kšœœ¡œ Ÿœ œœ œœ˜†Kšœ‹™‹Kšœ2œ˜8šœ¤ œœ˜'K–M[key: REF ANY, technology: CD.Technology _ NIL, default: REF ANY _ NIL]šœŸœ'œ8˜–M[key: REF ANY, technology: CD.Technology _ NIL, default: REF ANY _ NIL]šœŸ3œ3œ8˜¹K™6—KšœŸœM˜uKšœŸœR˜ƒKšœŸœR˜ƒKšœŸœS˜KšœŸ#œU˜Kšœ˜Kšœ˜—šœ¤ œœ˜(K–M[key: REF ANY, technology: CD.Technology _ NIL, default: REF ANY _ NIL]šœŸœ'œ9˜ŽK–M[key: REF ANY, technology: CD.Technology _ NIL, default: REF ANY _ NIL]šœŸ.œ/œ9˜±KšœŸœE˜mKšœŸœS˜ˆKšœ˜Kšœ˜—šœ¤ œœ˜'KšœŸ œ&œ3˜€KšœŸ œB˜cKšœŸ"œ,œ8˜¡KšœŸ"œ1œ8˜¦KšœŸœP˜zKšœ˜Kšœ˜—šœ¤ œœ˜'KšœŸ œ)œ-˜~KšœŸ œ>˜`KšœŸœP˜yKšœŸœQ˜zKšœŸœQ˜zKšœ˜Kšœ˜—šœ¤ œœ˜%KšœŸœ*œ5˜‰KšœŸ œI˜mKšœ˜Kšœ˜—šœ¤ œœ˜'KšœŸ œ#œ5˜KšœŸ œI˜jKšœ˜Kšœ˜——K˜——™ šŸ œ"˜-Kš œœ œœœœ™EKšœœœœ ˜4šœ˜ Kšœœ ˜-Kšœ œ˜"šœ˜Kšœ œ9˜FKšœS˜SKšœ ˜K˜—Kšœœ ˜—Kšœ¥˜—šŸœœœ˜*™5Jš œœœœœ ™Y—Jš˜Kšœ œœ ˜Kšœ+œœ ˜>Kšœœ˜#Kšœ œ˜(Kšœ œ˜Kšœ œ˜"Kšœœœ ˜'KšœœG˜NKšœœ˜#Kšœœ˜Kš œ(œœœœ˜>Kšœœ˜%Kšœ0œ¥(˜]Kšœ œœ˜*N™0šœ˜KšœR˜R—š˜KšœS˜S—N™OKšœ˜šœœ2˜?š œ"œCœœ˜šœ˜Kšœœ˜4Kšœ$œ˜AKšœb˜bKšœœœ@˜S—Jš˜——JšœœœF˜SNšœv™všœ˜šœ¥˜1Kš˜Kšœ<œ˜DKšœ1˜1Kšœ:˜:Kšœ,˜,KšœB˜BKšœB˜BKšœ?˜?Icode1šœJ˜JOšœF˜Fšœ˜ Kšœœ<˜D—N™Kšœ œ@˜Mšœ œ¥4˜GKš˜Kšœ˜KšœN˜NKšœœP˜WKšœ˜KšœN˜NKšœœP˜WKšœ˜—N™Kšœ0˜0Kšœœ_˜fKšœ0˜0Kšœœ_˜fKšœt™tKšœ’˜’N™4KšœÇ˜ÇKšœÆ˜ÆN™ šœ˜Kš˜Kš œœ œ œ œ ˜;Kš œœœœœB˜rKšœ œ9˜FKšœh˜hKšœ˜—Kšœ¥˜—šœ¥˜0Kš˜Kšœœ!˜+Kšœœ"˜3Kšœœ˜KšœVœ7˜”Kšœ8˜<š œœœœœœ˜Bšœœ˜CKšœ(˜(—šœœ˜CKšœ(˜(—Jšœ˜—Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ]˜]Kšœ-˜-OšœB˜BOšœI˜IOšœD˜DOšœI˜IOšœ˜šœ˜ Kšœœ<˜D—N™Kšœ œ?˜LKšœœQ˜Xšœ œœ¥4˜NKšœœ˜$Kšœœ˜"šœ™KšœP˜PKšœœO˜V—šœ™KšœP˜PKšœœO˜V—Kšœ(˜(šœ™KšœI˜IKšœœP˜W—šœ™KšœF˜FKšœœO˜V—Kšœ¥ ˜—N™š˜Kšœœ˜#KšœZ˜ZKšœœ`¥˜oKšœZ˜ZKšœœ`¥˜nKšœ˜KšœI˜IKšœœ`¥˜oKšœI˜IKšœœ_¥˜m—Kšœ¥ ˜Kšœt™tKšœ(˜(KšœÑ˜ÑKšœ)˜)KšœÑ˜ÑN™4Kšœf˜fKšœ¼˜¼šœœœ¥˜8Kš˜KšœL˜LKšœÆ˜ÆKšœ˜—KšœE˜EKšœ»˜»KšœD˜DKšœÆ˜ÆN™ šœ˜Kš˜Kš œœ œ œ œ ˜;Kš œœœœœB˜rKšœ œ9˜FKšœh˜hKšœ˜—Kšœ¥ ˜%—NšœœœR˜jNšœœœE˜X—Nšœ$œœ'˜QK™ Kšœ\˜^KšœA˜CKšœ>˜@KšœE˜GKšœI˜KKšœF˜HJšœ¥˜—šŸœœ˜4Kš œ œœœ œœ™ušžœ œœœ˜@Kšœœœœ˜Dš œœœœ3œœ˜išœ(œ˜0Kšœ.˜.Kšœ˜Kš˜K˜—Kšœ˜—Kšœ˜Kšœ¥˜—NšœM˜MNšœ˜šœ˜Kšœ ˜ Kšœ˜šœ.˜.Kšœ˜Kšœ˜K˜šœœ˜)Kšœ˜Kšœ˜Kšœ ˜—Kšœ ˜ Kšœ˜Kšœ˜—Kšœ˜—KšœQ˜QKšœ˜Kšœ ˜ K˜!K˜ Kšœ˜Kšœ¥˜—šŸœœ˜5Kš œ œœœ œœ™ušžœ œœ˜+š œœœœ3œœ˜išœ(œ˜0Kšœ.˜.Kš˜K˜—Kšœ˜—Kšœœ ˜Kšœ¥˜—Kšœ œ ™Kšœ œ¡œ˜Kšœœ˜Nšœœ œ ˜.šœœ˜7Kšœ$˜$Kšœ$˜$Kšœ˜K˜—Kšœ˜Kšœœ ˜K˜Kšœœ ˜K˜Kšœœ ˜Kšœœ¡œ˜0Kšœœœ¡œ˜LN™äKšœ_˜_šœœ˜Kš œœœœœ˜cKšœœœœ=˜c—Nšœ˜Kšœ¥˜——™Kšœœ˜.Kšœ œ˜#Lšœ œ¡œ˜Kšœœ¡œ˜"Kšœœ¡œ˜#šŸœœ˜1KšR™RKšœ œ˜Kšœ œ˜Kšœ œ7˜Bšœ˜#Kš˜Kšœ[˜[Kš˜Kšœ˜—Nšœ<˜Kš œ œ6œœœ œ™uKšœœ=˜\Kšœœ;˜Xšœ&œœ˜:Kšœ œœ ˜Kšœœœ˜-šœ¥:˜?K–’[circuit: REF SX.Circuit, subcircuitNode: REF SX.CircuitNode, qualifier: LIST OF CD.ApplicationPtr, insertIfNotInCircuit: BOOLEAN _ FALSE]šœ œiœ˜—šœ$œœ˜8Kš œœœœœ˜Gšœœ˜Kšœœ˜.—Kš˜—Kšœ˜—šœœ˜KšœQ˜Q—š œ8œœ6œ˜KšœF˜F—Kšœ˜ Kšœ¥˜—šŸœœœ˜;Kšœœœ ™Kšœœ1˜=Kšœ!œ˜&Kšœ˜N™š œœ3œœ˜PKšœœœD˜Ršœ#œœ˜7KšœPœ˜UKšœ\œ˜ašœ œœ˜%K™NK–¬[circuit: REF SpinifexCircuit.Circuit, subcircuitNode: REF SpinifexCircuit.CircuitNode, qualifier: LIST OF CD.ApplicationPtr, insertIfNotInCircuit: BOOLEAN _ FALSE]šœ œKœœ˜~šœ œ˜K™cK–†[pointInCell: CD.Position, cellSize: CD.Position, cellInstOrient: CD.Orientation, cellInstPos: CD.Position _ [x: 0, y: 0]]šœœ[˜cKšœh˜hK˜—Kšœ¥˜—Kšœ¥˜—Kšœ¥˜—NšœŽ™Žšœ)œœ˜=KšœOœ˜Tšœ œ˜KšœœK˜aK™Hšœ#œœ˜7Kšœ œ˜'šœ%œœ˜Dšœ œ%˜9Kšœ$¥˜>—Kš˜—Kšœ¥ ˜—šœœœ œ˜)K™*Kšœœ˜$Kšœv˜vKšœ˜—š œœœœœœ˜=K™*Kšœœ˜$Kšœp˜pšœ#œœ˜7Kšœœ˜$KšœHœ;œH˜ÒKšœ˜—K˜—Kšœ¥˜—Kšœ¥˜—Kšœ¥˜—šŸœœœ˜0Kšœœœ œœœœœ œœ™£Kšœ œœœX¡œ¡œ¡œ¡œ˜…Kšœœœœ˜Kšœbœœ˜|Kšœ¥˜——™šžœ œ˜NšÐbl œœœ ˜Nšœœœ˜,Kšœœœ˜,Kšœœœ˜,Kšœœœ˜-šœ&™&šœ œœœ™"Kšœœ™ Kšœ¥"™;Kšœœœ¥{™¥Kšœ@œ¥D™K™—Nšœœ%œ˜LKšœœ)™=Kšœœ-˜CKšœœ-˜AKšœœ&œ˜OKšœœ2œ˜\Kšœœ.˜DNšœœ%œ˜MKšœœ.˜DKšœœ&œ˜OKšœœ2œ˜\Nšœœ+œ˜UKšœœ+œ˜UKšœœ5œ˜bKšœœ5œ˜bKšœœ)˜=Kšœœ&˜Kšœœ*œ˜QN˜Kšœœœ ˜&Kšœœœ ˜'–14 in lineLengthšœ,˜,Idefault–14 in lineLengthšœÐosD™YP–14 in lineLengthšªH˜HP–14 in lineLengthšªJ˜JP–14 in lineLengthšª0Ñbosª˜IP–14 in lineLengthšªR˜RP–14 in lineLengthšªO˜OP–14 in lineLengthšªL˜LP–14 in lineLengthšª«ª7˜NP–14 in lineLengthšªS˜SP–14 in lineLengthšªœ˜P–14 in lineLength˜—–14 in lineLengthšœ,™,P–14 in lineLengthšœªD™YP–14 in lineLengthšªO™OP–14 in lineLengthšªO™OP–14 in lineLengthšªQ™QP–14 in lineLengthšªQ™QP–14 in lineLengthšªZ™ZP–14 in lineLengthšªV™VP–14 in lineLengthšªS™SP–14 in lineLengthšªW™WP–14 in lineLengthšª[™[P–14 in lineLengthšªœ™P–14 in lineLength™—šœ,˜,Pšœª)™>Pšª9˜9Pšª:˜:Pšª'«ª˜9PšªC˜CPšª>˜>Pšª«ª(˜?J˜ K˜—–14 in lineLengthšœ,˜,P–14 in lineLengthšœªh™}P–14 in lineLengthšªX˜XP–14 in lineLengthšªS˜SP–14 in lineLengthšª[˜[P–14 in lineLengthšª[˜[P–14 in lineLengthšª<«ª!˜aP–14 in lineLengthšª<«ª!˜aP–14 in lineLengthšª«ª«ª(˜RP–14 in lineLengthšªR˜RP–14 in lineLengthšªY˜YP–14 in lineLengthšªY˜YP–14 in lineLengthšœ˜K–14 in lineLengthšœ˜—–14 in lineLengthšœ,™,P–14 in lineLengthšœªh™}P–14 in lineLengthšªX™XP–14 in lineLengthšªS™SP–14 in lineLengthšª[™[P–14 in lineLengthšª[™[P–14 in lineLengthšªd™dP–14 in lineLengthšªd™dP–14 in lineLengthšªX™XP–14 in lineLengthšªR™RP–14 in lineLengthšªY™YP–14 in lineLengthšªY™YP–14 in lineLengthšœ™K–14 in lineLengthšœ™—–14 in lineLengthšœ,™,P–14 in lineLengthšœªh™}P–14 in lineLengthšªm™mP–14 in lineLengthšªd™dP–14 in lineLengthšªq™qP–14 in lineLengthšªq™qP–14 in lineLengthšªz™zP–14 in lineLengthšªz™zP–14 in lineLengthšªn™nP–14 in lineLengthšªq™qP–14 in lineLengthšªb™bP–14 in lineLengthšªv™vP–14 in lineLengthšªg™gP–14 in lineLengthšªn™nP–14 in lineLengthšªn™nP–14 in lineLengthšœ™K–14 in lineLengthšœ™—šœ-˜-Pšœª™0Pšª)˜)Pšª)˜)Pšª*˜*Pšª*˜*Pšª'˜'P˜ K˜—NšœD˜DKšœD˜DKšœE˜EKšœG˜GK˜—šœ#™#Nš œ œœ‘¡œ ¡œZ˜ŠNšœ œœ‘¡œZ™ÿKšœŸ œœ˜1KšœŸ œœ˜1KšœŸœœ˜,KšœŸœœ˜,KšœŸœœ˜-KšœŸœœ˜+KšœŸœœ˜+KšœŸœœ˜,š œ Ÿ œœ2¡œœœ·˜¤KšœX™X—Kšœ Ÿ œœ·˜èKšœ ŸœœU˜Kšœ ŸœœU˜Kš œ ŸœœM¡œ ¡œ˜ˆKš œ ŸœœM¡œ¥Ñacl™ŠKšœ Ÿœœ!˜LKšœ Ÿœœ$˜OKšœ Ÿœœ$˜PK™š˜Kšœ œ ¡œ¥"˜:Kšœ]™]Kšœ Ÿœœˆ˜³Kšœ ŸœœC˜oKšœ ŸœœP˜{Kšœ˜——šœ™NšœB˜BKšœB˜BKšœ;˜;Kšœ<˜™>Nšœ@˜@Kšœ@˜@Kšœ?˜?Kšœ@˜@—šœ™Nšœ˜—šœ:™:N–<[propList: Atom.PropList, prop: REF ANY, val: REF ANY]šœY˜Y—šœ™NšœÀ˜ÀKšœÄ˜ÄKšœÁ˜ÁKšœÅ˜ÅKšœÄ˜ÄNšœo˜oKšœo˜oNšœo˜oKšœs˜sKšœt˜tKšœx˜xKšœq˜qKšœr˜rKšœu˜uKšœi˜iKšœn˜n—K˜——™N˜Kšœœfœ˜—Lšœ˜™#K™—™$K™&—™!KšœB™BKšœ Ïrœ­œ™N—™!K™Kšœ ­œ¡œ¡œ™4—™!Kšœ!™!Kšœ ­æœ™ó—™"K™Kšœ ­×™ã—™K™Kšœ ­œ:™T—™ K™OKšœ ­œ/­œi™¸—™#Kšœ6¥2œ™iKšœ ­œ­œ™>—™#K™UKšœ ­™—™$K™jKš œ ­œÏeœ®œ®œ®œ™\—™ K™*Kšœ ­™ —™"K™HKšœ ­Î™Ú—™#Kš œ®¢œ®œ®œ®œT¢¡œ6™€Kšœ ­™——…—«€*$