<> <> <> <> <> <> <> <> <<>> DIRECTORY Basics, BasicTime, CD, CDAtomicObjects, CDBasics, CDBasicsInline, CDCells, CDDirectory, CDInstances, CDLayers, CDProperties, CDRects, CDRoutingObjects, CDSatellites, CDSymbolicObjects, CedarProcess, Core, CoreClasses, CoreOps, CoreProperties, CoreGeometry, GList, InstanceTable, IO, MessageWindow, Process, PW, RefTab, Rope, RopeList, Saguaro, Sinix, SymTab, TerminalIO; SinixImpl: CEDAR PROGRAM IMPORTS Basics, BasicTime, CD, CDAtomicObjects, CDBasics, CDCells, CDDirectory, CDInstances, CDLayers, CDProperties, CDRects, CDSatellites, CDSymbolicObjects, CedarProcess, CoreClasses, CoreOps, CoreProperties, CoreGeometry, GList, InstanceTable, IO, MessageWindow, Process, PW, RefTab, Rope, RopeList, Saguaro, SymTab, TerminalIO EXPORTS Sinix SHARES CDRects, CoreGeometry = BEGIN OPEN Sinix; <> InternalBug: PUBLIC SIGNAL [name: ROPE] = CODE; CallerBug: PUBLIC SIGNAL [] = CODE; FusionPropMismatch: PUBLIC SIGNAL [name: ROPE, prop: ATOM, value1, value2: REF] = CODE; FusionStructureMismatch: PUBLIC SIGNAL [name: ROPE, wire1, wire2: Wire] = CODE; StructureMismatch: PUBLIC SIGNAL [name: ROPE, index: NAT, actual, subPublic: WireSeq] = CODE; FusionByNameMismatch: PUBLIC SIGNAL [name, msg: ROPE, wire: Wire] = CODE; StructuralLoop: PUBLIC SIGNAL [name: ROPE, wire: Wire] = CODE; <> ROPES: TYPE = LIST OF ROPE; Transformation: TYPE = CoreGeometry.Transformation; Instance: TYPE = CoreGeometry.Instance; Instances: TYPE = CoreGeometry.Instances; <> instanceCacheProp: ATOM _ PW.RegisterProp[$SinixInstanceCache, FALSE, TRUE]; objectCacheProp: ATOM _ PW.RegisterProp[$SinixObjectCache, FALSE, TRUE]; InstanceCache: TYPE = REF InstanceCacheRec; InstanceCacheRec: TYPE = RECORD [ mode: Mode, properties: CD.PropList _ NIL, userData: REF _ NIL, result: REF, props: Properties _ NIL ]; ObjectCache: TYPE = LIST OF ObjectCacheRec; ObjectCacheRec: TYPE = RECORD [ mode: Mode, userData: REF _ NIL, result: REF ]; <> SearchObjectCache: PROC [obj: Object, mode: Mode, userData: REF] RETURNS [result: REF _ NIL] = { FOR list: ObjectCache _ NARROW [CDProperties.GetObjectProp[obj, objectCacheProp]], list.rest WHILE list#NIL DO cache: ObjectCacheRec = list.first; IF cache.mode=mode AND mode.objectEqualProc[obj, cache.userData, userData] THEN RETURN [result: cache.result]; ENDLOOP; }; <> AddInCache: PROC [obj: Object, mode: Mode, userData: REF, result: REF] = { cache: ObjectCache _ NARROW [CDProperties.GetObjectProp[obj, objectCacheProp]]; cache _ CONS [[mode: mode, userData: userData, result: result], cache]; CDProperties.PutObjectProp[obj, objectCacheProp, cache]; }; FlushCache: PUBLIC PROC [obj: CD.Object] = { CDProperties.PutObjectProp[obj, instanceCacheProp, NIL]; CDProperties.PutObjectProp[obj, objectCacheProp, NIL]; }; <> NameWire: TYPE = RECORD [name: ROPE, wire: Wire]; FusionData: TYPE = REF FusionDataRec; FusionDataRec: TYPE = RECORD [ mode: Mode, -- to avoid passing it around nir: CD.Rect, -- Rectangles for which geometry that is strictly inside (edge excluded) is not promoted public name: ROPE, -- name of the object currently extracted isAbut: BOOL, -- recording publics depend on this property fused: RefTab.Ref, -- Association [fused -> root] [Wire -> Wire]. If root=NIL, then this wire is a root. Basically all the wires ever created belong to this table. data: REF, -- different information for Abut and Cell. For abuts it contains the next rects, (REF InstanceTable.Table). For Cell, it is a LIST OF NameWire. This list is not sorted at creation time, and same name may appear several times. rects: SEQUENCE nbOfLayers: NAT OF InstanceTable.Table -- Association (per layer) [fusion geometry -> wire] [CD.Rect -> IW]. Wire may or may not be a root. ]; AbutData: TYPE = REF AbutDataRec; AbutDataRec: TYPE = RECORD [ inX: BOOL, -- to avoid passing it around nextRects: SEQUENCE nbOfLayers: NAT OF InstanceTable.Table -- Association (per layer) [fusion geometry -> wire] [CD.Rect -> IW]. Wire may or may not be a root. ]; rect: PROC [r: CD.Rect] RETURNS [IO.Value] = { RETURN [IO.rope[IO.PutFR["[%g, %g, %g, %g]", IO.int[r.x1], IO.int[r.y1], IO.int[r.x2], IO.int[r.y2]]]]; }; CreateRoot: PROC [fusionData: FusionData, size: NAT, props: Properties _ NIL] RETURNS [wire: Wire] = { EachProperty: PROC [prop: ATOM, val: REF ANY _ NIL] = { newVal: REF ANY _ SELECT prop FROM fusionData.mode.decoration.pinsProp => NIL, fusionData.mode.decoration.geometryProp => NIL, CoreOps.nameProp => NIL, ENDCASE => val; CoreProperties.PutWireProp[wire, prop, newVal]; }; wire _ CoreOps.CreateWires[size: size]; CoreProperties.Enumerate[props, EachProperty]; [] _ RefTab.Store[fusionData.fused, wire, NIL]; }; <> InsertInstances: PROC [fusionData: FusionData, transformation: Transformation, instances: Instances, wire: Wire, copyGeometry: BOOL] = { IF ~RefTab.Fetch[fusionData.fused, wire].found THEN SIGNAL InternalBug[fusionData.name]; IF RootWire[fusionData, wire]#wire THEN SIGNAL InternalBug[fusionData.name]; FOR is: Instances _ instances, is.rest WHILE is#NIL DO inst: Instance _ CoreGeometry.Transform[transformation, is.first]; layers: LayerRange _ fusionData.mode.instanceLayer[inst]; FOR i: NAT IN [layers.min .. layers.max] DO InstanceTable.Insert[fusionData[i], inst, wire] ENDLOOP; <> IF CoreGeometry.AtEdge[fusionData.nir, inst] THEN CoreProperties.PutWireProp[wire, $Public, $Public]; ENDLOOP; IF copyGeometry THEN CoreGeometry.AddGeometry[fusionData.mode.decoration, wire, CoreGeometry.TransformList[transformation, instances]]; }; <> <> CreateDAGWireSeq: PROC [table: RefTab.Ref] RETURNS [wire: WireSeq] = { wires: LIST OF Wire _ NIL; EachKeyDelete: RefTab.EachPairAction = { WireDelete: PROC [wire: Wire] = { IF ~RefTab.Delete[table, wire] THEN RETURN; -- already done FOR i: NAT IN [0 .. wire.size) DO WireDelete[wire[i]]; ENDLOOP; }; wire: Wire _ NARROW [key]; FOR i: NAT IN [0 .. wire.size) DO <> WireDelete[wire[i]]; ENDLOOP; }; index: NAT _ 0; SummarizeWires: RefTab.EachPairAction = { wire[index] _ NARROW [key]; index _ index+1; }; [] _ RefTab.Pairs[table, EachKeyDelete]; wire _ CoreOps.CreateWires[RefTab.GetSize[table]]; [] _ RefTab.Pairs[table, SummarizeWires]; IF index#RefTab.GetSize[table] THEN SIGNAL InternalBug[NIL]; }; MakeResult: PROC [fusionData: FusionData, obj: CD.Object, cellInstances: LIST OF CoreClasses.CellInstance] RETURNS [record: CellType] = { decoration: CoreGeometry.Decoration = fusionData.mode.decoration; publics: RefTab.Ref _ RefTab.Create[3]; internals: RefTab.Ref _ RefTab.Create[5]; visitOnceTab: RefTab.Ref _ RefTab.Create[]; InternalDagIfy: RefTab.EachPairAction = { WireDagIfy: PROC [wire: Wire, maxIter: NAT _ 32] = { <<32 should be enough to avoid 815>> IF maxIter=0 THEN SIGNAL StructuralLoop[fusionData.name, wire]; -- probably loop in the Wire structure IF RootWire[fusionData, wire]#wire THEN SIGNAL InternalBug[fusionData.name]; FOR i: NAT IN [0 .. wire.size) DO wire[i] _ RootWire[fusionData, wire[i]]; WireDagIfy[wire[i], maxIter-1]; ENDLOOP; }; wire: Wire _ NARROW [key]; IF val#NIL THEN RETURN; -- we dagify only the roots [] _ RefTab.Store[internals, wire, NIL]; IF CoreProperties.GetWireProp[wire, $Public]#NIL THEN { [] _ RefTab.Store[publics, wire, NIL]; CoreProperties.PutWireProp[wire, $Public, NIL]; }; WireDagIfy[wire]; }; AddDecorateWire: CoreOps.EachWireProc = { pins: Instances _ NIL; AddPin: CoreGeometry.EachInstanceProc = { IF CoreGeometry.AtEdge[fusionData.nir, instance] THEN pins _ CONS [instance, pins]; }; IF ~RefTab.Store[visitOnceTab, wire, wire] THEN RETURN[FALSE, FALSE]; -- only once [] _ CoreGeometry.EnumerateGeometry[decoration, wire, AddPin]; CoreGeometry.AddPins[decoration, wire, pins]; }; <> [] _ RefTab.Pairs[fusionData.fused, InternalDagIfy]; <> FOR list: LIST OF CoreClasses.CellInstance _ cellInstances, 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]]; IF ~CoreOps.CorrectConform[wire, instance.type.public[i]] THEN SIGNAL StructureMismatch[fusionData.name, i, actual, instance.type.public]; actual[i] _ wire; ENDLOOP; ENDLOOP; <> record _ CoreClasses.CreateRecordCell[ public: CreateDAGWireSeq[publics], internal: CreateDAGWireSeq[internals], instances: cellInstances, name: fusionData.name, giveNames: TRUE ]; CoreGeometry.PutObject[decoration, record, obj]; <> CoreGeometry.PutRecordLazyPins[decoration, record, fusionData.nir]; <> [] _ CoreOps.VisitWireSeq[record.public, AddDecorateWire]; <> RefTab.Erase[visitOnceTab]; visitOnceTab _ NIL; FOR i: NAT IN [0 .. fusionData.mode.nbOfLayers) DO InstanceTable.DeleteOutside[fusionData[i], InstanceTable.empty]; ENDLOOP; }; LayoutFusionByName: PROC [fusionData: FusionData] = { refList: REF LIST OF NameWire = NARROW [fusionData.data]; nameToWire: SymTab.Ref = SymTab.Create[mod: 11]; FOR nameWires: LIST OF NameWire _ refList^, nameWires.rest WHILE nameWires#NIL DO wire: Wire _ RootWire[fusionData, nameWires.first.wire]; name: ROPE _ OrNames[nameWires.first.name, CoreOps.GetShortWireName[wire], fusionData.name]; previousWire: Wire _ NARROW [SymTab.Fetch[nameToWire, name].val]; IF previousWire#NIL THEN { previousWire _ RootWire[fusionData, previousWire]; IF previousWire#wire THEN { wire _ StructuredFusion[fusionData, wire, previousWire]; PutF["Fusion by name for '%g' in cell '%g'.\n", IO.rope[name], IO.rope[fusionData.name]]; CoreProperties.PutWireProp[wire, $FusedByName, $FusedByName]; }; }; [] _ SymTab.Store[nameToWire, name, wire]; [] _ CoreOps.SetShortWireName[wire, name]; ENDLOOP; }; NoFusionByName: PROC [fusionData: FusionData] = { refList: REF LIST OF NameWire = NARROW [fusionData.data]; EachNameWire: SymTab.EachPairAction = { uniqueID: INT _ 0; name: ROPE = NARROW [key]; wires: Wires _ NARROW [val]; [] _ CoreOps.SetShortWireName[wires.first, name]; wires _ wires.rest; IF wires=NIL THEN RETURN; PutF["NO fusion by name for '%g' in cell '%g'.\n", IO.rope[name], IO.rope[fusionData.name]]; WHILE wires#NIL DO [] _ CoreOps.SetShortWireName[wires.first, IO.PutFR["%g$%g$", IO.rope[name], IO.int[uniqueID]]]; uniqueID _ uniqueID + 1; wires _ wires.rest; ENDLOOP; }; nameToWires: SymTab.Ref = SymTab.Create[mod: 11]; -- contains (for every name) the list of roots that have it for name FOR nameWires: LIST OF NameWire _ refList^, nameWires.rest WHILE nameWires#NIL DO name: ROPE _ nameWires.first.name; wire: Wire = RootWire[fusionData, nameWires.first.wire]; wires: Wires _ NARROW [SymTab.Fetch[nameToWires, name].val]; IF NOT CoreOps.Member[wires, wire] THEN wires _ CONS [wire, wires]; [] _ SymTab.Store[nameToWires, name, wires]; ENDLOOP; [] _ SymTab.Pairs[nameToWires, EachNameWire]; }; SchematicsFusionByName: PROC [fusionData: FusionData] = { refList: REF LIST OF NameWire = NARROW [fusionData.data]; nameToWire: SymTab.Ref = SymTab.Create[mod: 11]; names: ROPES _ NIL; <> FOR nameWires: LIST OF NameWire _ refList^, nameWires.rest WHILE nameWires#NIL DO wire: Wire _ RootWire[fusionData, nameWires.first.wire]; name: ROPE _ OrNames[nameWires.first.name, CoreOps.GetShortWireName[wire], fusionData.name]; previousWire: Wire _ NARROW [SymTab.Fetch[nameToWire, name].val]; hasComponents: BOOL = CoreOps.ParseWireName[name].components#NIL; IF previousWire#NIL THEN previousWire _ RootWire[fusionData, previousWire]; IF previousWire#NIL AND previousWire#wire THEN wire _ StructuredFusion[fusionData, wire, previousWire] ELSE IF hasComponents THEN names _ CONS [name, names]; [] _ SymTab.Store[nameToWire, name, wire]; IF NOT hasComponents THEN [] _ CoreOps.SetShortWireName[wire, name]; ENDLOOP; <> <> FOR list: ROPES _ RopeList.Sort[names, RopeList.Compare], list.rest WHILE list#NIL DO name: ROPE _ list.first; wire: Wire = RootWire[fusionData, NARROW [SymTab.Fetch[nameToWire, name].val]]; base: ROPE; components: ROPES _ NIL; matchingWire: Wire; [base, components] _ CoreOps.ParseWireName[name]; matchingWire _ NARROW [SymTab.Fetch[nameToWire, base].val]; WHILE components#NIL DO index: INT _ -1; IF matchingWire=NIL THEN SIGNAL FusionByNameMismatch[fusionData.name, IO.PutFR["Path name %g does not correspond to any wire", IO.rope[name]], wire]; matchingWire _ RootWire[fusionData, matchingWire]; FOR i: NAT IN [0 .. matchingWire.size) DO subWireName: ROPE _ CoreOps.GetShortWireName[matchingWire[i]]; <> IF subWireName=NIL THEN subWireName _ IF i<256 THEN numbers[i] ELSE IO.PutR1[IO.int[i]]; -- JMF: speedup hack to avoid allocating lots of ropes IF Rope.Equal[subWireName, components.first] THEN { IF index=-1 THEN index _ i ELSE FusionByNameMismatch[fusionData.name, IO.PutFR["Current wire has 2 or more sub-wires with field `%g'", IO.rope[components.first]], wire]; }; ENDLOOP; IF index=-1 THEN SIGNAL FusionByNameMismatch[fusionData.name, IO.PutFR["Current wire does not have a sub-wire with field `%g'", IO.rope[components.first]], wire]; matchingWire _ matchingWire[index]; components _ components.rest; ENDLOOP; [] _ StructuredFusion[fusionData, matchingWire, wire]; ENDLOOP; }; AddNameWire: PROC [fusionData: FusionData, name: ROPE, wire: Wire] = { nameWires: REF LIST OF NameWire _ NARROW [fusionData.data]; nameWires^ _ CONS [[name: name, wire: wire], nameWires^]; }; <> RootWire: PROC [fusionData: FusionData, wire: Wire] RETURNS [rootWire: Wire] = { IF wire=NIL THEN SIGNAL InternalBug[fusionData.name]; rootWire _ NARROW [RefTab.Fetch[fusionData.fused, wire].val]; IF rootWire=NIL THEN RETURN [wire]; IF rootWire=wire THEN SIGNAL InternalBug[fusionData.name]; rootWire _ RootWire[fusionData, rootWire]; [] _ RefTab.Replace[fusionData.fused, wire, rootWire]; }; <> PropFusionProc: TYPE = PROC [prop: ATOM, value1, value2: REF ANY, name: ROPE] RETURNS [value: REF ANY]; NameFusion: PropFusionProc = { value _ OrNames[NARROW [value1], NARROW [value2], name]; }; DefaultFusion: PropFusionProc = { IF value1#NIL AND value2#NIL AND value1#value2 THEN SIGNAL FusionPropMismatch[name, prop, value1, value2]; value _ IF value1=NIL THEN value2 ELSE value1; }; <<>> <> FuseProperties: PUBLIC PROC [mode: Mode, fused, root: Wire, name: ROPE] = { EachProperty: PROC [prop: ATOM, val: REF ANY] = { rootValue: REF _ CoreProperties.GetWireProp[root, prop]; SELECT prop FROM CoreOps.nameProp => CoreProperties.PutWireProp[root, prop, NameFusion[prop, val, rootValue, name]]; mode.decoration.geometryProp => CoreGeometry.AddGeometry[mode.decoration, root, CoreGeometry.GetGeometry[mode.decoration, fused]]; mode.decoration.pinsProp => CoreGeometry.AddPins[mode.decoration, root, CoreGeometry.GetPins[mode.decoration, fused]]; -- this never happens during Cell or Abut extraction, because pins are not yet there, but might occur when called from SisyphImpl.ProcessGlobalName ENDCASE => CoreProperties.PutWireProp[root, prop, DefaultFusion[prop, val, rootValue, name]]; }; CoreProperties.Enumerate[fused.properties, EachProperty]; }; <<>> <> DeleteFused: PROC [fusionData: FusionData, fused, root: Wire] = { IF ~RefTab.Fetch[fusionData.fused, fused].found THEN SIGNAL InternalBug[fusionData.name]; IF RootWire[fusionData, fused]#fused THEN SIGNAL InternalBug[fusionData.name]; IF ~RefTab.Fetch[fusionData.fused, root].found THEN SIGNAL InternalBug[fusionData.name]; IF RootWire[fusionData, root]#root THEN SIGNAL InternalBug[fusionData.name]; IF fused=root THEN SIGNAL InternalBug[fusionData.name]; -- should never occur FuseProperties[fusionData.mode, fused, root, fusionData.name]; fused.properties _ NIL; -- to help GC [] _ RefTab.Store[fusionData.fused, fused, root]; }; StructuredFusion: PROC [fusionData: FusionData, wire1, wire2: Wire] RETURNS [wire: Wire] = { wire1 _ RootWire[fusionData, wire1]; wire2 _ RootWire[fusionData, wire2]; IF wire1=wire2 THEN RETURN [wire1]; SELECT TRUE FROM wire1=wire2 => wire _ wire1; wire1.size=0 => {DeleteFused[fusionData, wire1, wire2]; wire _ wire2}; wire2.size=0 => {DeleteFused[fusionData, wire2, wire1]; wire _ wire1}; wire1.size=wire2.size => { wire _ CreateRoot[fusionData, wire1.size]; FOR i: NAT IN [0 .. wire.size) DO wire[i] _ StructuredFusion[fusionData, wire1[i], wire2[i]]; ENDLOOP; DeleteFused[fusionData, wire1, wire]; DeleteFused[fusionData, wire2, wire]; }; ENDCASE => SIGNAL FusionStructureMismatch[fusionData.name, wire1, wire2]; }; FindTouchingWires: PROC [fusionData: FusionData, transformation: Transformation, geometry: Instances] RETURNS [touchingWires: LIST OF Wire _ NIL] = { FOR insts: Instances _ geometry, insts.rest WHILE insts#NIL DO inst: Instance _ CoreGeometry.Transform[transformation, insts.first]; layers: LayerRange _ fusionData.mode.instanceLayer[inst]; rect: CD.Rect _ CoreGeometry.InlineBBox[inst]; InternalFindTouchingWires: PROC [instance: Instance, value: InstanceTable.Value] = { wire: Wire _ RootWire[fusionData, NARROW [value]]; IF ~RefTab.Fetch[fusionData.fused, wire].found THEN SIGNAL InternalBug[fusionData.name]; IF CoreOps.Member[touchingWires, wire] THEN RETURN; IF fusionData.mode.touchProc[fusionData.mode.touchProc, instance, inst] THEN touchingWires _ CONS [wire, touchingWires]; }; FOR i: NAT IN [layers.min .. layers.max] DO InstanceTable.Enumerate[fusionData[i], InternalFindTouchingWires, rect]; ENDLOOP; ENDLOOP; }; <> FusionGeometry: PROC [fusionData: FusionData, transformation: Transformation, geometry: Instances, copyGeometry: BOOL] RETURNS [wire: Wire _ NIL] = { touchingWires: LIST OF Wire _ FindTouchingWires[fusionData, transformation, geometry]; IF touchingWires=NIL THEN { wire _ CreateRoot[fusionData, 0]; InsertInstances[fusionData, transformation, geometry, wire, copyGeometry]; RETURN; }; wire _ touchingWires.first; InsertInstances[fusionData, transformation, geometry, wire, copyGeometry]; touchingWires _ touchingWires.rest; WHILE touchingWires#NIL DO fused: Wire _ touchingWires.first; wire _ StructuredFusion[fusionData, fused, wire]; touchingWires _ touchingWires.rest; ENDLOOP; }; <> FusionWire: PROC [fusionData: FusionData, dagTable: RefTab.Ref, public: Wire, transformation: Transformation, copyProps: BOOL] RETURNS [actual: Wire] = { prevActual: Wire _ NARROW [RefTab.Fetch[dagTable, public].val]; structActual: Wire; publicName: ROPE _ CoreOps.GetShortWireName[public]; pins: Instances _ CoreGeometry.GetPins[fusionData.mode.decoration, public]; IF prevActual#NIL THEN RETURN [prevActual]; structActual _ CreateRoot[fusionData, public.size, IF copyProps THEN public.properties ELSE NIL]; FOR i: NAT IN [0 .. public.size) DO structActual[i] _ FusionWire[fusionData, dagTable, public[i], transformation, copyProps]; ENDLOOP; actual _ IF pins=NIL THEN structActual ELSE StructuredFusion[ fusionData, structActual, FusionGeometry[fusionData, transformation, pins, copyProps] ]; IF copyProps AND publicName#NIL THEN AddNameWire[fusionData, publicName, actual]; [] _ RefTab.Store[dagTable, public, actual]; }; FusionWireSeq: PROC [fusionData: FusionData, public: WireSeq, transformation: Transformation] RETURNS [actual: Wire] = { dagTable: RefTab.Ref _ RefTab.Create[3]; actual _ CoreOps.CreateWires[public.size]; FOR i: NAT IN [0 .. actual.size) DO actual[i] _ FusionWire[fusionData, dagTable, public[i], transformation, FALSE]; ENDLOOP; }; <> SortInstances: PROC [instances: LIST OF CD.Instance] RETURNS [sorted: LIST OF CD.Instance _ NIL] = { Eval: PROC [inst: CD.Instance] RETURNS [INT] = { <> pos: CD.Position = CDBasics.BaseOfRect[CDBasicsInline.MapRect[CD.InterestRect[inst.ob], inst.trans]]; -- JMF: new version, slightly faster RETURN [pos.x+pos.y]; }; Compare: GList.CompareProc = { RETURN [Basics.CompareInt[Eval[NARROW [ref1]], Eval[NARROW [ref2]]]]; }; sorted _ NARROW [GList.Sort[instances, Compare]]; }; <> InitialOverlap: PROC [bbox, nir: CD.Rect] RETURNS [overlap: INT _ 0] = { overlap _ UnionOverlap[overlap, bbox, [FIRST[INT], FIRST[INT], nir.x1, LAST[INT]]]; overlap _ UnionOverlap[overlap, bbox, [nir.x2, FIRST[INT], LAST[INT], LAST[INT]]]; overlap _ UnionOverlap[overlap, bbox, [FIRST[INT], FIRST[INT], LAST[INT], nir.y1]]; overlap _ UnionOverlap[overlap, bbox, [FIRST[INT], nir.y2, LAST[INT], LAST[INT]]]; }; UnionOverlap: PROC [overlap: INT, bbox, rect: CD.Rect] RETURNS [INT] = { interSize: CD.Position; IF overlap*2>bbox.x2-bbox.x1 OR overlap*2>bbox.y2-bbox.y1 THEN RETURN [overlap]; interSize _ CDBasics.SizeOfRect[CDBasics.Intersection[rect, CDBasics.Extend[bbox, -overlap]]]; overlap _ MAX [overlap, MIN [interSize.x, interSize.y]]; IF overlap*2>bbox.x2-bbox.x1 OR overlap*2>bbox.y2-bbox.y1 THEN RETURN [overlap]; interSize _ CDBasics.SizeOfRect[CDBasics.Intersection[rect, CDBasics.Extend[bbox, -overlap]]]; overlap _ MAX [overlap, MIN [interSize.x, interSize.y]]; RETURN [overlap]; }; ExtractCell: PUBLIC ExtractProc = { ir: CD.Rect _ CD.InterestRect[obj]; cdInstances: LIST OF CD.Instance _ NIL; nbOfInstances: INT = CDCells.CountInstances[obj]; fusionData: FusionData _ NEW [FusionDataRec[mode.nbOfLayers]]; currentInstances: LIST OF CoreClasses.CellInstance _ NIL; EachInstance: CDCells.InstEnumerator = {cdInstances _ CONS [inst, cdInstances]}; time: BasicTime.GMT = BasicTime.Now[]; result _ SearchObjectCache[obj, mode, userData]; IF result#NIL THEN RETURN; [] _ CDCells.EnumerateInstances[obj, EachInstance]; cdInstances _ SortInstances[cdInstances]; -- Modified in place! fusionData.mode _ mode; fusionData.name _ mode.nameProc[obj, userData]; fusionData.nir _ IF mode.fusionByName=none THEN CDBasics.Extend[ir, - NARROW [userData, REF INT]^] ELSE ir; fusionData.fused _ RefTab.Create[3]; fusionData.data _ NEW [LIST OF NameWire _ NIL]; fusionData.isAbut _ FALSE; FOR i: NAT IN [0 .. mode.nbOfLayers) DO fusionData[i] _ InstanceTable.Create[range: obj.bbox]; ENDLOOP; PutF["Extracting [%g] cell %g (bbox: %g, instances: %g)\n", IO.rope[IF mode.fusionByName=none THEN IO.PutFR["%g[%g]", IO.rope[mode.decoration.name], IO.int[NARROW [userData, REF INT]^]] ELSE mode.decoration.name], IO.rope[fusionData.name], rect[obj.bbox], IO.int[nbOfInstances]]; CDProperties.PutObjectProp[obj, satellitesProp, CDSatellites.GetSatelliteRopes[obj]]; -- to reinforce invariantes on the object (restriction of CDSatellites) WHILE cdInstances#NIL DO cdInstance: CD.Instance _ cdInstances.first; subUserData: REF _ userData; subResult: REF; subProps: Properties; CDProperties.PutInstanceProp[cdInstance, satellitesProp, CDSatellites.GetSatelliteRopes[cdInstance]]; IF mode.fusionByName=none THEN { EachInstanceOverlap: CDCells.InstEnumerator = { IF inst#cdInstance THEN overlap _ UnionOverlap[overlap, bbox, CDInstances.InstRectO[inst]]; }; <> bbox: CD.Rect _ CDInstances.InstRectI[cdInstance]; overlap: INT _ InitialOverlap[bbox, fusionData.nir]; [] _ CDCells.EnumerateInstances[obj, EachInstanceOverlap]; subUserData _ NEW [INT _ overlap]; }; [subResult, subProps] _ Extract[cdInstance.ob, mode, cdInstance.properties, subUserData]; IF subResult#NIL THEN WITH subResult SELECT FROM subWire: Wire => { [] _ FusionWire[fusionData, RefTab.Create[1], subWire, cdInstance.trans, TRUE]; }; subWires: Wires => { dagTable: RefTab.Ref _ RefTab.Create[3]; WHILE subWires#NIL DO [] _ FusionWire[fusionData, dagTable, subWires.first, cdInstance.trans, TRUE]; subWires _ subWires.rest; ENDLOOP; }; subCellType: CellType => { bbox: CD.Rect _ CDInstances.BoundingRectO[cdInstances.rest]; instance: CoreClasses.CellInstance _ CoreClasses.CreateInstance[ actual: FusionWireSeq[fusionData, subCellType.public, cdInstance.trans], type: subCellType, props: subProps ]; <> CoreGeometry.PutTrans[mode.decoration, instance, cdInstance.trans]; currentInstances _ CONS [instance, currentInstances]; <> FOR i: NAT IN [0 .. mode.nbOfLayers) DO InstanceTable.DeleteOutside[fusionData[i], bbox]; ENDLOOP; }; ENDCASE => SIGNAL InternalBug[fusionData.name]; cdInstances _ cdInstances.rest; ENDLOOP; <