<> <> <> <> <> 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; 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 * <> 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 * <> <> 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 * <> <> 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 * 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~ 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 ~ { <<[r: CD.Rect, l: CD.Layer, data: REF ANY] RETURNS [TransistorMaterial]>> cir: REF SX.Circuit ~ NARROW [data, REF SX.Circuit]; SELECT l FROM CMosB.ndif, CMosB.pdif => RETURN [diffusion]; CMosB.pol => RETURN [polysilicon]; CMosB.nwell => { wellNode: REF SX.CircuitNode _ cir.AddRect [lev~ CMosB.nwell, dim~ r]; wellNode.properties _ Properties.PutProp [wellNode.properties, wellNode, wellNode]; RETURN [nothing]; }; ENDCASE => RETURN [nothing]; }; -- MapMaterial ConvTransistor: PUBLIC SX.ConversionProc = <> <> 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 ~ { <<[desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc]>> PrintAttachment: PROCEDURE [key: ATOM, portName: Rope.ROPE] ~ { cellStream.Put [IO.rope[" (\""], IO.rope[portName], IO.rope["\" "]]; FOR attachments: LIST OF REF SX.AttachedNode _ linkage.nodes, attachments.rest WHILE attachments # NIL DO IF attachments.first.attachmentType = key THEN { PrintNode[cellStream, attachments.first.node]; cellStream.PutRope[")"]; RETURN } ENDLOOP; cellStream.PutRope ["\"?\")"]; }; -- PrintAttachment naming: SXOutputPrivate.Naming _ SXOutputPrivate.GetANaming [linkage.source]; cellStream.PutRope["(CI "]; SXOutputPrivate.PrintNaming[ cellStream, naming, Rope.Cat[" \"", SXOutputPrivate.NameTransType[ desWDir: desWDir, obj: linkage.source.ob, dfStream: dfStream, type: SELECT linkage.source.ob.layer FROM CMosB.ndif, CMosB.wndif => $n, CMosB.pdif, CMosB.wpdif => $p, ENDCASE => $funny, mode: $E, length: linkage.l, width: linkage.w], "\""] ]; SXOutputPrivate.PrintRoseInstantiationTransformation[cellStream, linkage.source]; cellStream.PutRope [" (CIC"]; PrintAttachment [$Gate, "gate"]; PrintAttachment [$Source, "ch1"]; PrintAttachment [$Drain, "ch2"]; cellStream.PutRope ["))"] }; -- RoseTransistor ThymeTransistor: PUBLIC SXOutput.LinkagePrintProc ~ { <<[desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc]>> PrintAttachment: PROCEDURE [key: ATOM] ~ { FOR attachments: LIST OF REF SX.AttachedNode _ linkage.nodes, attachments.rest WHILE attachments # NIL DO IF attachments.first.attachmentType = key THEN { PrintNode[cellStream, attachments.first.node]; RETURN } ENDLOOP; cellStream.Put [IO.char['?]]; }; -- PrintAttachment <> defaultL: INTEGER = 2* 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/ IF linkage.l # defaultL THEN cellStream.PutF[", L_%g", IO.int[linkage.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 * splitContWidth: CD.Number ~ 2 * splitContHeight: CD.Number ~ 6 * ConvertPDifRect: PUBLIC SX.ConversionProc = BEGIN <<[appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit]>> 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 <<[appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit]>> 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], END; -- PointRect CopyWellConnections: PUBLIC SX.CombineNodePropertyProc ~ BEGIN <<[circuit: REF Circuit, to, from: Properties.PropList, fromNesting: LIST OF CD.Instance] RETURNS [Properties.PropList]>> 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 { < VIOLATION>> 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 { < VIOLATION>> 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 { < VIOLATION>> 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: [ 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, ,,,,,,,], ,,,,,,, ]; <> <> <<[ 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, ,,,,,,],>> <<,,,,,,>> <<];>> 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, ,,,,,], ,,,,, ]; <> <> <<[ 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, ,,,,,],>> <<,,,,,>> <<];>> <> <> <<[ 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, ,,],>> <<,,>> <<];>> 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, 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 ~ <> 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. <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <>