DIRECTORY CD USING [CreateDrawRef, DrawRectProc, DrawRef, Error, FetchObjectClass, Instance, Layer, Number, ObjectClass, Object, Transformation, Rect, Technology], CDBasics USING [Extend, NonEmpty, universe], CDProperties USING [PutTechnologyProp, PutProp], CStitching USING [Area, ChangeRect, EEdge, EN, EnumerateArea, ListArea, ChangeTile, NE, NewTesselation, NEdge, TileProc, Region, SEdge, SW, Tesselation, Tile, WEdge, WS], SX USING [AddBox, AddRect, Circuit, CircuitNode, Constraint, ConstraintArray, ConstraintIndex, ConstraintResolution, ConversionProc, excludeIndex, LogicalCell, LookupNode, SpinifexLayerIndex, TechHandle, violateIndex], SXAccessInternal USING [GetLogicalCell], SXAtoms USING [fini, rosePrint, spinifex, thymePrint], SXOutput USING [LinkageHousekeeper, LinkagePrintProc], SXTechnology USING [PerDrawRectProc, ReportDifProc, ResolutionTable, TransistorMaterial]; SXTechnologyImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDProperties, CStitching, SX, SXAccessInternal, SXAtoms EXPORTS SXTechnology SHARES CStitching = BEGIN TilePtr: TYPE = CStitching.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: CStitching.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 CStitching.Region _ NARROW[CStitching.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, new~chanPtr]; chanPtr => data.tes.ChangeRect[ rect~occupants.first.rect, new~chanPtr]; ENDCASE; occupants _ occupants.rest ENDLOOP }; polysilicon => { occupants: LIST OF REF CStitching.Region _ NARROW[CStitching.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, new~chanPtr]; chanPtr => data.tes.ChangeRect[ rect~occupants.first.rect, new~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, trans: CD.Transformation, 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: CStitching.TileProc -- [tile: TilePtr, data: REF ANY] RETURNS [REF ANY] -- ~{ occupants, tmp: LIST OF REF CStitching.Region; tes: CStitching.Tesselation ~ NARROW [data]; IF tile.value = chanPtr THEN { occupants _ NARROW[CStitching.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: CStitching.TileProc -- [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.WS, st.NE WHILE st.WEdge < tile.EEdge DO CheckChangeAndAdd[ st]; ENDLOOP; FOR wt: TilePtr _ tile.SW, wt.EN WHILE wt.SEdge < tile.NEdge DO CheckChangeAndAdd[ wt]; ENDLOOP; FOR nt: TilePtr _ tile.EN, nt.SW WHILE nt.EEdge > tile.WEdge DO CheckChangeAndAdd[ nt]; ENDLOOP; FOR et: TilePtr _ tile.NE, et.WS WHILE et.NEdge > tile.SEdge 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: CStitching.Tesselation ~ CStitching.NewTesselation []; sdList: LIST OF REF SX.CircuitNode _ NIL; dr: CD.DrawRef ~ CD.CreateDrawRef [[]]; chEdge: LIST OF REF CStitching.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, trans, dr]; IF (gateNode _ AddParm.gateNode) = NIL THEN ERROR; [] _ tranGeom.EnumerateArea[ rect~CDBasics.universe, eachTile~FindChannelEdge, data~tranGeom]; [] _ tranGeom.EnumerateArea[ rect~CDBasics.universe, eachTile~ConvertMaskGeom]; IF PostProcessor # NIL THEN FOR pL: LIST OF REF Post _ AddParm.postRectList, pL.rest WHILE pL # NIL DO FindNodes: CStitching.TileProc -- [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, eachTile~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.PutTechnologyProp[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: 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.GetLogicalCell[cdOb]; IF sx#NIL THEN { IF sx.analysisState#useCircuit THEN ERROR; c _ sx.circuit } END; 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: Christian Jacobi, November 7, 1986 1:18:42 pm PST Last edited by: gbb June 6, 1986 3:27:26 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. --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. Module Initialization. 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™AK™/—unitšฯk ˜ Kšžœžœ‘˜™Kšœ žœ˜,Kšœ žœ˜0Kšœ žœš˜ชKšžœžœา˜ฺKšœžœ˜(Kšœžœ)˜6Kšœ žœ(˜6Kšœ žœG˜Y—code2šฯnœžœž˜Mšžœžœ&žœ˜MMšžœ ˜Mšžœž˜—Lšœ žœ˜ Kš œžœžœžœžœ˜Kš œžœžœžœžœ˜Kš œ žœžœžœžœ˜šœžœžœ˜Kšœžœ˜ Kšœžœ˜ K˜—šœžœžœ˜"Kšœ˜Kšœžœ ˜Kšœ*˜*Kšœ žœ˜Kšœžœžœžœ˜Kšœ žœž˜K˜—šฯb œžœะcs&œ˜HKšœ-™-Kšœžœžœ˜8KšœQ˜QLšžœžœžœ˜%šžœž˜Kšœ žœ˜šœ˜Kš œ žœžœžœžœ"˜SKšœ ˜ šžœ žœž˜šžœž˜!KšœG˜GKšœH˜HKšžœ˜—K˜Kšž˜—Kšœ˜—šœ˜Kš œ žœžœžœžœ"˜SKšœ ˜ šžœ žœž˜šžœž˜!KšœG˜GKšœH˜HKšžœ˜—K˜Kšžœ˜—šžœžœž˜Kšœ.˜.—šž˜Kšœ9˜9—Kšœ˜—šœ˜K™OKšœžœžœ*˜GK˜—Kšžœฯc`˜j—K˜—š$Ÿœžœž œ žœžœžœWžœ)žœ:žœžœžœ.žœžœ žœ#žœžœžœ#žœ˜ะK™บšŸœข6œ˜^Kšœžœžœžœ˜.Kšœžœ˜,šžœžœ˜Kšœ žœC˜Ušžœ žœž˜Kšœ˜šžœ žœ˜(Kšœ˜Kšœ˜K˜—Kšœ˜Kšž˜—K˜—K˜—šŸœข6œ˜^K™๊šžœ ž˜šœ ˜ šŸœž œ˜-šžœžœ˜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šœžœžœ5˜?šžœžœžœ˜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™—…—- M