-- AbutRoute: uses a channel router to connect adjacent objects
AbutRouteList:
PROC [design:
CD.Design, listOb, bottomOrLeftListOb, topOrRightListOb:
PW.ListOb, params: RouterParams, isX:
BOOL, routeType: RouteType]
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, bottomOrLeftObj, topOrRightObj, params, isX, routeType];
newListObj ← CONS[obj2, CONS[channel, newListObj]];
obj1 ← obj2; -- just before looping
ENDLOOP;
newListObj ← PW.Reverse[newListObj];
IF isX THEN obj ← PW.AbutListX[design, newListObj]
ELSE obj ← PW.AbutListY[design, newListObj];
END;
AbutChRouteListX:
PUBLIC
PROC [design:
CD.Design,
listOb: PW.ListOb,
bottomListOb: PW.ListOb ← NIL,
topListOb: PW.ListOb ← NIL,
params: RouterParams ← defaultRouterParams] RETURNS [obj: PW.Object] =
{obj ← AbutRouteList[design, listOb, bottomListOb, topListOb, params, TRUE, channel]};
AbutChRouteListY:
PUBLIC
PROC [design:
CD.Design,
listOb: PW.ListOb,
leftListOb: PW.ListOb ← NIL,
rightListOb: PW.ListOb ← NIL,
params: RouterParams ← defaultRouterParams] RETURNS [obj: PW.Object] =
{obj ← AbutRouteList[design, listOb, leftListOb, rightListOb, params, FALSE, channel]};
AbutSbRoute:
PUBLIC
PROC [design:
CD.Design,
bottomOb, rightOb, topOb, leftOb: PW.Object ← NIL,
trunkDir: HorV ← horizontal,
params: RouterParams ← defaultRouterParams] RETURNS [obj: PW.Object] = {
IF trunkDir = horizontal
THEN
obj ← MakeChannel[design, bottomOb, topOb, leftOb, rightOb, params, FALSE, switchBox]
ELSE
obj ← MakeChannel[design, leftOb, rightOb, bottomOb, topOb, params, TRUE, switchBox]};
InsertPin:
PROC [tab: SymTab.Ref, inst:
CD.Instance, side: PWPins.Side, params: RouterParams] = {
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];
};
MakeChannel:
PUBLIC
PROC[design:
CD.Design, obj1, obj2, bottomOrLeftObj, topOrRightObj:
CD.Object, params: RouterParams, isX:
BOOL, routeType: RouteType]
RETURNS [channel:
CD.Object] = {
tab: SymTab.Ref;
result: Route.RoutingResult;
sideCoords: Route.PositionVec; -- the positions of the sides in a "large" coord system
r1, r2, rbl, rtr, routingRect: CD.Rect ← [0, 0, 0, 0];
pBottom, pLeft, pTop, pRight: CD.Position;
-- 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]
IF obj1 # NIL THEN r1 ← CD.InterestRect[obj1];
IF obj2 # NIL THEN r2 ← CD.InterestRect[obj2];
IF bottomOrLeftObj # NIL THEN rbl ← CD.InterestRect[bottomOrLeftObj];
IF topOrRightObj # NIL THEN rtr ← CD.InterestRect[topOrRightObj];
IF isX
THEN
-- AbutX
BEGIN
pBottom ← [0, - rbl.y2 + rbl.y1];
pLeft ← [- r1.x2 + r1.x1, 0];
pTop ← [0, MAX[r1.y2 - r1.y1, r2.y2 - r2.y1]];
pRight ← [MAX[rbl.x2 - rbl.x1, rtr.x2 - rtr.x1], 0];
Route.IncludeRoutingAreaSide[routingArea, left, [r1.x1, r1.y1]];
Route.IncludeRoutingAreaSide[routingArea, right, [r2.x1, r2.y1]];
Route.IncludeRoutingAreaSide[routingArea, bottom, [rbl.x1, rbl.y1]];
Route.IncludeRoutingAreaSide[routingArea, top, [rtr.x1, rtr.y1]];
END
ELSE
BEGIN
-- AbutY
pBottom ← [0, - r1.y2 + r1.y1];
pLeft ← [- rbl.x2 + rbl.x1, 0];
pTop ← [0, MAX[rbl.y2 - rbl.y1, rtr.y2 - rtr.y1]];
pRight ← [MAX[r1.x2 - r1.x1, r2.x2 - r2.x1], 0];
Route.IncludeRoutingAreaSide[routingArea, bottom, [r1.x1, r1.y1]];
Route.IncludeRoutingAreaSide[routingArea, top, [r2.x1, r2.y1]];
Route.IncludeRoutingAreaSide[routingArea, left, [rbl.x1, rbl.y1]];
Route.IncludeRoutingAreaSide[routingArea, right, [rtr.x1, rtr.y1]];
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];
ParsePins[design, topOrRightObj, tab, IF isX THEN bottom ELSE left, params];
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 ← [pBottom, pRight, pTop, pLeft];
routingRect ← [0, 0, pRight.x, pTop.y];
SELECT routeType
FROM
channel => result ← Route.ChannelRoute[routingArea, sideCoords, routingRect];
switchBox => result ← Route.SwitchBoxRoute[routingArea, sideCoords, routingRect];
ENDCASE;
channel ← Route.RetrieveRouting[result, result.routingArea.name, design, NIL, NIL].object;
};