<> <> <> <> <> <> <<>> DIRECTORY Basics, CD, CDBasics, CDCells, CDDirectory, CDInstances, CDProperties, CDSatellites, CDSymbolicObjects, CedarProcess, Core, CoreClasses, CoreOps, CoreProperties, CoreGeometry, GList, HashTable, IO, Process, PWObjects, Rope, RopeList, Sinix, SinixD2Intervals, TerminalIO; SinixImpl: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDCells, CDDirectory, CDInstances, CDProperties, CDSatellites, CDSymbolicObjects, CedarProcess, CoreClasses, CoreOps, CoreProperties, CoreGeometry, SinixD2Intervals, GList, HashTable, IO, Process, PWObjects, Rope, RopeList, TerminalIO EXPORTS Sinix SHARES 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, 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; <> Cache: TYPE = REF CacheRec; CacheRec: TYPE = RECORD [ mode: Mode, properties: CD.PropList _ NIL, userData: REF _ NIL, result: REF, props: Properties _ NIL ]; FlushCache: PUBLIC PROC [obj: CD.Object] = {CDProperties.PutObjectProp[obj, cacheProp, 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: HashTable.Table, -- 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 SinixD2Intervals.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 SinixD2Intervals.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 SinixD2Intervals.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]; [] _ HashTable.Store[fusionData.fused, wire, NIL]; }; <> InsertInstances: PROC [fusionData: FusionData, transformation: Transformation, instances: Instances, wire: Wire, copyGeometry: BOOL] = { IF ~HashTable.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 SinixD2Intervals.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: HashTable.Table] RETURNS [wire: WireSeq] = { wires: LIST OF Wire _ NIL; EachKeyDelete: HashTable.EachPairAction = { WireDelete: PROC [wire: Wire] = { IF ~HashTable.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: HashTable.EachPairAction = { wire[index] _ NARROW [key]; index _ index+1; }; [] _ HashTable.Pairs[table, EachKeyDelete]; wire _ CoreOps.CreateWires[HashTable.GetSize[table]]; [] _ HashTable.Pairs[table, SummarizeWires]; IF index#HashTable.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: HashTable.Table _ HashTable.Create[3]; internals: HashTable.Table _ HashTable.Create[5]; InternalDagIfy: HashTable.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 value#NIL THEN RETURN; -- we dagify only the roots [] _ HashTable.Store[internals, wire, NIL]; IF CoreProperties.GetWireProp[wire, $Public]#NIL THEN { [] _ HashTable.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]; }; [] _ CoreGeometry.EnumerateGeometry[decoration, wire, AddPin]; CoreGeometry.AddPins[decoration, wire, pins]; }; <> [] _ HashTable.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, wire, instance.type.public[i]]; actual[i] _ wire; ENDLOOP; ENDLOOP; <> record _ CoreClasses.CreateRecordCell[ public: CreateDAGWireSeq[publics], internal: CreateDAGWireSeq[internals], instances: cellInstances, name: CDDirectory.Name[obj], giveNames: TRUE ]; CoreGeometry.PutObject[decoration, record, obj]; <> CoreGeometry.PutRecordLazyPins[decoration, record, fusionData.nir]; <> [] _ CoreOps.VisitWireSeq[record.public, AddDecorateWire]; }; LayoutFusionByName: PROC [fusionData: FusionData] = { refList: REF LIST OF NameWire = NARROW [fusionData.data]; nameToWire: HashTable.Table = HashTable.Create[mod: 11, equal: HashTable.RopeEqual, hash: HashTable.HashRope]; 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 [HashTable.Fetch[nameToWire, name].value]; IF previousWire#NIL THEN { previousWire _ RootWire[fusionData, previousWire]; IF previousWire#wire THEN { wire _ StructuredFusion[fusionData, wire, previousWire]; TerminalIO.PutF["Fusion by name for '%g' in cell '%g'.\n", IO.rope[name], IO.rope[fusionData.name]]; CoreProperties.PutWireProp[wire, $FusedByName, $FusedByName]; }; }; [] _ HashTable.Store[nameToWire, name, wire]; [] _ CoreOps.SetShortWireName[wire, name]; ENDLOOP; }; NoFusionByName: PROC [fusionData: FusionData] = { refList: REF LIST OF NameWire = NARROW [fusionData.data]; EachNameWire: HashTable.EachPairAction = { uniqueID: INT _ 0; name: ROPE = NARROW [key]; wires: Wires _ NARROW [value]; [] _ CoreOps.SetShortWireName[wires.first, name]; wires _ wires.rest; IF wires=NIL THEN RETURN; TerminalIO.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: HashTable.Table = HashTable.Create[mod: 11, equal: HashTable.RopeEqual, hash: HashTable.HashRope]; -- 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 [HashTable.Fetch[nameToWires, name].value]; IF NOT CoreOps.Member[wires, wire] THEN wires _ CONS [wire, wires]; [] _ HashTable.Store[nameToWires, name, wires]; ENDLOOP; [] _ HashTable.Pairs[nameToWires, EachNameWire]; }; SchematicsFusionByName: PROC [fusionData: FusionData] = { refList: REF LIST OF NameWire = NARROW [fusionData.data]; nameToWire: HashTable.Table = HashTable.Create[mod: 11, equal: HashTable.RopeEqual, hash: HashTable.HashRope]; 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 [HashTable.Fetch[nameToWire, name].value]; 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]; [] _ HashTable.Store[nameToWire, name, wire]; IF NOT hasComponents THEN [] _ CoreOps.SetShortWireName[wire, name]; ENDLOOP; <> names _ RopeList.Sort[names, RopeList.Compare]; FOR list: ROPES _ RopeList.Sort[names, RopeList.Compare], list.rest WHILE list#NIL DO name: ROPE _ list.first; wire: Wire = RootWire[fusionData, NARROW [HashTable.Fetch[nameToWire, name].value]]; base: ROPE; components: ROPES _ NIL; matchingWire: Wire; [base, components] _ CoreOps.ParseWireName[name]; matchingWire _ NARROW [HashTable.Fetch[nameToWire, base].value]; 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 _ IO.PutR1[IO.int[i]]; 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 [HashTable.Fetch[fusionData.fused, wire].value]; IF rootWire=NIL THEN RETURN [wire]; IF rootWire=wire THEN SIGNAL InternalBug[fusionData.name]; rootWire _ RootWire[fusionData, rootWire]; [] _ HashTable.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: Sinix.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 ~HashTable.Fetch[fusionData.fused, fused].found THEN SIGNAL InternalBug[fusionData.name]; IF RootWire[fusionData, fused]#fused THEN SIGNAL InternalBug[fusionData.name]; IF ~HashTable.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 [] _ HashTable.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, wire: Wire] = { wire _ RootWire[fusionData, wire]; IF ~HashTable.Fetch[fusionData.fused, wire].found THEN SIGNAL InternalBug[fusionData.name]; IF CoreOps.Member[touchingWires, wire] THEN RETURN; IF fusionData.mode.touchProc[instance, inst] THEN touchingWires _ CONS [wire, touchingWires]; }; FOR i: NAT IN [layers.min .. layers.max] DO SinixD2Intervals.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: HashTable.Table, public: Wire, transformation: Transformation, copyProps: BOOL] RETURNS [actual: Wire] = { prevActual: Wire _ NARROW [HashTable.Fetch[dagTable, public].value]; 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]; [] _ HashTable.Store[dagTable, public, actual]; }; FusionWireSeq: PROC [fusionData: FusionData, public: WireSeq, transformation: Transformation] RETURNS [actual: Wire] = { dagTable: HashTable.Table _ HashTable.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[CDInstances.InstRectI[inst]]; RETURN [pos.x+pos.y]; }; Compare: GList.CompareProc = { RETURN [Basics.CompareINT[Eval[NARROW [ref1]], Eval[NARROW [ref2]]]]; }; sorted _ NARROW [GList.Sort[instances, Compare]]; }; <> cacheProp: ATOM _ PWObjects.RegisterProp[$SinixCache, FALSE, TRUE]; Extract: PUBLIC ExtractProc = { cache: Cache _ NARROW [CDProperties.GetObjectProp[obj, cacheProp]]; CDProperties.PutObjectProp[obj, satellitesProp, CDSatellites.GetSatelliteRopes[obj]]; IF cache#NIL AND cache.mode=mode AND mode.equalProc[obj, cache.properties, cache.userData, properties, userData] THEN RETURN [result: cache.result, props: cache.props]; BEGIN priority: CedarProcess.Priority _ CedarProcess.GetPriority[]; atom: ATOM _ NARROW [CDProperties.GetListProp[properties, mode.extractProcProp]]; extractProc: ExtractProc; IF atom=NIL THEN atom _ NARROW [CDProperties.GetObjectProp[obj, mode.extractProcProp]]; IF atom=NIL THEN atom _ NARROW [CDProperties.GetProp[obj.class, mode.extractProcProp]]; IF atom=NIL THEN extractProc _ ExtractExpand ELSE { refProc: REF ExtractProc _ NARROW [HashTable.Fetch[registeredExtractProcs, atom].value]; IF refProc=NIL THEN { TerminalIO.PutF["*** ExtractProc $%g not registered. You must run the program defining it.\n", IO.atom[atom]]; SIGNAL CallerBug[]; }; extractProc _ refProc^; }; CedarProcess.CheckAbort[]; CedarProcess.SetPriority[background]; Process.Yield[]; [result, props] _ extractProc[obj, mode, properties, userData]; <> WITH result SELECT FROM wire: Wire => {}; wires: Wires => {}; cellType: CellType => IF NOT CoreGeometry.HasObject[mode.decoration, cellType] THEN SIGNAL CallerBug[]; -- decorations missing! ENDCASE => IF result#NIL THEN SIGNAL CallerBug[]; -- probably some ExtractProc is grossly wrong CedarProcess.SetPriority[priority]; CDProperties.PutObjectProp[obj, cacheProp, NEW [CacheRec _ [mode: mode, properties: properties, userData: userData, result: result, props: props]]]; END; }; registeredExtractProcs: HashTable.Table _ HashTable.Create[]; RegisterExtractProc: PUBLIC PROC [key: ATOM, extractProc: ExtractProc] = { IF NOT HashTable.Store[registeredExtractProcs, key, NEW [ExtractProc _ extractProc]] THEN TerminalIO.PutF["ExtractProc overwritten for $%g.\n", IO.atom[key]]; }; 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]}; [] _ CDCells.EnumerateInstances[obj, EachInstance]; cdInstances _ SortInstances[cdInstances]; -- Modified in place! TerminalIO.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[CDDirectory.Name[obj]], rect[obj.bbox], IO.int[nbOfInstances]]; fusionData.mode _ mode; fusionData.name _ CDDirectory.Name[obj]; fusionData.nir _ IF mode.fusionByName=none THEN CDBasics.Extend[ir, - NARROW [userData, REF INT]^] ELSE ir; fusionData.fused _ HashTable.Create[3]; fusionData.data _ NEW [LIST OF NameWire _ NIL]; fusionData.isAbut _ FALSE; FOR i: NAT IN [0 .. mode.nbOfLayers) DO fusionData[i] _ SinixD2Intervals.Create[ logHashSize: SELECT TRUE FROM nbOfInstances<=7 => 3, nbOfInstances<=60 => 5, ENDCASE => 11, range: obj.bbox ]; ENDLOOP; 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 { UnionOverlap: PROC [rect: CD.Rect] = { interSize: CD.Position; IF overlap+overlap>bbox.x2-bbox.x1 OR overlap+overlap>bbox.y2-bbox.y1 THEN RETURN; interSize _ CDBasics.SizeOfRect[CDBasics.Intersection[rect, CDBasics.Extend[bbox, -overlap]]]; overlap _ MAX [overlap, MIN [interSize.x, interSize.y]]; IF overlap+overlap>bbox.x2-bbox.x1 OR overlap+overlap>bbox.y2-bbox.y1 THEN RETURN; interSize _ CDBasics.SizeOfRect[CDBasics.Intersection[rect, CDBasics.Extend[bbox, -overlap]]]; overlap _ MAX [overlap, MIN [interSize.x, interSize.y]]; }; EachInstanceOverlap: CDCells.InstEnumerator = { IF inst#cdInstance THEN UnionOverlap[CDInstances.InstRectO[inst]]; }; <> bbox: CD.Rect _ CDInstances.InstRectI[cdInstance]; overlap: INT _ 0; UnionOverlap[[FIRST[INT], FIRST[INT], fusionData.nir.x1, LAST[INT]]]; UnionOverlap[[fusionData.nir.x2, FIRST[INT], LAST[INT], LAST[INT]]]; UnionOverlap[[FIRST[INT], FIRST[INT], LAST[INT], fusionData.nir.y1]]; UnionOverlap[[FIRST[INT], fusionData.nir.y2, LAST[INT], LAST[INT]]]; [] _ 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, HashTable.Create[1], subWire, cdInstance.trans, TRUE]; }; subWires: Wires => { dagTable: HashTable.Table _ HashTable.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 SinixD2Intervals.DeleteOutside[fusionData[i], bbox]; ENDLOOP; }; ENDCASE => SIGNAL InternalBug[fusionData.name]; cdInstances _ cdInstances.rest; ENDLOOP; <