PWCoreRouteImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reversed.
Bertrand Serlet June 9, 1986 11:57:21 am PDT
Louis Monier June 14, 1986 5:16:38 pm PDT
DIRECTORY CD, CDCells, CDSimpleRules, CDSymbolicObjects, CedarProcess, CoreClasses, CoreOps, CoreProperties, IO, PW, PWCore, PWCoreRoute, PWRoute, Rope, Route;
PWCoreRouteImpl: CEDAR PROGRAM    
IMPORTS CD, CDCells, CDSimpleRules, CDSymbolicObjects, CedarProcess, CoreClasses, CoreOps, CoreProperties, IO, PW, PWCore, PWRoute, Rope, Route
EXPORTS PWCoreRoute =
BEGIN OPEN PWCoreRoute;
technologyKey: PUBLIC ATOM ← $cmosB;
GndAndVdd25Met2MinWidth: PUBLIC PWRoute.WireWidthProc = {
wireWidth ← CDSimpleRules.MinWidth[CDSimpleRules.GetLayer[technologyKey, "metal2"]]
*(IF Rope.Equal[netName, "Vdd"] OR Rope.Equal[netName, "Gnd"] THEN 25 ELSE 1);
};
Channel: PUBLIC PWCore.LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
leftOrBottomCT: CellType ← data[0].type;
rightOrTopCT: CellType ← data[1].type;
leftOrBottom: CD.Object ← PWCore.Layout[leftOrBottomCT];
rightOrTop: CD.Object ← PWCore.Layout[rightOrTopCT];
obj1, obj2, bottomOrLeftObj, topOrRightObj, channel, extended1, extended2: PW.Object;
params: PWRoute.RouterParams;
channelData: ChannelData ← NARROW [CoreProperties.GetCellTypeProp[cellType, $ChannelData]];
inX: BOOL ← channelData.inX;
leftOrBottomHeight: INTIF inX THEN CD.InterestSize[leftOrBottom].y ELSE CD.InterestSize[leftOrBottom].x;
rightOrTopHeight: INTIF inX THEN CD.InterestSize[rightOrTop].y ELSE CD.InterestSize[rightOrTop].x;
leftOrBottomExtend: INTIF channelData.extend THEN MAX[leftOrBottomHeight, rightOrTopHeight] - leftOrBottomHeight ELSE 0;
rightOrTopExtend: INTIF channelData.extend THEN MAX[leftOrBottomHeight, rightOrTopHeight] - rightOrTopHeight ELSE 0;
trLayer: CD.Layer ← CDSimpleRules.GetLayer[technologyKey, channelData.trunkLayer];
brLayer: CD.Layer ← CDSimpleRules.GetLayer[technologyKey, channelData.branchLayer];
priority: CedarProcess.Priority ← CedarProcess.GetPriority[];
IF data.size#2 THEN ERROR;
extended1 ← Filler[leftOrBottomCT, inX, trLayer, leftOrBottomExtend, channelData.extendTopOrRight];
extended2 ← Filler[rightOrTopCT, inX, trLayer, rightOrTopExtend, channelData.extendTopOrRight];
obj1 ← MakeOutline[data[0], data.internal, IF inX THEN right ELSE top, brLayer, CD.InterestSize[extended1], IF channelData.extendTopOrRight THEN 0 ELSE leftOrBottomExtend];
obj2 ← MakeOutline[data[1], data.internal, IF inX THEN left ELSE bottom, brLayer, CD.InterestSize[extended2], IF channelData.extendTopOrRight THEN 0 ELSE rightOrTopExtend];
-- check if interestRects do not match
IF (IF inX THEN CD.InterestSize[obj1].y ELSE CD.InterestSize[obj1].x)#(IF inX THEN CD.InterestSize[obj2].y ELSE CD.InterestSize[obj2].x) THEN ERROR;
-- Make fake objects
bottomOrLeftObj ← MakeFakeObject[data.internal, channelData.bottomOrLeftWires, channelData.inX, trLayer, IF inX THEN bottom ELSE left];
topOrRightObj ← MakeFakeObject[data.internal, channelData.topOrRightWires, channelData.inX, trLayer, IF inX THEN top ELSE right];
params ← NEW [PWRoute.RouterParamsRec ← [
trunkLayer: channelData.trunkLayer,
branchLayer: channelData.branchLayer, 
wireWidthProc: channelData.wireWidthProc,
technologyKey: technologyKey,
signalSinglePinNets: FALSE, -- SIGNAL if there are any single pin nets
signalCoincidentPins: FALSE, -- SIGNAL if there any pins are coincident
opt: noIncompletes  -- return the first correct routing
]];
CedarProcess.CheckAbort[];
CedarProcess.SetPriority[background];
channel ← PWRoute.MakeChannel[
obj1: obj1, obj2: obj2,
bottomOrLeftObj: bottomOrLeftObj, topOrRightObj: topOrRightObj,
params: params,
isX: channelData.inX ! Route.Signal => {PW.WriteF["*** Routing warning: %g\n", IO.rope[explanation]]}];
CedarProcess.SetPriority[priority];
IF channel=NIL OR NARROW [channel.specificRef, CD.CellPtr].contents=NIL THEN ERROR;
obj ← (IF inX THEN PW.AbutX ELSE PW.AbutY)[extended1, channel, extended2];
};
DecorateChannel: PWCore.DecorateProc = {
channelData: ChannelData ← NARROW [CoreProperties.GetCellTypeProp[cellType, $ChannelData]];
(IF channelData.inX THEN PWCore.DecorateAbutX ELSE PWCore.DecorateAbutY)[cellType, obj];
};
-- Given the layout associated with the cellType, this proc extracts all the pins located on the edge of the channel which have the appropriate layer and are part (full name) of the public of the channel; it assemble these pins into a fake object passed to the router.
MakeOutline: PROC [cellInstance: CoreClasses.CellInstance, internal: Wire, iSide: PWCore.Side, iLayer: CD.Layer, iSize: CD.Position, displacement: INT] RETURNS [obj: CD.Object] ~ {
AddPinToOutline: PWCore.EachWirePinProc ~ {
inst: CD.Instance;
name: ROPE;
pos: CD.Position;
IF wire.size#0 THEN ERROR;
name ← CoreOps.GetFullWireNames[internal, CoreClasses.CorrespondingActual[cellInstance, wire]].first;
IF side#iSide OR layer#iLayer THEN RETURN;
pos ← SELECT side FROM
left => [0, min+displacement],
right => [iSize.x-minW, min+displacement],
top => [min+displacement, iSize.y-minW],
bottom => [min+displacement, 0],
ENDCASE => ERROR;
inst ← PW.IncludeInCell[obj, CDSymbolicObjects.CreatePin[IF side=left OR side=right THEN [minW, max-min] ELSE [max-min, minW]], pos];
CDSymbolicObjects.SetLayer[inst, layer];
CDSymbolicObjects.SetName[inst, name];
};
minW: INT ← CDSimpleRules.MinWidth[iLayer]-1;
obj ← PW.CreateEmptyCell[];
[] ← PWCore.EnumerateNonOverlappingWirePins[cellInstance.type, AddPinToOutline];
PW.SetInterestRect[obj, iSize];
PW.RepositionCell[obj];
obj ← obj; -- for debugging
};
-- A cell containing only pins (plus a rectangle; hack!) whose posiiton and size does not matter; used to specify the sides of the channel to the router.
MakeFakeObject: PROC [internal: Wire, sideWires: LIST OF Wire, inX: BOOL, layer: CD.Layer, purposeSide: PWCore.Side] RETURNS [obj: PW.Object] ~ {
AppendPin: PROC [wire: Wire] ~ {
inst: CD.Instance;
name: ROPE ← CoreOps.GetFullWireNames[internal, wire].first;
inst ← PW.IncludeInCell[obj, CDSymbolicObjects.CreatePin[[minW, minW]], pos];
CDSymbolicObjects.SetLayer[inst, layer];
CDSymbolicObjects.SetName[inst, name];
pos ← IF inX THEN [pos.x+delta, pos.y] ELSE [pos.x, pos.y+delta];
};
minW: INT ← CDSimpleRules.MinWidth[layer];
delta: INT ← CDSimpleRules.MinDist[layer, layer]+minW;
pos: CD.Position ← [0, 0];
obj ← PW.CreateEmptyCell[];
[] ← PW.IncludeInCell[obj, CDSimpleRules.Rect[[1, 1], CD.undefLayer], [1, 1]]; -- to avoid reposionning empty cell
FOR list: LIST OF Wire ← sideWires, list.rest WHILE list#NIL DO
[] ← CoreOps.VisitAtomicWires[list.first, AppendPin];
ENDLOOP;
[] ← CDCells.SetInterestRect[obj, IF inX THEN [-minW, IF purposeSide=top THEN 0 ELSE -5*minW, pos.x, IF purposeSide=top THEN 10*minW ELSE minW] ELSE [IF purposeSide=left THEN -5*minW ELSE 0, -minW, IF purposeSide=left THEN minW ELSE 10*minW, pos.y]];
PW.RepositionCell[obj];
};
Filler: PROC [sourceCT: CellType, inX: BOOL, extLayer: CD.Layer, extension: INT, extendTopOrRight: BOOL] RETURNS [extended: CD.Object] = {
source: CD.Object ← PWCore.Layout[sourceCT];
AddPinToExtension: PWCore.EachWirePinProc = {
IF wire.size#0 THEN ERROR;
IF side#(IF inX THEN (IF extendTopOrRight THEN top ELSE bottom) ELSE (IF extendTopOrRight THEN right ELSE left)) OR layer#extLayer THEN RETURN;
[] ← PW.IncludeInCell[
obj,
CDSimpleRules.Rect[IF inX THEN [max-min, extension] ELSE [extension, max-min], layer],
IF inX THEN [min, 0] ELSE [0, min]
];
};
obj: CD.Object;
size: CD.Position ← CD.InterestSize[source];
IF extension=0 THEN RETURN [source];
obj ← PW.CreateEmptyCell[];
[] ← PWCore.EnumerateNonOverlappingWirePins[sourceCT, AddPinToExtension];
PW.SetInterestRect[obj, IF inX THEN [size.x, extension] ELSE [extension, size.y]];
PW.RepositionCell[obj];
extended ← (IF inX THEN PW.AbutY ELSE PW.AbutX)[IF extendTopOrRight THEN source ELSE obj, IF extendTopOrRight THEN obj ELSE source];
};
[] ← PWCore.RegisterLayoutAtom[$Channel, Channel, DecorateChannel];
END.