<> <> <> <> <> <> <> <> <> DIRECTORY CD USING [Instance, Layer, Number, Position, Rect], CDBasics, CDProperties USING [GetInstanceProp], CDSimpleRules USING [MinDist, MinWidth], IO USING [char, int, Put, PutF, PutRope, rope], NMos USING [lambda, nmos, dif, pol, met, ovg, cut], NMosContacts USING [ContactPtr], NMosTransistors USING [enhancement, strongDepletion, TransistorPtr, weakDepletion, zeroTresh], Rope USING [Cat, ROPE], SX USING [AddBox, AddRect, AdjustNode, AttachedNode, Circuit, CircuitNode, Constraint, ConstraintArray, ConstraintIndex, ConstraintResolution, ConversionProc, CreateLinkage, GeometricRule, IllegalConstruct, LinkageAttach, MapRec, MergeNode, nodeIndex, NodeLinkage, spaceIndex, SpinifexLayerIndex, techCIndexBase, TechHandle, violateIndex], SXOutput USING [LinkageHousekeeper, LinkagePrintProc], SXOutputPrivate USING [GetANaming, NameTransType, Naming, PrintNaming, PrintRoseInstantiationTransformation, UnNameTransType], SXQuadTree USING [RectDelta], SXTechnology USING [ESWGrow, NESGrow, PerDrawRectProc, ProcessMosTransistor, RegisterSpinifexObjectProcs, RegisterTechnologyHandle, ReportDifProc, ResolutionTable, SetUpResolution, SWNGrow, WNEGrow], TerminalIO USING [PutRope]; SXNMos: CEDAR PROGRAM IMPORTS CDBasics, CDProperties, CDSimpleRules, IO, NMos, Rope, SX, SXOutputPrivate, SXTechnology, TerminalIO = BEGIN <> polOverDif: CD.Number = NMos.lambda; <> difToPolExtSep: CD.Number = 0; polSep: CD.Number = NMos.lambda; difToPolSep: CD.Number = difToPolExtSep + polSep; -- not halved! contactWidth: CD.Number = 4 * NMos.lambda; <> ConvertNMosTransistor: SX.ConversionProc ~ { <<[appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF]>> p: NMosTransistors.TransistorPtr = NARROW[inst.ob.specific]; size: CD.Position _ CDBasics.SizeOfRect[inst.ob.bbox]; xstr: REF SX.NodeLinkage; gateNode, sourceNode, drainNode, metNode: REF SX.CircuitNode; polExt: CD.Number ~ IF p.pullup THEN MIN[ (size.x-contactWidth)/2, p.wExt] ELSE p.wExt; <> IF ~ p.angle THEN { -- Oh this is easy! <> gateNode _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[0, p.lExt, polExt, p.lExt+p.length], trans~trans, interestBloat~SXTechnology.SWNGrow[(CDSimpleRules.MinDist[NMos.pol, NMos.pol]/2)]]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt, size.x-polExt, p.lExt+p.length], trans~trans, value~gateNode]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[size.x-polExt, p.lExt, size.x, p.lExt+p.length], trans~trans, interestBloat~SXTechnology.NESGrow[(CDSimpleRules.MinDist[NMos.pol, NMos.pol]/2)], value~gateNode]; <> IF p.lExt-difToPolSep > 0 THEN { <> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt+p.length+difToPolSep, size.x-polExt, size.y], trans~trans, interestBloat~SXTechnology.WNEGrow[difToPolExtSep], value~pCnstr[pExcl]]; <<... and the bottom>> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, 0, size.x-p.wExt, p.lExt-difToPolSep], trans~trans, interestBloat~SXTechnology.ESWGrow[difToPolExtSep], value~pCnstr[pExcl]] }; <> <> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt+p.length, size.x-polExt, p.lExt+p.length+difToPolSep], trans~trans, value~pCnstr[pChE]]; <<... and the bottom>> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, p.lExt-difToPolSep, size.x-p.wExt, p.lExt], trans~trans, value~pCnstr[pChE]]; <> [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[p.wExt, p.lExt, size.x-p.wExt, p.lExt+p.length], trans~trans, interestBloat~[dx1~ (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), dy1~ 0, dx2~ (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), dy2~ 0], value~dCnstr[dCh]]; IF polExt < p.wExt THEN [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[polExt, p.lExt+p.length- p.lExt+p.length], trans~trans, interestBloat~[dx1~ (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), dy1~ 0, dx2~ (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), dy2~ (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)], value~dCnstr[dCh]]; <> sourceNode _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[polExt, p.lExt+p.length, size.x-polExt, size.y], trans~trans, interestBloat~SXTechnology.WNEGrow[(CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)]]; drainNode _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[p.wExt, 0, size.x-p.wExt, p.lExt], trans~trans, interestBloat~SXTechnology.ESWGrow[(CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)]]; IF p.pullup THEN { metNode _ cir.AddRect [lev~NMos.met, dim~[(size.x-contactWidth)/2, size.y-6* } ELSE metNode _ NIL } ELSE { -- Oh no not a bent transistor yetcchh! sourceDrainList: LIST OF REF SX.CircuitNode; sourceDrainCount: INTEGER; sourceHint: REF SX.CircuitNode _ NIL; NoteSourceHint: SXTechnology.ReportDifProc ~ { sourceHint _ difNode }; [gateNode, sourceDrainList, sourceDrainCount] _ SXTechnology.ProcessMosTransistor[inst, trans, cir, difSpinifex, polSpinifex, dCnstr[dCh], pCnstr[pChE], (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), difToPolSep, MapMaterial, cir, NoteSourceHint]; IF sourceDrainCount = 2 THEN { sourceNode _ sourceDrainList.first; drainNode _ sourceDrainList.rest.first; IF p.pullup THEN { SELECT sourceHint FROM sourceNode => NULL; drainNode => { drainNode _ sourceNode; sourceNode _ sourceHint }; ENDCASE => ERROR -- Including case when sourceHint = NIL } } ELSE { TerminalIO.PutRope[ Rope.Cat["Xstr with ", (SELECT sourceDrainCount FROM 0 => "no", 1 => "only 1", ENDCASE => "more than 2"), " sources/drains not included in circuit description\n"]]; RETURN } }; <> xstr _ cir.CreateLinkage[inst, p.length, p.width]; <> SX.AdjustNode[ gateNode, polSpinifex, size.y*p.length, (size.y+p.length)*2, absolute]; SX.AdjustNode[ sourceNode, difSpinifex, (size.y-(p.lExt+p.length))*(size.x-2*polExt), (size.y-(p.lExt+p.length))*2 + size.x-2*polExt, absolute]; -- Ignore perim leading into channel. SX.AdjustNode[ drainNode, difSpinifex, p.lExt*p.width, 2*p.lExt + p.width, absolute]; -- Ignore perim leading into channel. IF p.pullup THEN { cir.MergeNode[ gateNode, sourceNode]; sourceNode _ gateNode; cir.MergeNode[ gateNode, metNode]; metNode _ gateNode; }; SX.LinkageAttach[link~xstr, attachType~$Gate, node~gateNode]; SX.LinkageAttach[link~xstr, attachType~$Source, node~sourceNode]; SX.LinkageAttach[link~xstr, attachType~$Drain, node~drainNode]; }; <> MapMaterial: SXTechnology.PerDrawRectProc ~ { <<[r: CD.Rect, l: CD.Layer, data: REF ANY] RETURNS [TransistorMaterial]>> cir: REF SX.Circuit ~ NARROW [data, REF SX.Circuit]; SELECT l FROM NMos.dif => RETURN [diffusion]; NMos.pol => RETURN [polysilicon]; NMos.met => { [] _ cir.AddRect[ lev~ NMos.met, dim~ r]; RETURN [nothing]; }; NMos.cut => { RETURN [postProcess]; }; ENDCASE => RETURN [nothing]; }; <> ConvertNMosContactDifAndPol: SX.ConversionProc ~ { <<[appl: CD.Instance, trans: CD.Transformation, cir: REF SX.Circuit]>> box: CD.Rect _ inst.ob.bbox; node: REF SX.CircuitNode; <> node _ cir.AddRect[ lev~NMos.met, dim~box, trans~trans]; [] _ cir.AddRect[ lev~inst.ob.layer, dim~box, trans~trans, value~node]; IF inst.ob.layer = NMos.dif THEN [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~box, trans~trans, value~pCnstr[pExCon]]; }; ConvertNMosMmContact: SX.ConversionProc ~ { <<[appl: CD.Instance, trans: CD.Transformation, cir: REF SX.Circuit]>> s: CD.Position = CDBasics.SizeOfRect[inst.ob.bbox]; [] _ cir.AddBox [ spinifexLayer: metSpinifex, dim: [l/2, l/2, s.x-l/2, s.y-l/2], -- cut bloated by 1/2 lambda trans: trans, value: mCnstr[mCutEx]]; [] _ cir.AddBox [ spinifexLayer: metSpinifex, dim: [l, l, s.x-l, s.y-l], -- cut unbloated trans: trans, value: mCnstr[mCut]];}; ConvertNMosButtingContact: SX.ConversionProc ~ { <<[appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit]>> rimWidth: CD.Number ~ box: CD.Rect _ inst.ob.bbox; size: CD.Position _ CDBasics.SizeOfRect[box]; polSize: CD.Number ~ size.y/2; node: REF SX.CircuitNode; node _ cir.AddRect[ lev~NMos.met, dim~box, trans~trans]; [] _ cir.AddRect[ lev~NMos.pol, dim~[0,0, size.x, polSize], trans~trans, value~node]; <> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[-rimWidth,polSize, size.x+rimWidth, polSize+difToPolSep], trans~trans, value~pCnstr[pChE]]; [] _ cir.AddBox [spinifexLayer~polSpinifex, dim~[-rimWidth,polSize-rimWidth, 0, polSize], trans~trans, value~pCnstr[pDxorP]]; [] _ cir.AddBox [spinifexLayer~polSpinifex, dim~[size.x,polSize-rimWidth, size.x+rimWidth, polSize], trans~trans, value~pCnstr[pDxorP]]; [] _ cir.AddBox [spinifexLayer~polSpinifex, dim~[0,polSize+difToPolSep, size.x, size.y], trans~trans, interestBloat~SXTechnology.WNEGrow[difToPolExtSep], value~pCnstr[pExCon]]; <> [] _ cir.AddBox [spinifexLayer~difSpinifex, dim~[0,polSize, size.x, size.y], trans~trans, interestBloat~[(CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)], value~node]; }; ConvertNMosBuriedContact: SX.ConversionProc ~ { <<[appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit]>> <> s: CD.Position ~ CDBasics.SizeOfRect[inst.ob.bbox]; cp: NMosContacts.ContactPtr ~ NARROW[inst.ob.specific]; node: REF SX.CircuitNode ~ cir.AddRect[ lev~NMos.pol, dim~[2* <> [] _ cir.AddBox [ spinifexLayer: metSpinifex, dim: [l/2, l/2, s.x-l/2, s.y-l/2], -- actual dimensions of cut trans: trans, value: mCnstr[mBCCut]]; [] _ cir.AddBox [ spinifexLayer: metSpinifex, dim: [-l/2, -l/2, s.x+l/2, s.y+l/2], -- cut bloated by 1 lambda trans: trans, value: mCnstr[mBCEx]]; <<[] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [l/2, l/2, s.x-l/2, s.y-l/2], -- actual dimensions of cut trans: trans, value: pCnstr[pBCCut]];>> <<[] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [0, 0, s.x, s.y], --cut Bloated by 1/2 lambda (poly is bloated by lambda) trans: trans, value: pCnstr[pBCExcl]];>> SELECT TRUE FROM cp.lExt < 2* <> wex: CD.Number ~ MAX[cp.wExt+ lex: CD.Number ~ MAX[cp.lExt+ bcExclConstraint: SX.Constraint _ pCnstr[pBCExcl]^; bcExclConstraint.specificCorrespondingNode _ node; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [-l/2, -l/2, 0, s.y+l/2], -- buried contact poly exclude (left side) trans: trans, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddRect [ lev: inst.ob.layer, dim: [ trans: trans, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* trans: trans, value: pCnstr[pChE]]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* trans: trans, value: pCnstr[pDandP]]; [] _ cir.AddBox [ spinifexLayer: difSpinifex, dim: [2* trans: trans, value: node]; }; cp.lExt < 2* <> lex: CD.Number ~ MAX[cp.lExt+ bcExclConstraint: SX.Constraint _ pCnstr[pBCExcl]^; bcExclConstraint.specificCorrespondingNode _ node; <> [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [s.x, -l/2, s.x+l/2, s.y+l/2], -- buried contact poly exclude (right side) trans: trans, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [-l/2, -l/2, 0, s.y+l/2], -- buried contact poly exclude (left side) trans: trans, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddBox [ spinifexLayer: difSpinifex, dim: [2*trans: trans, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* trans: trans, value: pCnstr[pDandP]]; <> [] _ cir.AddRect [lev: inst.ob.layer, dim: [ trans: trans, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* trans: trans, value: pCnstr[pChE]]; <> [] _ cir.AddRect [ lev: inst.ob.layer, dim: [s.x-cp.wExt, lex, s.x-(cp.wExt- trans: trans, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [s.x-cp.wExt, lex, s.x-(cp.wExt-difToPolSep), s.y-lex], trans: trans, value: pCnstr[pChE]]; }; cp.lExt >= 2* <> wex: CD.Number ~ MAX[cp.wExt+ lex: CD.Number ~ cp.lExt- bcExclConstraint: SX.Constraint _ pCnstr[pBCExcl]^; bcExclConstraint.specificCorrespondingNode _ node; <> [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [-l/2, -l/2, l/2, s.y+l/2], -- buried contact poly exclude (left side) trans: trans, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [l/2, s.y, s.x+l/2, s.y+l/2], -- buried contact poly exclude (top side) trans: trans, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [l/2, -l/2, s.x, 0], -- buried contact poly exclude (bottom side) trans: trans, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* trans: trans, value: pCnstr[pDandP]]; <> [] _ cir.AddRect [ lev: inst.ob.layer, dim: [ trans: trans, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* trans: trans, value: pCnstr[pChE]]; <> [] _ cir.AddRect [ lev: inst.ob.layer, dim: [2* trans: trans, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* trans: trans, value: pCnstr[pChE]]; <> [] _ cir.AddRect [ lev: inst.ob.layer, dim: [2* trans: trans, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* trans: trans, value: pCnstr[pChE]]; }; cp.lExt >= 2* <> ERROR SX.IllegalConstruct [inst.ob.class.interestRect[inst.ob], "Polysilicon surrounded by diffusion or all sides in Buried Contact"]; }; ENDCASE => ERROR; }; <> RoseNMosTransistor: SXOutput.LinkagePrintProc ~ { <<[desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc]>> PrintAttachment: PROCEDURE [key: ATOM, portName: Rope.ROPE] ~ { cellStream.Put[ IO.rope[" (\""], IO.rope[portName], IO.rope["\" "]]; FOR attachments: LIST OF REF SX.AttachedNode _ linkage.nodes, attachments.rest WHILE attachments # NIL DO IF attachments.first.attachmentType = key THEN { PrintNode[cellStream, attachments.first.node]; cellStream.PutRope[")"]; RETURN } ENDLOOP; cellStream.PutRope[ "\"?\")"]; }; p: NMosTransistors.TransistorPtr ~ NARROW [linkage.source.ob.specific]; naming: SXOutputPrivate.Naming _ SXOutputPrivate.GetANaming [linkage.source]; cellStream.PutRope ["(CI "]; SXOutputPrivate.PrintNaming [ cellStream, naming, Rope.Cat[" \"", SXOutputPrivate.NameTransType [ desWDir: desWDir, obj: linkage.source.ob, dfStream: dfStream, type: $n, mode: IF p.pullup THEN $D ELSE SELECT p.implant FROM NMosTransistors.enhancement => $E, NMosTransistors.strongDepletion => $D, NMosTransistors.zeroTresh => $Z, NMosTransistors.weakDepletion => $W, ENDCASE => ERROR, length: p.length, width: p.width], "\""]]; SXOutputPrivate.PrintRoseInstantiationTransformation [cellStream, linkage.source]; cellStream.PutRope [" (CIC"]; PrintAttachment [$Gate, "gate"]; PrintAttachment [$Source, "in"]; PrintAttachment [$Drain, "out"]; cellStream.PutRope ["))"] }; ThymeNMosTransistor: SXOutput.LinkagePrintProc ~ { <<[desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, PrintNode: NodePrintProc]>> PrintAttachment: PROCEDURE [ key: ATOM] ~ { FOR attachments: LIST OF REF SX.AttachedNode _ linkage.nodes, attachments.rest WHILE attachments # NIL DO IF attachments.first.attachmentType = key THEN { PrintNode [cellStream, attachments.first.node]; RETURN } ENDLOOP; cellStream.Put[IO.char['?]]; }; p: NMosTransistors.TransistorPtr ~ NARROW [linkage.source.ob.specific]; defaultL: INTEGER ~ 2* propertyValue: REF; cellStream.Put [IO.rope[name], IO.rope[": "]]; cellStream.PutRope [IF ~p.pullup THEN SELECT p.implant FROM NMosTransistors.enhancement => "ETran[", NMosTransistors.strongDepletion => "DTran[", NMosTransistors.zeroTresh => "ZTran[", NMosTransistors.weakDepletion => "WTran", ENDCASE => ERROR ELSE "DTran [" ]; PrintAttachment [$Gate]; cellStream.Put [IO.char[',]]; PrintAttachment [$Source]; cellStream.Put [IO.char[',]]; PrintAttachment [$Drain]; cellStream.Put [IO.char['|]]; cellStream.PutF [" W_N*%g", IO.int[p.width/ IF p.length # defaultL THEN cellStream.PutF [", L_%g", IO.int[p.length/ <> propertyValue _ CDProperties.GetInstanceProp [from: linkage.source, prop: $Crystal]; WITH propertyValue SELECT FROM crystalHack: Rope.ROPE => IO.Put [stream: cellStream, v1: IO.rope["; "], v2: IO.rope[crystalHack]]; ENDCASE => IF propertyValue # NIL THEN TerminalIO.PutRope [" $Crystal property must be a rope. /n"]; cellStream.PutRope ["];"] }; <> <> nMosHandle: REF SX.TechHandle; difSpinifex: SX.SpinifexLayerIndex ~ SX.SpinifexLayerIndex.FIRST; polSpinifex: SX.SpinifexLayerIndex ~ difSpinifex.SUCC; metSpinifex: SX.SpinifexLayerIndex ~ polSpinifex.SUCC; Constraint: TYPE ~ SX.Constraint; <> dCnstr: REF SX.ConstraintArray _ NEW[SX.ConstraintArray]; -- Diffusion constraints dCh: SX.ConstraintIndex ~ SX.techCIndexBase; -- Diffusion channel <> pCnstr: REF SX.ConstraintArray _ NEW[SX.ConstraintArray]; -- Poly constraints pExcl: SX.ConstraintIndex ~ SX.techCIndexBase; -- Poly not allowed here. pExCon: SX.ConstraintIndex ~ pExcl.SUCC; -- Poly not allowed here because of Contact to n-Diffusion. pDPErr: SX.ConstraintIndex ~ pExCon.SUCC; -- Poly and Diffusion found together here. pChE: SX.ConstraintIndex ~ pDPErr.SUCC; -- Close to Xstr Gate, (Channel Edge). pDxorP: SX.ConstraintIndex ~ pChE.SUCC; -- Diffusion XOR Poly allowed here. pDandP: SX.ConstraintIndex ~ pDxorP.SUCC; -- Diffusion AND Poly may appear together here. pBCExcl: SX.ConstraintIndex = pDandP.SUCC; -- Buried Contact Cut Exclusion pBCErr: SX.ConstraintIndex = pBCExcl.SUCC; -- Buried Contact Cut Separation violation <> mCnstr: REF SX.ConstraintArray _ NEW[SX.ConstraintArray]; -- metal constraints mBCEx: SX.ConstraintIndex = SX.techCIndexBase; -- Buried Contact Cut Bloated mBCErr: SX.ConstraintIndex = mBCEx.SUCC; -- Buried Contact Cut Separation violation mBCCut: SX.ConstraintIndex = mBCErr.SUCC; -- Buried Contact Cut Unbloated mCutEx: SX.ConstraintIndex = mBCCut.SUCC; -- Metal Contact Cut Bloated mCut: SX.ConstraintIndex = mCutEx.SUCC; -- Metal Contact Cut Unbloated mBCExM: SX.ConstraintIndex = mCut.SUCC; -- Buried Contact Cut Bloated over metal mBCErrM: SX.ConstraintIndex = mBCExM.SUCC; -- Buried Contact Cut Separation violation over metal mBCCutM: SX.ConstraintIndex = mBCErrM.SUCC; -- Buried Contact Cut Unbloated over metal mCutExM: SX.ConstraintIndex = mBCCutM.SUCC; -- Metal Contact Cut Bloated over metal mCutM: SX.ConstraintIndex = mCutExM.SUCC; -- Metal Contact Cut Unbloated over metal Init: PROCEDURE ~ { GeometricRule: TYPE ~ SX.GeometricRule; difSpacingRule, difWidthRule: REF GeometricRule; polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule, polBuriedSpacingRuleA, polBuriedSpacingRuleB: REF GeometricRule; metSpacingRule, metWidthRule, bcCutSpacingRule, bcMetalCutSpacingRuleA, bcMetalCutSpacingRuleB: REF GeometricRule; detectOpaqueViolation: REF GeometricRule; TriggerMap: TYPE ~ PACKED ARRAY SX.ConstraintIndex OF BOOLEAN _ ALL[FALSE]; spaceRuleTrigger: TriggerMap; widthRuleTrigger: TriggerMap; polOverDifTrigger1, polOverDifTrigger2, polDifSepTriggerA, polDifSepTriggerB: TriggerMap; difSpaceTrigger1: TriggerMap; polWidthTrigger: TriggerMap; polBuriedSpaceTriggerA, polBuriedSpaceTriggerB, polSpaceTrigger, metSpaceTrigger, metWidthTrigger: TriggerMap; bcSpaceTrigger, bcMetalCutSpacingTriggerA, bcMetalCutSpacingTriggerB: TriggerMap; difResolution: REF SX.ConstraintResolution; polyResolution: REF SX.ConstraintResolution; metResolution: REF SX.ConstraintResolution; <> dCnstr[dCh] _ NEW[ Constraint _ [ $DifChannel, dCh]]; pCnstr[pExcl] _ NEW[ Constraint _ [ $ExcludePol, pExcl]]; pCnstr[pExCon] _ NEW[ Constraint _ [ $ExcludePolByContact, pExCon]]; pCnstr[pDPErr] _ NEW[ Constraint _ [ $PolDifError, pDPErr]]; pCnstr[pChE] _ NEW[ Constraint _ [ $ChannelEdge, pChE]]; pCnstr[pDxorP]_ NEW[ Constraint _ [ $PolXorDif, pDxorP]]; pCnstr[pDandP] _ NEW[ Constraint _ [ $PolAndDif, pDandP, TRUE, polSpinifex]]; pCnstr[pBCExcl] _ NEW[ Constraint _ [ $PolyBCExcl, pBCExcl, TRUE]]; pCnstr[pBCErr] _ NEW[ Constraint _ [ $PolyBCErr, pBCErr, TRUE]]; <> mCnstr[mBCEx] _ NEW[ Constraint _ [ $BCExclCut, mBCEx]]; mCnstr[mBCErr] _ NEW[ Constraint _ [ $BCErr, mBCErr]]; mCnstr[mBCCut] _ NEW[ Constraint _ [ $BCCut, mBCCut]]; mCnstr[mCutEx] _ NEW[ Constraint _ [ $CutExcl, mCutEx]]; mCnstr[mCut] _ NEW[ Constraint _ [ $Cut, mCut]]; mCnstr[mBCExM] _ NEW[ Constraint _ [ $BCExclCutM, mBCExM]]; mCnstr[mBCErrM] _ NEW[ Constraint _ [ $BCErrM, mBCErrM]]; mCnstr[mBCCutM] _ NEW[ Constraint _ [ $BCCutM, mBCCutM]]; mCnstr[mCutExM] _ NEW[ Constraint _ [ $CutExclM, mCutExM]]; mCnstr[mCutM] _ NEW[ Constraint _ [ $CutM, mCutM]]; { nd: SX.ConstraintIndex ~ SX.nodeIndex; sp: SX.ConstraintIndex ~ SX.spaceIndex; dResTab: SXTechnology.ResolutionTable ~ [ [ sp, nd, dCh, ,,,,,,,,,,,,], [ nd, nd, dCh, ,,,,,,,,,,,,], [ dCh, dCh, dCh, ,,,,,,,,,,,,], ,,,,,,,,,,,, ]; pResTab: SXTechnology.ResolutionTable = [ [ sp, nd, pExcl, pExCon, pDPErr, pChE, pDxorP, pDandP, pBCExcl, pBCErr, ,,,,,], [ nd, nd, pDPErr, pDPErr, pDPErr, pDPErr, nd, pDandP, pBCErr, pBCErr, ,,,,,], [ pExcl, pDPErr, pExcl, pExCon, pDPErr, pChE, pChE, pDandP, pExcl, pExcl, ,,,,,], [ pExCon, pDPErr, pExCon, pExCon, pDPErr, pExCon, pExCon, pDandP, pExCon, pExCon, ,,,,,], [ pDPErr, pDPErr, pDPErr, pDPErr, pDPErr, pDPErr, pDPErr, pDandP, pDPErr, pDPErr, ,,,,,], [ pChE, pDPErr, pChE, pExCon, pDPErr, pChE, pChE, pDandP, pChE, pChE, ,,,,,], [ pDxorP, nd, pChE, pExCon, pDPErr, pChE, pDxorP, pDandP, pDxorP, pDxorP, ,,,,,], [ pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, pDandP, ,,,,,], [ pBCExcl, pBCErr, pExcl, pExCon, pDPErr, pChE, pDxorP, pDandP, pBCExcl, pBCErr, ,,,,,], [ pBCErr, pBCErr, pExcl, pExCon, pDPErr, pChE, pDxorP, pDandP, pBCErr, pBCErr, ,,,,,], ,,,,, ]; mResTab: SXTechnology.ResolutionTable = [ [ sp, nd, mBCEx, mBCErr, mBCCut, mCutEx, mCut, mBCExM, mBCErrM, mBCCutM, mCutExM, mCutM,,,,], [ nd, nd, mBCExM, mBCErrM, mBCCutM, mCutExM, mCutM, mBCExM, mBCErrM, mBCCutM, mCutExM, mCutM,,,,], [ mBCEx, mBCExM, mBCErr, mBCErr, mBCCut, mBCErr, mCut, mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM,,,,], [ mBCErr, mBCErrM, mBCErr, mBCErr, mBCCut, mBCErr, mCut, mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM,,,,], [ mBCCut, mBCCutM, mBCCut, mBCCut, mBCCut, mBCCut, mCut, mBCCutM, mBCCutM, mBCCutM, mBCCutM, mCutM,,,,], [ mCutEx, mCutExM, mBCErr, mBCErr, mBCCut, mCutEx, mCut, mBCErrM, mBCErrM, mBCCutM, mCutExM, mCutM,,,,], [ mCut, mCutM, mCut, mCut, mCut, mCut, mCut, mCutM, mCutM, mCutM, mCutM, mCutM,,,,], [ mBCExM, mBCExM, mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM, mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM,,,,], [ mBCErrM, mBCErrM, mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM, mBCErrM, mBCErrM, mBCCutM, mBCErrM, mCutM,,,,], [ mBCCutM, mBCCutM, mBCCutM, mBCCutM, mBCCutM, mBCCutM, mCutM, mBCCutM, mBCCutM, mBCCutM, mBCCutM, mCutM,,,,], [ mCutExM, mCutExM, mBCErrM, mBCErrM, mBCCutM, mCutExM, mCutM, mBCErrM, mBCErrM, mBCCutM, mBCExM, mCutM,,,,], [ mCutM, mCutM, mCutM, mCutM, mCutM, mCutM, mCutM, mCutM, mCutM, mCutM, mCutM, mCutM,,,,], ,,, ]; difResolution _ SXTechnology.SetUpResolution[ dCnstr, dResTab]; polyResolution _ SXTechnology.SetUpResolution[ pCnstr, pResTab]; metResolution _ SXTechnology.SetUpResolution[ mCnstr, mResTab]; }; <> nMosHandle _ NEW[SX.TechHandle _ [numSpinifexLayers~3, layerInterestBloat~[(CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), (CDSimpleRules.MinDist[NMos.pol, NMos.pol]/2), (CDSimpleRules.MinDist[NMos.met, NMos.met]/2), ,,,,]] ]; nMosHandle.illegalLayer[NMos.dif] _ FALSE; nMosHandle.illegalLayer[NMos.pol] _ FALSE; nMosHandle.illegalLayer[NMos.met] _ FALSE; nMosHandle.illegalLayer[NMos.ovg] _ FALSE; nMosHandle.cdLayerMapping[NMos.dif] _ LIST[ [difSpinifex, (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)], [polSpinifex,difToPolExtSep,pCnstr[pExcl]]]; nMosHandle.cdLayerMapping[NMos.pol] _ LIST[ [polSpinifex,(CDSimpleRules.MinDist[NMos.pol, NMos.pol]/2)]]; nMosHandle.cdLayerMapping[NMos.met] _ LIST[ [metSpinifex,(CDSimpleRules.MinDist[NMos.met, NMos.met]/2)]]; <> nMosHandle.spinifexLayerNames[difSpinifex].layerId _ $Diffusion; nMosHandle.spinifexLayerNames[polSpinifex].layerId _ $Poly; nMosHandle.spinifexLayerNames[metSpinifex].layerId _ $Metal; <> nMosHandle.spinifexLayerNames[difSpinifex].thymeName _ "D"; nMosHandle.spinifexLayerNames[polSpinifex].thymeName _ "P"; nMosHandle.spinifexLayerNames[metSpinifex].thymeName _ "M"; <> nMosHandle.constraintResolutions[difSpinifex] _ difResolution; nMosHandle.constraintResolutions[polSpinifex] _ polyResolution; nMosHandle.constraintResolutions[metSpinifex] _ metResolution; <> spaceRuleTrigger[SX.nodeIndex] _ TRUE; widthRuleTrigger[SX.spaceIndex] _ TRUE; <> difSpaceTrigger1[SX.nodeIndex] _ TRUE; difSpaceTrigger1[dCh] _ TRUE; polWidthTrigger _ ALL[TRUE]; polWidthTrigger[ SX.nodeIndex] _ FALSE; polWidthTrigger [pDandP] _ FALSE; -- newly added by gbb polWidthTrigger[pBCErr] _ FALSE; -- added by Bowers polDifSepTriggerA[ SX.nodeIndex] _ TRUE; polDifSepTriggerB[ pExcl] _ TRUE; polDifSepTriggerB[ pExCon] _ TRUE; <> polOverDifTrigger1[ pDPErr] _ TRUE; polOverDifTrigger2 _ ALL[TRUE]; bcSpaceTrigger[mBCCut] _ TRUE; bcMetalCutSpacingTriggerA[mCut] _ TRUE; bcMetalCutSpacingTriggerB[mBCCut] _ TRUE; polBuriedSpaceTriggerA[pBCErr] _ TRUE; polBuriedSpaceTriggerA[pBCExcl] _ TRUE; polBuriedSpaceTriggerB[SX.nodeIndex] _ TRUE; polSpaceTrigger[SX.nodeIndex] _ TRUE; polSpaceTrigger[pBCErr] _ TRUE; metSpaceTrigger[SX.nodeIndex] _ TRUE; metSpaceTrigger[mBCExM] _ TRUE; metSpaceTrigger[mBCErrM] _ TRUE; metSpaceTrigger[mBCCutM] _ TRUE; metSpaceTrigger[mCutExM] _ TRUE; metSpaceTrigger[mCutM] _ TRUE; metWidthTrigger[SX.spaceIndex] _ TRUE; metWidthTrigger[mBCEx] _ TRUE; metWidthTrigger[mBCErr] _ TRUE; metWidthTrigger[mBCCut] _ TRUE; metWidthTrigger[mCutEx] _ TRUE; metWidthTrigger[mCut] _ TRUE; <> difSpacingRule _ NEW[ GeometricRule _ [extent~CDSimpleRules.MinDist[NMos.dif, NMos.dif], message~"Diffusion spacing", okIfConnected~TRUE, trigger1~difSpaceTrigger1, trigger2~spaceRuleTrigger]]; difWidthRule _ NEW[ GeometricRule _ [extent~CDSimpleRules.MinWidth[NMos.dif], message~"Diffusion width", trigger1~widthRuleTrigger, trigger2~widthRuleTrigger]]; polSpacingRule _ NEW[ GeometricRule _ [extent~CDSimpleRules.MinDist[NMos.pol, NMos.pol], message~"Poly spacing", okIfConnected~TRUE, trigger1~polSpaceTrigger, trigger2~polSpaceTrigger]]; polWidthRule _ NEW[ GeometricRule _ [extent~CDSimpleRules.MinWidth[NMos.pol], message~"Poly width", trigger1~polWidthTrigger, trigger2~polWidthTrigger]]; polDifSepRuleA _ NEW[ GeometricRule _ [extent~CDSimpleRules.MinDist[NMos.pol, NMos.dif], message~"Poly/Diffusion spacing[debug:A]", trigger1~polDifSepTriggerA, trigger2~polDifSepTriggerB]]; polDifSepRuleB _ NEW[ GeometricRule _ [extent~CDSimpleRules.MinDist[NMos.pol, NMos.dif], message~"Poly/Diffusion spacing[debug:B]", trigger1~polDifSepTriggerB, trigger2~polDifSepTriggerA]]; polOverDifRule _ NEW[ GeometricRule _ [extent~polOverDif, message~"Poly over Diffusion", trigger1~polOverDifTrigger1, trigger2~polOverDifTrigger2]]; metSpacingRule _ NEW[ GeometricRule _ [extent~CDSimpleRules.MinDist[NMos.met, NMos.met], message~"Metal spacing", okIfConnected~TRUE, trigger1~metSpaceTrigger, trigger2~metSpaceTrigger]]; metWidthRule _ NEW[ GeometricRule _ [extent~CDSimpleRules.MinWidth[NMos.met], message~"Metal width", trigger1~metWidthTrigger, trigger2~metWidthTrigger]]; bcCutSpacingRule _ NEW[ GeometricRule _ [extent: 2*trigger1~bcSpaceTrigger, trigger2~bcSpaceTrigger]]; bcMetalCutSpacingRuleA _ NEW[ GeometricRule _ [extent: 3*okIfConnected: FALSE, trigger1~bcMetalCutSpacingTriggerA, trigger2~bcMetalCutSpacingTriggerB]]; bcMetalCutSpacingRuleB _ NEW[ GeometricRule _ [extent: 3*okIfConnected: FALSE, trigger1~bcMetalCutSpacingTriggerB, trigger2~bcMetalCutSpacingTriggerA]]; polBuriedSpacingRuleA _ NEW[ GeometricRule _ [extent: okIfConnected: TRUE, trigger1~polBuriedSpaceTriggerA, trigger2~polBuriedSpaceTriggerB]]; polBuriedSpacingRuleB _ NEW[ GeometricRule _ [extent: okIfConnected: TRUE, trigger1~polBuriedSpaceTriggerB, trigger2~polBuriedSpaceTriggerA]]; detectOpaqueViolation _ NEW[ GeometricRule _ [ extent~ ALL[TRUE]]]; <> detectOpaqueViolation.trigger1[SX.violateIndex] _ FALSE; nMosHandle.rules[ difSpinifex] _ LIST[difSpacingRule, difWidthRule, detectOpaqueViolation]; nMosHandle.rules[ polSpinifex] _ LIST[polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule, polBuriedSpacingRuleA, polBuriedSpacingRuleB, detectOpaqueViolation]; nMosHandle.rules[ metSpinifex] _ LIST[metSpacingRule, metWidthRule, bcCutSpacingRule, bcMetalCutSpacingRuleA, bcMetalCutSpacingRuleB, detectOpaqueViolation]; <> SXTechnology.RegisterTechnologyHandle[cdTech~ NMos.nmos, technologyHandle~ nMosHandle]; <> SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosTransistor, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor, fini~SXOutputPrivate.UnNameTransType]; SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosATransistor, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor]; SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosPullUp, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor]; SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosContactDifAndPol, conv~ConvertNMosContactDifAndPol]; SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosContactBut, conv~ConvertNMosButtingContact]; SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosBurContact, conv~ConvertNMosBuriedContact]; SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosMmContact, conv~ConvertNMosMmContact]; }; Init[]; TerminalIO.PutRope["nMos technology parameters Loaded\n"]; END. <> < $Conflict.>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>>