<> <> <> <> <> <> <> DIRECTORY CD USING [CreateDrawRef, DrawOb, DrawRectProc, DrawRef, Error, FetchObjectClass, 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 => { <<-- Save on list and process and enumerate Diffusion nodes in this region later.>> 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 [ ob: CD.Object, 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~ob.layer, dim~t.Area, value~node] } ELSE WITH t.value SELECT FROM cn: REF SX.CircuitNode => SX.LookupNode[cn].superceded _ node; <<--Ch. J., Jan 30, 1985 included LookupNode without further thinking>> ENDCASE; }; node: REF SX.CircuitNode _ cir.AddRect[lev~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; CD.DrawOb[dr, ob, trans, NIL]; --see requirement: does not depend on instance properties 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]; <<-- Debugging aid for technology writer.>> 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]; <> < IF ec = doubleRegistration THEN CONTINUE];>> < IF ec = doubleRegistration THEN CONTINUE];>> < IF ec = doubleRegistration THEN CONTINUE];>> < IF ec = doubleRegistration THEN CONTINUE];>> < IF ec = doubleRegistration THEN CONTINUE];>> }; 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]]; <<-- Set up default technology independent Opaque cell constraints.>> 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. <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>>