DIRECTORY CD USING [lambda, Rect, DesignNumber, DesignPosition, DesignRect, Level, ObjectProcs, FetchObjectProcs, ApplicationPtr, highLightError, Error], CDObjectProcs USING [RegisterFurther, StoreFurther], CDInline USING [RectAt], CDProperties USING [PutPropOnTechnology], TerminalIO USING [WriteRope], NMos USING [nmos, dif, pol, met, ovg, cut], NMosTransistors USING [TransistorPtr, enhancement, strongDepletion], NMosContacts USING [ContactPtr], IO USING [PutRope, Put, PutF, char, int, rope], Rope USING [Cat, ROPE], SpinifexAtoms USING [ spinifex, thymePrint, rosePrint], SpinifexCircuit USING [Circuit, NodeLinkage, CircuitNode, CircuitConstraint, ConstraintResolution, SpinifexLayerIndex, TechHandle, MapRec, ConversionProc, AddRect, AddBox, CreateLinkage, LinkageAttach, IllegalConstruct, RectDelta, GeometricRule, SpinifexConstraintIndex, spaceIndex, nodeIndex, AttachedNode, AdjustNode, MergeNode], SpinifexOutput USING [LinkagePrintProc], SpinifexExtras USING [ProcessMosTransistor, PerDrawRectProc, SWNGrow, NESGrow, WNEGrow, ESWGrow, ReportDifProc] ; NMosSpinifex: CEDAR PROGRAM IMPORTS NMos, CD, CDObjectProcs, TerminalIO, CDInline, CDProperties, IO, Rope, SpinifexAtoms, SpinifexCircuit, SpinifexExtras ~ BEGIN l: CD.DesignNumber ~ CD.lambda; ConvertNMosTransistor: SpinifexCircuit.ConversionProc -- [appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, cir: REF ] -- ~ { p: NMosTransistors.TransistorPtr = NARROW[appl.ob.specificRef]; size: CD.DesignPosition _ appl.ob.size; xstr: REF SpinifexCircuit.NodeLinkage; gateNode, sourceNode, drainNode, metNode: REF SpinifexCircuit.CircuitNode; polExt: CD.DesignNumber ~ 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], appl~appl, pos~ pos, orient~ orient, interestBloat~SpinifexExtras.SWNGrow[polSep]]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt, size.x-polExt, p.lExt+p.length], appl~appl, pos~ pos, orient~ orient, value~gateNode]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[size.x-polExt, p.lExt, size.x, p.lExt+p.length], appl~appl, pos~ pos, orient~ orient, interestBloat~SpinifexExtras.NESGrow[polSep], value~gateNode]; IF p.lExt-difToPolSep > 0 THEN { [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt+p.length+difToPolSep, size.x-polExt, size.y], appl~appl, pos~ pos, orient~ orient, interestBloat~SpinifexExtras.WNEGrow[ difToPolExtSep], value~excludePol]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, 0, size.x-p.wExt, p.lExt-difToPolSep], appl~appl, pos~ pos, orient~ orient, interestBloat~SpinifexExtras.ESWGrow[ difToPolExtSep], value~excludePol] }; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt+p.length, size.x-polExt, p.lExt+p.length+difToPolSep], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, p.lExt-difToPolSep, size.x-p.wExt, p.lExt], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[p.wExt, p.lExt, size.x-p.wExt, p.lExt+p.length], appl~appl, pos~ pos, orient~ orient, value~difChannel]; IF polExt < p.wExt THEN [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[polExt, p.lExt+p.length-l, size.x-polExt, p.lExt+p.length], appl~appl, pos~ pos, orient~ orient, value~difChannel]; sourceNode _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[polExt, p.lExt+p.length, size.x-polExt, size.y], appl~appl, pos~ pos, orient~ orient, interestBloat~SpinifexExtras.WNEGrow[difSep]]; drainNode _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[p.wExt, 0, size.x-p.wExt, p.lExt], appl~appl, pos~ pos, orient~ orient, interestBloat~SpinifexExtras.ESWGrow[difSep]]; IF p.pullup THEN { metNode _ cir.AddRect[ lev~NMos.met, dim~[ (size.x-contactWidth)/2, size.y-6*l, (size.x+contactWidth)/2, size.y], appl~appl, pos~ pos, orient~ orient]; } ELSE metNode _ NIL } ELSE { -- Oh no not a bent transistor yetcchh! sourceDrainList: LIST OF REF SpinifexCircuit.CircuitNode; sourceDrainCount: INTEGER; sourceHint: REF SpinifexCircuit.CircuitNode _ NIL; NoteSourceHint: SpinifexExtras.ReportDifProc ~ { sourceHint _ difNode }; [gateNode, sourceDrainList, sourceDrainCount] _ SpinifexExtras.ProcessMosTransistor[appl, pos, orient, cir, difSpinifex, polSpinifex, difChannel, channelEdge, difToPolSep, MapMaterial, cir, NoteSourceHint]; IF sourceDrainCount = 2 THEN { sourceNode _ sourceDrainList.first; drainNode _ sourceDrainList.rest.first; IF p.pullup THEN { SELECT sourceHint FROM sourceNode => NULL; drainNode => { drainNode _ sourceNode; sourceNode _ sourceHint }; ENDCASE => ERROR -- Including case when sourceHint = NIL } } ELSE { TerminalIO.WriteRope[ Rope.Cat["Xstr with ", (SELECT sourceDrainCount FROM 0 => "no", 1 => "only 1", ENDCASE => "more than 2"), " sources/drains not included in circuit description\n"]]; RETURN } }; xstr _ cir.CreateLinkage[appl]; SpinifexCircuit.AdjustNode[ gateNode, polSpinifex, size.y*p.length, (size.y+p.length)*2, absolute]; SpinifexCircuit.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. SpinifexCircuit.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; }; SpinifexCircuit.LinkageAttach[link~xstr, attachType~$Gate, node~gateNode]; SpinifexCircuit.LinkageAttach[link~xstr, attachType~$Source, node~sourceNode]; SpinifexCircuit.LinkageAttach[link~xstr, attachType~$Drain, node~drainNode]; }; MapMaterial: SpinifexExtras.PerDrawRectProc -- [r: CD.DesignRect, l: CD.Level, data: REF ANY] RETURNS [TransistorMaterial] -- ~ { cir: REF SpinifexCircuit.Circuit ~ NARROW[ data, REF SpinifexCircuit.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: SpinifexCircuit.ConversionProc -- [appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, cir: REF SpinifexCircuit.Circuit] -- ~ { box: CD.Rect _ CDInline.RectAt[pos~[0,0], size~appl.ob.size]; node: REF SpinifexCircuit.CircuitNode; node _ cir.AddRect[ lev~NMos.met, dim~box, appl~appl, pos~ pos, orient~ orient]; [] _ cir.AddRect[ lev~appl.ob.level, dim~box, appl~appl, pos~ pos, orient~ orient, value~node]; }; ConvertNMosButtingContact: SpinifexCircuit.ConversionProc -- [appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, cir: REF SpinifexCircuit.Circuit] -- ~ { rimWidth: CD.DesignNumber ~ l; polSize: CD.DesignNumber ~ appl.ob.size.y/2; box: CD.Rect _ CDInline.RectAt[pos~[0,0], size~appl.ob.size]; node: REF SpinifexCircuit.CircuitNode; node _ cir.AddRect[ lev~NMos.met, dim~box, appl~appl, pos~ pos, orient~ orient]; [] _ cir.AddRect[ lev~NMos.pol, dim~[0,0, appl.ob.size.x, polSize], appl~appl, pos~ pos, orient~ orient, value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[-rimWidth,polSize, appl.ob.size.x+rimWidth, polSize+difToPolSep], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[-rimWidth,polSize-rimWidth, 0, polSize], appl~appl, pos~ pos, orient~ orient, value~polXorDif]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[appl.ob.size.x,polSize-rimWidth, appl.ob.size.x+rimWidth, polSize], appl~appl, pos~ pos, orient~ orient, value~polXorDif]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[0,polSize+difToPolSep, appl.ob.size.x, appl.ob.size.y], appl~appl, pos~ pos, orient~ orient, interestBloat~SpinifexExtras.WNEGrow[ difToPolExtSep], value~excludePol]; [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[0,polSize, appl.ob.size.x, appl.ob.size.y], appl~appl, pos~ pos, orient~ orient, interestBloat~[ difSep, difSep, difSep, difSep], value~node]; }; ConvertNMosBuriedContact: SpinifexCircuit.ConversionProc -- [appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, cir: REF SpinifexCircuit.Circuit] -- ~ { s: CD.DesignPosition ~ appl.ob.size; cp: NMosContacts.ContactPtr ~ NARROW[appl.ob.specificRef]; node: REF SpinifexCircuit.CircuitNode ~ cir.AddRect[ lev~NMos.pol, dim~[2*l, cp.lExt, s.x-cp.wExt, s.y-cp.lExt], appl~appl, pos~ pos, orient~ orient]; SELECT TRUE FROM cp.lExt < 2*l AND cp.wExt < 2*l => { wex: CD.DesignNumber ~ MAX[cp.wExt+l, 2*l]; lex: CD.DesignNumber ~ MAX[cp.lExt+l, 2*l]; [] _ cir.AddRect[ lev~appl.ob.level, dim~[l, lex, 2*l, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2*l-difToPolSep, lex, 2*l, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2*l, lex, s.x-wex, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~polAndDif]; [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[2*l, lex, s.x-wex, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~node]; }; cp.lExt < 2*l AND cp.wExt >= 2*l => { lex: CD.DesignNumber ~ MAX[cp.lExt+l, 2*l]; [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[2*l, lex, s.x-cp.wExt, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2*l, lex, s.x-cp.wExt, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~polAndDif]; [] _ cir.AddRect[ lev~appl.ob.level, dim~[l, lex, 2*l, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2*l-difToPolSep, lex, 2*l, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; [] _ cir.AddRect[ lev~appl.ob.level, dim~[s.x-cp.wExt, lex, s.x-(cp.wExt-l), s.y-lex], appl~appl, pos~ pos, orient~ orient, value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[s.x-cp.wExt, lex, s.x-(cp.wExt-difToPolSep), s.y-lex], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; }; cp.lExt >= 2*l AND cp.wExt < 2*l => { wex: CD.DesignNumber ~ MAX[cp.wExt+l, 2*l]; lex: CD.DesignNumber ~ cp.lExt-l; [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[2*l, cp.lExt, s.x-cp.wExt, s.y-cp.lExt], appl~appl, pos~ pos, orient~ orient, value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2*l, cp.lExt, s.x-cp.wExt, s.y-cp.lExt], appl~appl, pos~ pos, orient~ orient, value~polAndDif]; [] _ cir.AddRect[ lev~appl.ob.level, dim~[l, lex, 2*l, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2*l-difToPolSep, lex, 2*l, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; [] _ cir.AddRect[ lev~appl.ob.level, dim~[2*l, s.y-cp.lExt, s.x-wex, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2*l, s.y-cp.lExt, s.x-wex, s.y-(cp.lExt-difToPolSep)], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; [] _ cir.AddRect[ lev~appl.ob.level, dim~[2*l, lex, s.x-wex, cp.lExt], appl~appl, pos~ pos, orient~ orient, value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2*l, cp.lExt-difToPolSep, s.x-wex, cp.lExt], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; }; cp.lExt >= 2*l AND cp.wExt >= 2*l => { ERROR SpinifexCircuit.IllegalConstruct[appl.ob.p.insideRect[appl.ob], "Polysilicon surrounded by diffusion or all sides in Buried Contact"]; }; ENDCASE => ERROR; }; RoseNMosTransistor: SpinifexOutput.LinkagePrintProc -- [ stream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc] -- ~ { PrintAttachment: PROCEDURE [ key: ATOM, portName: Rope.ROPE] ~ { stream.Put[ IO.rope[" (\""], IO.rope[portName], IO.rope["\" "]]; FOR attachments: LIST OF REF SpinifexCircuit.AttachedNode _ linkage.nodes, attachments.rest WHILE attachments # NIL DO IF attachments.first.attachmentType = key THEN { PrintNode[stream, attachments.first.node]; stream.PutRope[")"]; RETURN } ENDLOOP; stream.PutRope[ "\"?\")"]; }; p: NMosTransistors.TransistorPtr ~ NARROW[ linkage.source.ob.specificRef]; stream.Put[ IO.rope["(C "], IO.rope[name], IO.rope[" \"Transistor[strength: drive, positive: TRUE, mode: "]]; stream.PutRope[ IF p.pullup THEN "Depletion" ELSE SELECT linkage.source.ob.level FROM NMosTransistors.enhancement => "Enhancement", NMosTransistors.strongDepletion => "Depletion", ENDCASE => "UNKNOWN" ]; stream.Put[ IO.rope[", unidirectional: UNKNOWN, biased: FALSE, offStrength: "], IO.rope[IF p.pullup THEN "weak" ELSE SELECT linkage.source.ob.level FROM NMosTransistors.enhancement => "none", NMosTransistors.strongDepletion => "weak", ENDCASE => "UNKNOWN"], IO.rope["]\""] ]; PrintAttachment[ $Gate, "gate"]; PrintAttachment[ $Source, "in"]; PrintAttachment[ $Drain, "out"]; stream.PutRope[ ")"] }; ThymeNMosTransistor: SpinifexOutput.LinkagePrintProc -- [ stream: IO.STREAM, linkage: REF NodeLinkage, PrintNode: NodePrintProc] -- ~ { PrintAttachment: PROCEDURE [ key: ATOM] ~ { FOR attachments: LIST OF REF SpinifexCircuit.AttachedNode _ linkage.nodes, attachments.rest WHILE attachments # NIL DO IF attachments.first.attachmentType = key THEN { PrintNode[stream, attachments.first.node]; RETURN } ENDLOOP; stream.Put[ IO.char['?]]; }; p: NMosTransistors.TransistorPtr ~ NARROW[ linkage.source.ob.specificRef]; defaultW: INTEGER ~ 2*l; defaultL: INTEGER ~ 2*l; stream.Put[ IO.rope[name], IO.rope[": "]]; stream.PutRope[ IF ~p.pullup THEN SELECT p.implant FROM NMosTransistors.enhancement => "ETrans[", NMosTransistors.strongDepletion => "DTrans[", ENDCASE => "FunnyTrans[" ELSE "DTrans[" ]; PrintAttachment[ $Gate]; stream.Put[ IO.char[',]]; PrintAttachment[ $Source]; stream.Put[ IO.char[',]]; PrintAttachment[ $Drain]; IF p.width # defaultW OR p.length # defaultL THEN { stream.Put[ IO.char['|]]; IF p.width # defaultW THEN stream.PutF[" W_%g", IO.int[p.width/l]]; IF p.width # defaultW AND p.length # defaultL THEN stream.Put[ IO.char[',]]; IF p.length # defaultL THEN stream.PutF[" L_%g", IO.int[p.length/l]] }; stream.PutRope[ "];"]; }; nMosHandle: REF SpinifexCircuit.TechHandle; difSpinifex: SpinifexCircuit.SpinifexLayerIndex ~ 0; polSpinifex: SpinifexCircuit.SpinifexLayerIndex ~ 1; metSpinifex: SpinifexCircuit.SpinifexLayerIndex ~ 2; difSep: CD.DesignNumber~3*l/2; difToPolExtSep: CD.DesignNumber~0; polSep: CD.DesignNumber~l; metSep: CD.DesignNumber~3*l/2; difToPolSep: CD.DesignNumber~difToPolExtSep+polSep; -- not halved! contactWidth: CD.DesignNumber~4*l; CircuitConstraint: TYPE ~ SpinifexCircuit.CircuitConstraint; excludePol: REF CircuitConstraint; polXorDif: REF CircuitConstraint; polAndDif: REF CircuitConstraint; channelEdge: REF CircuitConstraint; difChannel: REF CircuitConstraint; polDifError: REF CircuitConstraint; Init: PROCEDURE ~ { ObjConverter: PROCEDURE [objectType: ATOM, conv: SpinifexCircuit.ConversionProc, thyme: SpinifexOutput.LinkagePrintProc _ NIL, rose: SpinifexOutput.LinkagePrintProc _ NIL] ~ { op: REF CD.ObjectProcs; IF (op_CD.FetchObjectProcs[ objectType~objectType, technology~NMos.nmos]) = NIL THEN ERROR; CDObjectProcs.StoreFurther[ p~op, key~SpinifexAtoms.spinifex, value~ NEW[SpinifexCircuit.ConversionProc_conv]]; IF thyme # NIL THEN CDObjectProcs.StoreFurther[ p~op, key~SpinifexAtoms.thymePrint, value~ NEW[SpinifexOutput.LinkagePrintProc_thyme]]; IF rose # NIL THEN CDObjectProcs.StoreFurther[ p~op, key~SpinifexAtoms.rosePrint, value~ NEW[SpinifexOutput.LinkagePrintProc_thyme]]; }; GeometricRule: TYPE ~ SpinifexCircuit.GeometricRule; difSpacingRule, difWidthRule: REF GeometricRule; polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule: REF GeometricRule; metSpacingRule, metWidthRule: REF GeometricRule; TriggerMap: TYPE ~ PACKED ARRAY SpinifexCircuit.SpinifexConstraintIndex OF BOOLEAN _ ALL[FALSE]; spaceRuleTrigger: TriggerMap; widthRuleTrigger: TriggerMap; polOverDifTrigger1, polOverDifTrigger2, polDifSepTrigger1, polDifSepTrigger2: TriggerMap; difSpaceTrigger1: TriggerMap; polWidthTrigger: TriggerMap; difChannel _ NEW[ CircuitConstraint _ [ $DifChannel, 2]]; channelEdge _ NEW[ CircuitConstraint _ [ $ChannelEdge, SpinifexCircuit.spaceIndex]]; excludePol _ NEW[ CircuitConstraint _ [ $ExcludePol, 2]]; polXorDif _ NEW[ CircuitConstraint _ [ $PolXorDif, SpinifexCircuit.spaceIndex]]; polAndDif _ NEW[ CircuitConstraint _ [ $polAndDif, SpinifexCircuit.nodeIndex]]; polDifError _ NEW[ CircuitConstraint _ [ $PolDifError, 3]]; excludePol.withNode _ channelEdge.withNode _ polDifError.withNode _ polDifError; channelEdge.withConstraint _ LIST[ [excludePol, channelEdge]]; polDifError.withConstraint _ LIST[ [excludePol, polDifError], [channelEdge, polDifError]]; polXorDif.withConstraint _ LIST[ [excludePol, channelEdge]]; polAndDif.withNode _ polAndDif; polAndDif.withConstraint _ LIST[ [excludePol, polAndDif], [polXorDif, polAndDif], [polDifError, polAndDif], [channelEdge, polAndDif]]; nMosHandle _ NEW[SpinifexCircuit.TechHandle _ [ errorLevel~CD.highLightError, numSpinifexLayers~3, layerInterestBloat~[difSep,polSep,metSep,,,,,]] ]; nMosHandle.illegalLevel[NMos.dif] _ FALSE; nMosHandle.illegalLevel[NMos.pol] _ FALSE; nMosHandle.illegalLevel[NMos.met] _ FALSE; nMosHandle.illegalLevel[NMos.ovg] _ FALSE; nMosHandle.cdLayerMapping[NMos.dif] _ LIST[ [difSpinifex,difSep], [polSpinifex,difToPolExtSep,excludePol]]; nMosHandle.cdLayerMapping[NMos.pol] _ LIST[ [polSpinifex,polSep]]; nMosHandle.cdLayerMapping[NMos.met] _ LIST[ [metSpinifex,metSep]]; CDProperties.PutPropOnTechnology[onto~ NMos.nmos, prop~SpinifexAtoms.spinifex, val~nMosHandle]; nMosHandle.spinifexLayerNames[difSpinifex].thymeName _ "D"; nMosHandle.spinifexLayerNames[polSpinifex].thymeName _ "P"; nMosHandle.spinifexLayerNames[metSpinifex].thymeName _ "M"; spaceRuleTrigger[SpinifexCircuit.nodeIndex] _ TRUE; widthRuleTrigger[SpinifexCircuit.spaceIndex] _ TRUE; difSpaceTrigger1[SpinifexCircuit.nodeIndex] _ TRUE; difSpaceTrigger1[2] _ TRUE; polWidthTrigger[SpinifexCircuit.spaceIndex] _ TRUE; polWidthTrigger[2] _ TRUE; polDifSepTrigger1[ SpinifexCircuit.nodeIndex] _ TRUE; polDifSepTrigger2[ excludePol.index] _ TRUE; polOverDifTrigger1[ polDifError.index] _ TRUE; polOverDifTrigger2 _ ALL[TRUE]; difSpacingRule _ NEW[ GeometricRule _ [extent~3*l, message~"Diffusion spacing", okIfConnected~TRUE, trigger1~difSpaceTrigger1, trigger2~spaceRuleTrigger]]; difWidthRule _ NEW[ GeometricRule _ [extent~2*l, message~"Diffusion width", trigger1~widthRuleTrigger, trigger2~widthRuleTrigger]]; polSpacingRule _ NEW[ GeometricRule _ [extent~2*l, message~"Poly spacing", okIfConnected~TRUE, trigger1~spaceRuleTrigger, trigger2~spaceRuleTrigger]]; polWidthRule _ NEW[ GeometricRule _ [extent~2*l, message~"Poly width", trigger1~polWidthTrigger, trigger2~polWidthTrigger]]; polDifSepRuleA _ NEW[ GeometricRule _ [extent~l, message~"Poly/Diffusion spacing[debug:A]", trigger1~polDifSepTrigger1, trigger2~polDifSepTrigger2]]; polDifSepRuleB _ NEW[ GeometricRule _ [extent~l, message~"Poly/Diffusion spacing[debug:B]", trigger1~polDifSepTrigger2, trigger2~polDifSepTrigger1]]; polOverDifRule _ NEW[ GeometricRule _ [extent~l, message~"Poly over Diffusion", trigger1~polOverDifTrigger1, trigger2~polOverDifTrigger2]]; metSpacingRule _ NEW[ GeometricRule _ [extent~3*l, message~"Metal spacing", okIfConnected~TRUE, trigger1~spaceRuleTrigger, trigger2~spaceRuleTrigger]]; metWidthRule _ NEW[ GeometricRule _ [extent~3*l, message~"Metal width", trigger1~widthRuleTrigger, trigger2~widthRuleTrigger]]; nMosHandle.rules[ difSpinifex] _ LIST[difSpacingRule, difWidthRule]; nMosHandle.rules[ polSpinifex] _ LIST[polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule]; nMosHandle.rules[ metSpinifex] _ LIST[metSpacingRule, metWidthRule]; CDObjectProcs.RegisterFurther[key~SpinifexAtoms.spinifex, technology~NMos.nmos ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~SpinifexAtoms.thymePrint, technology~NMos.nmos ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~SpinifexAtoms.rosePrint, technology~NMos.nmos ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; ObjConverter[ objectType~$NMosTransistor, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor]; ObjConverter[ objectType~$NMosATransistor, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor]; ObjConverter[ objectType~$NMosPullUp, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor]; ObjConverter[ objectType~$NMosContactDifAndPol, conv~ConvertNMosContactDifAndPol]; ObjConverter[ objectType~$NMosContactBut, conv~ConvertNMosButtingContact]; ObjConverter[ objectType~$NMosBurContact, conv~ConvertNMosBuriedContact]; }; Init[]; TerminalIO.WriteRope["nMos technology parameters Loaded\n"]; END. NMosSpinifex.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Written by Shand, September 12, 1983 11:40 pm Last Edited by: Shand, September 2, 1984 5:42:21 pm PDT -- New Regime Transistor converters (IE the Shand unified xstr representaion) IF p.bendList = NIL THEN { -- Oh this is easy! -- Add poly boxes -- Add rects for poly exclusion -- At the top -- ... and the bottom -- Add rects for channel lead-in. -- At the top -- ... and the bottom -- Fill channel gap -- Add rects for diff width spacing and connection -- Add Linkages for transistor. -- We're a lot smarter than this program, so let's adjust the area and perim values its got. -- Contact converters -- Add rect for poly exclusion -- Add rect for diff width spacing and connection Buried contacts come in three flavours, Pol-Surround, Dif-Surround and Crossing. The buried contacts in chipndale are parameterized by lExt and wExt, their interpretation is as follows: Diff always extends 1l to the left, material above/below and to the right is determined by lExt and wExt respectively. 2l is the pivotal value, below 2l the material is Pol, at 2l or above the material is Diff. (Note: some combinations give Diff on all four sides, it is assumed that such combinations will not be created.) Polysilicon Surround Polysilicon/Diffusion Crossing. Left side. Right side. Diffusion Surround Left side. Top. Bottom. Diffusion Surround ! on all sides ??? -- Module Initialization -- These numbers are halved (sorry about any confusion this may cause) -- Layer Constraints. -- Basic nMosHandle & cdLayerMappings. -- Thyme stray capacitance layer names. -- Geometric rule triggers. Corners are defined by union of dif and gate, but checking only looks at dif -- What follows is a real hack! Purely local errors are not handled in a natural manner by my scheme, so for every corner we find in polDifError 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. -- Technology specific objects. ÊB˜code™Kšœ Ïmœ1™˜ˆKšœ ˜ Kšœ˜—šœ  œžœ  œ˜%Kš¤™Kš œžœžœ  œ œ˜+Kšœžœ œ˜!Kšœ3 œW˜‹Kšœ1 œ\˜K™ Kšœ* œ  œ=˜rKšœ3 œ œD˜ŽK™Kšœ, œS˜€Kšœ3 œl˜ K™Kšœ, œK˜xKšœ3 œb˜–Kšœ˜—šœ  œžœ œ˜&Kš¤%™%Kšžœ‡˜ŒKšœ˜—Kšžœžœ˜—K˜—š¡œ"£¢Y£œ˜—š¡œž œžœžœ˜@Kšœ žœ2˜@š žœžœžœžœ@žœžœž˜všžœ(žœ˜0Kšœ*˜*Kšœ˜Kšž˜K˜—Kšžœ˜—Kšœ˜K˜—Lšœ#žœ!˜JLšœ žœžœ žœ@˜mšœžœ žœ ž˜1šžœž˜#Kšœ-˜-Kšœ/˜/Kšžœ ˜—K˜—šœ ˜ KšžœA˜Cšœžœ žœž˜$šžœž˜#Kšœ&˜&Kšœ*˜*Kšžœ˜——Kšœ˜Kšœ˜—Kšœ ˜ K˜ K˜ Kšœ˜K˜—š¡œ"£¢H£œ˜‡š¡œž œžœ˜+š žœžœžœžœ@žœžœž˜všžœ(žœ˜0Kšœ*˜*Kšž˜K˜—Kšžœ˜—Kšœ žœ ˜K˜—Lšœ#žœ!˜JKšœ žœ œ˜Kšœ žœ œ˜Lšœ žœ žœ ˜*šœžœ ž˜!šžœ ž˜Kšœ)˜)Kšœ-˜-Jšžœ˜—šž˜Jšœ ˜ —J˜—Kšœ˜Kšœ˜K˜Kšœ˜K˜šžœžœžœ˜3Kšœ˜Kšžœžœ% œ˜CKšžœžœžœ žœ ˜LKšžœžœžœ œ˜DK˜—Kšœ˜K˜—LšÏl™Lšœ žœ˜+Lšœ4˜4Kšœ4˜4Kšœ4˜4LšœF™FLšœžœ œ˜Kšœžœ˜"Kšœžœ œ˜Kšœžœ œ˜Kšœ žœ&£˜CKšœžœ œ˜"Lšœžœ%˜Kšœžœ9˜ZKšœžœ˜