-- 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]};
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;
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;