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: BOOLEAN ← IF 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:
BOOLEAN ←
FALSE] ~ {
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.ROPE ← IF 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.