<> <> <> <> <> <> <> <> DIRECTORY CD USING [Instance, lambda, Layer, Number, Position, Rect], CDBasics USING [RectAt], CDInstances USING [InstRectO], CDProperties USING [GetPropFromInstance], CDSimpleRules, Core USING [CellType], CoreOps USING [CreateRecordWire], CDOrient USING [CreateTransform], CoreProperties USING [PutProp], CoreRecord USING [CellInstance, CellInstanceList, CellInstanceRec], CoreTransistor USING [Create, Transistor, TransistorRec], ImagerTransformation USING [Transformation], IO USING [char, int, Put, PutF, PutRope, rope], NMos USING [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], SXAtoms USING [cdCellHint, crystalAttr, instanceTransf], SXNMosBasicRules, SXOutput USING [LinkageHousekeeper, LinkagePrintProc], SXOutputPrivate USING [coreCellInstance, coreDesign, coreNodeBuffer, GetANaming, InsertNode, NameTransType, Naming, PrintNaming, PrintRoseInstantiationTransformation, UnNameTransType], SXQuadTree USING [RectDelta], SXTechnology USING [ESWGrow, NESGrow, PerDrawRectProc, ProcessMosTransistor, RegisterSpinifexObjectProcs, RegisterTechnologyHandle, ReportDifProc, ResolutionTable, SetUpResolution, SWNGrow, WNEGrow], TerminalIO USING [WriteRope] ; SXNMos: CEDAR PROGRAM IMPORTS CDBasics, CDInstances, CDOrient, CDProperties, CDSimpleRules, CoreOps, CoreProperties, CoreTransistor, IO, NMos, Rope, SX, SXAtoms, SXOutputPrivate, SXTechnology, TerminalIO = BEGIN <<-- New Regime Transistor converters (IE the Shand unified xstr representaion)>> ConvertNMosTransistor: SX.ConversionProc -- [appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF ] -- ~ { p: NMosTransistors.TransistorPtr = NARROW[inst.ob.specificRef]; size: CD.Position _ inst.ob.size; xstr: REF SX.NodeLinkage; gateNode, sourceNode, drainNode, metNode: REF SX.CircuitNode; polExt: CD.Number ~ IF p.pullup THEN MIN[ (size.x-SXNMosBasicRules.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], inst~inst, pos~ pos, orient~ orient, 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], inst~inst, pos~ pos, orient~ orient, value~gateNode]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[size.x-polExt, p.lExt, size.x, p.lExt+p.length], inst~inst, pos~ pos, orient~ orient, interestBloat~SXTechnology.NESGrow[(CDSimpleRules.MinDist[NMos.pol, NMos.pol]/2)], value~gateNode]; <<-- Add rects for poly exclusion>> IF p.lExt-SXNMosBasicRules.difToPolSep > 0 THEN { <<-- At the top>> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[polExt, p.lExt+p.length+SXNMosBasicRules.difToPolSep, size.x-polExt, size.y], inst~inst, pos~ pos, orient~ orient, interestBloat~SXTechnology.WNEGrow[ SXNMosBasicRules.difToPolExtSep], value~pCnstr[pExcl]]; <<-- ... and the bottom>> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, 0, size.x-p.wExt, p.lExt-SXNMosBasicRules.difToPolSep], inst~inst, pos~ pos, orient~ orient, interestBloat~SXTechnology.ESWGrow[ SXNMosBasicRules.difToPolExtSep], value~pCnstr[pExcl]] }; <<-- 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+SXNMosBasicRules.difToPolSep], inst~inst, pos~ pos, orient~ orient, value~pCnstr[pChE]]; <<-- ... and the bottom>> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[p.wExt, p.lExt-SXNMosBasicRules.difToPolSep, size.x-p.wExt, p.lExt], inst~inst, pos~ pos, orient~ orient, value~pCnstr[pChE]]; <<-- Fill channel gap>> [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[p.wExt, p.lExt, size.x-p.wExt, p.lExt+p.length], inst~inst, pos~ pos, orient~ orient, 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], inst~inst, pos~ pos, orient~ orient, 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]]; <<-- Add rects for diff width spacing and connection>> sourceNode _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[polExt, p.lExt+p.length, size.x-polExt, size.y], inst~inst, pos~ pos, orient~ orient, 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], inst~inst, pos~ pos, orient~ orient, interestBloat~SXTechnology.ESWGrow[(CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2)]]; IF p.pullup THEN { metNode _ cir.AddRect[ lev~NMos.met, dim~[ (size.x-SXNMosBasicRules.contactWidth)/2, size.y-6* (size.x+SXNMosBasicRules.contactWidth)/2, size.y], inst~inst, pos~ pos, orient~ orient]; } 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, pos, orient, cir, difSpinifex, polSpinifex, dCnstr[dCh], pCnstr[pChE], (CDSimpleRules.MinDist[NMos.dif, NMos.dif]/2), SXNMosBasicRules.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[inst, p.length, p.width]; <<-- We're a lot smarter than this program, so let's adjust the area and perim values its got.>> 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]; }; <<-- Contact converters>> ConvertNMosContactDifAndPol: SX.ConversionProc -- [appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit] -- ~ { box: CD.Rect _ CDBasics.RectAt[pos~[0,0], size~inst.ob.size]; node: REF SX.CircuitNode; <> node _ cir.AddRect[ lev~NMos.met, dim~box, inst~inst, pos~ pos, orient~ orient]; [] _ cir.AddRect[ lev~inst.ob.layer, dim~box, inst~inst, pos~ pos, orient~ orient, value~node]; IF inst.ob.layer = NMos.dif THEN [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~box, inst~inst, pos~ pos, orient~ orient, value~pCnstr[pExCon]]; }; ConvertNMosMmContact: SX.ConversionProc -- [appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit] -- ~ { s: CD.Position = inst.ob.size; [] _ cir.AddBox [ spinifexLayer: metSpinifex, dim: [l/2, l/2, s.x-l/2, s.y-l/2], -- cut bloated by 1/2 lambda inst: inst, pos: pos, orient: orient, value: mCnstr[mCutEx]]; [] _ cir.AddBox [ spinifexLayer: metSpinifex, dim: [l, l, s.x-l, s.y-l], -- cut unbloated inst: inst, pos: pos, orient: orient, value: mCnstr[mCut]];}; ConvertNMosButtingContact: SX.ConversionProc -- [appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit] -- ~ { rimWidth: CD.Number ~ polSize: CD.Number ~ inst.ob.size.y/2; box: CD.Rect _ CDBasics.RectAt[pos~[0,0], size~inst.ob.size]; node: REF SX.CircuitNode; node _ cir.AddRect[ lev~NMos.met, dim~box, inst~inst, pos~ pos, orient~ orient]; [] _ cir.AddRect[ lev~NMos.pol, dim~[0,0, inst.ob.size.x, polSize], inst~inst, pos~ pos, orient~ orient, value~node]; <<-- Add rect for poly exclusion>> [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[-rimWidth,polSize, inst.ob.size.x+rimWidth, polSize+SXNMosBasicRules.difToPolSep], inst~inst, pos~ pos, orient~ orient, value~pCnstr[pChE]]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[-rimWidth,polSize-rimWidth, 0, polSize], inst~inst, pos~ pos, orient~ orient, value~pCnstr[pDxorP]]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[inst.ob.size.x,polSize-rimWidth, inst.ob.size.x+rimWidth, polSize], inst~inst, pos~ pos, orient~ orient, value~pCnstr[pDxorP]]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[0,polSize+SXNMosBasicRules.difToPolSep, inst.ob.size.x, inst.ob.size.y], inst~inst, pos~ pos, orient~ orient, interestBloat~SXTechnology.WNEGrow[ SXNMosBasicRules.difToPolExtSep], value~pCnstr[pExCon]]; <<-- Add rect for diff width spacing and connection>> [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~[0,polSize, inst.ob.size.x, inst.ob.size.y], inst~inst, pos~ pos, orient~ orient, 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 ~ inst.ob.size; cp: NMosContacts.ContactPtr ~ NARROW[inst.ob.specificRef]; node: REF SX.CircuitNode ~ cir.AddRect[ lev~NMos.pol, dim~[2* orient]; <> [] _ cir.AddBox [ spinifexLayer: metSpinifex, dim: [l/2, l/2, s.x-l/2, s.y-l/2], -- actual dimensions of cut inst: inst, pos: pos, orient: orient, 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 inst: inst, pos: pos, orient: orient, value: mCnstr[mBCEx]]; <<[] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [l/2, l/2, s.x-l/2, s.y-l/2], -- actual dimensions of cut inst: inst, pos: pos, orient: orient, 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) inst: inst, pos: pos, orient: orient, 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) inst: inst, pos: pos, orient: orient, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddRect [ lev: inst.ob.layer, dim: [ inst: inst, pos: pos, orient: orient, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* inst: inst, pos: pos, orient: orient, value: pCnstr[pChE]]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* inst: inst, pos: pos, orient: orient, value: pCnstr[pDandP]]; [] _ cir.AddBox [ spinifexLayer: difSpinifex, dim: [2* inst: inst, pos: pos, orient: orient, 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) inst: inst, pos: pos, orient: orient, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [-l/2, -l/2, 0, s.y+l/2], -- buried contact poly exclude (left side) inst: inst, pos: pos, orient: orient, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddBox [ spinifexLayer: difSpinifex, dim: [2* inst: inst, pos: pos, orient: orient, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* inst: inst, pos: pos, orient: orient, value: pCnstr[pDandP]]; <> [] _ cir.AddRect [lev: inst.ob.layer, dim: [ inst: inst, pos: pos, orient: orient, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* inst: inst, pos: pos, orient: orient, value: pCnstr[pChE]]; <> [] _ cir.AddRect [ lev: inst.ob.layer, dim: [s.x-cp.wExt, lex, s.x-(cp.wExt- inst: inst, pos: pos, orient: orient, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [s.x-cp.wExt, lex, s.x-(cp.wExt-SXNMosBasicRules.difToPolSep), s.y-lex], inst: inst, pos: pos, orient: orient, 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) inst: inst, pos: pos, orient: orient, 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) inst: inst, pos: pos, orient: orient, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [l/2, -l/2, s.x, 0], -- buried contact poly exclude (bottom side) inst: inst, pos: pos, orient: orient, value: NEW[Constraint _ bcExclConstraint]]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* inst: inst, pos: pos, orient: orient, value: pCnstr[pDandP]]; <> [] _ cir.AddRect [ lev: inst.ob.layer, dim: [ inst: inst, pos: pos, orient: orient, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* inst: inst, pos: pos, orient: orient, value: pCnstr[pChE]]; <> [] _ cir.AddRect [ lev: inst.ob.layer, dim: [2* inst: inst, pos: pos, orient: orient, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* inst: inst, pos: pos, orient: orient, value: pCnstr[pChE]]; <> [] _ cir.AddRect [ lev: inst.ob.layer, dim: [2* inst: inst, pos: pos, orient: orient, value: node]; [] _ cir.AddBox [ spinifexLayer: polSpinifex, dim: [2* inst: inst, pos: pos, orient: orient, 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.specificRef]; 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.specificRef]; 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.GetPropFromInstance [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.WriteRope [" $Crystal property must be a rope. /n"]; cellStream.PutRope[ "];"] }; MakeCoreNMOSTransistor: PUBLIC SXOutput.LinkagePrintProc ~ BEGIN <<[desWDir: Rope.ROPE, dfStream, cellStream: IO.STREAM, linkage: REF SX.NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc]>> t: CoreTransistor.Transistor _ NEW [CoreTransistor.TransistorRec]; tInstance: CoreRecord.CellInstance _ NEW [CoreRecord.CellInstanceRec]; o: Core.CellType; cm: NMosTransistors.TransistorPtr ~ NARROW [linkage.source.ob.specificRef]; InsertAttachment: PROCEDURE [key: ATOM] ~ BEGIN FOR a: LIST OF REF SX.AttachedNode _ linkage.nodes, a.rest WHILE a # NIL DO IF a.first.attachmentType = key THEN BEGIN SXOutputPrivate.InsertNode [a.first.node]; RETURN END ENDLOOP; END; -- InsertAttachment t.type _ IF cm.pullup THEN nD -- WRONG (no provision for NMos in Core as yet) ELSE SELECT cm.implant FROM NMosTransistors.enhancement => nE, NMosTransistors.strongDepletion => pE, ENDCASE => nD; t.length _ linkage.l/ o _ CoreTransistor.Create [SXOutputPrivate.coreDesign, t]; <<-- coreNodeBuffer was niled out in SXOutputImplA just before this code is executed.>> InsertAttachment [$Gate]; InsertAttachment [$Source]; InsertAttachment [$Drain]; tInstance.actualWire _ CoreOps.CreateRecordWire [name: "attachements", components: SXOutputPrivate.coreNodeBuffer]; SXOutputPrivate.coreNodeBuffer _ NIL; tInstance.name _ name; tInstance.type _ o; BEGIN -- properties t: ImagerTransformation.Transformation; pos, size: CD.Position; ir: CD.Rect; propertyValue: REF; ir _ CDInstances.InstRectO [linkage.source]; pos _ [x: ir.x1, y: ir.y1]; size _ [x: ir.x2 - ir.x1, y: ir.y2 - ir.y1]; t _ CDOrient.CreateTransform [cellSize: size, cellInstOrient: linkage.source.orientation, cellInstPos: pos]; tInstance.properties _ CoreProperties.PutProp [on: tInstance.properties, prop: SXAtoms.cdCellHint, value: linkage.source]; tInstance.properties _ CoreProperties.PutProp [on: tInstance.properties, prop: SXAtoms.instanceTransf, value: t]; <> propertyValue _ CDProperties.GetPropFromInstance [from: linkage.source, prop: SXAtoms.crystalAttr]; WITH propertyValue SELECT FROM crystalHack: Rope.ROPE => tInstance.properties _ CoreProperties.PutProp [tInstance.properties, SXAtoms.crystalAttr, crystalHack]; ENDCASE => IF propertyValue # NIL THEN TerminalIO.WriteRope [" Crystal property must be a rope./n"] END; SXOutputPrivate.coreCellInstance.instances _ CONS [tInstance, SXOutputPrivate.coreCellInstance.instances] END; -- MakeCoreNMosTransistor <<-- Module Initialization>> <> nMosHandle: REF SX.TechHandle; difSpinifex: SX.SpinifexLayerIndex ~ SX.SpinifexLayerIndex.FIRST; polSpinifex: SX.SpinifexLayerIndex ~ difSpinifex.SUCC; metSpinifex: SX.SpinifexLayerIndex ~ polSpinifex.SUCC; Constraint: TYPE ~ SX.Constraint; <<-- Diffusion layer>> dCnstr: REF SX.ConstraintArray _ NEW[SX.ConstraintArray]; -- Diffusion constraints dCh: SX.ConstraintIndex ~ SX.techCIndexBase; -- Diffusion channel <<-- Poly layer>> 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; 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; <<-- Construction of the Layer Constraints.>> 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]; }; <<-- Basic nMosHandle & cdLayerMappings.>> 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,SXNMosBasicRules.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)]]; <<-- Spinifex Layer Identification.>> nMosHandle.spinifexLayerNames[difSpinifex].layerId _ $Diffusion; nMosHandle.spinifexLayerNames[polSpinifex].layerId _ $Poly; nMosHandle.spinifexLayerNames[metSpinifex].layerId _ $Metal; <<-- Thyme stray capacitance layer names.>> nMosHandle.spinifexLayerNames[difSpinifex].thymeName _ "D"; nMosHandle.spinifexLayerNames[polSpinifex].thymeName _ "P"; nMosHandle.spinifexLayerNames[metSpinifex].thymeName _ "M"; <<-- Set Constraint Resolutions for each layer into the TechHandle.>> nMosHandle.constraintResolutions[difSpinifex] _ difResolution; nMosHandle.constraintResolutions[polSpinifex] _ polyResolution; nMosHandle.constraintResolutions[metSpinifex] _ metResolution; <<-- Geometric rule triggers.>> 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; <<-- Purely local errors are not handled in a natural manner by the corner-based scheme, so for every corner we find in pCnstr[pDPErr] we generate an error if there is anything on any layer nearby, of course there is always something so we get our error.>> 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; <<-- The geometric rules.>> 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~SXNMosBasicRules.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*CD.lambda, message: "Buried Contact Cut Spacing", okIfConnected: FALSE, trigger1~bcSpaceTrigger, trigger2~bcSpaceTrigger]]; bcMetalCutSpacingRuleA _ NEW[ GeometricRule _ [extent: 3*CD.lambda/2, message: "Buried Contact Cut/Metal Cut Spacing[debug: A]", okIfConnected: FALSE, trigger1~bcMetalCutSpacingTriggerA, trigger2~bcMetalCutSpacingTriggerB]]; bcMetalCutSpacingRuleB _ NEW[ GeometricRule _ [extent: 3*CD.lambda/2, message: "Buried Contact Cut/Metal Cut Separation[debug: B]", okIfConnected: FALSE, trigger1~bcMetalCutSpacingTriggerB, trigger2~bcMetalCutSpacingTriggerA]]; polBuriedSpacingRuleA _ NEW[ GeometricRule _ [extent: CD.lambda/2, message: "Buried Contact Cut/Unrelated Poly Spacing[debug:A]", okIfConnected: TRUE, trigger1~polBuriedSpaceTriggerA, trigger2~polBuriedSpaceTriggerB]]; polBuriedSpacingRuleB _ NEW[ GeometricRule _ [extent: CD.lambda/2, message: "Buried Contact Cut/Unrelated Poly Spacing[debug:B]", okIfConnected: TRUE, trigger1~polBuriedSpaceTriggerB, trigger2~polBuriedSpaceTriggerA]]; nMosHandle.rules[ difSpinifex] _ LIST[difSpacingRule, difWidthRule]; nMosHandle.rules[ polSpinifex] _ LIST[polSpacingRule, polWidthRule, polDifSepRuleA, polDifSepRuleB, polOverDifRule, polBuriedSpacingRuleA, polBuriedSpacingRuleB]; nMosHandle.rules[ metSpinifex] _ LIST[metSpacingRule, metWidthRule, bcCutSpacingRule, bcMetalCutSpacingRuleA, bcMetalCutSpacingRuleB]; <<-- Technology handle is attached to the ChipNDale technology.>> SXTechnology.RegisterTechnologyHandle[cdTech~ NMos.nmos, technologyHandle~ nMosHandle]; <<-- Technology specific objects.>> SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosTransistor, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor, core~MakeCoreNMOSTransistor, fini~SXOutputPrivate.UnNameTransType]; SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosATransistor, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor, core~MakeCoreNMOSTransistor]; SXTechnology.RegisterSpinifexObjectProcs[ cdTech~ NMos.nmos, objectType~$NMosPullUp, conv~ConvertNMosTransistor, thyme~ThymeNMosTransistor, rose~RoseNMosTransistor, core~MakeCoreNMOSTransistor]; 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.WriteRope["nMos technology parameters Loaded\n"]; END. <> < $Conflict.>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>>