<> <> <> <> <> <> <<>> DIRECTORY Basics, CD, CDBasics, CDDefaultProcs, CDDirectory, CDInstances, CDOrient, CDProperties, CDSatellites, CDSymbolicObjects, CedarProcess, Core, CoreClasses, CoreOps, CoreProperties, CoreGeometry, D2Intervals, GList, HashTable, IO, Process, PW, PWObjects, Rope, RopeList, Sinix; SinixImpl: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDDefaultProcs, CDDirectory, CDInstances, CDOrient, CDProperties, CDSatellites, CDSymbolicObjects, CedarProcess, CoreClasses, CoreOps, CoreProperties, CoreGeometry, D2Intervals, GList, HashTable, IO, Process, PW, PWObjects, Rope, RopeList 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: Wire] = CODE; FusionByNameMismatch: PUBLIC SIGNAL [name, msg: ROPE, wire: Wire] = CODE; StructuralLoop: PUBLIC SIGNAL [name: ROPE, wire: Wire] = CODE; ROPES: TYPE = LIST OF ROPE; 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 D2Intervals.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 D2Intervals.Table -- Association (per layer) [fusion geometry -> wire] [D2Intervals.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 D2Intervals.Table -- Association (per layer) [fusion geometry -> wire] [D2Intervals.Rect -> IW]. Wire may or may not be a root. ]; IW: TYPE = REF IWRec; IWRec: TYPE = RECORD [instance: CD.Instance, wire: Wire]; RectToRect: PROC [cdRect: CD.Rect] RETURNS [rect: D2Intervals.Rect] = INLINE { rect _ [[cdRect.x1, cdRect.x2], [cdRect.y1, cdRect.y2]]; }; InstanceToRect: PROC [inst: CD.Instance] RETURNS [rect: D2Intervals.Rect] = INLINE { rect _ RectToRect[ IF inst.ob.class.interestRect=CDDefaultProcs.InterestRect -- simple rectangles ! THEN CDInstances.InstRectO[inst] ELSE CDBasics.Surround[CDInstances.InstRectO[inst], CDInstances.InstRectI[inst]] ]; }; IWToRect: PROC [table: D2Intervals.Table, value: D2Intervals.Value] RETURNS [rect: D2Intervals.Rect] = { iw: IW _ NARROW [value]; mode: Mode _ NARROW [table.userData]; rect _ InstanceToRect[iw.instance]; }; 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: CD.Instance, instances: LIST OF CD.Instance, wire: Wire, copyGeometry: BOOL] = { pins: LIST OF CD.Instance _ CoreGeometry.GetPins[fusionData.mode.decoration, wire]; IF ~HashTable.Fetch[fusionData.fused, wire].found THEN SIGNAL InternalBug[fusionData.name]; IF RootWire[fusionData, wire]#wire THEN SIGNAL InternalBug[fusionData.name]; <> FOR is: LIST OF CD.Instance _ instances, is.rest WHILE is#NIL DO inst: CD.Instance _ CoreGeometry.Transform[transformation, is.first]; iw: IW _ NEW [IWRec _ [instance: inst, wire: wire]]; layers: LayerRange _ fusionData.mode.instanceLayer[inst]; IF copyGeometry THEN CoreGeometry.PutGeometry[fusionData.mode.decoration, wire, CONS [inst, CoreGeometry.GetGeometry[fusionData.mode.decoration, wire]]]; FOR i: NAT IN [layers.min .. layers.max] DO D2Intervals.Insert[fusionData[i], iw] ENDLOOP; IF NOT CoreGeometry.AtEdge[fusionData.nir, inst] THEN LOOP; <> IF fusionData.isAbut THEN CoreProperties.PutWireProp[wire, $Public, $Public] ELSE pins _ CONS [inst, pins]; ENDLOOP; CoreGeometry.PutPins[fusionData.mode.decoration, wire, pins]; }; <> <> CreateDAGWire: PROC [table: HashTable.Table] RETURNS [wire: Wire] = { 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]; }; 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 name: ROPE = nameWires.first.name; wire: Wire _ RootWire[fusionData, nameWires.first.wire]; previousName: ROPE = CoreOps.GetShortWireName[wire]; previousWire: Wire _ NARROW [HashTable.Fetch[nameToWire, name].value]; IF previousName#NIL AND ~Rope.Equal[name, previousName] THEN SIGNAL FusionPropMismatch[fusionData.name, CoreOps.nameProp, name, previousName]; IF previousWire#NIL THEN { previousWire _ RootWire[fusionData, previousWire]; IF previousWire#wire THEN { wire _ StructuredFusion[fusionData, wire, previousWire]; PW.WriteF["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; PW.WriteF["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 name: ROPE = nameWires.first.name; wire: Wire _ RootWire[fusionData, nameWires.first.wire]; previousName: ROPE = CoreOps.GetShortWireName[wire]; previousWire: Wire _ NARROW [HashTable.Fetch[nameToWire, name].value]; hasComponents: BOOL = CoreOps.ParseWireName[name].components#NIL; IF previousName#NIL AND ~Rope.Equal[name, previousName] THEN SIGNAL FusionPropMismatch[fusionData.name, CoreOps.nameProp, name, previousName]; 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 = { rope1: ROPE _ NARROW [value1]; rope2: ROPE _ NARROW [value2]; IF rope1#NIL AND rope2#NIL AND ~Rope.Equal[rope1, rope2] THEN SIGNAL FusionPropMismatch[name, prop, rope1, rope2]; value _ IF rope1=NIL THEN rope2 ELSE rope1; }; <> <> <> <> <<};>> <<>> 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 mode.decoration.pinsProp => CoreGeometry.PutPins[mode.decoration, root, CDInstances.AppendToList[CoreGeometry.GetPins[mode.decoration, root], CoreGeometry.GetPins[mode.decoration, fused]]]; mode.decoration.geometryProp => CoreGeometry.PutGeometry[mode.decoration, root, CDInstances.AppendToList[CoreGeometry.GetGeometry[mode.decoration, root], CoreGeometry.GetGeometry[mode.decoration, fused]]]; CoreOps.nameProp => CoreProperties.PutWireProp[root, prop, NameFusion[prop, val, rootValue, name]]; ENDCASE => CoreProperties.PutWireProp[root, prop, DefaultFusion[prop, val, rootValue, name]]; }; CoreProperties.Enumerate[fused.properties, EachProperty]; }; <<>> <> DeleteFusioned: 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 => {DeleteFusioned[fusionData, wire1, wire2]; wire _ wire2}; wire2.size=0 => {DeleteFusioned[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; DeleteFusioned[fusionData, wire1, wire]; DeleteFusioned[fusionData, wire2, wire]; }; ENDCASE => SIGNAL FusionStructureMismatch[fusionData.name, wire1, wire2]; }; FindTouchingWires: PROC [fusionData: FusionData, transformation: CD.Instance, geometry: LIST OF CD.Instance] RETURNS [touchingWires: LIST OF Wire _ NIL] = { FOR insts: LIST OF CD.Instance _ geometry, insts.rest WHILE insts#NIL DO inst: CD.Instance _ CoreGeometry.Transform[transformation, insts.first]; layers: LayerRange _ fusionData.mode.instanceLayer[inst]; rect: D2Intervals.Rect _ InstanceToRect[inst]; InternalFindTouchingWires: PROC [table: D2Intervals.Table, value: D2Intervals.Value] RETURNS [quit: BOOL _ FALSE] = { iw: IW _ NARROW [value]; instance: CD.Instance _ iw.instance; wire: Wire _ RootWire[fusionData, iw.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 [] _ D2Intervals.Enumerate[fusionData[i], InternalFindTouchingWires, rect]; ENDLOOP; ENDLOOP; }; <> FusionGeometry: PROC [fusionData: FusionData, transformation: CD.Instance, geometry: LIST OF CD.Instance, 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: CD.Instance, copyProps: BOOL] RETURNS [actual: Wire] = { prevActual: Wire _ NARROW [HashTable.Fetch[dagTable, public].value]; structActual: Wire; publicName: ROPE _ CoreOps.GetShortWireName[public]; pins: LIST OF CD.Instance _ 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]; }; FusionWires: PROC [fusionData: FusionData, public: Wire, transformation: CD.Instance] 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[CDInstances.AppendToList[instances, NIL], Compare]]; -- it is important to copy instances, because GList.Sort modifies physically its argument }; <> cacheProp: PUBLIC ATOM _ PW.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 { PW.WriteF["*** 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.HasIR[mode.decoration, cellType] THEN SIGNAL CallerBug[]; -- IR decoration 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 PW.WriteF["ExtractProc overwritten for $%g.\n", IO.atom[key]]; }; ExtractCell: PUBLIC ExtractProc = { cellType: CellType; -- the result ir: CD.Rect _ CD.InterestRect[obj]; publics: HashTable.Table _ HashTable.Create[3]; internals: HashTable.Table _ HashTable.Create[3]; cellPtr: CD.CellPtr _ NARROW [obj.specificRef]; cdInstances: LIST OF CD.Instance _ SortInstances[cellPtr.contents]; fusionData: FusionData _ NEW [FusionDataRec[mode.nbOfLayers]]; currentInstances: LIST OF CoreClasses.CellInstance _ NIL; count: NAT _ 0; FOR list: LIST OF CD.Instance _ cdInstances, list.rest WHILE list#NIL DO count _ count+1 ENDLOOP; PW.WriteF["Extracting [%g] cell %g (size: [%g, %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]], IO.int[obj.size.x], IO.int[obj.size.y], IO.int[count]]; 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] _ D2Intervals.Create[ range: RectToRect[CDBasics.Surround[CDBasics.RectAt[[0, 0], obj.size], ir]], valueRect: IWToRect, userData: mode]; 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]]; }; <> 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]]]; FOR list: LIST OF CD.Instance _ cellPtr.contents, list.rest WHILE list#NIL DO IF list.first#cdInstance THEN UnionOverlap[CDInstances.InstRectO[list.first]]; ENDLOOP; 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, TRUE]; }; subWires: Wires => { dagTable: HashTable.Table _ HashTable.Create[3]; WHILE subWires#NIL DO [] _ FusionWire[fusionData, dagTable, subWires.first, cdInstance, TRUE]; subWires _ subWires.rest; ENDLOOP; }; subCellType: CellType => { bbox: CD.Rect _ CDInstances.BoundingRectO[cdInstances.rest]; instance: CoreClasses.CellInstance _ CoreClasses.CreateInstance[ actual: FusionWires[fusionData, subCellType.public, cdInstance], type: subCellType, props: subProps ]; <> CoreGeometry.PutTransf[mode.decoration, instance, cdInstance]; currentInstances _ CONS [instance, currentInstances]; <> FOR i: NAT IN [0 .. mode.nbOfLayers) DO DeleteOutsideRange: PROC [table: D2Intervals.Table, value: D2Intervals.Value] RETURNS [quit: BOOL _ FALSE] = { valueInst: CD.Instance _ NARROW [value, IW].instance; IF ~CoreGeometry.Intersect[bbox, valueInst] THEN D2Intervals.Delete[fusionData[i], value]; }; [] _ D2Intervals.Enumerate[fusionData[i], DeleteOutsideRange, [[FIRST[INT], bbox.x1], D2Intervals.universe.y]]; [] _ D2Intervals.Enumerate[fusionData[i], DeleteOutsideRange, [[bbox.x2, LAST[INT]], D2Intervals.universe.y]]; [] _ D2Intervals.Enumerate[fusionData[i], DeleteOutsideRange, [D2Intervals.universe.x, [FIRST[INT], bbox.y1]]]; [] _ D2Intervals.Enumerate[fusionData[i], DeleteOutsideRange, [D2Intervals.universe.x, [bbox.y2, LAST[INT]]]]; ENDLOOP; }; ENDCASE => SIGNAL InternalBug[fusionData.name]; cdInstances _ cdInstances.rest; ENDLOOP; <