SCExprRouteImpl.mesa: Implements of SCExprGlobalRoute.DetailedRoute
Copyright Ó 1986, 1987, 1988 by Xerox Corporation. All rights reserved.
Frank Bowers June 3, 1986 10:58:48 am PDT
Last Edited by: Bryan Preas March 26, 1988 6:52:05 pm PST
Christian Le Cocq December 2, 1987 2:59:49 pm PST
Jean-Marc Frailong October 14, 1987 5:47:09 pm PDT
DIRECTORY
CD, CDCells, CDOps, CDProperties, Convert, Core, CoreGeometry, CoreOps, CoreRoute, DABasics, List, Rope, Route, RouteUtil, RTBasic, SC, SCChanUtil, SCExprGlobalRoute, SCInstUtil, SCNetUtil, SCPrivate, SCExprRoutePinsUtil, SCRowUtil, SCUtil, SCNewWidth, Sinix;
SCExprRouteImpl: CEDAR PROGRAM
IMPORTS CDCells, CDOps, CDProperties, Convert, CoreGeometry, CoreOps, CoreRoute, List, Rope, Route, RouteUtil, RTBasic, SC, SCChanUtil, SCInstUtil, SCNetUtil, SCExprRoutePinsUtil, SCRowUtil, SCUtil, SCNewWidth
EXPORTS SCExprGlobalRoute
SHARES SC = BEGIN
Local Types
SegInChan: TYPE = REF SegInChanRec;
SegInChanRec: TYPE = RECORD [
segNum: INT ← 0,
net: SCPrivate.Net ← NIL,
leftExit, rightExit: BOOLFALSE,
pinsInSeg: PinsInSeg ← NIL];
PinsInSeg: TYPE = LIST OF Route.Pin;
Detail Route Operation
DetailRoute: PUBLIC PROC [handle: SC.Handle] RETURNS [result: SC.Result] = {
lgRows: SCPrivate.LgRows ← NARROW[handle.layoutData, SCPrivate.LayoutData].lgRows;
SCNewWidth.ComputeAllChanDW[handle, areaFom];
SCInstUtil.AllOffsets[handle];
[lgRows.maxRowWidth, lgRows.numMaxRows] ← SCRowUtil.FindMaxRow[handle];
result ← NEW[SC.ResultRec ← [handle: handle, object: RouteChannels[handle]]];
SCInstUtil.AsgnChanPos[handle];
[] ← SCUtil.WriteResults["End detailed routing\n", handle, 0]};
Construct The Rows
ConstructRow: PROC [handle: SC.Handle, lgRow: SCPrivate.LgRow] RETURNS [row: CD.Object ← CDCells.CreateEmptyCell[]] ~ {
LeftEnumerateSegments: PROC [eachSegment: PROC [CoreRoute.Segment]] ~ {
enumerate public wires for left side of row
EachWirePin: CoreGeometry.EachWirePinProc = {
PROC [wire: Wire, min, max: INT, side: Side, layer: CD.Layer] RETURNS [quit: BOOL ← FALSE];
IF side=left THEN eachSegment[[label: CoreOps.GetShortWireName[wire], min: min, max: max, layer: layer]]};
[] ← CoreGeometry.EnumerateWireSides[mode.decoration, lgRow.lgsOnRow[1].object.cellType, EachWirePin]};
RightEnumerateSegments: PROC [eachSegment: PROC [CoreRoute.Segment]] ~ {
enumerate public wires for right side of row
EachWirePin: CoreGeometry.EachWirePinProc = {
PROC [wire: Wire, min, max: INT, side: Side, layer: CD.Layer] RETURNS [quit: BOOL ← FALSE];
IF side=right THEN eachSegment[[label: CoreOps.GetShortWireName[wire], min: min, max: max, layer: layer]]};
[] ← CoreGeometry.EnumerateWireSides[mode.decoration, lgRow.lgsOnRow[lgRow.nLgsOnRow].object.cellType, EachWirePin]};
ForEachInstance: SCRowUtil.EachInstProc = {
[pos: NAT, instance: SCPrivate.Instance] RETURNS [quit: BOOLFALSE]
LabelProc: PROC [pinName: Rope.ROPE] RETURNS [label: Route.Label ← NIL] ~ {
find label for this pin
EachPin: SCInstUtil.EachPinProc ~ {
PROC [instance: SCPrivate.Instance, pin: NAT, netPin: SCPrivate.PinNet] RETURNS [quit: BOOLFALSE];
IF Rope.Equal[netPin.pin.name, pinName] THEN {
label ← netPin.net.name; quit ← TRUE;
};
};
IF SCUtil.IsPowerName[handle, pinName] THEN label ← pinName
ELSE IF ~SCInstUtil.EnumeratePinsOnInst[instance: instance, eachPin: EachPin] THEN
SC.Signal[callingError, "FeedThrough definition in library does not have all rectangles marked."]};
instOrientation: CD.Orientation ← SCInstUtil.CDOrien[instance];
object: CD.Object ← IF (instance.whichClass = ft) OR (instance.object = parms.vddObject) OR (instance.object = parms.gndObject) THEN CoreRoute.MakeRoutingCell[instance.object.cdOb, LabelProc]
ELSE instance.object.cdOb;
instPosition: CD.Position ← CDOps.FitObjectI[ob: object, location: [offset, 0], orientation: instOrientation].off;
cdInst: CD.Instance ← RouteUtil.Include[cell: row, ob: object, position: instPosition, orientation: instOrientation];
CDProperties.PutInstanceProp[cdInst, $InstanceName, instance.name];
offset ← offset + RTBasic.IRSize[object].x};
parms: SCPrivate.Parms = NARROW [handle.parms];
mode: Sinix.Mode = parms.mode;
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
maxRowWidth: CD.Number ← layoutData.lgRows.maxRowWidth;
rowLength: SC.Number ← lgRow.size.p;
rowOffset: SC.Number ← lgRow.rowOrg.p - layoutData.lgRows.horzRowOrg;
offset: SC.Number ← 0;
IF rowOffset > 0 THEN {
leftObject: CD.Object ← CoreRoute.ExtendObject[enumerateSegments: LeftEnumerateSegments, size: [rowOffset, lgRow.size.q], side: left, extendProc: CoreRoute.ExtendSegment];
[] ← RouteUtil.Include[cell: row, ob: leftObject, position: [offset, 0]];
offset ← offset + RTBasic.IRSize[leftObject].x};
[] ← SCRowUtil.EnumerateAllInstsOnRow[handle, lgRow.rowNum, ForEachInstance];
IF rowOffset + rowLength < maxRowWidth THEN {
rightObject: CD.Object ← CoreRoute.ExtendObject[enumerateSegments: RightEnumerateSegments, size: [maxRowWidth - (rowOffset + rowLength), lgRow.size.q], side: right, extendProc: CoreRoute.ExtendSegment];
[] ← RouteUtil.Include[cell: row, ob: rightObject, position: [offset, 0]];
offset ← offset + RTBasic.IRSize[rightObject].x};
RTBasic.RepositionCell[row]};
Route The Channels
RouteChannels: PROC [handle: SC.Handle] RETURNS [obj: CD.Object ← CDCells.CreateEmptyCell[]] ~ {
route the channels and include rows and channels into the layout
RouteChannel: PROC [enumerateNets: Route.EnumerateChannelNetsProc, rowChan: SCPrivate.RowChan] ~ {
route the specified channeland include in the object being constructed
BrokenNet: Route.BrokenNetProc ~ {
PROC [channelData, netData: REF, sourceNet: Label, regionNumber, numberOfRegions: NAT] RETURNS [newLabel: Label];
net: SCPrivate.Net ← NARROW[netData, SegInChan].net;
net.numberOfRegions ← net.numberOfRegions + 1;
newLabel ← CoreRoute.LabelBrokenNet[net.name, regionNumber];
net.brokenNets ← CONS[newLabel, net.brokenNets]};
HACK (BTP, 3/26/88) How to break private nets?
IF NOT net.externNet THEN newLabel ← NIL
ELSE {
net.numberOfRegions ← net.regionNumber + 1;
newLabel ← CoreRoute.LabelBrokenNet[net.name, net.numberOfRegions];
net.brokenNets ← CONS[newLabel, net.brokenNets]}};
channel: CD.Object ← Route.Channel[enumerateNets: enumerateNets, min: lgRows.horzRowOrg, max: lgRows.horzRowOrg + lgRows.maxRowWidth, rulesParameters: handle.rules.rowParms, name: Rope.Cat[handle.name, "Chan", Convert.RopeFromInt[rowChan.chanNum]], brokenNets: BrokenNet, channelData: handle].object;
[] ← RouteUtil.Include[cell: obj, ob: channel, position: [0, offset]];
offset ← offset + RTBasic.IRSize[channel].y;
rowChan.chanWidth ← RTBasic.IRSize[channel].y};
EachChannel: SCChanUtil.EachRowChanProc ~ {
[chan: SCPrivate.MaxChanSr, rowChan: SCPrivate.RowChan] RETURNS [quit: BOOLFALSE]
route the channel specified by rowChan
LowerChannel: Route.EnumerateChannelNetsProc ~ {
PROC [channelData: REF, eachNet: EachChannelNetProc];
LowerChannelNet: SCNetUtil.EachNetProc ~ {
PROC [net: SCPrivate.Net] RETURNS [quit: BOOLFALSE];
numberOfSegments: INT ← List.Length[net.segsInChan];
FOR segList: LIST OF REF ANY ← net.segsInChan, segList.rest WHILE segList # NIL DO
segInChan: SegInChan ← NARROW[segList.first];
name: Rope.ROPE;
IF numberOfSegments <= 1 THEN name ← net.name
ELSE {
name ← CoreRoute.LabelBrokenNet[net.name, segInChan.segNum];
net.numberOfRegions ← net.numberOfRegions + 1;
net.brokenNets ← CONS[name, net.brokenNets]};
eachNet[name: name,
enumeratePins: LowerChannelPins,
exitLeftOrBottom: segInChan.leftExit,
exitRightOrTop: segInChan.rightExit,
trunkSize: net.trunkWidth,
netData: segInChan];
ENDLOOP};
[] ← SCNetUtil.EnumerateNets[handle, LowerChannelNet]};
LowerChannelPins: Route.EnumerateChannelPinsProc ~ {
PROC [channelData, netData: REF, eachPin: EachChannelPinProc];
segInChan: SegInChan ← NARROW[netData];
FOR pins: PinsInSeg ← segInChan.pinsInSeg, pins.rest UNTIL pins = NIL DO
pin: Route.Pin ← pins.first;
bottomOrLeftSide: BOOL ← pin.side = bottom;
xfer: BOOLEAN ← segInChan.net.externNet AND SCNetUtil.ExitOnSide[handle, segInChan.net, bottom] AND pin.side = top;
eachPin[bottomOrLeftSide: bottomOrLeftSide, min: pin.min, max: pin.max, depth: pin.depth, layer: pin.layer];
IF xfer THEN eachPin[bottomOrLeftSide: ~bottomOrLeftSide, min: pin.min, max: pin.max, depth: pin.depth, layer: pin.layer];
ENDLOOP};
InteriorChannel: Route.EnumerateChannelNetsProc ~ {
PROC [name: Label, enumeratePins: EnumerateChannelPinsProc, exitLeftOrBottom, exitRightOrTop: BOOLFALSE, mayExit: BOOLTRUE, trunkSize: CD.Number ← 0, channelData, netData: REFNIL];
InteriorChannelNet: SCNetUtil.EachNetProc ~ {
PROC [net: SCPrivate.Net] RETURNS [quit: BOOLFALSE];
numberOfSegments: INT ← List.Length[net.segsInChan];
FOR segList: LIST OF REF ANY ← net.segsInChan, segList.rest WHILE segList # NIL DO
segInChan: SegInChan ← NARROW[segList.first];
name: Rope.ROPE;
IF numberOfSegments <= 1 THEN name ← net.name
ELSE {
name ← CoreRoute.LabelBrokenNet[net.name, segInChan.segNum];
net.numberOfRegions ← net.numberOfRegions + 1;
net.brokenNets ← CONS[name, net.brokenNets]};
eachNet[name: name,
enumeratePins: InteriorChannelPins,
exitLeftOrBottom: segInChan.leftExit,
exitRightOrTop: segInChan.rightExit,
trunkSize: net.trunkWidth,
netData: segInChan];
ENDLOOP};
[] ← SCNetUtil.EnumerateNets[handle, InteriorChannelNet]};
InteriorChannelPins: Route.EnumerateChannelPinsProc ~ {
PROC [channelData, netData: REF, eachPin: EachChannelPinProc];
segInChan: SegInChan ← NARROW[netData];
FOR pins: PinsInSeg ← segInChan.pinsInSeg, pins.rest UNTIL pins = NIL DO
pin: Route.Pin ← pins.first;
bottomOrLeftSide: BOOL ← pin.side = bottom;
eachPin[bottomOrLeftSide: bottomOrLeftSide, min: pin.min, max: pin.max, depth: pin.depth, layer: pin.layer];
ENDLOOP};
GetGlobalRouteForChannel[handle: handle, rowChan: rowChan];
IF chan # 1 THEN { -- include the specified row in the object being constructed
[] ← RouteUtil.Include[cell: obj, ob: ConstructRow[handle, lgRows.rows[chan-1]], position: [0, offset]];
offset ← offset + lgRows.rows[chan-1].size.q};
IF chan = 1 AND rowChans.count = 2 THEN {
do the bottom channel if it is the only one
RouteChannel[LowerChannel, rowChan]};
IF chan # rowChans.count AND chan # 1 THEN {
do the interior channels
RouteChannel[InteriorChannel, rowChan]}};
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
structureData: SCPrivate.StructureData ← NARROW[handle.structureData];
rowChans: SCPrivate.RowChans ← layoutData.rowChans;
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
offset: SC.Number ← 0;
[] ← SCChanUtil.EnumerateRowChans[handle, EachChannel];
RTBasic.SetCDCellName[obj, handle.name];
RTBasic.RepositionCell[obj]};
GetGlobalRouteForChannel: PROC [handle: SC.Handle, rowChan: SCPrivate.RowChan] ~ {
collect the pins that are to be connected for this channel
InitNet: SCNetUtil.EachNetProc = {net.segsInChan ← NIL};
MakeNetSeg: SCExprRoutePinsUtil.SegProc = {
PROC [segNum: SC.Number, net: SCPrivate.Net];
seg: SegInChan ← NEW[SegInChanRec ← [segNum: segNum, net: net, leftExit: leftExit, rightExit: rightExit, pinsInSeg: pinList]];
net.segsInChan ← CONS[seg, net.segsInChan];
pinList ← NIL; leftExit ← rightExit ← FALSE};
MakeNetPin: SCExprRoutePinsUtil.PinProc = {
PROC [min, max, depth: SC.Number, side: SC.Side, layer: SC.Layer, net: SCPrivate.Net];
pin: Route.Pin ← NEW[Route.PinRec ← [min: min, max: max, depth: depth, layer: layer, side: side]];
pinList ← CONS[pin, pinList]};
MakeNetExit: SCExprRoutePinsUtil.ExitProc = {
PROC [side: SCPrivate.LRSide, layer: SC.Layer, net: SCPrivate.Net];
IF side = left THEN leftExit ← TRUE
ELSE IF side = right THEN rightExit ← TRUE
ELSE SC.Error[programmingError, "Not suppose to happen."]};
pinList: PinsInSeg ← NIL;
leftExit, rightExit: BOOLFALSE;
[] ← SCNetUtil.EnumerateNets[handle, InitNet];
SCExprRoutePinsUtil.GetAllNetSegInChan[handle, rowChan, MakeNetSeg, MakeNetPin, MakeNetExit]};
END.