ConnectionsImpl.mesa 
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reversed.
Created by Bryan Preas, May 22, 1986 1:18:54 pm PDT
Bertrand Serlet April 27, 1987 0:18:04 am PDT
DIRECTORY
CD, CDSymbolicObjects, Connections, RefTab, RefTabExtras, PWPins, Rope, RTBasic;
ConnectionsImpl: CEDAR PROGRAM
IMPORTS CDSymbolicObjects, RefTab, RefTabExtras, PWPins
EXPORTS Connections = BEGIN OPEN Connections;
Building The Connection Table
CreateForRopes: PUBLIC PROC [mod: NAT ← 17] RETURNS [Table] ~ {
RETURN[RefTab.Create[mod, RefTabExtras.EqualRope, RefTabExtras.HashRope]]};
Creates new table, whose length is mod. Does the right thing for Rope tables.
Fetch: PUBLIC PROC [table: Table, key: Key] RETURNS [found: BOOL, net: Net] ~ {
looks up key in table, returns associated net (if any)
if found is TRUE, net is value associated with given key
if found is FALSE, net is NIL
value: REF;
[found, value] ← RefTab.Fetch[table, key];
net ← NARROW[value]};
Store: PUBLIC PROC [table: Table, key: Key, net: Net] RETURNS [BOOL] ~ {
returns TRUE after inserting new pair
returns FALSE after overwriting old net for existing key-net pair
RETURN[RefTab.Store[table, key, net]]};
InsertPins: PUBLIC PROC [table: Table, object: CD.Object, pinFilter: PinFilterProc, makeHashKey: HashKeyProc] ~ {
put the pins on the interest rec of the object in the table if pinFilter returns true.
EachPin: CDSymbolicObjects.InstEnumerator = {
[inst: CD.Instance] RETURNS [quit: BOOLFALSE]
usePin: BOOLIF pinFilter = NIL THEN TRUE ELSE pinFilter[inst, object];
IF usePin THEN InsertSegments[table, object, inst, makeHashKey]};
IF object # NIL THEN [] ← PWPins.EnumerateEdgePins[object, EachPin];
};
Using The Connection Table
EnumerateNets: PUBLIC PROC [table: Table, action: EachNetAction] RETURNS [BOOL] ~ {
enumerates pairs currently in symbol table in unspecified order
pairs inserted/deleted during enumeration may or may not be seen
applies action to each pair until action returns TRUE or no more pairs
returns TRUE if some action returns TRUE
eachPair: RefTab.EachPairAction ~ {quit ← action[key, NARROW [val]]};
RETURN [RefTab.Pairs[table, eachPair]]};
EnumerateSegments: PUBLIC PROC [net: Net, action: EachSegmentAction] RETURNS [quit: BOOLFALSE] ~ {
enumerates segments currently in net in unspecified order
segments inserted/deleted during enumeration may or may not be seen
applies action to each segment until action returns TRUE or no more segments
returns TRUE if some action returns TRUE
FOR l: Segments ← net.segments, l.rest WHILE ~quit AND l # NIL DO
segment: Segment ← l.first;
quit ← action[net, segment];
ENDLOOP};
Internal Procedures
make a segment from a pin (inst) on an object and put it in the table
InsertSegments: PROC [table: Table, object: CD.Object, instance: CD.Instance, makeHashKey: HashKeyProc] ~ {
found: BOOL;
val: REF;
net: Net;
side: RTBasic.Side ← FromSideToSide[PWPins.GetSide[object, instance].side];
rect: CD.Rect ← CDSymbolicObjects.Denotes[instance];
name: Rope.ROPE ← CDSymbolicObjects.GetName[instance];
segment: Segment ← NEW[SegmentRec ← [name: name, object: object, range: CoordsAlongSide[instance, side, object], side: side, layer: CDSymbolicObjects.GetLayer[instance], segmentDat: NIL]];
tabIndex: Rope.ROPEIF makeHashKey=NIL THEN name ELSE makeHashKey[instance];
[found, val] ← Fetch[table, tabIndex];
net ← IF ~found THEN NEW[NetRec ← [name: name]] ELSE NARROW[val];
net.segments ← CONS[segment, net.segments];
[] ← Store[table, tabIndex, net]};
CoordsAlongSide: PROC [instance: CD.Instance, side: RTBasic.Side, object: CD.Object] RETURNS [range: Range] ~ {
rect: CD.Rect ← CDSymbolicObjects.Denotes[instance];
SELECT side FROM
top, bottom => range ← [rect.x1 - object.bbox.x1, rect.x2 - object.bbox.x1];
left, right => range ← [rect.y1 - object.bbox.y1, rect.y2 - object.bbox.y1];
ENDCASE};
FromSideToSide: PROC [side: PWPins.Side] RETURNS [routeSide: RTBasic.Side] = {
routeSide ← SELECT side FROM
left => left,
right => right,
top => top,
bottom => bottom,
ENDCASE => ERROR;
};
END.