DIRECTORY CD USING [Rect, DesignNumber, DesignPosition, DesignRect, Orientation, Level, ObjectProcs, ApplicationPtr, DrawRef, DrawRectProc, NewNullDeviceDrawRef], CDInline USING [Extend, NonEmpty, universe], SpinifexCircuit USING [Circuit, CircuitNode, CircuitConstraint, SpinifexLayerIndex, AddRect, AddBox], CornerStitching USING [NewTesselation, Tesselation, ChangeRect, EnumerateArea, ChangeTile, Region, PerTileProc, Area, Value, TilePtr, WestEdge, EastEdge, SouthEdge, NorthEdge, SWestNeighbour, NEastNeighbour, WSouthNeighbour, ENorthNeighbour], SpinifexExtras ; SpinifexExtrasImpl: CEDAR PROGRAM IMPORTS CD, CDInline, SpinifexCircuit, CornerStitching EXPORTS SpinifexExtras ~ BEGIN polPtr: REF INT _ NEW[INT]; difPtr: REF INT _ NEW[INT]; chanPtr: REF INT _ NEW[INT]; Post: TYPE ~ RECORD [ r: CD.DesignRect, l: CD.Level ]; AddRectParameters: TYPE ~ RECORD [ tes: REF CornerStitching.Tesselation, cir: REF SpinifexCircuit.Circuit, PerDrawRect: SpinifexExtras.PerDrawRectProc, gateNode: REF SpinifexCircuit.CircuitNode, postRectList: LIST OF REF Post, clientData: REF ANY ]; AddRectangle: CD.DrawRectProc -- [r: DesignRect, l: Level, pr: DrawRef] -- ~ { data: REF AddRectParameters ~ NARROW[ pr.devicePrivate]; level: SpinifexExtras.TransistorMaterial ~ data.PerDrawRect[r, l, data.clientData]; IF ~CDInline.NonEmpty[r] THEN RETURN; SELECT level FROM nothing => NULL; diffusion => { occupants: LIST OF REF CornerStitching.Region _ NARROW[data.tes.EnumerateArea[r]]; data.tes.ChangeRect[ r, difPtr]; WHILE occupants # NIL DO SELECT occupants.first.value FROM polPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr]; chanPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr]; ENDCASE; occupants _ occupants.rest ENDLOOP }; polysilicon => { occupants: LIST OF REF CornerStitching.Region _ NARROW[data.tes.EnumerateArea[r]]; data.tes.ChangeRect[ r, polPtr]; WHILE occupants # NIL DO SELECT occupants.first.value FROM difPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr]; chanPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr]; ENDCASE; occupants _ occupants.rest ENDLOOP; IF data.gateNode = NIL THEN data.gateNode _ data.cir.AddRect[lev~l, dim~r] ELSE [] _ data.cir.AddRect[lev~l, dim~r, value~data.gateNode]; }; postProcess => { data.postRectList _ CONS[ NEW[Post _ [r~ r, l~ l]], data.postRectList]; }; ENDCASE; -- I guess the end case is implant, well let me tell you one thing I don't deal with implant OK. }; ProcessMosTransistor: PUBLIC PROCEDURE [ appl: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, cir: REF SpinifexCircuit.Circuit, difSpinifex, polSpinifex: SpinifexCircuit.SpinifexLayerIndex, difChannel, channelEdge: REF SpinifexCircuit.CircuitConstraint, difToPolSep: CD.DesignNumber, PerDrawRect: SpinifexExtras.PerDrawRectProc, data: REF ANY _ NIL, PostProcessor: SpinifexExtras.ReportDifProc _ NIL] RETURNS [gateNode: REF SpinifexCircuit.CircuitNode, sourceDrainNodes: LIST OF REF SpinifexCircuit.CircuitNode, sourceDrainCount: INTEGER] ~ { FindChannelEdge: CornerStitching.PerTileProc -- [tile: TilePtr, data: REF ANY] RETURNS [REF ANY] -- ~{ occupants, tmp: LIST OF REF CornerStitching.Region; tes: REF CornerStitching.Tesselation ~ NARROW[data]; IF tile.Value = chanPtr THEN { occupants _ NARROW[tes.EnumerateArea[CDInline.Extend[tile.Area, difToPolSep]]]; WHILE occupants # NIL DO tmp _ occupants.rest; IF occupants.first.value = difPtr THEN { occupants.rest _ chEdge; chEdge _ occupants }; occupants _ tmp ENDLOOP } }; ConvertMaskGeom: CornerStitching.PerTileProc -- [tile: TilePtr, data: REF ANY] RETURNS [REF ANY] -- ~{ SELECT tile.Value FROM difPtr => { CheckChangeAndAdd: PROCEDURE [t: CornerStitching.TilePtr] ~ { IF t.Value = difPtr THEN { tranGeom.ChangeTile[ t, node]; [] _ cir.AddRect[ lev~appl.ob.level, dim~t.Area, value~node] } ELSE WITH t.Value SELECT FROM cn: REF SpinifexCircuit.CircuitNode => cn.superceded _ node; ENDCASE; }; node: REF SpinifexCircuit.CircuitNode _ cir.AddRect[lev~appl.ob.level, dim~tile.Area]; sdList _ CONS[ node, sdList]; tranGeom.ChangeTile[ tile, node]; FOR st: CornerStitching.TilePtr _ tile.WSouthNeighbour, st.NEastNeighbour WHILE st.WestEdge < tile.EastEdge DO CheckChangeAndAdd[ st]; ENDLOOP; FOR wt: CornerStitching.TilePtr _ tile.SWestNeighbour, wt.ENorthNeighbour WHILE wt.SouthEdge < tile.NorthEdge DO CheckChangeAndAdd[ wt]; ENDLOOP; FOR nt: CornerStitching.TilePtr _ tile.ENorthNeighbour, nt.SWestNeighbour WHILE nt.EastEdge > tile.WestEdge DO CheckChangeAndAdd[ nt]; ENDLOOP; FOR et: CornerStitching.TilePtr _ tile.NEastNeighbour, et.WSouthNeighbour WHILE et.NorthEdge > tile.SouthEdge DO CheckChangeAndAdd[ et]; ENDLOOP; }; chanPtr => { [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~tile.Area, value~difChannel]; }; polPtr => NULL; ENDCASE }; AddParm: REF AddRectParameters ~ NEW[AddRectParameters]; tranGeom: REF CornerStitching.Tesselation ~ CornerStitching.NewTesselation[]; sdList: LIST OF REF SpinifexCircuit.CircuitNode _ NIL; dr: CD.DrawRef ~ CD.NewNullDeviceDrawRef[NIL]; chEdge: LIST OF REF CornerStitching.Region _ NIL; AddParm.tes _ tranGeom; AddParm.cir _ cir; AddParm.PerDrawRect _ PerDrawRect; AddParm.gateNode _ NIL; AddParm.postRectList _ NIL; AddParm.clientData _ data; dr.drawRect _ AddRectangle; dr.saveRect _ AddRectangle; dr.devicePrivate _ AddParm; appl.ob.p.drawMe[appl, pos, orient, dr]; IF (gateNode _ AddParm.gateNode) = NIL THEN ERROR; [] _ tranGeom.EnumerateArea[ rect~CDInline.universe, perTile~FindChannelEdge, data~tranGeom]; [] _ tranGeom.EnumerateArea[ rect~CDInline.universe, perTile~ConvertMaskGeom]; IF PostProcessor # NIL THEN FOR pL: LIST OF REF Post _ AddParm.postRectList, pL.rest WHILE pL # NIL DO FindNodes: CornerStitching.PerTileProc -- [tile: TilePtr, data: REF ANY] RETURNS [REF ANY] -- ~{ WITH tile.Value SELECT FROM cn: REF SpinifexCircuit.CircuitNode => PostProcessor[cn, pL.first.r, pL.first.l]; ENDCASE }; [] _ tranGeom.EnumerateArea[ rect~pL.first.r, perTile~FindNodes]; ENDLOOP; WHILE chEdge # NIL DO [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~chEdge.first.rect, value~channelEdge]; chEdge _ chEdge.rest ENDLOOP; sourceDrainNodes _ NIL; sourceDrainCount _ 0; WHILE sdList # NIL DO sdfirst: LIST OF REF SpinifexCircuit.CircuitNode ~ sdList; sdList _ sdList.rest; IF sdfirst.first.superceded # NIL THEN LOOP; FOR alreadySeen: LIST OF REF SpinifexCircuit.CircuitNode _ sourceDrainNodes, alreadySeen.rest WHILE alreadySeen # NIL DO IF alreadySeen.first = sdfirst.first THEN EXIT; REPEAT FINISHED => { sdfirst.rest _ sourceDrainNodes; sourceDrainNodes _ sdfirst; sourceDrainCount _ sourceDrainCount.SUCC; } ENDLOOP; ENDLOOP; }; END. DSpinifexExtrasImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Written by Shand, June 12, 1984 3:11:49 pm PDT Last Edited by: Shand, July 28, 1984 7:23:52 pm PDT -- I don't care about efficiency here I'm afraid -- Save on list and process and enumerate Diffusion nodes in this region later. -- When we get these crazy bent guys well I tell you we just don't know what to do, so we grab ourselves a tile world and plunk it down in that, then maybe we can start to make sense of it. -- We are fairly liberal with interest boundaries here, its could be made a lot tighter as is done in the processing of normal Xstrs. All this means is that bent Xstrs will be instantiated for analysis even when they appear in isolation. Acutally this may be what we want since bent transistors are not so constrained that errors are totally precluded in an isolated object (they are for straight Xstrs). Also we let the other code calculate areas and perims, it is likely to be inaccurate. -- Called for pullups where we can make a sensible decision on which node is the source. Κa˜code™Kšœ Οmœ1™