SinixImpl.mesa
Copyright © 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
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;
Utilities
debug: BOOLTRUE;
Properties hanging on the resulting Core
layoutProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[PWCore.layoutProp, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]];
coreProp: PUBLIC ATOM ← PWCore.coreProp;
extractedCoreProp: PUBLIC ATOMPW.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]]];
Operations for an easy management of those properties
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]];
};
Flushing caches when interactive edition
Mechanism for flushing during edits
FlushCoreAfterReplace: CDEvents.EventProc = {
[event: REF ANY, design: CD.Design, x: REF ANY] RETURNS [dont: BOOL ← FALSE]
xname: ROPE ← CDDirectory.Name[NARROW [x]];
names: LIST OF ROPEIF xname=NIL THEN NIL ELSE LIST [xname]; -- names is going to be the transitive closure of all cells depending on xname
FindInvalidNames: CDDirectory.EachEntryAction = {
[name: ROPE, ob: CD.Object] RETURNS [quit: BOOL ← FALSE]
someChildIsName: BOOLFALSE;
IsSomeChildName: CDDirectory.EnumerateObjectsProc = {
[me: CD.Object, x: REF ANY]
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 = {
[name: ROPE, ob: CD.Object] RETURNS [quit: BOOL ← FALSE]
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];
};
HighLighting errors utilities
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];
};
Fusion data structure and internal manipulation
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]
];
Geometry can be attached at all levels of a structured wire.
IW: TYPE = REF IWRec;
IWRec: TYPE = RECORD [instance: CD.Instance, wire: Wire];
EqualIW: PROC [value1, value2: Intervals.Value] RETURNS [BOOL] = {
iw1: IWNARROW [value1]; iw2: IWNARROW [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]]];
};
Fusion external manipulation
Enforces the invariant: all roots have all their sub-wires which are roots
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]]
]];
};
The following PROC implements Fisher-Galler fusion, not for efficiency, but for simplicity
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;
};
This proc really does the fusion of fusioned and root, by wiping fusioned of some tables, and adding interesting properties of fusioned to root.
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: BOOLTRUE] 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: IWNARROW [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;
};
Conceptually same as the previous one that uses the intervals but faster for getting all wires (or nearly all).
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];
};
Other Internal utilities
MatchOnlyIfPinsProp: PROC [wire: Wire, geometry: LIST OF CD.Instance] RETURNS [BOOL] = {
RETURN [CoreProperties.GetWireProp[wire, pinsProp]#NIL];
};
decorates the wire on the way
MatchAlways: PROC [wire: Wire, geometry: LIST OF CD.Instance] RETURNS [BOOL] = {
PutWireGeometryPropOnWire[wire, geometry];
RETURN [TRUE];
};
wire (at the moment of the call) is a non fusioned wire (a root wire appearing in fusionData.geometry)
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];
we add the wires that make a connection by name
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;
};
Check that touchingWires only contains unnamed wires or wires named name
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;
};
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: BOOLFALSE] = {
yes ← TouchListList[GetWireGeometryPropFromWire[wire1], GetWireGeometryPropFromWire[wire2]];
};
TouchWireInstances: PROC [wire: Wire, geometry: LIST OF CD.Instance] RETURNS [yes: BOOLFALSE] = {
yes ← TouchListList[GetWireGeometryPropFromWire[wire], geometry];
};
TouchWireInstance: PROC [wire: Wire, geometry: CD.Instance] RETURNS [yes: BOOLFALSE] = {
yes ← TouchList[GetWireGeometryPropFromWire[wire], geometry];
};
Extraction
extractProcProp: PUBLIC ATOMPW.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;
Enumerate all the internals, and add as a pin property all the geometry that crosses the interestRect
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 ;
We replace in all instances wires by their roots
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]];
IF FindRootGeometry[fusionData, wire]=NIL THEN ERROR; -- non connected actual
actual[i] ← wire;
ENDLOOP;
ENDLOOP;
We build the CellType
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!
We fusion using the nets property, and we put pin properties for future use
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;
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
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
};
Geometry Primitives
touchProcProp: PUBLIC ATOMPW.RegisterProp[$TouchProc];
Touch: PUBLIC TouchProc = {
refProc: REF TouchProc;
IF ~CDBasics.Intersect[CDInstances.InstRectO[instance1], CDInstances.InstRectO[instance2]] THEN RETURN;
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
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;
};
Geometry Utilities
TouchSomeLayer: PROC [instances: LIST OF CD.Instance, bound: CD.Rect] RETURNS [yes: BOOLFALSE] = {
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: BOOLFALSE] = {
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: BOOLTRUE] RETURNS [yes: BOOLFALSE] = {
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: BOOLTRUE] RETURNS [yes: BOOLFALSE] = {
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: BOOLTRUE] RETURNS [yes: BOOLFALSE] = {
FOR list: LIST OF CD.Instance ← instances1, list.rest WHILE list#NIL DO
IF TouchList[instances2, list.first, compareLayers] THEN RETURN [TRUE];
ENDLOOP;
};
Initialization
CDEvents.RegisterEventProc[$AfterCellReplacement, FlushCoreAfterReplace];
END.