<> <> <> <> 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 <<-- New Regime Transistor converters (IE the Shand unified xstr representaion)>> 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! <<-- Add poly boxes>> 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]; <<-- Add rects for poly exclusion>> IF p.lExt-difToPolSep > 0 THEN { <<-- At the top>> [] _ 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]; <<-- ... and the bottom>> [] _ 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] }; <<-- Add rects for channel lead-in.>> <<-- At the top>> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt+p.length, size.x-polExt, p.lExt+p.length+difToPolSep], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; <<-- ... and the bottom>> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, p.lExt-difToPolSep, size.x-p.wExt, p.lExt], appl~appl, pos~ pos, orient~ orient, value~channelEdge]; <<-- Fill channel gap>> [] _ 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- p.lExt+p.length], appl~appl, pos~ pos, orient~ orient, value~difChannel]; <<-- Add rects for diff width spacing and connection>> 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* 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 } }; <<-- Add Linkages for transistor.>> xstr _ cir.CreateLinkage[appl]; <<-- We're a lot smarter than this program, so let's adjust the area and perim values its got.>> 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]; }; <<-- Contact converters>> 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 ~ 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]; <<-- Add rect for poly exclusion>> [] _ 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]; <<-- Add rect for diff width spacing and connection>> [] _ 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* pos, orient~ orient]; SELECT TRUE FROM cp.lExt < 2* <> wex: CD.DesignNumber ~ MAX[cp.wExt+ lex: CD.DesignNumber ~ MAX[cp.lExt+ [] _ cir.AddRect[ lev~appl.ob.level, dim~[ [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2* value~channelEdge]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2* [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[2* }; cp.lExt < 2* <> lex: CD.DesignNumber ~ MAX[cp.lExt+ [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[2* [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2* value~polAndDif]; <> [] _ cir.AddRect[ lev~appl.ob.level, dim~[ [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2* value~channelEdge]; <> [] _ cir.AddRect[ lev~appl.ob.level, dim~[s.x-cp.wExt, lex, s.x-(cp.wExt- 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* <> wex: CD.DesignNumber ~ MAX[cp.wExt+ lex: CD.DesignNumber ~ cp.lExt- [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[2* value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2* value~polAndDif]; <> [] _ cir.AddRect[ lev~appl.ob.level, dim~[ [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2* value~channelEdge]; <> [] _ cir.AddRect[ lev~appl.ob.level, dim~[2* [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2* orient~ orient, value~channelEdge]; <> [] _ cir.AddRect[ lev~appl.ob.level, dim~[2* [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2* value~channelEdge]; }; cp.lExt >= 2* <> 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* defaultL: INTEGER ~ 2* 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/ 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/ }; stream.PutRope[ "];"]; }; <<-- Module Initialization>> nMosHandle: REF SpinifexCircuit.TechHandle; difSpinifex: SpinifexCircuit.SpinifexLayerIndex ~ 0; polSpinifex: SpinifexCircuit.SpinifexLayerIndex ~ 1; metSpinifex: SpinifexCircuit.SpinifexLayerIndex ~ 2; <<-- These numbers are halved (sorry about any confusion this may cause)>> difSep: CD.DesignNumber~3* difToPolExtSep: CD.DesignNumber~0; polSep: CD.DesignNumber~ metSep: CD.DesignNumber~3* difToPolSep: CD.DesignNumber~difToPolExtSep+polSep; -- not halved! contactWidth: CD.DesignNumber~4* 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; <<-- Layer Constraints.>> 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]]; <<-- Basic nMosHandle & cdLayerMappings.>> 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]; <<-- Thyme stray capacitance layer names.>> nMosHandle.spinifexLayerNames[difSpinifex].thymeName _ "D"; nMosHandle.spinifexLayerNames[polSpinifex].thymeName _ "P"; nMosHandle.spinifexLayerNames[metSpinifex].thymeName _ "M"; <<-- Geometric rule triggers.>> 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; <<-- 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.>> polOverDifTrigger1[ polDifError.index] _ TRUE; polOverDifTrigger2 _ ALL[TRUE]; <<-- The geometric rules.>> difSpacingRule _ NEW[ GeometricRule _ [extent~3*trigger2~spaceRuleTrigger]]; difWidthRule _ NEW[ GeometricRule _ [extent~2* polSpacingRule _ NEW[ GeometricRule _ [extent~2*trigger2~spaceRuleTrigger]]; polWidthRule _ NEW[ GeometricRule _ [extent~2* polDifSepRuleA _ NEW[ GeometricRule _ [extent~trigger2~polDifSepTrigger2]]; polDifSepRuleB _ NEW[ GeometricRule _ [extent~trigger2~polDifSepTrigger1]]; polOverDifRule _ NEW[ GeometricRule _ [extent~trigger2~polOverDifTrigger2]]; metSpacingRule _ NEW[ GeometricRule _ [extent~3*trigger2~spaceRuleTrigger]]; metWidthRule _ NEW[ GeometricRule _ [extent~3* nMosHandle.rules[ difSpinifex] _ LIST[difSpacingRule, difWidthRule]; nMosHandle.rules[ polSpinifex] _ LIST[polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule]; nMosHandle.rules[ metSpinifex] _ LIST[metSpacingRule, metWidthRule]; <<-- Technology specific objects.>> 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.