<> <> <> <> <<>> DIRECTORY CD, CDBasics, CDCells, CDDirectory, CDProperties, CDRects, CDSymbolicObjects, CDTexts, CMosB, Core, CoreClasses, CoreGeometry, CoreOps, CoreProperties, HashTable, IO, PWObjects, Rope, Sinix, SinixOps, SinixRawCMosB, TerminalIO; SinixRawCMosBImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDDirectory, CDProperties, CDRects, CDSymbolicObjects, CDTexts, CMosB, CoreGeometry, CoreClasses, CoreOps, CoreProperties, 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]; 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[]; CoreGeometry.PutPins[mode.decoration, wire, pins]; [] _ CDCells.EnumerateInstances[obj, EachInst]; result _ wire; }; <> 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. 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, CountEachUse]; [] _ HashTable.Pairs[usage, MarkUniques]; }; <> MatchSourceToExtracted: PROC [sourcePublic: Wire, extractedCT: CellType, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [new: CellType] = { FillTable: PROC [extractedWire: Wire] = { FillTableInternal: PROC [sourcePublic, newPublic: Wire] = { prevSource: Wire; sourcePins: CoreGeometry.Instances _ CoreGeometry.GetPins[standardMode.decoration, sourcePublic]; IF NOT CoreGeometry.TouchListList[sourcePins, extractedPins] THEN RETURN; prevSource _ NARROW [HashTable.Fetch[table, extractedWire].value]; IF prevSource#NIL AND prevSource#newPublic THEN ERROR; [] _ HashTable.Store[table, extractedWire, newPublic]; }; EachWirePair: CoreOps.EachWirePairProc = {FillTableInternal[actualWire, publicWire]}; extractedPins: CoreGeometry.Instances _ CoreGeometry.GetPins[mode.decoration, extractedWire]; [] _ CoreOps.VisitBindingSeq[sourcePublic, public, EachWirePair]; }; public: Wire _ CoreOps.CopyWire[sourcePublic]; table: HashTable.Table _ HashTable.Create[]; CoreOps.VisitRootAtomics[extractedCT.public, FillTable]; new _ CoreClasses.CreatePermutedRecordCell[iconPublic: public, schCell: extractedCT, table: table, name: name, props: props]; }; <> ExplicitPins: CoreOps.EachWireProc = { CoreGeometry.PutPins[mode.decoration, wire, CoreGeometry.GetPins[mode.decoration, wire]]; }; 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; <> [] _ CoreOps.VisitWireSeq[record.public, ExplicitPins]; -- we want to avoid the TransWireIR lazyness which is using the InterestRect IF NOT flattenSomeChild THEN RETURN; TerminalIO.PutF["In cell %g, flattening:", IO.rope[CDDirectory.Name[obj]]]; <> [] _ CoreOps.VisitWireSeq[record.public, ExplicitPins]; 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 _ CoreGeometry.GetGeometry[mode.decoration, old]; IF geometry#NIL THEN geometry _ LIST [CoreGeometry.Transform[trans, geometry.first]]; -- Hack to save some space for now! 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]; geometry: CoreGeometry.Instances _ CoreGeometry.GetGeometry[mode.decoration, pub]; IF geometry#NIL THEN CoreGeometry.AddGeometry[ mode.decoration, act, LIST [CoreGeometry.Transform[trans, geometry.first]] ]; -- 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>> IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]=$Smash THEN Sinix.FlushCache[CoreGeometry.GetObject[mode.decoration, rct[i].type]]; }; ENDLOOP; 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; }; <> 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[$ExtractCellAsWire, ExtractCellAsWire]; <> CDProperties.PutProp[CDCells.pCellClass, mode.extractProcProp, $RawExtractCell]; <> 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]; END.