DIRECTORY Basics, CD, CDBasics, CDCells, CDDirectory, CDProperties, CDRects, CDSymbolicObjects, CDTexts, CMosB, Core, CoreClasses, CoreFlat, CoreGeometry, CoreGeometryBackdoor, CoreOps, CoreProperties, GList, HashTable, IO, PWObjects, Rope, Sinix, SinixOps, SinixRawCMosB, TerminalIO; SinixRawCMosBImpl: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDCells, CDDirectory, CDProperties, CDRects, CDSymbolicObjects, CDTexts, CMosB, CoreFlat, CoreGeometry, CoreGeometryBackdoor, CoreClasses, CoreOps, CoreProperties, GList, HashTable, IO, PWObjects, Rope, Sinix, SinixOps, TerminalIO EXPORTS SinixRawCMosB SHARES CDCells, CDRects, CDSymbolicObjects, CDTexts = BEGIN CellType: TYPE = Core.CellType; Wire: TYPE = Core.Wire; Wires: TYPE = Core.Wires; Object: TYPE = CD.Object; Properties: TYPE = Core.Properties; ROPE: TYPE = Core.ROPE; standardMode: Sinix.Mode = SinixOps.GetExtractMode[CMosB.cmosB]; justKeepOne: BOOL _ FALSE; mode: PUBLIC Sinix.Mode _ NEW [Sinix.ModeRec _ [ extractProcProp: PWObjects.RegisterProp[$RawCMosBExtractProc, TRUE], decoration: CoreGeometry.CreateDecoration["RawCMosB"], nbOfLayers: standardMode.nbOfLayers, instanceLayer: standardMode.instanceLayer, touchProc: CoreGeometry.Touch, fusionByName: none, equalProc: SmallerOverlap, userData: UserData ]]; SmallerOverlap: PROC [obj: Object, cacheProperties: CD.PropList, cacheUserData: REF, properties: CD.PropList, userData: REF] RETURNS [cacheOK: BOOL] = { cacheData: REF INT = NARROW [cacheUserData]; data: REF INT = NARROW [userData]; cacheOK _ Sinix.CompareProps[obj, cacheProperties, cacheUserData, properties, userData] AND cacheData^>=data^; }; UserData: PROC [design: CD.Design] RETURNS [REF] = {RETURN [NEW [INT _ 0]]}; ExtractCellAsWire: Sinix.ExtractProc = { EachInst: CDCells.InstEnumerator = {pins _ CONS [[inst.ob, inst.trans], pins]}; pins: CoreGeometry.Instances _ NIL; wire: Wire _ CoreOps.CreateWire[]; [] _ CDCells.EnumerateInstances[obj, EachInst]; CoreGeometry.PutPins[mode.decoration, wire, pins]; result _ wire; }; PreExtracted: Sinix.ExtractProc = {result _ CDProperties.GetObjectProp[obj, $PreExtracted]}; Mark: PROC [design: CD.Design] RETURNS [total, marked: INT _ 0] = { usage: HashTable.Table = HashTable.Create[]; -- maps every cell to the containing cell. Objects are keys, and values are either $unique, or $many if several cell contain that object. replaceList: LIST OF CDDirectory.ReplaceRec _ NIL; ReplaceRoutingCells: CDDirectory.EachEntryAction = { nodes: HashTable.Table; CheckHasSignalName: CDCells.InstEnumerator = { quit _ CDProperties.GetInstanceProp[inst, $SignalName]=NIL OR inst.trans.orient#original OR CDSymbolicObjects.IsSymbolicOb[inst.ob]; }; InsertInst: CDCells.InstEnumerator = { name: ROPE = NARROW [CDProperties.GetInstanceProp[inst, $SignalName]]; list: REF LIST OF PWObjects.PlacedObject _ NARROW [HashTable.Fetch[nodes, name].value]; IF list=NIL THEN list _ NEW [LIST OF PWObjects.PlacedObject _ NIL]; list^ _ CONS [[object: inst.ob, position: inst.trans.off], list^]; [] _ HashTable.Store[nodes, name, list]; }; IF NOT CDCells.IsCell[ob] THEN RETURN; IF CDCells.EnumerateInstances[ob, CheckHasSignalName] THEN RETURN; TerminalIO.PutF["### Replacing routing cell %g!\n", IO.rope[CDDirectory.Name[ob]]]; nodes _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; [] _ CDCells.EnumerateInstances[ob, InsertInst]; replaceList _ CONS [[old: ob, new: PWObjects.CreateRouting[CD.InterestRect[ob], PWObjects.CreateNodes[nodes]]], replaceList]; }; CountEachUse: CDDirectory.EachEntryAction = { EachInst: CDCells.InstEnumerator = { value: REF = HashTable.Fetch[usage, inst.ob].value; IF NOT CDCells.IsCell[inst.ob] THEN RETURN; [] _ HashTable.Store[usage, inst.ob, IF value=NIL THEN $unique ELSE $many]; }; IF NOT CDCells.IsCell[ob] THEN RETURN; total _ total + 1; [] _ CDCells.EnumerateInstances[ob, EachInst]; }; MarkUniques: HashTable.EachPairAction = { IF value=$many THEN RETURN; marked _ marked + 1; CDProperties.PutProp[key, $RawFlatten, $RawFlatten]; }; [] _ CDDirectory.Enumerate[design, ReplaceRoutingCells]; WHILE replaceList#NIL DO CDDirectory.ReplaceObject[design, replaceList.first.old, replaceList.first.new]; replaceList _ replaceList.rest; ENDLOOP; [] _ CDDirectory.Enumerate[design, CountEachUse]; [] _ HashTable.Pairs[usage, MarkUniques]; }; SortedEdges: TYPE = ARRAY CoreGeometry.Side OF LIST OF Wire _ ALL [NIL]; WireMinMax: TYPE = RECORD [wire: Wire, min, max: INT]; SortEdges: PROC [mode: Sinix.Mode, ll: CD.Layer, cellType: CellType] RETURNS [edges: SortedEdges] = { FOR ss: CoreGeometry.Side IN CoreGeometry.Side DO wmm: LIST OF REF WireMinMax _ NIL; edge: LIST OF Wire _ NIL; EachWirePin: CoreGeometry.EachWirePinProc = { IF wire.size#0 OR side#ss OR layer#ll THEN RETURN; wmm _ CONS [NEW [WireMinMax _ [wire, min, max]], wmm]; }; CompareWMM: GList.CompareProc = { wmm1: REF WireMinMax = NARROW [ref1]; wmm2: REF WireMinMax = NARROW [ref2]; RETURN [Basics.CompareINT[wmm2.min, wmm1.min]]; }; [] _ CoreGeometry.EnumerateNonOverlappingSides[mode.decoration, cellType, EachWirePin]; FOR list: LIST OF REF WireMinMax _ NARROW [GList.Sort[wmm, CompareWMM]], list.rest WHILE list#NIL DO edge _ CONS [list.first.wire , edge]; ENDLOOP; edges[ss] _ edge; ENDLOOP; }; MatchSourceToExtracted: PROC [sourceMode: Sinix.Mode, layer: CD.Layer, source, extractedCT: CellType, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [new: CellType] = { sourceEdges: SortedEdges _ SortEdges[sourceMode, layer, source]; extractedEdges: SortedEdges _ SortEdges[mode, CMosB.ovg, extractedCT]; public: Wire _ CoreOps.CopyWire[source.public]; table: HashTable.Table _ HashTable.Create[]; -- from extracted to new sourceToNew: HashTable.Table _ CoreOps.CreateBindingTable[source.public, public]; -- from source to new FOR side: CoreGeometry.Side IN CoreGeometry.Side DO length: INT = GList.Length[sourceEdges[side]]; IF length#GList.Length[extractedEdges[side]] THEN ERROR; THROUGH [0 .. length) DO sourceWire: Wire _ sourceEdges[side].first; extractedWire: Wire _ extractedEdges[side].first; newWire: Wire _ NARROW [HashTable.Fetch[sourceToNew, sourceWire].value]; prevNew: Wire _ NARROW [HashTable.Fetch[table, extractedWire].value]; IF prevNew#NIL AND prevNew#newWire THEN ERROR; [] _ HashTable.Store[table, extractedWire, newWire]; sourceEdges[side] _ sourceEdges[side].rest; extractedEdges[side] _ extractedEdges[side].rest; ENDLOOP; ENDLOOP; IF HashTable.GetSize[table]#CoreOps.WireBits[public] THEN ERROR; new _ CoreClasses.CreatePermutedRecordCell[iconPublic: public, schCell: extractedCT, table: table, name: name, props: props]; }; IsOverglass: PROC [obj: CD.Object] RETURNS [BOOL] = { RETURN [obj.class=CDRects.bareRectClass AND obj.layer=CMosB.ovg]; }; SpecialGetGeometry: PROC [wire: Wire] RETURNS [geometry: CoreGeometry.Instances _ NIL, ovg: BOOL _ FALSE] = { ConsEachGeom: CoreGeometry.EachInstanceProc = { SELECT TRUE FROM IsOverglass[instance.obj] => {ovg _ TRUE; geometry _ CONS [instance, geometry]}; geometry=NIL => geometry _ LIST [instance]; ENDCASE => IF NOT justKeepOne THEN geometry _ CONS [instance, geometry]; }; [] _ CoreGeometry.EnumerateGeometry[mode.decoration, wire, ConsEachGeom]; }; RawExtractCell: Sinix.ExtractProc = { flattenSomeChild: BOOL _ FALSE; rct: CoreClasses.RecordCellType; new, record: CellType; newInternals: Wires _ NIL; -- used only if flatten of a child necessary instances: LIST OF CoreClasses.CellInstance _ NIL; -- used only if flatten of a child necessary [result, props] _ Sinix.ExtractCell[obj, mode, properties, userData]; record _ NARROW [result]; rct _ NARROW [record.data]; IF rct.size=0 THEN CoreProperties.PutCellTypeProp[record, $RawFlatten, $Keep]; IF CDProperties.GetObjectProp[obj, $RawFlatten]=$RawFlatten THEN CoreProperties.PutCellTypeProp[record, $RawFlatten, $Smash]; FOR i: NAT IN [0 .. rct.size) DO IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]#NIL THEN flattenSomeChild _ TRUE; ENDLOOP; IF NOT flattenSomeChild THEN RETURN; TerminalIO.PutF["In cell %g, flattening:", IO.rope[CDDirectory.Name[obj]]]; FOR i: NAT IN [0 .. rct.size) DO IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]=NIL THEN instances _ CONS [rct[i], instances] ELSE { CreateWire: PROC [old: Wire] RETURNS [wire: Wire] = { geometry: CoreGeometry.Instances; ovg: BOOL; [geometry, ovg] _ SpecialGetGeometry[old]; geometry _ CoreGeometry.TransformList[trans, geometry]; wire _ CoreOps.CreateWire[]; CoreGeometry.PutGeometry[mode.decoration, wire, geometry]; newInternals _ CONS [wire, newInternals]; }; AddInTable: PROC [subInternal: Wire] = { IF HashTable.Fetch[intToInt, subInternal].value#NIL THEN RETURN; [] _ HashTable.Store[intToInt, subInternal, CreateWire[subInternal]]; }; CreateActual: PROC [oldAct: Wire] RETURNS [newAct: Wire] = { newAct _ NARROW [HashTable.Fetch[intToInt, oldAct].value]; IF newAct#NIL THEN RETURN; IF oldAct.size=0 THEN [] _ HashTable.Store[intToInt, oldAct, newAct _ CreateWire[oldAct]] ELSE { newAct _ CoreOps.CreateWires[size: oldAct.size]; FOR i: NAT IN [0 .. oldAct.size) DO newAct[i] _ CreateActual[oldAct[i]] ENDLOOP; }; }; DecorateBinding: HashTable.EachPairAction = { pub: Wire = NARROW [key]; act: Wire = NARROW [value]; CoreGeometry.AddGeometry[ mode.decoration, act, CoreGeometry.TransformList[trans, SpecialGetGeometry[pub].geometry] ]; -- Hack to save some space for now! }; name: ROPE = CoreOps.GetCellTypeName[rct[i].type]; trans: CoreGeometry.Transformation = CoreGeometry.GetTrans[mode.decoration, rct[i]]; subrct: CoreClasses.RecordCellType = NARROW [rct[i].type.data]; intToInt: HashTable.Table _ CoreOps.CreateBindingTable[rct[i].type.public, rct[i].actual]; [] _ HashTable.Pairs[intToInt, DecorateBinding]; IF NOT Rope.Equal[CDDirectory.Name[CoreGeometry.GetObject[mode.decoration, rct[i].type]], name] THEN ERROR; TerminalIO.PutF[" %g[%g]", IO.rope[name], IO.int[subrct.size]]; CoreOps.VisitRootAtomics[subrct.internal, AddInTable]; FOR j: NAT IN [0 .. subrct.size) DO instance: CoreClasses.CellInstance _ CoreClasses.CreateInstance[actual: CreateActual[subrct[j].actual], type: subrct[j].type, props: subrct[j].properties]; CoreGeometry.PutTrans[mode.decoration, instance, CDBasics.ComposeTransform[itemInCell: CoreGeometry.GetTrans[mode.decoration, subrct[j]], cellInWorld: trans]]; instances _ CONS [instance, instances] ENDLOOP; IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]=$Smash THEN Sinix.FlushCache[CoreGeometry.GetObject[mode.decoration, rct[i].type]]; }; ENDLOOP; IF instances=NIL AND newInternals=NIL AND record.public.size=1 AND rct.internal.size=1 THEN {result _ record.public[0]; RETURN}; -- optimization good for Big contacts! new _ CoreClasses.CreateRecordCell[ record.public, CoreOps.UnionWire[rct.internal, CoreOps.CreateWire[newInternals]], instances, NIL, record.properties, TRUE ]; CoreGeometry.PutObject[mode.decoration, new, CoreGeometry.GetObject[mode.decoration, record]]; IF CDProperties.GetObjectProp[obj, $RawFlatten]#$RawFlatten AND instances=NIL THEN CoreProperties.PutCellTypeProp[new, $RawFlatten, $Keep]; TerminalIO.PutF[".\n"]; result _ new; }; Search: PROC [rootCT: CellType, name: ROPE] RETURNS [ct: CellType _ NIL, flat: CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType] = { UnboundFlatCell: CoreFlat.UnboundFlatCellProc = { IF Rope.Equal[CoreOps.GetCellTypeName[cell], name] THEN {ct _ cell; flat _ flatCell; RETURN}; IF cell.class=CoreClasses.recordCellClass THEN CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, UnboundFlatCell]; }; UnboundFlatCell[rootCT]; }; Same: PROC [nameOrClass: REF] = { class: CD.ObjectClass; WITH nameOrClass SELECT FROM c: CD.ObjectClass => class _ c; r: ATOM => class _ CD.FetchObjectClass[r, CMosB.cmosB]; ENDCASE => ERROR; CDProperties.PutProp[class, mode.extractProcProp, CDProperties.GetProp[class, standardMode.extractProcProp]]; }; Sinix.RegisterExtractProc[$RawExtractCell, RawExtractCell]; Sinix.RegisterExtractProc[$PreExtracted, PreExtracted]; Sinix.RegisterExtractProc[$ExtractCellAsWire, ExtractCellAsWire]; CDProperties.PutProp[CDCells.pCellClass, mode.extractProcProp, $RawExtractCell]; Same[PWObjects.routingClass]; Same[CDSymbolicObjects.pinClass]; Same[CDSymbolicObjects.segmentClass]; Same[CDSymbolicObjects.markClass]; Same[CDRects.bareRectClass]; Same[$C2SimpleCon]; Same[$C2WellSimpleCon]; Same[$C2LargeSimpleCon]; Same[$C2LargeWellSimpleCon]; Same[$C2DifShortCon]; Same[$C2WellDifShortCon]; Same[$C2Via]; Same[$C2LargeVia]; Same[$C2PDifRect]; Same[$C2NDifRect]; Same[$C2Trans]; Same[$C2WellTrans]; Same[$C2LTrans]; Same[$C2LWellTrans]; Same[CDTexts.rigidTextClass]; Same[CDTexts.flipTextClass]; SinixOps.RegisterModeCommands[mode, CMosB.cmosB]; CoreGeometryBackdoor.RegisterDecorationIO[mode.decoration] END. :SinixRawCMosBImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet October 30, 1986 12:49:32 pm PST Bertrand Serlet March 26, 1987 11:24:37 pm PST Last Edited by: Louis Monier March 3, 1987 10:28:59 pm PST Types Mode we use the knowledge of what is the cache and what is the call Extracting PadBlank and Fake extract Necessary so that vias get extracted as one guy, not as many! To say that the result comes from the property $PreExtracted Marking Cells used once and Convert routing cells Computing corresponding cells Cell extraction same as CoreGeometry.GetGeometry, but only keeps 1 instances (+ all overglass rectangles!). The following code does not deal properly with DAGS. Who cares? -- We flush the Sinix cache for name. When we flush, we do not need to explicit the pins because there is no circularity If obj had already the $RawFlatten property, fine. If it did not have it and we have zero instance, let's make sure we'll flatten this cell. We do not flatten cell with only one instance, since wire decorations might kill us! Looking for a named CellType Test function Test: PROC [obj: CD.Object, mode: Sinix.Mode] RETURNS [new: CD.Object] = { ct: Core.CellType _ NARROW [Sinix.Extract[obj, mode].result]; name: ROPE _ CoreOps.GetCellTypeName[ct]; [] _ CoreIO.ReportSaveCellType[ct]; ct _ CoreIO.RestoreCellType[name]; ct _ CoreOps.Recast[ct]; new _ CoreGeometry.GetObject[mode.decoration, ct]; }; Initialization Registering extract procs Cells Pins Rectangles Contacts Diffusion wires Transistors Angle Transistors Texts Κ x˜codešœ™Kšœ Οmœ1™˜R—K˜•StartOfExpansion[]šΟnœžœžœ˜!Kšžœ žœΒžœ/˜…Kšžœ˜Kšžœ0ž˜;—head™Jšœ žœ˜Jšœžœ ˜Jšœžœ˜Jšœžœžœ˜Jšœ žœ˜#Jšžœžœžœ˜—™šœ@˜@K˜—Jšœ žœžœ˜šœžœžœ˜0Jšœ>žœ˜DJšœ6˜6Jšœ$˜$Jšœ*˜*Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜J˜—J–‘ -- [obj: CD.Object, mode: Sinix.Mode, properties: PropertyLists.PropList _ NIL, userData: REF ANY _ NIL] RETURNS [result: REF ANY, props: Core.Properties _ NIL]šœ>™>šŸœžœ žœžœžœžœžœ žœ˜˜Jšœ žœžœžœ˜,Jšœžœžœžœ ˜"JšœXžœ˜nJšœ˜J˜—JšŸœžœ žœ žœžœžœžœžœ˜L—™$Jšœ=™=šŸœ˜(JšŸœ#žœ ˜OJšœžœ˜#J˜"Jšœ/˜/Jšœ2˜2J˜J˜J˜—J™