DIRECTORY CD USING [Rect, DesignNumber, DesignPosition, DesignRect, Level, ObjectProcs, ApplicationPtr], CDInline USING [RectAt, Extend, NonEmpty, universe], TerminalIO USING [WriteRope], CMos USING [ndif, pdif, pol, met, met2, nwel, wellSurround, nwelCont, pwelCont], CMosTransistors USING [TransistorPtr], CMosContacts USING [ContactPtr, ContactType], Atom USING [GetPropFromList, PutPropOnList], IO USING [PutRope, Put, char, rope, PutF, int], Rope USING [Cat, ROPE], SpinifexCircuit USING [AddBox, AddRect, AdjustNode, AttachedNode, CellPostProcessProc, Circuit, CircuitConstraint, CircuitNode, CombineNodePropertyProc, ConversionProc, CreateLinkage, Dimension, FindRootNode, IllegalConstruct, LinkageAttach, LookupNode, NodeLinkage, PaintErrorRect, EnumerateGeometry, PerRectProc, Rectangle, RectDelta, SpinifexLayerIndex, TechHandle, BoxMapProc], SpinifexOutput USING [LinkagePrintProc], SpinifexExtras USING [ProcessMosTransistor, PerDrawRectProc, --SWNGrow, NESGrow,-- WNEGrow, ESWGrow], CMosSpinifex ; CMosSpinifexObjConvImpl: CEDAR PROGRAM IMPORTS Atom, IO, Rope, CMos, CDInline, TerminalIO, SpinifexCircuit, SpinifexExtras, CMosSpinifex EXPORTS CMosSpinifex ~ BEGIN OPEN CMosSpinifex; ConvTransistor: PUBLIC SpinifexCircuit.ConversionProc -- [appl: CD.ApplicationPtr, cir: REF ] -- ~ { p: CMosTransistors.TransistorPtr = NARROW[appl.ob.specificRef]; xstr: REF SpinifexCircuit.NodeLinkage; gateNode, sourceNode, drainNode: REF SpinifexCircuit.CircuitNode; difSpinifexLayer: SpinifexCircuit.SpinifexLayerIndex ~ IF appl.ob.level = CMos.ndif THEN ndifSpinifex ELSE pdifSpinifex; difChannel: REF CircuitConstraint ~ IF appl.ob.level = CMos.ndif THEN nDifChannel ELSE pDifChannel; IF ~ p.angle THEN { -- Oh this is easy! wellPolSurround: CD.DesignNumber ~ MAX[0, CMos.wellSurround-p.wExt]; pdBox: CD.Rect ~ IF appl.ob.level = CMos.ndif THEN [0, 0, appl.ob.size.x, appl.ob.size.y] ELSE [wellPolSurround, CMos.wellSurround, appl.ob.size.x-wellPolSurround, appl.ob.size.y-CMos.wellSurround]; polBox: CD.Rect ~ [pdBox.x1, pdBox.y1+p.lExt, pdBox.x2, pdBox.y2-p.lExt]; channel: CD.Rect ~ [pdBox.x1+p.wExt, pdBox.y1+p.lExt, pdBox.x2-p.wExt, pdBox.y2-p.lExt]; difExtSouth: CD.Rect ~ [pdBox.x1+p.wExt, pdBox.y1, pdBox.x2-p.wExt, pdBox.y1+p.lExt]; difExtNorth: CD.Rect ~ [pdBox.x1+p.wExt, pdBox.y2-p.lExt, pdBox.x2-p.wExt, pdBox.y2]; excludePol: REF CircuitConstraint ~ IF appl.ob.level = CMos.ndif THEN excludePolByNDif ELSE excludePolByPDif; IF appl.ob.level # CMos.ndif THEN { polWellSurround: CD.DesignNumber ~ MAX[0, CMos.wellSurround-p.wExt]; wellNode: REF SpinifexCircuit.CircuitNode _ cir.AddRect[ lev~ CMos.nwel, dim~ [0, polWellSurround, appl.ob.size.x, appl.ob.size.y-polWellSurround], appl~ appl, pos~ pos, orient~ orient]; wellNode.properties _ wellNode.properties.PutPropOnList[WellNodeAtom, WellNodeAtom]; }; gateNode _ cir.AddRect[ lev~CMos.pol, dim~polBox, appl~appl, pos~ pos, orient~ orient]; [] _ cir.AddBox[ spinifexLayer~ polSpinifex, dim~ [difExtNorth.x1, difExtNorth.y1, difExtNorth.x2, difExtNorth.y1+difToPolSep], appl~ appl, pos~ pos, orient~ orient, value~ channelEdge]; [] _ cir.AddBox[ spinifexLayer~ polSpinifex, dim~ [difExtNorth.x1, difExtNorth.y1+difToPolSep, difExtNorth.x2, difExtNorth.y2], appl~ appl, pos~ pos, orient~ orient, interestBloat~ SpinifexExtras.WNEGrow[ difToPolExtSep], value~ excludePol]; [] _ cir.AddBox[ spinifexLayer~ polSpinifex, dim~ [difExtSouth.x1, difExtSouth.y2-difToPolSep, difExtSouth.x2, difExtSouth.y2], appl~ appl, pos~ pos, orient~ orient, value~ channelEdge]; [] _ cir.AddBox[ spinifexLayer~ polSpinifex, dim~ [difExtSouth.x1, difExtSouth.y1, difExtSouth.x2, difExtSouth.y2-difToPolSep], appl~ appl, pos~ pos, orient~ orient, interestBloat~ SpinifexExtras.ESWGrow[ difToPolExtSep], value~ excludePol]; [] _ cir.AddBox[ spinifexLayer~ difSpinifexLayer, dim~ channel, appl~ appl, pos~ pos, orient~ orient, value~ difChannel]; sourceNode _ cir.AddBox[ spinifexLayer~difSpinifexLayer, dim~difExtNorth, appl~appl, pos~ pos, orient~ orient, interestBloat~SpinifexExtras.WNEGrow[difSep]]; drainNode _ cir.AddBox[ spinifexLayer~ difSpinifexLayer, dim~ difExtSouth, appl~ appl, pos~ pos, orient~ orient, interestBloat~ SpinifexExtras.ESWGrow[difSep]] } ELSE { -- Oh no not a bent transistor yetcchh! sourceDrainList: LIST OF REF SpinifexCircuit.CircuitNode; sourceDrainCount: INTEGER; [gateNode, sourceDrainList, sourceDrainCount] _ SpinifexExtras.ProcessMosTransistor[appl, pos, orient, cir, difSpinifexLayer, polSpinifex, difChannel, channelEdge, difToPolSep, MapMaterial, cir]; IF sourceDrainCount = 2 THEN { sourceNode _ sourceDrainList.first; drainNode _ sourceDrainList.rest.first; } 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, (p.width+2*p.wExt)*p.length, ((p.width+2*p.wExt)+p.length)*2, absolute]; SpinifexCircuit.AdjustNode[ sourceNode, difSpinifexLayer, p.lExt*p.width, 2*p.lExt + p.width, absolute]; SpinifexCircuit.AdjustNode[ drainNode, difSpinifexLayer, p.lExt*p.width, 2*p.lExt + p.width, absolute]; -- Ignore perim leading into channel. 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 CMos.ndif, CMos.pdif => RETURN [diffusion]; CMos.pol => RETURN [polysilicon]; CMos.nwel => { wellNode: REF SpinifexCircuit.CircuitNode _ cir.AddRect[ lev~ CMos.nwel, dim~ r]; wellNode.properties _ wellNode.properties.PutPropOnList[WellNodeAtom, WellNodeAtom]; RETURN [nothing]; }; ENDCASE => RETURN [nothing]; }; ConvertPDifRect: PUBLIC SpinifexCircuit.ConversionProc -- [appl: CD.ApplicationPtr, cir: REF SpinifexCircuit.Circuit] -- ~ { wellNode: REF SpinifexCircuit.CircuitNode; nWellBox: CD.Rect _ CDInline.RectAt[pos~[0,0], size~appl.ob.size]; pDifBox: CD.Rect _ CDInline.Extend[nWellBox, -CMos.wellSurround]; IF ~CDInline.NonEmpty[pDifBox] THEN ERROR; [] _ cir.AddRect[ lev~CMos.pdif, dim~pDifBox, appl~appl, pos~ pos, orient~ orient]; wellNode _ cir.AddRect[ lev~CMos.nwel, dim~nWellBox, appl~appl, pos~ pos, orient~ orient]; wellNode.properties _ wellNode.properties.PutPropOnList[WellNodeAtom, WellNodeAtom]; }; ContactMap: TYPE ~ RECORD [ rm: LIST OF RectMap, bm: LIST OF BoxMap ]; MapRectDelta: TYPE ~ RECORD [dx1, dy1, dx2, dy2: INT]; RectMap: TYPE ~ RECORD [ level: CD.Level, delta: MapRectDelta ]; BoxMap: TYPE ~ RECORD [ layer: SpinifexCircuit.SpinifexLayerIndex, value: REF ANY, delta: MapRectDelta ]; MapArray: TYPE ~ ARRAY {mnDif, mpDif, mnWCont, mpWCont, nDifShort, pDifShort, nbutt, pbutt, mPol, mm2 } OF ContactMap; ContactMaps: REF MapArray; InitContacts: PUBLIC PROCEDURE ~ { ws: CD.DesignNumber ~ CMos.wellSurround; ContactMaps _ NEW[MapArray _ ALL[ [NIL, NIL] ]]; ContactMaps[mnDif].rm _ LIST[[CMos.ndif, [0,0,0,0]], [CMos.met, [0,0,0,0]] ]; ContactMaps[mpDif].rm _ LIST[[CMos.pdif, [0,0,0,0]], [CMos.met, [0,0,0,0]], [CMos.nwel, [ws,ws,ws,ws]] ]; ContactMaps[mnWCont].rm _ LIST[[CMos.met, [0,0,0,0]], [CMos.nwelCont, [0,0,0,0]] ]; ContactMaps[mpWCont].rm _ LIST[[CMos.met, [0,0,0,0]], [CMos.pwelCont, [0,0,0,0]] ]; ContactMaps[mPol].rm _ LIST[[CMos.pol, [0,0,0,0]], [CMos.met, [0,0,0,0]] ]; ContactMaps[mm2].rm _ LIST[[CMos.met2, [0,0,0,0]], [CMos.met, [0,0,0,0]] ]; ContactMaps[nDifShort].rm _ LIST[[CMos.ndif, [0,0,0,-4*l]], [CMos.met, [0,0,0,0]] ]; ContactMaps[pDifShort].rm _ LIST[[CMos.pdif, [0,0,0,-4*l]], [CMos.met, [0,0,0,0]], [CMos.nwel, [ws,ws,ws,ws-4*l]] ]; ContactMaps[nbutt].rm _ LIST[[CMos.ndif, [0,-3*l,0,0]], [CMos.pol, [0,0,0,-3*l]], [CMos.met, [0,0,0,0]] ]; ContactMaps[nbutt].bm _ LIST[[polSpinifex, channelEdge, [l, -3*l, l, -2*l]], [polSpinifex, polXorDif, [l, -2*l, -4*l, -3*l]], [polSpinifex, polXorDif, [-4*l, -2*l, l, -3*l]]--, [polSpinifex, polAndDif, [0, -2*l, 0, -3*l]]-- ]; -- Causes problems with false poly spacing reports if commented BoxMap is included. ContactMaps[pbutt].rm _ LIST[[CMos.pdif, [0,-3*l,0,0]], [CMos.pol, [0,0,0,-3*l]], [CMos.met, [0,0,0,0]], [CMos.nwel, [ws,ws-2*l,ws,ws]] ]; ContactMaps[pbutt].bm _ ContactMaps[nbutt].bm; }; ConvertContact: PUBLIC SpinifexCircuit.ConversionProc -- [appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, cir: REF SpinifexCircuit.Circuit] -- ~ { DeltaBox: PROCEDURE [box: CD.Rect, delta: MapRectDelta] RETURNS [CD.Rect] ~ INLINE { RETURN [ [x1~ box.x1-delta.dx1, y1~ box.y1-delta.dy1, x2~ box.x2+delta.dx2, y2~ box.y2+delta.dy2] ] }; SimpleMapping: PROCEDURE [map: ContactMap] ~ { node: REF SpinifexCircuit.CircuitNode _ NIL; box: CD.Rect _ appl.ob.p.insideRect[appl.ob]; FOR r: LIST OF RectMap _ map.rm, r.rest WHILE r # NIL DO SELECT r.first.level FROM CMos.nwel => { wellNode: REF SpinifexCircuit.CircuitNode _ cir.AddRect[ lev~r.first.level, dim~DeltaBox[box, r.first.delta], appl~appl, pos~ pos, orient~ orient]; wellNode.properties _ wellNode.properties.PutPropOnList[ WellNodeAtom, WellNodeAtom]; }; ENDCASE => node _ cir.AddRect[ lev~r.first.level, dim~DeltaBox[box, r.first.delta], appl~appl, pos~ pos, orient~ orient, value~node]; ENDLOOP; FOR b: LIST OF BoxMap _ map.bm, b.rest WHILE b # NIL DO node _ cir.AddBox[ spinifexLayer~ b.first.layer, dim~ DeltaBox[box, b.first.delta], appl~ appl, pos~ pos, orient~ orient, value~ IF b.first.value # NIL THEN b.first.value ELSE node]; ENDLOOP; }; cp: CMosContacts.ContactPtr ~ NARROW[appl.ob.specificRef]; SELECT cp.typ FROM burr => { s: CD.DesignPosition ~ appl.ob.size; node: REF SpinifexCircuit.CircuitNode ~ cir.AddRect[ lev~CMos.pol, dim~[2*l, cp.lExt, s.x-cp.wExt, s.y-cp.lExt], appl~appl, pos~ pos, orient~ orient]; IF appl.ob.level # CMos.ndif THEN ERROR SpinifexCircuit.IllegalConstruct[appl.ob.p.insideRect[appl.ob], "Buried Contact may only connect to n-Diffusion"]; [] _ cir.AddBox[ spinifexLayer~ ndifSpinifex, dim~ [2*l, 2*l, s.x-2*l, s.y-2*l], appl~ appl, pos~ pos, orient~ orient, value~ buriedNDifPol, interestBloat~ [difSep, difSep, difSep, difSep]]; 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~ndifSpinifex, dim~[2*l, lex, s.x-wex, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~node]; [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~[2*l, lex, s.x-wex, s.y-lex], appl~appl, pos~ pos, orient~ orient, value~polAndDif]; }; cp.lExt < 2*l AND cp.wExt >= 2*l => { lex: CD.DesignNumber ~ MAX[cp.lExt+l, 2*l]; [] _ cir.AddBox[ spinifexLayer~ndifSpinifex, 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~ndifSpinifex, 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; }; mDif => SimpleMapping[ContactMaps[ SELECT appl.ob.level FROM CMos.ndif => mnDif, CMos.pdif => mpDif, CMos.nwelCont => mnWCont, CMos.pwelCont => mpWCont, ENDCASE => ERROR]]; difShort => SimpleMapping[ContactMaps[ SELECT appl.ob.level FROM CMos.ndif => nDifShort, CMos.pdif => pDifShort, ENDCASE => ERROR]]; butt => SimpleMapping[ContactMaps[ SELECT appl.ob.level FROM CMos.ndif => nbutt, CMos.pdif => pbutt, ENDCASE => ERROR]]; mPol => SimpleMapping[ContactMaps[mPol]]; mm2 => SimpleMapping[ContactMaps[mm2]]; ENDCASE => ERROR; }; RoseTransistor: PUBLIC 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: CMosTransistors.TransistorPtr ~ NARROW[ linkage.source.ob.specificRef]; stream.Put[ IO.rope["(CI "], IO.rope[name], IO.rope[" \"Transistor[strength: drive, positive: "]]; stream.PutRope[ SELECT linkage.source.ob.level FROM CMos.ndif => "TRUE", CMos.pdif => "FALSE", ENDCASE => "UNKNOWN" ]; stream.PutRope[ ", mode: Enhancement, unidirectional: FALSE, biased: FALSE, offStrength: none]\""]; stream.PutRope[ " (CIC"]; PrintAttachment[ $Gate, "gate"]; PrintAttachment[ $Source, "ch1"]; PrintAttachment[ $Drain, "ch2"]; stream.PutRope[ "))"] }; ThymeTransistor: PUBLIC SpinifexOutput.LinkagePrintProc -- [ stream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, 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: CMosTransistors.TransistorPtr ~ NARROW[ linkage.source.ob.specificRef]; defaultW: INTEGER ~ 4*l; defaultL: INTEGER ~ 2*l; stream.Put[ IO.rope[name], IO.rope[": "]]; stream.PutRope[ SELECT linkage.source.ob.level FROM CMos.ndif => "ETran[", CMos.pdif => "CTran[", ENDCASE => "FunnyTrans[" ]; 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[ "];"] }; wellConnection: ATOM ~ $SpinifexCMosWellConnection; WellNodeAtom: ATOM ~ $SpinifexCMosNWellNode; CopyWellConnections: PUBLIC SpinifexCircuit.CombineNodePropertyProc -- [circuit: REF Circuit, to, from: Atom.PropList, fromNesting: LIST OF CD.ApplicationPtr] RETURNS [Atom.PropList] -- ~ { fromConnections: LIST OF REF SpinifexCircuit.CircuitNode _ NARROW[from.GetPropFromList[ wellConnection]]; toConnections: LIST OF REF SpinifexCircuit.CircuitNode _ NARROW[to.GetPropFromList[ wellConnection]]; FOR fl: LIST OF REF SpinifexCircuit.CircuitNode _ fromConnections, fl.rest WHILE fl # NIL DO fromNode: REF SpinifexCircuit.CircuitNode ~ IF fromNesting = NIL THEN fl.first ELSE circuit.FindRootNode[fl.first, fromNesting, TRUE].node; -- Side Effect !! may add fl.first to subcircuits ports. FOR tl: LIST OF REF SpinifexCircuit.CircuitNode _ toConnections, tl.rest WHILE tl # NIL DO IF fromNode.LookupNode[] = tl.first.LookupNode[] THEN EXIT; REPEAT FINISHED => toConnections _ CONS[fromNode, toConnections] ENDLOOP ENDLOOP; IF toConnections # NIL THEN to _ to.PutPropOnList[ wellConnection, toConnections]; IF from.GetPropFromList[ WellNodeAtom] # NIL AND to.GetPropFromList[ WellNodeAtom] = NIL THEN to _ to.PutPropOnList[ WellNodeAtom, WellNodeAtom]; RETURN [ to ] }; CheckWellConnections: PUBLIC SpinifexCircuit.CellPostProcessProc -- [cell: REF SpinifexCircuit.LogicalCell] -- ~ { FOR nl: LIST OF REF SpinifexCircuit.CircuitNode _ cell.circuit.nodes, nl.rest WHILE nl # NIL DO IF nl.first.properties.GetPropFromList[ WellNodeAtom] # NIL THEN { wellConnects: LIST OF REF SpinifexCircuit.CircuitNode _ NARROW[nl.first.properties.GetPropFromList[ wellConnection]]; FOR wl: LIST OF REF SpinifexCircuit.CircuitNode _ wellConnects, wl.rest WHILE wl # NIL DO wl.first _ wl.first.LookupNode[]; FOR restOfWl: LIST OF REF SpinifexCircuit.CircuitNode _ wl, restOfWl.rest WHILE restOfWl.rest # NIL DO IF wl.first = restOfWl.rest.first.LookupNode[] THEN restOfWl.rest _ restOfWl.rest.rest -- Drop this list element. ENDLOOP ENDLOOP; IF wellConnects = NIL OR wellConnects.rest # NIL THEN { PaintWellErrorOverGeom: SpinifexCircuit.PerRectProc -- [r: REF Rectangle, data: REF ANY] -- ~ { IF r.nodeInformation = data THEN cell.PaintErrorRect[ errorBox~ r.Dimension[], message~ message] }; message: Rope.ROPE ~ IF wellConnects = NIL THEN "Floating n-well" ELSE "n-well plugged to more than one node"; cell.circuit.EnumerateGeometry[wellSpinifex, CDInline.universe, PaintWellErrorOverGeom, nl.first] } } ENDLOOP }; AttachNWellContact: PUBLIC SpinifexCircuit.BoxMapProc -- [cir: REF Circuit, dim: CD.Rect, appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, node: REF CircuitNode] RETURNS [cirNode: REF CircuitNode _ NIL] -- ~ { wellCon: REF SpinifexCircuit.CircuitNode _ cir.AddBox[ spinifexLayer~ wellSpinifex, dim~ dim, appl~appl, pos~ pos, orient~ orient, interestBloat~ [l, l, l, l]]; IF node = NIL THEN ERROR; wellCon.properties _ wellCon.properties.PutPropOnList[ wellConnection, NARROW[ LIST[node], LIST OF REF SpinifexCircuit.CircuitNode] ]; }; END. dCMosSpinifexObjConvImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Written by Shand, September 12, 1983 11:40 pm Last Edited by: Shand, September 4, 1984 9:03:48 pm PDT -- New Regime Transistor converters (IE the Shand unified xstr representaion) IF p.bendList = NIL THEN { -- Oh this is easy! -- Get the Xstr bounding box exclusive of nwel, i.e. only pol and dif. polExtWest: CD.Rect ~ [pdBox.x1, pdBox.y1+p.lExt, pdBox.x1+p.wExt, pdBox.y2-p.lExt]; polExtEast: CD.Rect ~ [pdBox.x2-p.wExt, pdBox.y1+p.lExt, pdBox.x2, pdBox.y2-p.lExt]; -- Add poly boxes -- Add rects for poly exclusion and channel lead-in. -- At the top -- ... and the bottom -- Fill channel gap -- Add rects for diff width spacing and connection -- We're a lot smarter than this program, so let's adjust the area and perim values its got. -- Contact converters `Normal' levels must precede nwelCont. -- 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 ??? Clean up list to eliminate REFs to superceded nodes. n-well ERROR Κƒ˜code™Kšœ Οmœ1™˜ˆKšœ ˜ Kšœ˜—šœ €œžœ €œ˜%Kš’™Kš œžœžœ €œ€œ˜+Kšœžœ€œ˜!Kšœ4€œ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˜—Kš œ#žœžœ]žœžœ˜¬Kš œ'žœžœ1žœžœ˜„Kš œ#žœžœ)žœžœ˜xKšœ)˜)Kšœ'˜'Kšžœžœ˜—K˜—šœžœ!Ÿ‘YŸœ˜šš£œž œžœžœ˜@Kšœ žœžœžœ˜@š žœžœžœžœ@žœžœž˜všžœ(žœ˜0Kšœ*˜*Kšœ˜Kšž˜K˜—Kšžœ˜—Kšœ˜K˜—Lšœ#žœ!˜JLšœ žœžœ žœ4˜bšœžœž˜3Kšœ˜Kšœ˜Kšžœ ˜K˜—Kšœc˜cKšœ˜Kšœ ˜ K˜!K˜ Kšœ˜K˜—šœžœ!Ÿ‘YŸœ˜›š£œž œžœ˜+š žœžœžœžœ@žœžœž˜všžœ(žœ˜0Kšœ*˜*Kšž˜K˜—Kšžœ˜—Kšœ žœ ˜K˜—Lšœ#žœ!˜JKšœ žœ€œ˜Kšœ žœ€œ˜Lšœ žœ žœ ˜*šœžœž˜3Kšœ˜Kšœ˜Kšžœ˜K˜—Kšœ˜Kšœ žœ ˜K˜Kšœ žœ ˜K˜šžœžœžœ˜3Kšœ žœ ˜Kšžœžœžœ €œ˜CKšžœžœžœ žœ ˜LKšžœžœžœ€œ˜DK˜—Kšœ˜K˜—Lšœžœ˜3Kšœžœ˜,šœžœ)Ÿ‘oŸœ˜½Kš œžœžœžœžœ(˜iKš œžœžœžœžœ&˜eš žœžœžœžœ8žœžœž˜\Kšœ žœžœžœžœ žœ-žœ Ÿ8˜Εš žœžœžœžœ6žœžœž˜ZKšžœ/žœžœ˜;šžœžœ˜Kšœžœ˜-—Kšž˜—Kšžœ˜—šžœžœž˜Kšœ6˜6—š žœ'žœžœ%žœž˜]Kšœ3˜3—Kšžœ˜ K˜—šœžœ%Ÿ‘'Ÿœ˜rš žœžœžœžœ;žœžœž˜_šžœ6žœžœ˜BKš œžœžœžœžœ7˜uK™4š žœžœžœžœ5žœžœž˜YKšœ!˜!š žœ žœžœžœ1žœžœž˜fšžœ-ž˜3Kšœ$Ÿ˜>—Kšž˜—Kšžœ˜—š žœžœžœžœžœ˜7K™ š’œ‘'œ˜`šžœž˜ Kšœ?˜?—K˜—Lš œžœžœžœžœžœ(˜nKšœa˜aK˜—K˜—Kšž˜—K˜—š’œžœ‘―œ˜κKš œ žœ‡€œ€œ€œ€œ˜ Kšžœžœžœžœ˜Kš œGžœžœžœžœžœ ˜†Kšœ˜—Kšžœ˜—…—KNa5