ConnectionsImpl.mesa 
Copyright © 1986 by Xerox Corporation. All rights reversed.
Created by Bryan Preas, May 22, 1986 1:18:54 pm PDT
DIRECTORY
CD, CDSymbolicObjects, Connections, HashTable, PWPins, Rope, RTBasic;
ConnectionsImpl: CEDAR PROGRAM
IMPORTS CDSymbolicObjects, HashTable, PWPins
EXPORTS Connections =
BEGIN
CreateForRopes: PUBLIC PROC [mod: Connections.SeqIndex ← 17] RETURNS [Connections.Table] ~ {
RETURN[HashTable.Create[mod, HashTable.RopeEqual, HashTable.HashRope]]};
CreateForRefs: PUBLIC PROC [mod: Connections.SeqIndex ← 17] RETURNS [Connections.Table] ~ {
RETURN[HashTable.Create[mod]]};
Creates new table, whose length is mod. They do the right thing for Rope and Ref tables.
Fetch: PUBLIC PROC [table: Connections.Table, key: Connections.Key] RETURNS [found: BOOLEAN, net: Connections.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] ← HashTable.Fetch[table, key];
net ← NARROW[value]};
Store: PUBLIC PROC [table: Connections.Table, key: Connections.Key, net: Connections.Net] RETURNS [BOOLEAN] ~ {
returns TRUE after inserting new pair
returns FALSE after overwriting old net for existing key-net pair
RETURN[HashTable.Store[table, key, net]]};
InsertPins: PUBLIC PROC [table: Connections.Table, object: CD.Object, pinFilter: Connections.PinFilterProc, makeHashKey: Connections.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: BOOL ← FALSE]
usePin: BOOLEANIF 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: Connections.Table, action: Connections.EachNetAction] RETURNS [BOOLEAN] ~ {
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: HashTable.EachPairAction ~ {
TRUSTED{net ← LOOPHOLE[value]};
quit ← action[key, net]};
net: Connections.Net;
RETURN[HashTable.Pairs[table, eachPair]]};
EnumerateSegments: PUBLIC PROC [net: Connections.Net, action: Connections.EachSegmentAction] RETURNS [quit: BOOLEANFALSE] ~ {
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: Connections.Segments ← net.segments, l.rest WHILE ~quit AND l # NIL DO
segment: Connections.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: Connections.Table, object: CD.Object, instance: CD.Instance, makeHashKey: Connections.HashKeyProc] ~ {
found: BOOL;
val: REF;
net: Connections.Net;
side: RTBasic.Side ← FromSideToSide[PWPins.GetSide[object, instance].side];
rect: CD.Rect ← CDSymbolicObjects.Denotes[instance];
name: Rope.ROPE ← CDSymbolicObjects.GetName[instance];
segment: Connections.Segment ← NEW[Connections.SegmentRec ← [name, object, CoordsAlongSide[instance, side], side, CDSymbolicObjects.GetLayer[instance]]];
tabIndex: Rope.ROPEIF makeHashKey=NIL THEN name ELSE makeHashKey[instance];
[found, val] ← Fetch[table, tabIndex];
net ← IF ~found THEN NEW[Connections.NetRec ← [name: name]] ELSE NARROW[val];
net.segments ← CONS[segment, net.segments];
[] ← Store[table, tabIndex, net]};
CoordsAlongSide: PROC [instance: CD.Instance, side: RTBasic.Side] RETURNS [range: Connections.Range] ~ {
rect: CD.Rect ← CDSymbolicObjects.Denotes[instance];
SELECT side FROM
top, bottom => range ← [rect.x1, rect.x2];
left, right => range ← [rect.y1, rect.y2];
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.