<> <> <> <> <> <> <> <> <<>> 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 => nameVal _ val; mode.decoration.geometryProp => geomVal _ val; mode.decoration.pinsProp => pinVal _ val; ENDCASE => CoreProperties.PutWireProp[root, prop, DefaultFusion[prop, val, rootValue, name]]; }; nameVal: REF ANY _ NIL; geomVal: REF ANY _ NIL; pinVal: REF ANY _ NIL; CoreProperties.Enumerate[fused.properties, EachProperty]; IF nameVal#NIL THEN { rootValue: REF ANY _ CoreProperties.GetWireProp[root, CoreOps.nameProp]; CoreProperties.PutWireProp[root, CoreOps.nameProp, NameFusion[CoreOps.nameProp, nameVal, rootValue, name]]; }; IF geomVal#NIL THEN CoreGeometry.AddGeometry[mode.decoration, root, CoreGeometry.GetGeometry[mode.decoration, fused]]; IF pinVal#NIL THEN CoreGeometry.AddPins[mode.decoration, root, CoreGeometry.GetPins[mode.decoration, fused]]; <> }; <> <> <> <