DIRECTORY CD USING [CreateDrawRef, DrawRectProc, DrawRef, Error, FetchObjectClass, Instance, Layer, Number, ObjectClass, Object, Orientation, Position, Rect, Technology], CDBasics USING [Extend, NonEmpty, universe], CDProperties USING [PutPropOnTechnology, PutProp], CornerStitching USING [Area, ChangeRect, EastEdge, ENorthNeighbour, EnumerateArea, ListArea, ChangeTile, NEastNeighbour, NewTesselation, NorthEdge, PerTileProc, Region, SouthEdge, SWestNeighbour, Tesselation, Tile, Value, WestEdge, WSouthNeighbour], SX, SXAccessInternal, SXAtoms USING [fini, rosePrint, spinifex, thymePrint], SXOutput USING [LinkageHousekeeper, LinkagePrintProc], SXTechnology; SXTechnologyImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDProperties, CornerStitching, SX, SXAccessInternal, SXAtoms EXPORTS SXTechnology SHARES CornerStitching = BEGIN TilePtr: TYPE = REF CornerStitching.Tile; polPtr: REF INT _ NEW[INT]; difPtr: REF INT _ NEW[INT]; chanPtr: REF INT _ NEW[INT]; Post: TYPE ~ RECORD [ r: CD.Rect, l: CD.Layer ]; AddRectParameters: TYPE ~ RECORD [ tes: REF CornerStitching.Tesselation, cir: REF SX.Circuit, PerDrawRect: SXTechnology.PerDrawRectProc, gateNode: REF SX.CircuitNode, postRectList: LIST OF REF Post, clientData: REF ANY ]; AddRectangle: CD.DrawRectProc -- [r: Rect, l: Layer, pr: DrawRef] -- ~ { data: REF AddRectParameters ~ NARROW[ pr.devicePrivate]; level: SXTechnology.TransistorMaterial ~ data.PerDrawRect[r, l, data.clientData]; IF ~CDBasics.NonEmpty[r] THEN RETURN; SELECT level FROM nothing => NULL; diffusion => { occupants: LIST OF REF CornerStitching.Region _ NARROW[CornerStitching.ListArea[data.tes,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[CornerStitching.ListArea[data.tes,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.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit, difSpinifex, polSpinifex: SX.SpinifexLayerIndex, difChannel, channelEdge: REF SX.Constraint, difChanSep, difToPolSep: CD.Number, PerDrawRect: SXTechnology.PerDrawRectProc, data: REF ANY _ NIL, PostProcessor: SXTechnology.ReportDifProc _ NIL] RETURNS [gateNode: REF SX.CircuitNode, sourceDrainNodes: LIST OF REF SX.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[CornerStitching.ListArea[tes,CDBasics.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: TilePtr] ~ { IF t.Value = difPtr THEN { tranGeom.ChangeTile[ t, node]; [] _ cir.AddRect[ lev~appl.ob.layer, dim~t.Area, value~node] } ELSE WITH t.Value SELECT FROM cn: REF SX.CircuitNode => SX.LookupNode[cn].superceded _ node; ENDCASE; }; node: REF SX.CircuitNode _ cir.AddRect[lev~appl.ob.layer, dim~tile.Area]; sdList _ CONS[ node, sdList]; tranGeom.ChangeTile[ tile, node]; FOR st: TilePtr _ tile.WSouthNeighbour, st.NEastNeighbour WHILE st.WestEdge < tile.EastEdge DO CheckChangeAndAdd[ st]; ENDLOOP; FOR wt: TilePtr _ tile.SWestNeighbour, wt.ENorthNeighbour WHILE wt.SouthEdge < tile.NorthEdge DO CheckChangeAndAdd[ wt]; ENDLOOP; FOR nt: TilePtr _ tile.ENorthNeighbour, nt.SWestNeighbour WHILE nt.EastEdge > tile.WestEdge DO CheckChangeAndAdd[ nt]; ENDLOOP; FOR et: TilePtr _ tile.NEastNeighbour, et.WSouthNeighbour WHILE et.NorthEdge > tile.SouthEdge DO CheckChangeAndAdd[ et]; ENDLOOP; }; chanPtr => { [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~tile.Area, interestBloat~ [difChanSep, difChanSep, difChanSep, difChanSep], value~difChannel]; }; polPtr => NULL; ENDCASE }; AddParm: REF AddRectParameters ~ NEW[AddRectParameters]; tranGeom: REF CornerStitching.Tesselation ~ CornerStitching.NewTesselation[]; sdList: LIST OF REF SX.CircuitNode _ NIL; dr: CD.DrawRef ~ CD.CreateDrawRef[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.devicePrivate _ AddParm; appl.ob.class.drawMe[appl, pos, orient, dr]; IF (gateNode _ AddParm.gateNode) = NIL THEN ERROR; [] _ tranGeom.EnumerateArea[ rect~CDBasics.universe, perTile~FindChannelEdge, data~tranGeom]; [] _ tranGeom.EnumerateArea[ rect~CDBasics.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 SX.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 SX.CircuitNode ~ sdList; sdList _ sdList.rest; IF sdfirst.first.superceded # NIL THEN LOOP; FOR alreadySeen: LIST OF REF SX.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; }; SetUpResolution: PUBLIC PROCEDURE [constrArray: REF SX.ConstraintArray, res: SXTechnology.ResolutionTable] RETURNS [REF SX.ConstraintResolution] ~ { Index: TYPE ~ SX.ConstraintIndex; CoreIndex: TYPE ~ [1 .. Index.LAST]; cnsRes: REF SX.ConstraintResolution ~ NEW [SX.ConstraintResolution _ ALL[ALL[NIL]]]; RowUsed, ColumnUsed: ARRAY CoreIndex OF BOOLEAN _ ALL[FALSE]; excl: Index ~ SX.excludeIndex; --2 viol: Index ~ SX.violateIndex; --3 exclusionConstraint: REF SX.Constraint ~ NEW[ SX.Constraint _ [ $ExcludeByOpaqueCell, SX.excludeIndex]]; violationConstraint: REF SX.Constraint ~ NEW[ SX.Constraint _ [ $OpaqueCellViolation, SX.violateIndex]]; RowUsed[excl] _ ColumnUsed[excl] _ RowUsed[viol] _ ColumnUsed[viol] _ TRUE; cnsRes[0][excl] _ cnsRes[excl][0] _ exclusionConstraint; cnsRes[0][viol] _ cnsRes[viol][0] _ violationConstraint; FOR i: Index IN [1 .. Index.LAST] DO cnsRes[excl][i] _ cnsRes[i][excl] _ exclusionConstraint; cnsRes[viol][i] _ cnsRes[i][viol] _ violationConstraint; ENDLOOP; cnsRes[excl][excl] _ violationConstraint; FOR i: Index IN [0..Index.LAST] DO xi: Index ~ res[i][0]; xj: Index ~ res[0][i]; cnsRes[0][i] _ cnsRes[i][0] _ constrArray[i]; IF constrArray[i] # NIL AND i # constrArray[i].index THEN CD.Error[ec~ other, explanation~ "constrArray entry position, index mismatch"]; IF xi # 0 THEN { IF ColumnUsed[xi] THEN CD.Error[ec~ other, explanation~ "Duplicate column key in Constraint Resolution Table"]; ColumnUsed[xi] _ TRUE }; IF xj # 0 THEN { IF RowUsed[xj] THEN CD.Error[ec~ other, explanation~ "Duplicate row key in Constraint Resolution Table"]; RowUsed[xj] _ TRUE }; ENDLOOP; FOR i: CoreIndex IN CoreIndex DO IF RowUsed[i] # ColumnUsed[i] THEN CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table between row & column keys"]; ENDLOOP; FOR i: CoreIndex IN CoreIndex DO xi: Index ~ res[i][0]; IF xi = 0 THEN FOR j: CoreIndex IN CoreIndex DO IF res[i][j] # 0 THEN CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table entries"]; ENDLOOP ELSE FOR j: CoreIndex IN CoreIndex DO xj: Index ~ res[0][j]; IF xj = 0 THEN FOR k: CoreIndex IN CoreIndex DO IF res[k][j] # 0 THEN CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table entries"]; ENDLOOP ELSE { result: Index ~ res[i][j]; IF result = 0 THEN CD.Error[ec~ other, explanation~ "Missing entry in Constraint Resolution Table"]; cnsRes[xi][xj] _ constrArray[ result ] } ENDLOOP ENDLOOP; FOR i: CoreIndex IN CoreIndex DO FOR j: CoreIndex IN CoreIndex DO IF cnsRes[i][j] # cnsRes[j][i] THEN CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table entries"]; ENDLOOP ENDLOOP; RETURN [cnsRes] }; RegisterTechnologyHandle: PUBLIC PROCEDURE [cdTech: CD.Technology, technologyHandle: REF SX.TechHandle] ~ { FOR i: SX.SpinifexLayerIndex IN [SX.SpinifexLayerIndex.FIRST .. technologyHandle.numSpinifexLayers) DO IF technologyHandle.constraintResolutions[i] = NIL THEN technologyHandle.constraintResolutions[i] _ defaultResolution; ENDLOOP; CDProperties.PutPropOnTechnology[onto~ cdTech, prop~ SXAtoms.spinifex, val~ technologyHandle]; }; RegisterSpinifexObjectProcs: PUBLIC PROCEDURE [cdTech: CD.Technology, objectType: ATOM, conv: SX.ConversionProc, thyme, rose: SXOutput.LinkagePrintProc _ NIL, fini: SXOutput.LinkageHousekeeper _ NIL] ~ { op: REF CD.ObjectClass; IF (op_CD.FetchObjectClass[ objectType~objectType, technology~cdTech]) = NIL THEN CD.Error[explanation: "Version mismatch among ChipNDale and Spinifex"]; CDProperties.PutProp[ onto~op.properties, prop~SXAtoms.spinifex, val~ NEW[SX.ConversionProc_conv]]; IF thyme # NIL THEN CDProperties.PutProp[ onto~op.properties, prop~SXAtoms.thymePrint, val~ NEW[SXOutput.LinkagePrintProc_thyme]]; IF rose # NIL THEN CDProperties.PutProp[ onto~op.properties, prop~SXAtoms.rosePrint, val~ NEW[SXOutput.LinkagePrintProc_rose]]; IF fini # NIL THEN CDProperties.PutProp[ onto~op.properties, prop~SXAtoms.fini, val~ NEW[SXOutput.LinkageHousekeeper_fini]]; }; defaultResolution: REF SX.ConstraintResolution; InitDefaultResolution: PROCEDURE ~ { Index: TYPE ~ SX.ConstraintIndex; CoreIndex: TYPE ~ [1 .. Index.LAST]; excl: Index ~ SX.excludeIndex; viol: Index ~ SX.violateIndex; res: REF SX.ConstraintResolution; exclusionConstraint: REF SX.Constraint ~ NEW[ SX.Constraint _ [ $ExcludeByOpaqueCell, SX.excludeIndex]]; violationConstraint: REF SX.Constraint ~ NEW[ SX.Constraint _ [ $OpaqueCellViolation, SX.violateIndex]]; defaultResolution _ NEW[SX.ConstraintResolution]; res _ defaultResolution; res[0][excl] _ res[excl][0] _ exclusionConstraint; res[0][viol] _ res[viol][0] _ violationConstraint; FOR i: CoreIndex IN CoreIndex DO res[excl][i] _ res[i][excl] _ exclusionConstraint; res[viol][i] _ res[i][viol] _ violationConstraint; ENDLOOP; res[excl][excl] _ violationConstraint; }; GetCircuitFromCDObject: PUBLIC PROCEDURE [cdOb: CD.Object] RETURNS [c: REF SX.Circuit_NIL] = BEGIN sx: REF SX.LogicalCell = SXAccessInternal.GetSXData[cdOb]; IF sx#NIL THEN { IF sx.analysisState#useCircuit THEN ERROR; c _ sx.circuit } END; -- Module Initialization. InitDefaultResolution[]; END. >SXTechnologyImpl.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Written by Shand, June 12, 1984 3:11:49 pm PDT Last Edited by: Shand, March 12, 1985 3:04:13 pm PST Last Edited by: Jacobi, July 17, 1985 7:57:30 pm PDT Last edited by: gbb November 24, 1985 4:38:35 pm PST -- 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. --Ch. J., Jan 30, 1985 included LookupNode without further thinking -- Called for pullups where we can make a sensible decision on which node is the source. -- First set up technology independent Opaque cell constraints. -- Now copy the elements of constrArray to the first row and column of cnsRes. -- Debugging aid for technology writer. -- Debugging aid for technology writer. NULL; The following stuff was found here and I did not find a reason for it. It now is fully independent of the technology in SXAtomsImpl. Note: Spinifex never could handle concurrently different technologies because of global variables containing the technology. CDObjectProcs.RegisterFurther[key~ SXAtoms.spinifex, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~ SXAtoms.thymePrint, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~ SXAtoms.rosePrint, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~ SXAtoms.init, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~ SXAtoms.fini, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; -- Set up default technology independent Opaque cell constraints. Edited on January 30, 1985 8:09:05 pm PST, by jacobi in CheckChangeAndAdd: "cn.superceded _ node" replaced by "SX.LookupNode[cn].superceded _ node" Edited on March 7, 1985 1:43:51 am PST, by Shand Add interest bound to difChannel to detect interatcions between channel and dif changes to: ProcessMosTransistor new parameter to pass bloat distance, ConvertMaskGeom (local of ProcessMosTransistor) interestBloat parameter passed to AddBox. Edited on March 9, 1985 5:33:13 pm PST, by Shand Changed name of CircuitConstraint in SX to Constraint Added new procedure SetUpResolution to aid technology dependent clients in the construction of ConstraintResolution ARRAYs. changes to: DIRECTORY, ProcessMosTransistor, SetUpResolution, SetUpResolution Edited on March 12, 1985 3:04:13 pm PST, by Shand Technology Independent constraints added for ensuring the integrity of Opaque cells. New procedure GetCircuitFromCDObject to allow SXAtoms to be confined to Technology Independent part. changes to: DIRECTORY, ProcessMosTransistor, SetUpResolution, SXExtrasImpl, RegisterTechnologyHandle, RegisterSpinifexObjectClass, technologyIndependentRules, InitTechnologyIndependentRules, defaultResolution, InitDefaultResolution, GetCircuitFromCDObject, SetUpResolution Edited on March 27, 1985 6:39:31 pm PST, by Beretta changes to: SetUpResolution: debugging. Edited on May 6, 1985 11:26:55 am PDT, by Beretta Converted to ChipNDale CD20 gbb August 9, 1985 2:36:53 pm PDT Implementation of Core output. changes to: RegisterSpinifexObjectProcs: added parameter for core. gbb November 24, 1985 4:38:20 pm PST Removed Core output. changes to: DIRECTORY, RegisterTechnologyHandle, RegisterSpinifexObjectProcs ΚΔ˜code™Kšœ Οmœ7™BK™.K™4J™4K™4—unitšΟk ˜ Kšžœžœ˜˜ Kšœ žœ˜,Kšœ žœ ˜2Kšœžœδ˜ωKšžœ˜Kšœ˜Kšœžœ)˜6Kšœ žœ(˜6Kšœ ˜ —šΡaoxœžœž˜KšžœžœH˜RKšžœ ˜Kšžœ˜—Kšž˜Lšœ žœžœ˜)Kš œžœžœžœžœ˜Kš œžœžœžœžœ˜Kš œ žœžœžœžœ˜šœžœžœ˜Kšœžœ˜ Kšœžœ˜ K˜—šœžœžœ˜"Kšœžœ˜%Kšœžœ ˜Kšœ*˜*Kšœ žœ˜Kšœžœžœžœ˜Kšœ žœž˜K˜—šΟb œžœΠcs&œ˜HKšœ0™0Kšœžœžœ˜8KšœQ˜QLšžœžœžœ˜%šžœž˜Kšœ žœ˜šœ˜Kš œ žœžœžœžœ'˜]Kšœ ˜ šžœ žœž˜šžœž˜!KšœL˜LKšœM˜MKšžœ˜—K˜Kšž˜—Kšœ˜—šœ˜Kš œ žœžœžœžœ'˜]Kšœ ˜ šžœ žœž˜šžœž˜!KšœL˜LKšœM˜MKšžœ˜—K˜Kšžœ˜—šžœžœž˜Kšœ.˜.—šž˜Kšœ9˜9—Kšœ˜—šœ˜K™OKšœžœžœ*˜GK˜—KšžœΟc`˜j—K˜—š&Οnœžœž œ žœžœžœžœWžœ)žœ:žœžœžœ.žœžœ žœ#žœžœžœ#žœ˜ΰK™½š£œ’6œ˜fKšœžœžœžœ˜3Kšœžœžœ˜4šžœžœ˜Kšœ žœH˜Zšžœ žœž˜Kšœ˜šžœ žœ˜(Kšœ˜Kšœ˜K˜—Kšœ˜Kšž˜—K˜—K˜—š£œ’6œ˜fK™νšžœ ž˜šœ ˜ š£œž œ˜-šžœžœ˜Kšœ˜Kšœ<˜˜>—Kšžœ˜—Lšœ^˜^L™Lš œJžœ žœžœžœ™€Kš œLžœ žœžœžœ™‚Kš œKžœ žœžœžœ™Kš œFžœ žœžœžœ™|Kš œFžœ žœžœžœ™|K˜—š£œžœž œ žœžœDžœ&žœ˜ΛKšœžœžœ ˜L–B[ec: CD.ErrorCode _ programmingError, explanation: ROPE _ NIL]š žœžœ@žœžœžœE˜™KšœFžœ˜cšžœ žœž˜KšœHžœ#˜n—šžœžœž˜KšœGžœ"˜l—šžœžœž˜KšœBžœ$˜i—K˜—Lšœžœ˜/š£œž œ˜$Kšœžœ˜!Kšœ žœžœ˜$Kšœ˜Kšœ˜Kšœžœ˜!Lšœžœžœ<˜hKšœžœžœ<˜hL™AKšœžœ˜1Kšœ˜Kšœ2˜2Kšœ2˜2šžœžœ ž˜ Kšœ2˜2Kšœ2˜2Kšžœ˜—Kšœ&˜&K˜—L˜š£œžœž œžœ žœžœžœ žœ˜\Lšž˜Kšœžœžœ0˜:šžœžœžœ˜Kšžœžœžœ˜*Kšœ˜Kšœ˜—Kšžœ˜—head˜Kšœ˜—Kšžœ˜K™™4Kšœ^™^—™0K™OKšœ Οrœ%₯œJ™ —™0Kšœ5™5Kšœ₯œX™{Kšœ ₯A™M—™1Kšœd£œ@™ΊKšœ ₯„™—™3Kšœ €œ ™'—™1K™—™!K™Kšœ ₯œ™B—™$K™Kšœ ₯@™L—K™—…—-μLξ