<> <> <<-- InitGetChanWidth - initialize for determining the width of a channel>> <<-- NewWsEntry - get a new wire segment entry and insert pos, return location>> <<-- EnterNet - enter a net on a channel into data base>> <<-- EnterRowDat - enter routing data for one side of one row into data base>> <<-- EnterSideDat - enter routing data for one side of one side into data base>> <<-- EnterExitDat - enter exit data for a channel into routing data base>> <<-- EnterMinDat - minmium route channels need special processing to>> <> <<-- SortPinDat - sort the pin data>> <<-- SortLimitDat - sort the data representing the extremes of each net on each channel>> <<-- GetChanWl - find wirelength for this channel>> <<-- MaxTrackDensity - find maximum track density on a channel>> <<-- GetChanWidth - get width of channel specified>> <<-- EnterCntdDat - enter data for connections between horiz and vert channels>> <<-- GetSideWidth - get width of channel on side>> <<-- AllChanWidths - find widths of all channels>> <<>> DIRECTORY RTBasic, SC, SCChanUtil, SCNetUtil, SCPrivate, SCRowUtil, SCWidthUtil, SCInstUtil; SCWidthUtilImpl: CEDAR PROGRAM IMPORTS SC, SCChanUtil, SCNetUtil, SCInstUtil, SCRowUtil EXPORTS SCWidthUtil SHARES SC = BEGIN <<>> <> InitOrTerm: TYPE = {init, term}; InitGetChanWidth: PROCEDURE [handle: SC.Handle, whatToDo: InitOrTerm] = { EachNet: SCNetUtil.EachNetProc = { net.bounds1 _ net.bounds2 _ NIL; net.minPinDist _ LAST[INT]; net.lastEntry _ NIL}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; layoutData.wireSegPins _ NEW[SCPrivate.WireSegPinsRec]; layoutData.wireSegs _ NEW[SCPrivate.WireSegsRec]; [] _ SCNetUtil.EnumerateNets[handle, EachNet]; IF whatToDo = init THEN { layoutData.wireSegs _ NEW[SCPrivate.WireSegsRec]; layoutData.wireSegPins _ NEW[SCPrivate.WireSegPinsRec]} ELSE { layoutData.wireSegs _ NIL; layoutData.wireSegPins _ NIL}}; <> NewWsEntry: PROCEDURE[handle: SC.Handle, pos: SC.Number, side: SC.Side] RETURNS [wireSeg: SCPrivate.WireSeg] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; wireSegs: SCPrivate.WireSegs _ layoutData.wireSegs; wireSegs.nWireSegsOnCh _ wireSegs.nWireSegsOnCh + 1; wireSeg _ NEW[SCPrivate.WireSegRec _ [pos, side]]; wireSegs.segs[wireSegs.nWireSegsOnCh] _ wireSeg}; <> EnterNet: PROCEDURE[handle: SC.Handle, net: SCPrivate.Net, pos: SC.Number, side: RTBasic.Side, minMaxRoute: SCPrivate.RouteType] = { <> SELECT minMaxRoute FROM maxRoute => { IF net.bounds1 = NIL THEN {net.bounds1 _ NewWsEntry[handle, pos, left]; net.bounds2 _ NewWsEntry[handle, pos, right]} ELSE {net.bounds1.pos _ MIN[net.bounds1.pos, pos]; net.bounds2.pos _ MAX[net.bounds2.pos, pos]}}; minRoute => { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; wireSegPins: SCPrivate.WireSegPins _ layoutData.wireSegPins; wireSegPin: SCPrivate.WireSegPin _ NEW[SCPrivate.WireSegPinRec _ [pos, net, side]]; wireSegPins.nPinsOnCh _ wireSegPins.nPinsOnCh +1; wireSegPins.pins[wireSegPins.nPinsOnCh] _ wireSegPin}; ENDCASE}; <> EnterRowDat: PROCEDURE[handle: SC.Handle, row: SCPrivate.MaxRowSr, side, intrestingSide: SC.Side, minMaxRoute: SCPrivate.RouteType] = { InstProc: SCRowUtil.EachInstProc = { PinProc: SCInstUtil.EachPinProc = { IF netPin.pin # NIL AND netPin.net # NIL THEN { pd: SCInstUtil.PinDescription _ SCInstUtil.PosOf[instance, netPin.pin]; IF pd.sideOn = intrestingSide THEN { net: SCPrivate.Net _ netPin.net; IF net # NIL THEN EnterNet[handle, net, instance.offset + lgRow.rowOrg.p + pd.xPos, intrestingSide, minMaxRoute]}}}; [ ] _ SCInstUtil.EnumeratePinsOnInst[instance, PinProc]}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRow: SCPrivate.LgRow _ layoutData.lgRows.rows[row]; [ ] _ SCRowUtil.EnumerateAllInstsOnRow[handle, row, InstProc]}; <> EnterSideDat: PROCEDURE[handle: SC.Handle, side, intrestingSide, chanSide: SC.Side, minMaxRoute: SCPrivate.RouteType] = { InstProc: SCRowUtil.EachInstProc = { PinProc: SCInstUtil.EachPinProc = { IF netPin.pin # NIL THEN { pd: SCInstUtil.PinDescription _ SCInstUtil.PosOf[instance, netPin.pin]; IF pd.sideOn = intrestingSide AND netPin.net # NIL THEN { net: SCPrivate.Net _ netPin.net; IF net # NIL THEN { xyPos: SC.Number; SELECT side FROM bottom => xyPos _ bpRow.sideOrg.p + instance.offset + pd.xPos; right => xyPos _ bpRow.sideOrg.q + instance.offset + pd.yPos; top => xyPos _ bpRow.sideOrg.p - instance.offset + pd.xPos; left => xyPos _ bpRow.sideOrg.q - instance.offset + pd.yPos; ENDCASE; EnterNet[handle, net, xyPos, chanSide, minMaxRoute]}}}}; [ ] _ SCInstUtil.EnumeratePinsOnInst[instance, PinProc]}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; bpRow: SCPrivate.BpRow _ layoutData.bpRows[side]; [ ] _ SCRowUtil.EnumerateAllInstsOnSide[handle, side, InstProc]}; <> EnterExitDat: PROCEDURE[handle: SC.Handle, rowChan: SCPrivate.RowChan, lrSide: SCPrivate.LRSide, side: SC.Side, minMaxRoute: SCPrivate.RouteType] = { ExitProc: SCChanUtil.EachExitProc = { EnterNet[handle, exit.net, sideChan.sideChanPos + MAX[sideChan.sideChanWidth, sideChan.minSideChanWidth]/2, side, minMaxRoute]}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; sideChan: SCPrivate.SideChan _ layoutData.sideChans[lrSide]; [] _ SCChanUtil.EnumerateExits[handle, rowChan, lrSide, ExitProc]}; <> <> EnterMinDat: PROCEDURE [handle: SC.Handle] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; wireSegPins: SCPrivate.WireSegPins _ layoutData.wireSegPins; FOR index: SCPrivate.ZMaxPinsOnChSr IN [1 .. wireSegPins.nPinsOnCh] DO entry: SCPrivate.WireSegPin _ wireSegPins.pins[index]; net: SCPrivate.Net _ entry.net; last: SCPrivate.WireSegPin _ net.lastEntry; <> IF last # NIL THEN { <> IF last.side = left OR entry.side = right THEN { [] _ NewWsEntry[handle, last.pos, last.side]; [] _ NewWsEntry[handle, entry.pos, entry.side]} ELSE IF entry.side # last.side THEN { <> thisDist: SC.Number _ ABS[entry.pos - last.pos]; IF thisDist < net.minPinDist THEN { net.minPinDist _ thisDist; IF net.bounds1 = NIL THEN { net.bounds1 _ NewWsEntry[handle, last.pos, last.side]; net.bounds2 _ NewWsEntry[handle, entry.pos, entry.side]} ELSE { net.bounds1.pos _ last.pos; net.bounds2.pos _ entry.pos}}}}; net.lastEntry _ entry; ENDLOOP}; <> <> SortPinDat: PROCEDURE [handle: SC.Handle] = BEGIN layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; wireSegPins: SCPrivate.WireSegPins _ layoutData.wireSegPins; gap: SCPrivate.ZMaxPinsOnChSr _ wireSegPins.nPinsOnCh /2; WHILE gap >0 DO FOR I: SCPrivate.ZMaxPinsOnChSr IN [gap+1 .. wireSegPins.nPinsOnCh] DO J: INTEGER _ I - gap; WHILE J > 0 DO Jg: SCPrivate.MaxPinsOnChSr _ J + gap; <> jgPtr: SCPrivate.WireSegPin _ wireSegPins.pins[Jg]; jPtr: SCPrivate.WireSegPin _ wireSegPins.pins[J]; IF jgPtr.pos < jPtr.pos THEN { wireSegPins.pins[Jg] _ jPtr; wireSegPins.pins[J] _ jgPtr}; J _ J -gap; ENDLOOP ; ENDLOOP; gap _ gap /2; ENDLOOP ; END; <> <> SortLimitDat: PROCEDURE [handle: SC.Handle] = BEGIN layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; wireSegs: SCPrivate.WireSegs _ layoutData.wireSegs; gap: SCPrivate.ZMaxWireSegsSr _ wireSegs.nWireSegsOnCh /2; WHILE gap > 0 DO FOR I: SCPrivate.ZMaxWireSegsSr IN [ gap+1 .. wireSegs.nWireSegsOnCh ] DO J: INTEGER _ I - gap; WHILE J > 0 DO Jg: SCPrivate.MaxWireSegsSr _ J +gap; <> jgPtr: SCPrivate.WireSeg _ wireSegs.segs[Jg]; jPtr: SCPrivate.WireSeg _ wireSegs.segs[J]; IF jgPtr.pos < jPtr.pos THEN { wireSegs.segs[Jg] _ jPtr; wireSegs.segs[J] _ jgPtr} ELSE IF jgPtr.pos <= jPtr.pos THEN { <> IF jgPtr.endType = left AND jPtr.endType = right THEN { wireSegs.segs[Jg] _ jPtr; wireSegs.segs[J] _ jgPtr}}; J _ J - gap; ENDLOOP ; ENDLOOP; gap _ gap /2; ENDLOOP ; END; <> GetChanWl: PUBLIC PROCEDURE [handle: SC.Handle] RETURNS [wireLength: SC.Number _ 0] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; wireSegs: SCPrivate.WireSegs _ layoutData.wireSegs; FOR index: SCPrivate.ZMaxWireSegsSr IN [1 .. wireSegs.nWireSegsOnCh] DO wireSeg: SCPrivate.WireSeg _ wireSegs.segs[index]; IF wireSeg.endType = left THEN wireLength _ wireLength - wireSeg.pos ELSE IF wireSeg.endType = right THEN wireLength _ wireLength + wireSeg.pos; ENDLOOP}; <> MaxTrackDensity: PROCEDURE[handle: SC.Handle] RETURNS [maxTracks: NAT _ 0] = { nTracks: NAT _ 0; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; wireSegs: SCPrivate.WireSegs _ layoutData.wireSegs; FOR index: SCPrivate.ZMaxWireSegsSr IN [1 .. wireSegs.nWireSegsOnCh] DO wireSeg: SCPrivate.WireSeg _ wireSegs.segs[index]; SELECT wireSeg.endType FROM left => { nTracks _ nTracks +1; maxTracks _ MAX[maxTracks, nTracks]}; right => { nTracks _ nTracks -1; IF nTracks < 0 THEN SC.Error[programmingError, "Invalid wires in channel"]}; ENDCASE; ENDLOOP}; GetChanWidth: PUBLIC PROCEDURE[handle: SC.Handle, rowChan: SCPrivate.RowChan, fom: SCPrivate.FomType, doWidth: BOOLEAN] RETURNS [chanWidth, wireLength: SC.Number _ 0] = { IF doWidth THEN { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; rowChans: SCPrivate.RowChans _ layoutData.rowChans; pitch: SC.Number _ handle.rules.rowRules.trunkToTrunk; minMaxRoute: SCPrivate.RouteType _ IF fom = wlFom THEN maxRoute ELSE rowChan.routeType; InitGetChanWidth[handle, init]; <> IF fom = wlFom THEN minMaxRoute _ maxRoute ELSE minMaxRoute _ rowChan.routeType; <> IF rowChan.chanNum = 1 THEN { EnterSideDat[handle, bottom, top, bottom, minMaxRoute]; EnterRowDat[handle, 1, bottom, top, minMaxRoute]} ELSE IF rowChan.chanNum = rowChans.count THEN { EnterRowDat[handle, lgRows.count, top, bottom, minMaxRoute]; EnterSideDat[handle, top, bottom, top, minMaxRoute]} ELSE { EnterRowDat[handle, rowChan.chanNum-1, top, bottom, minMaxRoute]; EnterRowDat[handle, rowChan.chanNum, bottom, top, minMaxRoute]}; EnterExitDat[handle, rowChan, left, left, minMaxRoute]; EnterExitDat[handle, rowChan, right, right, minMaxRoute]; <> wireLength _ GetChanWl[handle]; IF fom = wlFom THEN chanWidth _ wireLength * pitch * horzWireToAreaFact / lgRows.maxRowWidth ELSE { <> IF minMaxRoute = minRoute THEN { SortPinDat[handle]; EnterMinDat[handle]}; <> SortLimitDat[handle]; chanWidth _ MAX[1, MaxTrackDensity[handle]] * pitch}; InitGetChanWidth[handle, term]; }}; <> EnterCntdDat: PROCEDURE [handle: SC.Handle, lrSide: SCPrivate.LRSide, side, chanSide: SC.Side] = { ChansProc: SCChanUtil.EachRowChanProc = { ExitsProc: SCChanUtil.EachExitProc = { EnterNet[handle, exit.net, rowChan.chanPos + MAX[rowChan.chanWidth, rowChan.minChanWidth]/2, chanSide, maxRoute]}; [] _ SCChanUtil.EnumerateExits[handle, rowChan, lrSide, ExitsProc]}; [] _ SCChanUtil.EnumerateRowChans[handle, ChansProc]}; <> GetSideWidth: PUBLIC PROCEDURE[handle: SC.Handle, lRSide: SCPrivate.LRSide, fom: SCPrivate.FomType] RETURNS [chanWidth, wireLength: SC.Number] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; acBuses: SCPrivate.AcBuses _ layoutData.acBuses; powerBuses: SCPrivate.PowerBuses _ layoutData.powerBuses; rules: SC.DesignRules _ NARROW[handle.rules]; pitch: SC.Number _ rules.sideRules.trunkToTrunk; chanWidth _ acBuses[lRSide].width + powerBuses[lRSide].width; InitGetChanWidth[handle, init]; SELECT lRSide FROM right => { EnterSideDat[handle, right, left, bottom, maxRoute]; EnterCntdDat[handle, right, right, top]}; left => { EnterSideDat[handle, left, right, top, maxRoute]; EnterCntdDat[handle, left, left, bottom]}; ENDCASE; <> wireLength _ GetChanWl[handle]; IF fom = wlFom THEN { chanWidth _ chanWidth + wireLength*pitch*vertWireToAreaFact/layoutData.totHeight} ELSE { SortLimitDat[handle]; chanWidth _ chanWidth + MAX[1, MaxTrackDensity[handle]]*pitch}; InitGetChanWidth[handle, term]}; <> AllChanWidths: PUBLIC PROCEDURE[handle: SC.Handle, fom: SCPrivate.FomType] = BEGIN layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; SideChan: SCChanUtil.EachSideChanProc = { [sideChan.sideChanWidth, sideChan.wireLength] _ GetSideWidth[handle, lrSide, fom]}; RowChan: SCChanUtil.EachRowChanProc = { [rowChan.chanWidth, rowChan.wireLength] _ GetChanWidth[handle, rowChan, fom, TRUE]}; [] _ SCChanUtil.EnumerateSideChans[handle, SideChan]; [] _ SCChanUtil.EnumerateRowChans[handle, RowChan]; END; vertWireToAreaFact: SC.Number _ 3; horzWireToAreaFact: SC.Number _ 3; END.