PWRouteImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reversed.
Last Edited by: Monier, August 16, 1985 11:03:47 am PDT
Bertrand Serlet August 28, 1985 6:51:43 pm PDT
Louis Monier August 22, 1985 1:15:09 pm PDT
DIRECTORY
CD,
CDPinObjects,
CDSimpleRules,
PW,
PWPins,
PWRoute,
Route,
SymTab;
PWRouteImpl: CEDAR PROGRAM    
IMPORTS CD, CDPinObjects, CDSimpleRules, PW, PWPins, Route, SymTab
EXPORTS PWRoute =
BEGIN OPEN PWRoute;
-- AbutRoute: uses a channel router to connect adjacent objects
AbutRouteList: PROC [design: CD.Design, listOb, topOrRightListOb, bottomOrLeftListOb: PW.ListOb, params: RouterParams, isX: BOOL] RETURNS [obj: PW.Object] =
BEGIN
newListObj: PW.ListOb ← NIL;
obj1, obj2, topOrRightObj, bottomOrLeftObj, channel: PW.Object;
IF listOb=NIL THEN RETURN[NIL];
obj1 ← listOb.first; listOb ← listOb.rest;
newListObj ← CONS[obj1];
FOR l: PW.ListOb ← listOb, l.rest WHILE l#NIL DO
obj2 ← l.first;
IF topOrRightListOb=NIL THEN topOrRightObj ← NIL
ELSE {topOrRightObj ← topOrRightListOb.first;
topOrRightListOb ← topOrRightListOb.rest};
IF bottomOrLeftListOb=NIL THEN bottomOrLeftObj ← NIL
ELSE {bottomOrLeftObj ← bottomOrLeftListOb.first;
bottomOrLeftListOb ← bottomOrLeftListOb.rest};
channel ← MakeChannel[design, obj1, obj2, topOrRightObj, bottomOrLeftObj, params, TRUE];
newListObj ← CONS[obj2, CONS[channel, newListObj]];
obj1 ← obj2; -- just before looping
ENDLOOP;
newListObj ← PW.Reverse[newListObj];
obj ← PW.AbutListX[design, newListObj];
END;
AbutRouteListX: PUBLIC PROC [design: CD.Design,
listOb: PW.ListOb,
topListOb: PW.ListOb ← NIL,
bottomListOb: PW.ListOb ← NIL,
params: RouterParams ← defaultRouterParams] RETURNS [obj: PW.Object] =
{obj ← AbutRouteList[design, listOb, topListOb, bottomListOb, params, TRUE]};
AbutRouteListY: PUBLIC PROC [design: CD.Design,
listOb: PW.ListOb,
rightListOb: PW.ListOb ← NIL,
leftListOb: PW.ListOb ← NIL,
params: RouterParams ← defaultRouterParams] RETURNS [obj: PW.Object] =
{obj ← AbutRouteList[design, listOb, rightListOb, leftListOb, params, FALSE]};
-- Given two cells that we plan to abut, this module parses the corresponding edges, extract the pins, build nets according to the names on the pins, then calls the router to produce a cell containing the channel routing.
Net: TYPE = REF NetRec;
NetRec: TYPE = RECORD[
name: ROPENIL,     -- net name
pins: Route.PinList ← NIL];   -- the list of pins in the net
defaultRouterParams: PUBLIC RouterParams ← NEW[RouterParamsRec ← ["metal", "poly"]];
-- Gets all the pins on the edge; pack them Bryan-style into nets and in the SymTab.Ref
ParsePins: PROC[design: CD.Design, obj: CD.Object, tab: SymTab.Ref, side: PWPins.Side, params: RouterParams] =
BEGIN
EachPin: CDPinObjects.InstanceEnumerator = {
[inst: CD.Instance] RETURNS [quit: BOOL ← FALSE]
IF PWPins.GetSide[obj, inst].side=side THEN InsertPin[tab, inst, side, params];
};
[] ← PWPins.EnumerateEdgePins[obj, EachPin];
END;
FromSideToSide: PROC [side: PWPins.Side] RETURNS [bryanSide: Route.Side] = {
bryanSide ← SELECT side FROM
left => left,
right => right,
top => top,
bottom => bottom,
ENDCASE => ERROR;
};
OtherSide: PROC [side: Route.Side] RETURNS [opposite: Route.Side] = {
opposite ← SELECT side FROM
left => right,
right => left,
top => bottom,
bottom => top,
ENDCASE => ERROR;
};
-- Group pins in net and insert in table
InsertPin: PROC [tab: SymTab.Ref, inst: CD.Instance, side: PWPins.Side, params: RouterParams] =
BEGIN
pinName, netName: ROPE;
found: BOOL;
val: REF;
net: Net;
pin: Route.Pin ← Route.CreatePin[inst, OtherSide[FromSideToSide[side]]];
pinName ← CDPinObjects.GetName[inst];
netName ← IF params.makeNetsProc=NIL THEN pinName ELSE params.makeNetsProc[pinName];
[found, val] ← SymTab.Fetch[tab, netName];
net ← IF ~found THEN NEW[NetRec ← [netName]] ELSE NARROW[val];
net.pins ← CONS[pin, net.pins];
[] ← SymTab.Store[tab, netName, net];
END;
-- Read the table and ship the nets to the channel router
ShipNets: PROC [tab: SymTab.Ref, routingArea: Route.RoutingArea] =
BEGIN
EnterOneNet: SymTab.EachPairAction =
BEGIN
netName: ROPENARROW[key];
net: Net ← NARROW[val];
Route.IncludeNet[routingArea, netName, net.pins];
RETURN[FALSE];
END;
[] ← SymTab.Pairs[tab, EnterOneNet];
END;
MakeChannel: PUBLIC PROC[design: CD.Design, obj1, obj2, topOrRightObj, bottomOrLeftObj: CD.Object, params: RouterParams, isX: BOOL] RETURNS [channel: CD.Object] =
BEGIN
tab: SymTab.Ref;
result: Route.RoutingResult;
sideCoords: Route.PositionVec; -- the positions of the sides in a "large" coord system
r1, r2: CD.Rect;
-- Get the technology from thew CD design: better not be NIL!
technology: CD.Technology ← design.technology;
-- Make the design rules for proper spacing in this techno
rules: Route.DesignRules ←
IF isX THEN Route.CreateDesignRules[         -- abutX
technology.key,
CDSimpleRules.GetLayer[technology.key, params.branchLayer],
CDSimpleRules.GetLayer[technology.key, params.trunkLayer],
vertical]
ELSE Route.CreateDesignRules[           -- abutY
technology.key,
CDSimpleRules.GetLayer[technology.key, params.trunkLayer],
CDSimpleRules.GetLayer[technology.key, params.branchLayer],
horizontal];
-- Initialise the channel: no fancy option for now
routingArea: Route.RoutingArea ← Route.CreateRoutingArea["Channel", rules];
-- In prevision of the use of the IRect coord system, origins are [0, 0]
r1 ← CD.InterestRect[obj1];
r2 ← CD.InterestRect[obj2];
IF isX THEN-- AbutX
BEGIN
Route.IncludeRoutingAreaSide[routingArea, left, [r1.x2, r1.y1]];
Route.IncludeRoutingAreaSide[routingArea, right, [r2.x1, r2.y1]];
Route.IncludeRoutingAreaSide[routingArea, bottom, [0, 0]]; -- to be changed
Route.IncludeRoutingAreaSide[routingArea, top, [0, 0]];  -- to be changed
END
ELSE BEGIN-- AbutY
Route.IncludeRoutingAreaSide[routingArea, bottom, [r1.x1, r1.y2]];
Route.IncludeRoutingAreaSide[routingArea, top, [r2.x1, r2.y1]];
Route.IncludeRoutingAreaSide[routingArea, left, [0, 0]];  -- to be changed
Route.IncludeRoutingAreaSide[routingArea, right, [0, 0]];  -- to be changed
END;
tab ← SymTab.Create[mod: 17, case: TRUE]; -- the table of all nets
-- Parse the objects, get the pins, make the nets, put in table
ParsePins[design, obj1, tab, IF isX THEN right ELSE top, params];
ParsePins[design, obj2, tab, IF isX THEN left ELSE bottom, params];
IF topOrRightObj#NIL THEN ParsePins[design, topOrRightObj, tab, IF isX THEN bottom ELSE left, params];
IF bottomOrLeftObj#NIL THEN ParsePins[design, bottomOrLeftObj, tab, IF isX THEN top ELSE right, params];
-- Read the table and ship the nets to the channel router
ShipNets[tab, routingArea];
-- Now route!
sideCoords ← [[0, 0], [0, 0], [0, r1.y2-r1.y1], [0, 0]];
result ← Route.ChannelRoute[routingArea, sideCoords];
[channel, ] ← Route.RetrieveRouting[result, result.routingArea.name, design, NIL, NIL];
END;
END.