DIRECTORY CD, CDAtomicObjects, CDBasics, CDCells, CDDirectory, CDEvents, CDInstances, CDLayers, CDOrient, CDProperties, CDRects, CDSymbolicObjects, Core, CoreClasses, CoreOps, CoreProperties, Intervals, IO, Process, PW, PWCore, PWPins, RefTab, Rope, RopeList, Sinix, TerminalIO; SinixImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDDirectory, CDEvents, CDInstances, CDLayers, CDOrient, CDProperties, CDRects, CDSymbolicObjects, CoreClasses, CoreOps, CoreProperties, Intervals, IO, Process, PW, PWCore, PWPins, RefTab, Rope, RopeList, TerminalIO EXPORTS Sinix SHARES CDCells, CDRects = BEGIN OPEN Sinix; debug: BOOL _ TRUE; layoutProp: PUBLIC ATOM _ CoreProperties.RegisterProperty[PWCore.layoutProp, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]]; coreProp: PUBLIC ATOM _ PWCore.coreProp; extractedCoreProp: PUBLIC ATOM _ PW.RegisterProp[$SinixExtractedCore, TRUE]; pinsProp: PUBLIC ATOM _ CoreProperties.RegisterProperty[$SinixPins]; wireGeometryProp: PUBLIC ATOM _ CoreProperties.RegisterProperty[$SinixWireGeometry, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]]; instanceProp: PUBLIC ATOM _ CoreProperties.RegisterProperty[$SinixInstance]; errorsProp: PUBLIC ATOM _ CoreProperties.RegisterProperty[$SinixErrors, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]]; AddPinPropOnWire: PUBLIC PROC [wire: Wire, pin: CD.Instance] = { pins: LIST OF CD.Instance _ CONS [pin, NARROW [CoreProperties.GetWireProp[wire, pinsProp]]]; CoreProperties.PutWireProp[wire, pinsProp, pins]; }; AppendWireGeometryPropOnWire: PUBLIC PROC [wire: Wire, geometry: LIST OF CD.Instance] = { WHILE geometry#NIL DO AddWireGeometryPropOnWire[wire, geometry.first]; geometry _ geometry.rest; ENDLOOP; }; AddWireGeometryPropOnWire: PUBLIC PROC [wire: Wire, cdInstance: CD.Instance] = { PutWireGeometryPropOnWire[wire, CONS [cdInstance, GetWireGeometryPropFromWire[wire]]]; }; PutWireGeometryPropOnWire: PUBLIC PROC [wire: Wire, geometry: LIST OF CD.Instance] = { CoreProperties.PutWireProp[wire, wireGeometryProp, geometry]; }; GetWireGeometryPropFromWire: PUBLIC PROC [wire: Wire] RETURNS [geometry: LIST OF CD.Instance] = { geometry _ NARROW [CoreProperties.GetWireProp[wire, wireGeometryProp]]; }; FlushCoreAfterReplace: CDEvents.EventProc = { xname: ROPE _ CDDirectory.Name[NARROW [x]]; names: LIST OF ROPE _ IF xname=NIL THEN NIL ELSE LIST [xname]; -- names is going to be the transitive closure of all cells depending on xname FindInvalidNames: CDDirectory.EachEntryAction = { someChildIsName: BOOL _ FALSE; IsSomeChildName: CDDirectory.EnumerateObjectsProc = { IF RopeList.Memb[names, CDDirectory.Name[me]] THEN someChildIsName _ TRUE; }; CDDirectory.EnumerateChildObjects[ob, IsSomeChildName]; IF someChildIsName AND ~RopeList.Memb[names, name] THEN {names _ CONS[name, names]; quit _ TRUE}; }; InvalidateNames: CDDirectory.EachEntryAction = { IF RopeList.Memb[names, name] THEN { TerminalIO.WriteRope[Rope.Cat["Flush ", name, "\n"]]; CDProperties.PutPropOnObject[ob, extractedCoreProp, NIL]; }; }; WHILE CDDirectory.Enumerate[design, FindInvalidNames] DO {} ENDLOOP; [] _ CDDirectory.Enumerate[design, InvalidateNames]; }; Cellize: PROC [obj: CD.Object] RETURNS [cell: CD.Object]= { cellPtr: CD.CellPtr; cell _ CDCells.CreateEmptyCell[]; cellPtr _ NARROW [cell.specificRef]; cellPtr.contents _ LIST [PWPins.NewInstance[obj]]; cell.size _ obj.size; }; HighLightWires: PROC [fusionData: FusionData, cell: CD.Object, wires: LIST OF Wire] = { WHILE wires#NIL DO HighLightWire[fusionData, cell, wires.first]; wires _ wires.rest ENDLOOP; }; HighLightWire: PROC [fusionData: FusionData, cell: CD.Object, wire: Wire] = { HighLightInstances[cell, FindRootGeometry[fusionData, wire]]; }; HighLightInstances: PROC [cell: CD.Object, geometry: LIST OF CD.Instance] = { WHILE geometry#NIL DO HighLightInstance[cell, geometry.first]; geometry _ geometry.rest ENDLOOP; }; HighLightInstance: PROC [cell: CD.Object, inst: CD.Instance] = { cellPtr: CD.CellPtr _ NARROW [cell.specificRef]; hinst: CD.Instance _ PWPins.NewInstance[ ob: CDRects.CreateRect[inst.ob.size, CD.highLightShade], location: inst.location, orientation: inst.orientation]; cellPtr.contents _ CONS [hinst, cellPtr.contents]; }; FusionData: TYPE = REF FusionDataRec; FusionDataRec: TYPE = RECORD [ fusioned: RefTab.Ref, -- Association [fusioned -> root] [Wire -> Wire] geometry: RefTab.Ref, -- Association [root -> geometry] [Wire -> LIST OF CD.Instances] intervals: Intervals.Table -- Association [interval -> instance and root] [Intervals.Interval -> IW] ]; IW: TYPE = REF IWRec; IWRec: TYPE = RECORD [instance: CD.Instance, wire: Wire]; EqualIW: PROC [value1, value2: Intervals.Value] RETURNS [BOOL] = { iw1: IW _ NARROW [value1]; iw2: IW _ NARROW [value2]; RETURN [iw1^=iw2^]; }; InstanceToInterval: PROC [instance: CD.Instance] RETURNS [interval: Intervals.Interval] = { interval _ RectToInterval[CDInstances.InstRectO[instance]]; }; RectToInterval: PROC [rect: CD.Rect] RETURNS [interval: Intervals.Interval] = { interval _ [rect.x1+rect.y1, rect.x2+rect.y2]; }; InsertInstance: PROC [fusionData: FusionData, instance: CD.Instance, wire: Wire] = { newInstances: LIST OF CD.Instance _ CONS [instance, FindRootGeometry[fusionData, wire]]; [] _ RefTab.Store[fusionData.geometry, wire, newInstances]; Intervals.Insert[fusionData.intervals, InstanceToInterval[instance], NEW [IWRec _ [instance: instance, wire: wire]]]; }; DagIfy: PROC [fusionData: FusionData] = { WireDagIfy: PROC [wire: Wire] = { FOR i: NAT IN [0 .. wire.size) DO WireDagIfy[wire[i]]; wire[i] _ RootWire[fusionData, wire[i]]; ENDLOOP; }; InternalDagIfy: RefTab.EachPairAction = { wire: Wire _ NARROW [key]; quit _ FALSE; WireDagIfy[wire]; }; [] _ RefTab.Pairs[fusionData.geometry, InternalDagIfy]; }; CreateFusionData: PROC [rect: CD.Rect] RETURNS [fusionData: FusionData] = { fusionData _ NEW [FusionDataRec _ [ fusioned: RefTab.Create[], geometry: RefTab.Create[], intervals: Intervals.Create[RectToInterval[rect]] ]]; }; RootWire: PROC [fusionData: FusionData, wire: Wire] RETURNS [rootWire: Wire] = { rootWire _ NARROW [RefTab.Fetch[fusionData.fusioned, wire].val]; IF rootWire=NIL THEN RETURN [wire]; rootWire _ RootWire[fusionData, rootWire]; [] _ RefTab.Replace[fusionData.fusioned, wire, rootWire]; }; FindRootGeometry: PROC [fusionData: FusionData, wire: Wire] RETURNS [geometry: LIST OF CD.Instance] = { geometry _ NARROW [RefTab.Fetch[fusionData.geometry, wire].val]; }; InsertInstances: PROC [fusionData: FusionData, instances: LIST OF CD.Instance, wire: Wire] = { WHILE instances#NIL DO InsertInstance[fusionData, instances.first, wire]; instances _ instances.rest; ENDLOOP; }; DeleteFusioned: PROC [fusionData: FusionData, fusioned, root: Wire] = { fusionedGeometry: LIST OF CD.Instance _ FindRootGeometry[fusionData, fusioned]; IF fusioned=root THEN RETURN; -- might occur when called from InsureStructure root.properties _ CoreProperties.AppendProps[root.properties, fusioned.properties]; [] _ RefTab.Store[fusionData.fusioned, fusioned, root]; IF ~RefTab.Delete[fusionData.geometry, fusioned] THEN ERROR; FOR instances: LIST OF CD.Instance _ fusionedGeometry, instances.rest WHILE instances#NIL DO IF ~Intervals.Delete[fusionData.intervals, InstanceToInterval[instances.first], NEW [IWRec _ [instance: instances.first, wire: fusioned]], EqualIW] THEN ERROR; InsertInstance[fusionData, instances.first, root]; ENDLOOP; }; FindTouchingWires: PROC [fusionData: FusionData, geometry: LIST OF CD.Instance, compareLayers: BOOL _ TRUE] RETURNS [touchingWires: LIST OF Wire _ NIL] = { FOR insts: LIST OF CD.Instance _ geometry, insts.rest WHILE insts#NIL DO interval: Intervals.Interval _ InstanceToInterval[insts.first]; InternalFindTouchingWires: Intervals.EachIntervalValueProc = { iw: IW _ NARROW [value]; IF Touch[iw.instance, insts.first, compareLayers] AND ~CoreOps.Member[touchingWires, iw.wire] THEN touchingWires _ CONS [iw.wire, touchingWires]; }; [] _ Intervals.Enumerate[fusionData.intervals, InternalFindTouchingWires, interval]; ENDLOOP; }; AllMatchingWires: PROC [fusionData: FusionData, match: PROC [Wire, LIST OF CD.Instance] RETURNS [BOOL]] RETURNS [matchingWires: LIST OF Wire _ NIL] = { InternalEnumerate: RefTab.EachPairAction = { wire: Wire _ NARROW [key]; geometry: LIST OF CD.Instance _ NARROW [val]; quit _ FALSE; IF ~match[wire, geometry] THEN RETURN; matchingWires _ CONS [wire, matchingWires]; }; [] _ RefTab.Pairs[fusionData.geometry, InternalEnumerate]; }; MatchOnlyIfPinsProp: PROC [wire: Wire, geometry: LIST OF CD.Instance] RETURNS [BOOL] = { RETURN [CoreProperties.GetWireProp[wire, pinsProp]#NIL]; }; MatchAlways: PROC [wire: Wire, geometry: LIST OF CD.Instance] RETURNS [BOOL] = { PutWireGeometryPropOnWire[wire, geometry]; RETURN [TRUE]; }; InsureStructure: PROC [fusionData: FusionData, wire, structure: Wire, copyProps: BOOL] RETURNS [newWire, newStructure: Wire] = { SELECT TRUE FROM wire.size=0 AND structure.size=0 => { newWire _ wire; newStructure _ structure; }; wire.size=0 => { newWire _ CoreOps.CreateWires[structure.size]; [] _ RefTab.Store[fusionData.geometry, newWire, NIL]; -- so that enumerations do not forget this new wire newStructure _ CoreOps.CopyWire[structure]; DeleteFusioned[fusionData, wire, newWire]; FOR i: NAT IN [0 .. structure.size) DO newWire[i] _ CoreOps.CreateWire[props: IF copyProps THEN CoreProperties.CopyProps[structure[i].properties] ELSE NIL]; [] _ RefTab.Store[fusionData.geometry, newWire[i], NIL]; -- so that enumerations do not forget this new wire [newWire[i], newStructure[i]] _ InsureStructure[fusionData, newWire[i], structure[i], copyProps]; ENDLOOP; }; structure.size=0 => { newWire _ wire; newStructure _ wire; }; wire.size=structure.size => { newWire _ CoreOps.CreateWires[structure.size]; [] _ RefTab.Store[fusionData.geometry, newWire, NIL]; -- so that enumerations do not forget this new wire newStructure _ CoreOps.CopyWire[structure]; DeleteFusioned[fusionData, wire, newWire]; FOR i: NAT IN [0 .. wire.size) DO [newWire[i], newStructure[i]] _ InsureStructure[fusionData, wire[i], structure[i], copyProps]; DeleteFusioned[fusionData, wire[i], newWire[i]]; ENDLOOP; }; ENDCASE => ERROR; -- structure mismatch IF copyProps THEN newWire.properties _ CoreProperties.AppendProps[newWire.properties, structure.properties]; }; FusionStructureGeometryAndName: PROC [fusionData: FusionData, structure: Wire, geometry: LIST OF CD.Instance, name: ROPE, copyProps: BOOL] RETURNS [wire: Wire _ NIL] = { touchingWires: LIST OF Wire _ FindTouchingWires[fusionData, geometry]; IF name#NIL THEN { MatchName: PROC [wire: Wire, geometry: LIST OF CD.Instance] RETURNS [BOOL] = { RETURN [Rope.Equal[CoreOps.GetShortWireName[wire], name]]; }; sameNameWires: LIST OF Wire _ AllMatchingWires[fusionData, MatchName]; WHILE sameNameWires#NIL DO IF ~CoreOps.Member[touchingWires, sameNameWires.first] THEN { TerminalIO.WriteF["Fusion by name of %g\n", IO.rope[name]]; touchingWires _ CONS [sameNameWires.first, touchingWires]; }; sameNameWires _ sameNameWires.rest; ENDLOOP; }; FOR list: LIST OF Wire _ touchingWires, list.rest WHILE list#NIL DO touchingWireName: ROPE _ CoreOps.GetShortWireName[list.first]; SELECT TRUE FROM touchingWireName=NIL => {}; name=NIL => name _ touchingWireName; Rope.Equal[touchingWireName, name] => {}; ENDCASE => { TerminalIO.WriteF["Two wires that do not have the same name are touching: %g and %g.\n", IO.rope[name], IO.rope[touchingWireName]]; ERROR; }; ENDLOOP; IF touchingWires=NIL THEN { wire _ CoreOps.CreateWire[]; InsertInstances[fusionData, geometry, wire]; [] _ CoreOps.SetShortWireName[wire, name]; [wire, structure] _ InsureStructure[fusionData, wire, structure, copyProps]; RETURN; }; wire _ touchingWires.first; InsertInstances[fusionData, geometry, wire]; [] _ CoreOps.SetShortWireName[wire, name]; [wire, structure] _ InsureStructure[fusionData, wire, structure, copyProps]; touchingWires _ touchingWires.rest; WHILE touchingWires#NIL DO fusioned: Wire _ touchingWires.first; DeleteFusioned[fusionData, fusioned, wire]; [wire, structure] _ InsureStructure[fusionData, wire, fusioned, copyProps]; touchingWires _ touchingWires.rest; ENDLOOP; }; FusionWire: PROC [fusionData: FusionData, public: Wire, transformation: CD.Instance, copyProps: BOOL] RETURNS [actual: Wire] = { actual _ FusionStructureGeometryAndName[ fusionData, public, TransformList[transformation, NARROW [CoreProperties.GetWireProp[public, pinsProp]]], IF copyProps THEN CoreOps.GetShortWireName[public] ELSE NIL, copyProps ]; IF copyProps THEN actual.properties _ CoreProperties.AppendProps[actual.properties, public.properties]; FOR i: NAT IN [0 .. public.size) DO subActual: Wire _ FusionWire[fusionData, public[i], transformation, copyProps]; DeleteFusioned[fusionData, subActual, actual[i]]; IF ~CoreOps.Conform[subActual, actual[i]] THEN ERROR; ENDLOOP; }; FusionWires: PROC [fusionData: FusionData, public: Wire, transformation: CD.Instance] RETURNS [actual: Wire] = { actual _ CoreOps.CreateWires[public.size]; FOR i: NAT IN [0 .. actual.size) DO actual[i] _ FusionWire[fusionData, public[i], transformation, FALSE]; ENDLOOP; }; extractProcProp: PUBLIC ATOM _ PW.RegisterProp[$SinixExtractProc, TRUE]; Extract: PUBLIC ExtractProc = { refProc: REF ExtractProc _ NIL; cellType _ NARROW [CDProperties.GetPropFromObject[obj, extractedCoreProp]]; IF cellType#NIL THEN RETURN; refProc _ NARROW [CDProperties.GetPropFromList[properties, extractProcProp]]; IF refProc=NIL THEN refProc _ NARROW [CDProperties.GetPropFromObject[obj, extractProcProp]]; IF refProc=NIL THEN refProc _ NARROW [CDProperties.GetProp[obj.class, extractProcProp]]; [cellType, wire, category] _ (IF refProc=NIL THEN ExtractExpand ELSE refProc^)[obj, properties, userData]; }; ExtractExpand: PUBLIC ExtractProc = { newObj: CD.Object _ CDDirectory.Expand[obj, NIL, NIL]; TerminalIO.Write[IO.rope["Using ExpandProc for object of class "], IO.atom[obj.class.objectType], IO.rope[" \n"]]; IF newObj=NIL THEN ERROR; RETURN Extract[newObj, CDProperties.DangerousAppendProps[obj.properties, properties], userData]; }; ExtractWire: PUBLIC ExtractProc = { category _ $Wire; wire _ CoreOps.CreateWire[]; AddPinPropOnWire[wire, PWPins.NewInstance[obj]]; }; ExtractPin: PUBLIC ExtractProc = { instance: CD.Instance _ PWPins.NewInstance[ob: obj, properties: properties]; pinName: ROPE _ CDSymbolicObjects.GetName[instance]; category _ $Wire; wire _ CoreOps.CreateWire[name: pinName]; AddPinPropOnWire[wire, instance]; }; ExtractCell: PUBLIC ExtractProc = { cellPtr: CD.CellPtr _ NARROW [obj.specificRef]; cdInstances: LIST OF CD.Instance _ cellPtr.contents; fusionData: FusionData _ CreateFusionData[CDBasics.RectAt[[0, 0], obj.size]]; currentInstances: LIST OF CoreClasses.CellInstance _ NIL; count: NAT _ 0; Process.SetPriority[Process.priorityBackground]; FOR list: LIST OF CD.Instance _ cdInstances, list.rest WHILE list#NIL DO count _ count+1 ENDLOOP; TerminalIO.WriteF["Extracting cell %g (size: [%g, %g], instances: %g)\n", IO.rope[CDDirectory.Name[obj]], IO.int[obj.size.x], IO.int[obj.size.y], IO.int[count]]; WHILE cdInstances#NIL DO cdInstance: CD.Instance _ cdInstances.first; subCellType: Core.CellType; subWire: Wire; subCategory: ATOM; [subCellType, subWire, subCategory] _ Extract[cdInstance.ob, CDProperties.DangerousAppendProps[cdInstance.properties, properties], userData]; SELECT TRUE FROM subCategory=$Null => {}; subCategory=$Wire => { wire: Wire _ FusionWire[fusionData, subWire, cdInstance, TRUE]; }; subCategory=$Device => { instance: CoreClasses.CellInstance _ NEW [CoreClasses.CellInstanceRec _ [actual: FusionWires[fusionData, subCellType.public, cdInstance], type: subCellType]]; CoreProperties.PutCellInstanceProp[instance, instanceProp, cdInstance]; currentInstances _ CONS [instance, currentInstances]; }; ENDCASE => ERROR; cdInstances _ cdInstances.rest; ENDLOOP; BEGIN RectToInst: PROC [rect: CD.Rect] RETURNS [inst: CD.Instance] = { inst _ PWPins.NewInstance[CDRects.CreateRect[CDBasics.SizeOfRect[rect], CD.combined], CDBasics.BaseOfRect[rect]]; }; ir: CD.Rect _ CD.InterestRect[obj]; -- the interestRect ir1: CD.Rect _ [ir.x1, ir.y1-1, ir.x2, ir.y1+1]; ir2: CD.Rect _ [ir.x1-1, ir.y1, ir.x1+1, ir.y2]; ir3: CD.Rect _ [ir.x1, ir.y2-1, ir.x2, ir.y2+1]; ir4: CD.Rect _ [ir.x2-1, ir.y1, ir.x2+1, ir.y2]; irGeometry: LIST OF CD.Instance _ LIST [RectToInst[ir1], RectToInst[ir2], RectToInst[ir3], RectToInst[ir4]]; mightBePublic: LIST OF Wire _ FindTouchingWires[fusionData, irGeometry, FALSE]; WHILE mightBePublic#NIL DO wire: Wire _ mightBePublic.first; geometry: LIST OF CD.Instance _ FindRootGeometry[fusionData, wire]; IF geometry=NIL THEN ERROR; FOR instances: LIST OF CD.Instance _ geometry, instances.rest WHILE instances#NIL DO IF TouchList[irGeometry, instances.first, FALSE] THEN AddPinPropOnWire[wire, instances.first]; ENDLOOP; mightBePublic _ mightBePublic.rest; ENDLOOP; END ; FOR list: LIST OF CoreClasses.CellInstance _ currentInstances, list.rest WHILE list#NIL DO instance: CoreClasses.CellInstance _ list.first; actual: Wire _ instance.actual; FOR i: NAT IN [0 .. actual.size) DO wire: Wire _ RootWire[fusionData, actual[i]]; actual[i] _ wire; ENDLOOP; ENDLOOP; DagIfy[fusionData]; cellType _ CoreClasses.CreateRecordCell[ public: CoreOps.CreateWire[AllMatchingWires[fusionData, MatchOnlyIfPinsProp]], internal: CoreOps.CreateWire[AllMatchingWires[fusionData, MatchAlways]], instances: currentInstances, name: CDDirectory.Name[obj] ]; CoreProperties.PutCellTypeProp[cellType, layoutProp, obj]; CDProperties.PutPropOnObject[obj, extractedCoreProp, cellType]; }; ExtractAbut: PUBLIC ExtractProc = { newObj: CD.Object _ CDDirectory.Expand[obj, NIL, NIL]; IF newObj=NIL THEN ERROR; [cellType, wire, category] _ Extract[newObj, CDProperties.DangerousAppendProps[obj.properties, properties], userData]; IF cellType=NIL OR category#$Device THEN RETURN; CoreProperties.PutCellTypeProp[cellType, layoutProp, newObj]; CDProperties.PutPropOnObject[newObj, extractedCoreProp, cellType]; }; ExtractIndirect: PUBLIC ExtractProc = { nets: RefTab.Ref _ NARROW [CDProperties.GetPropFromObject[obj, PWCore.netsProp]]; sourceObject: CD.Object _ NARROW [obj.specificRef]; subCellType: Core.CellType; subWire: Wire; subCategory: ATOM; fusionData: FusionData _ CreateFusionData[CDBasics.RectAt[[0, 0], obj.size]]; subInstance: CoreClasses.CellInstance; fakeInstance: CD.Instance _ PWPins.NewInstance[obj]; TerminalIO.WriteF["Extracting indirect %g (size: [%g, %g])\n", IO.rope[CDDirectory.Name[obj]], IO.int[obj.size.x], IO.int[obj.size.y]]; [subCellType, subWire, subCategory] _ Extract[sourceObject, CDProperties.DangerousAppendProps[obj.properties, properties], userData]; IF nets=NIL THEN RETURN [subCellType, subWire, subCategory]; IF subCategory#$Device THEN ERROR; subInstance _ NEW [CoreClasses.CellInstanceRec _ [actual: FusionWires[fusionData, subCellType.public, fakeInstance], type: subCellType]]; CoreProperties.PutCellInstanceProp[subInstance, instanceProp, fakeInstance]; IF RefTab.GetSize[fusionData.fusioned]#0 THEN ERROR; -- we fusioned some wires! BEGIN FusionEachNet: PWCore.EachNetProc = { rootWire: Wire _ FusionStructureGeometryAndName[fusionData, wire, pins, NIL, FALSE]; rootWire.properties _ CoreProperties.AppendProps[rootWire.properties, wire.properties]; -- so to have a decent name, for example CoreProperties.PutWireProp[rootWire, pinsProp, pins]; }; [] _ PWCore.EnumerateNets[nets, FusionEachNet]; END; DagIfy[fusionData]; cellType _ CoreClasses.CreateRecordCell[ public: CoreOps.CreateWire[AllMatchingWires[fusionData, MatchOnlyIfPinsProp]], internal: CoreOps.CreateWire[AllMatchingWires[fusionData, MatchAlways]], instances: LIST [subInstance], name: CDDirectory.Name[obj] ]; IF CDProperties.GetPropFromObject[obj, coreProp]#NIL AND CoreOps.WireBits[NARROW [CDProperties.GetPropFromObject[obj, coreProp], Core.CellType].public]#CoreOps.WireBits[cellType.public] THEN ERROR; -- mismatch between the original core and the extracted core }; touchProcProp: PUBLIC ATOM _ PW.RegisterProp[$TouchProc]; Touch: PUBLIC TouchProc = { refProc: REF TouchProc; IF ~CDBasics.Intersect[CDInstances.InstRectO[instance1], CDInstances.InstRectO[instance2]] THEN RETURN; refProc _ NARROW [CDProperties.GetPropFromObject[instance1.ob, touchProcProp]]; IF refProc=NIL THEN refProc _ NARROW [CDProperties.GetProp[instance1.ob.class, touchProcProp]]; yes _ (IF refProc=NIL THEN TouchExpand ELSE refProc^)[instance1, instance2, compareLayers]; }; TouchExpand: PUBLIC TouchProc = { instance1 _ PWPins.NewInstance[ ob: CDDirectory.Expand[instance1.ob, NIL, NIL], location: instance1.location, orientation: instance1.orientation ]; IF instance1.ob=NIL THEN ERROR; RETURN [Touch[instance1, instance2, compareLayers]]; }; TouchPin: PUBLIC TouchProc = { RETURN [TouchRectObject[instance2, CDInstances.InstRectO[instance1], CDSymbolicObjects.GetLayer[instance1], compareLayers]]; }; TouchRect: PUBLIC TouchProc = { RETURN [TouchRectObject[instance2, CDInstances.InstRectO[instance1], instance1.ob.layer, compareLayers]]; }; TouchCell: PUBLIC TouchProc = { cellPtr: CD.CellPtr _ NARROW [instance1.ob.specificRef]; RETURN [TouchList[TransformList[instance1, cellPtr.contents], instance2, compareLayers]]; }; TouchAtomic: PUBLIC TouchProc = { FOR rList: CDAtomicObjects.DrawList _ NARROW [instance1.ob.specificRef, CDAtomicObjects.AtomicObsPtr].rList, rList.rest WHILE rList#NIL DO IF TouchRectObject[instance2, CDOrient.MapRect[rList.first.r, instance1.ob.size, instance1.orientation, instance1.location], rList.first.lev, compareLayers] THEN RETURN [TRUE]; ENDLOOP; }; TouchSomeLayer: PROC [instances: LIST OF CD.Instance, bound: CD.Rect] RETURNS [yes: BOOL _ FALSE] = { FOR list: LIST OF CD.Instance _ instances, list.rest WHILE list#NIL DO IF TouchSomeLayer1[list.first, bound] THEN RETURN [TRUE]; ENDLOOP; }; TouchSomeLayer1: PROC [instance: CD.Instance, bound: CD.Rect] RETURNS [yes: BOOL _ FALSE] = { IF ~CDBasics.Intersect[CDInstances.InstRectO[instance], bound] THEN RETURN; SELECT instance.ob.class FROM CDCells.cellClass => { cellPtr: CD.CellPtr _ NARROW [instance.ob.specificRef]; FOR instances: LIST OF CD.Instance _ cellPtr.contents, instances.rest WHILE instances#NIL DO IF TouchSomeLayer1[Transform[instance, instances.first], bound] THEN RETURN [TRUE]; ENDLOOP; }; ENDCASE => RETURN [TRUE]; }; TouchRectObject: PUBLIC PROC [instance: CD.Instance, rect: CD.Rect, layer: CD.Layer, compareLayers: BOOL _ TRUE] RETURNS [yes: BOOL _ FALSE] = { rectInstance: CD.Instance; IF ~CDBasics.Intersect[CDInstances.InstRectO[instance], rect] THEN RETURN; IF instance.ob.class=CDRects.bareRectClass THEN RETURN [~compareLayers OR CDLayers.AbstractToPaint[instance.ob.layer]=CDLayers.AbstractToPaint[layer]]; rectInstance _ PWPins.NewInstance[ ob: CDRects.CreateRect[CDBasics.SizeOfRect[rect], layer], location: CDBasics.BaseOfRect[rect] ]; yes _ Touch[instance, rectInstance, compareLayers]; }; Transform: PUBLIC PROC [transformation, instance: CD.Instance] RETURNS [result: CD.Instance] = { RETURN [PWPins.TransformInstance[instance, transformation.ob.size, transformation.location, transformation.orientation]]; }; TransformList: PUBLIC PROC [transformation: CD.Instance, instances: LIST OF CD.Instance] RETURNS [result: LIST OF CD.Instance _ NIL] = { WHILE instances#NIL DO result _ CONS [Transform[transformation, instances.first], result]; instances _ instances.rest; ENDLOOP; }; TouchList: PUBLIC PROC [instances: LIST OF CD.Instance, instance: CD.Instance, compareLayers: BOOL _ TRUE] RETURNS [yes: BOOL _ FALSE] = { FOR list: LIST OF CD.Instance _ instances, list.rest WHILE list#NIL DO IF Touch[list.first, instance, compareLayers] THEN RETURN [TRUE]; ENDLOOP; }; TouchListList: PUBLIC PROC [instances1, instances2: LIST OF CD.Instance, compareLayers: BOOL _ TRUE] RETURNS [yes: BOOL _ FALSE] = { FOR list: LIST OF CD.Instance _ instances1, list.rest WHILE list#NIL DO IF TouchList[instances2, list.first, compareLayers] THEN RETURN [TRUE]; ENDLOOP; }; CDEvents.RegisterEventProc[$AfterCellReplacement, FlushCoreAfterReplace]; END. θSinixImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet August 15, 1985 2:09:54 pm PDT Bertrand Serlet January 14, 1986 2:02:00 pm PST Pradeep Sindhu January 15, 1986 6:27:21 pm PST Barth, January 13, 1986 5:43:19 pm PST Utilities Properties hanging on the resulting Core Operations for an easy management of those properties Flushing caches when interactive edition Mechanism for flushing during edits [event: REF ANY, design: CD.Design, x: REF ANY] RETURNS [dont: BOOL _ FALSE] [name: ROPE, ob: CD.Object] RETURNS [quit: BOOL _ FALSE] [me: CD.Object, x: REF ANY] [name: ROPE, ob: CD.Object] RETURNS [quit: BOOL _ FALSE] HighLighting errors utilities Fusion data structure and internal manipulation Geometry can be attached at all levels of a structured wire. Fusion external manipulation Enforces the invariant: all roots have all their sub-wires which are roots The following PROC implements Fisher-Galler fusion, not for efficiency, but for simplicity This proc really does the fusion of fusioned and root, by wiping fusioned of some tables, and adding interesting properties of fusioned to root. Conceptually same as the previous one that uses the intervals but faster for getting all wires (or nearly all). Other Internal utilities decorates the wire on the way wire (at the moment of the call) is a non fusioned wire (a root wire appearing in fusionData.geometry) we add the wires that make a connection by name Check that touchingWires only contains unnamed wires or wires named name Dead Code (kept, for resurrection day). Be Grateful FusionName: PROC [name1, name2: ROPE] RETURNS [name: ROPE] = { name _ SELECT TRUE FROM name1=NIL => name2, name2=NIL => name1, Rope.Equal[name1, name2] => name1, ENDCASE => ERROR; -- different names on the same net (probably 2 pins of different nets connected together) }; WireToInterval: PROC [wire: Wire] RETURNS [interval: Intervals.Interval] = { interval _ InstancesToInterval[GetWireGeometryPropFromWire[wire]]; }; InstancesToInterval: PROC [instances: LIST OF CD.Instance] RETURNS [interval: Intervals.Interval] = { interval _ RectToInterval[CDInstances.BoundingRectO[instances]]; }; TouchWires: PROC [wire1, wire2: Wire] RETURNS [yes: BOOL _ FALSE] = { yes _ TouchListList[GetWireGeometryPropFromWire[wire1], GetWireGeometryPropFromWire[wire2]]; }; TouchWireInstances: PROC [wire: Wire, geometry: LIST OF CD.Instance] RETURNS [yes: BOOL _ FALSE] = { yes _ TouchListList[GetWireGeometryPropFromWire[wire], geometry]; }; TouchWireInstance: PROC [wire: Wire, geometry: CD.Instance] RETURNS [yes: BOOL _ FALSE] = { yes _ TouchList[GetWireGeometryPropFromWire[wire], geometry]; }; Extraction Enumerate all the internals, and add as a pin property all the geometry that crosses the interestRect We replace in all instances wires by their roots IF FindRootGeometry[fusionData, wire]=NIL THEN ERROR; -- non connected actual We build the CellType We fusion using the nets property, and we put pin properties for future use Test provisoire pour debug IF RefTab.GetSize[fusionData.fusioned]#0 THEN { Net connecting 2 subinternals not connected in layout cell: CD.Object _ Cellize[obj]; AddInCell: RefTab.EachPairAction = { wire: Wire _ NARROW [key]; geometry: LIST OF CD.Instance _ FindRootGeometry[RootWire[wire]]; quit _ FALSE; HighLightInstances[cell, geometry]; }; [] _ RefTab.Pairs[fusionData.fusioned, AddInCell]; ERROR; }; We build the CellType Geometry Primitives IF instance1.ob.class=CDSymbolicObjects.pinObjectsClass AND instance2.ob.class=CDSymbolicObjects.pinObjectsClass AND compareLayers THEN RETURN [CDLayers.AbstractToPaint[CDSymbolicObjects.GetLayer[instance1]]=CDLayers.AbstractToPaint[CDSymbolicObjects.GetLayer[instance2]]]; -- Speed up Hack Geometry Utilities Initialization ΚΑ– "cedar" style˜codešœ™Kšœ Οmœ1™ -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šœ?˜?šŸœ%˜>Jšœžœžœ ˜šžœ0žœ)˜^Jšžœžœ˜3—J˜—JšœT˜TJšžœ˜—J˜J˜—Jšœq™qš œžœ!žœžœžœžœ žœžœžœžœžœžœ˜—šŸœ˜,Jš œ žœžœžœžœ žœ˜HJšœžœ˜ Jšžœžœžœ˜&Jšœžœ˜+J˜—Jšœ:˜:J˜——™š œžœžœžœžœ žœžœ˜XJšžœ-žœ˜8J˜J˜—Jšœ™š  œžœžœžœžœ žœžœ˜PJšœ*˜*Jšžœžœ˜Jšœ˜J˜—Jšœf™fš œžœ<žœžœ"˜€šžœžœž˜šœ žœ˜&Jšœ)˜)J˜—šœ˜Jšœ/˜/Jšœ0žœ’3˜iJšœ+˜+Jšœ*˜*šžœžœžœž˜&Jš œ'žœ žœ3žœžœ˜uJšœ3žœ’3˜lJšœa˜aJšžœ˜—J˜—šœ˜Jšœ$˜$J˜—šœ!˜!Jšœ/˜/Jšœ0žœ’3˜iJšœ+˜+Jšœ*˜*šžœžœžœž˜!Jšœ^˜^Jšœ0˜0Jšžœ˜—J˜—Jšžœ žœ’˜/—Jšžœ žœ[˜lJ˜J˜—š œžœ5žœžœžœžœ žœžœžœ˜©Jšœžœžœ0˜Fšžœžœžœ˜š  œžœžœžœžœ žœžœ˜NJšžœ4˜:J˜—Jšœžœžœ0˜FJšœ/™/šžœžœžœ˜šžœ5žœ˜=Jšœ,žœ ˜;Jšœžœ'˜;J˜—Jšœ#˜#Jšžœ˜—J˜—JšœH™Hš žœžœžœ!žœžœž˜CJšœžœ(˜>šžœžœž˜Jšœžœ ˜ Jšœžœ$˜,Jšœ)˜)šžœ˜JšœYžœ žœ˜ƒJšžœ˜J˜——Jšžœ˜—šžœžœžœ˜Jšœ˜Jšœ,˜,Jšœ*˜*JšœL˜LJšžœ˜J˜—Jšœ˜Jšœ,˜,Jšœ*˜*JšœL˜LJšœ#˜#šžœžœž˜Jšœ%˜%Jšœ+˜+JšœK˜KJšœ#˜#Jšžœ˜—J˜—J˜š   œžœ8žœžœžœ˜€šœ(˜(Jšœ ˜ Jšœ˜Jšœžœ1˜UJšžœ žœ"žœžœ˜žœ˜EJšžœ˜—J˜——™4š   œžœžœžœžœ™>šœžœžœž™Jšœžœ™Jšœžœ™Jšœ#™#Jšžœ žœ’Y™q—J™—J˜š œžœžœ#™LJšœB™BJ™—J˜š  œžœ žœžœžœ žœ#™eJšœ@™@J™—J˜š   œžœžœžœžœ™EJšœ\™\J™—J˜š œžœžœžœžœ žœžœžœ™dJšœA™AJ™—J˜š  œžœžœ žœžœžœ™[Jšœ=™=J™——™ Jš œžœžœžœ!žœ˜HJ˜šŸœžœ˜Jšœ žœžœ˜Jšœ žœ:˜KJšžœ žœžœžœ˜Jšœ žœ=˜MJšžœ žœžœ žœ8˜\Jšžœ žœžœ žœ4˜XJš œžœ žœžœžœ&˜jJ˜—J˜šŸ œžœ˜%Jšœžœ"žœžœ˜6Jšœžœ0žœžœ˜rJšžœžœžœžœ˜JšžœZ˜`J˜—J˜šŸ œžœ˜#Jšœ˜J˜Jšœ0˜0Jšœ˜—J˜šŸ œžœ˜"Jšœ žœ@˜LJšœ žœ'˜4Jšœ˜Jšœ)˜)Jšœ!˜!Jšœ˜—J˜šŸ œžœ˜#Jšœ žœ žœ˜/Jšœ žœžœžœ˜4JšœM˜MJšœžœžœžœ˜9J–> -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šœžœ˜Jšœ0˜0Jšžœžœžœžœ#žœžœžœžœ˜aJš œJžœžœžœžœ ˜‘šžœ žœž˜Jšœ žœ˜,Jšœ8žœ˜>Jšœ˜šžœžœž˜Jšœ˜šœ˜Jšœ9žœ˜?J˜—šœ˜Jšœ%žœv˜žJšœG˜GJšœžœ˜5J˜—Jšžœžœ˜—Jšœ˜Jšžœ˜—J™ešžœ˜š   œžœžœžœžœ˜@KšœHžœ'˜qK˜—Jšœžœžœ’˜7J–> -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šœžœ)˜0J–> -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šœžœ)˜0J–> -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šœžœ)˜0J–> -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šœžœ)˜0Jš œ žœžœžœ žœF˜lJšœžœžœ2žœ˜Ošžœžœž˜Jšœ!˜!Jšœ žœžœžœ/˜CJšžœ žœžœžœ˜š žœ žœžœžœ%žœ žœž˜TJšžœ(žœžœ)˜^Jšžœ˜—Jšœ#˜#Jšžœ˜—Jšžœ˜—Jšœ0™0š žœžœžœ8žœžœž˜ZJšœ0˜0Jšœ˜šžœžœžœž˜#Jšœ-˜-Jš žœ$žœžœžœ’™NJšœ˜Jšžœ˜—Jšžœ˜—Jšœ™Jšœ˜šœ(˜(JšœO˜OJšœH˜HJšœ˜Jšœ˜J˜—Jšœ:˜:Jšœ?˜?J˜—J˜šŸ œžœ˜#Jšœžœ"žœžœ˜6Jšžœžœžœžœ˜Jšœv˜vJš žœ žœžœžœžœ˜0Jšœ=˜=JšœB˜BJ˜—J™šŸœžœ˜'Jšœžœ8˜QJšœžœ žœ˜3Jšœ8žœ˜>JšœM˜MJ–\ -- [wire1: Core.Wire, wire2: Core.Wire] RETURNS [subWires: BOOL _ TRUE, quit: BOOL _ FALSE]šœ&˜&Jšœžœ$˜4Jšœ?žœžœžœ˜‡Jšœ…˜…Jšžœžœžœžœ%˜žœžœžœ˜SJšžœ˜—Jšœ˜—Jšžœ žœžœ˜—J˜—J˜š£œžœžœ žœžœžœžœžœžœžœžœ˜Jšœžœ ˜Jšžœ<žœžœ˜JJšžœ)žœžœžœN˜—šœ"˜"Jšœ:˜:Jšœ#˜#Jšœ˜—Jšœ3˜3J˜—J˜š   œžœžœžœ žœ žœ˜`Jšžœs˜yJ˜—J˜š  œžœžœžœžœžœžœ žœ žœžœžœ žœ˜ˆšžœ žœžœ˜Jšœ žœ7˜DJšœ˜Jšžœ˜—J˜—J˜š  œžœžœ žœžœžœžœžœžœžœžœžœ˜Šš žœžœžœžœ!žœžœž˜FJšžœ,žœžœžœ˜AJšžœ˜—J˜—J˜š  œžœžœžœžœžœžœžœžœžœžœ˜„š žœžœžœžœ"žœžœž˜GJšžœ2žœžœžœ˜GJšžœ˜—J˜——šœ™JšœI˜IK˜—Kšžœ˜K˜——…—^h‹