<> <> <> <> <> <<>> 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; <<-- We flush the Sinix cache for name. When we flush, we do not need to explicit the pins because there is no circularity>> 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]; }; <> <> <> <> <<[] _ CoreIO.ReportSaveCellType[ct];>> <> <> <> <<};>> <> 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.