<> <> <> <> <<>> <> <> <<>> DIRECTORY IO, Rope, SC, SCStats, TerminalIO, SCPrivate, RefTab, RefTabExtras, CDSimpleRules, Real; SCStatsImpl: CEDAR PROGRAM IMPORTS SC, IO, TerminalIO, RefTab, RefTabExtras, CDSimpleRules, Real EXPORTS SCStats SHARES SC = BEGIN OPEN SCStats; CreateForRopes: PUBLIC PROC [mod: NAT _ 17] RETURNS [Table] ~ { RETURN[RefTab.Create[mod, RefTabExtras.EqualRope, RefTabExtras.HashRope]]}; Fetch: PUBLIC PROC [table: Table, key: Key] RETURNS [found: BOOL, netStat: NetStat] ~ { <<>> value: REF; [found, value] _ RefTab.Fetch[table, key]; netStat _ NARROW[value]}; Store: PUBLIC PROC [table: Table, key: Key, netStat: NetStat] RETURNS [BOOL] ~ { RETURN[RefTab.Store[table, key, netStat]]}; EnumerateNetStats: PUBLIC PROC [table: Table, action: EachNetStatAction] RETURNS [BOOL] ~ { eachPair: RefTab.EachPairAction ~ {quit _ action[key, NARROW [val]]}; RETURN [RefTab.Pairs[table, eachPair]]}; WriteSummaryStats: PUBLIC PROC [result: SC.Result] ~ { handle: SC.Handle _ result.handle; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; rowChans: SCPrivate.RowChans _ layoutData.rowChans; lgRows: SCPrivate.LgRows _ layoutData.lgRows; TerminalIO.PutRope[text: "\n Routing Summary Statistics"]; FOR chanNum: NAT IN [1 .. rowChans.count] DO chan: SCPrivate.RowChan _ rowChans.chans[chanNum]; TerminalIO.PutF[format: "\n\tchannel: %g", v1: IO.int[chanNum]]; TerminalIO.PutF[format: "\n\t\tnumTracks: %g", v1: IO.int[chan.chanWidth/handle.rules.rowRules.trunkToTrunk]]; ENDLOOP; FOR rowNum: NAT IN [1 .. lgRows.count] DO row: SCPrivate.LgRow _ lgRows.rows[rowNum]; TerminalIO.PutF[format: "\n\trow: %g", v1: IO.int[rowNum]]; TerminalIO.PutF[format: "\n\t\tCellsOnRow: %g", v1: IO.int[row.nLgsOnRow - row.nFtsOnRow]]; TerminalIO.PutF[format: "\n\t\tFtsOnRow: %g", v1: IO.int[row.nFtsOnRow]]; ENDLOOP; TerminalIO.PutRope[text: "\n End Routing Summary Statistics\n"]; }; WriteDetailStats: PUBLIC PROC [result: SC.Result] ~ { stats: LIST OF SC.ChannelStats _ result.stats; TerminalIO.PutRope[text: "\n Routing Statistics"]; UNTIL stats = NIL DO <> netStats: LIST OF SC.NetEntry _ stats.first.netStats; TerminalIO.PutF[format: "\n\tchannel: %g", v1: IO.int[stats.first.channel]]; UNTIL netStats = NIL DO <> pinStats: LIST OF SC.PinEntry _ netStats.first.pinStats; ftStats: LIST OF SC.PinEntry _ netStats.first.ftStats; TerminalIO.PutF[format: "\n\t\tname: %g, leftExit: %g, rightExit: %g", v1: IO.rope[netStats.first.name], v2: IO.bool[netStats.first.leftExit], v3: IO.bool[netStats.first.rightExit]]; UNTIL ftStats = NIL DO <> TerminalIO.PutF[format: "\n\t\t\tfeedThroughBottom: %g, position: %g", v1: IO.bool[ftStats.first.bottom], v2: IO.int[ftStats.first.position]]; ftStats _ ftStats.rest; ENDLOOP; UNTIL pinStats = NIL DO <> TerminalIO.PutF[format: "\n\t\t\tbottom: %g, position: %g", v1: IO.bool[pinStats.first.bottom], v2: IO.int[pinStats.first.position]]; pinStats _ pinStats.rest; ENDLOOP; netStats _ netStats.rest; ENDLOOP; stats _ stats.rest; ENDLOOP; TerminalIO.PutRope[text: "\n End Routing Statistics\n"]; }; CreateNetStats: PUBLIC PROC [result: SC.Result] RETURNS [table: Table] ~ { EachNet: RefTab.EachPairAction ~ { net: SCPrivate.Net _ NARROW [val]; netPin: SCPrivate.NetPin _ net.pins; numPins: NAT _ 0; netStat: NetStat; WHILE netPin#NIL DO next: SCPrivate.NetPin = netPin.link; numPins _ IF netPin.pinClass = compPin AND netPin.pin.pinPos.side = top THEN numPins + 1 ELSE numPins; netPin _ next; ENDLOOP; IF net.externNet THEN numPins _ numPins + 1; netStat _ Fetch[table, net.name].netStat; IF netStat#NIL THEN { netStat.numPins _ numPins; [] _ Store[table, net.name, netStat]}; }; technologyKey: ATOM = $cmosB; lambda: INT _ CDSimpleRules.GetTechnology[technologyKey].lambda; stats: LIST OF SC.ChannelStats _ result.stats; minX, maxX: INT; minY, maxY: INT; trackLength: INT; structureData: SCPrivate.StructureData _ NARROW[result.handle.structureData]; layoutData: SCPrivate.LayoutData _ NARROW[result.handle.layoutData]; totWidth: INT _ layoutData.totWidth / lambda; table _ CreateForRopes[]; TerminalIO.PutRope[text: "\n Routing Statistics"]; UNTIL stats = NIL DO <> netStats: LIST OF SC.NetEntry _ stats.first.netStats; netStat: NetStat; minY _ LAST[INT]; maxY _ FIRST[INT]; UNTIL netStats = NIL DO <> pinStats: LIST OF SC.PinEntry _ netStats.first.pinStats; ftStats: LIST OF SC.PinEntry _ netStats.first.ftStats; numFTs: INT _ 0; minX _ LAST[INT]; maxX _ FIRST[INT]; IF netStats.first.leftExit THEN minX _ 0; IF netStats.first.rightExit THEN maxX _ totWidth; UNTIL ftStats = NIL DO <> IF ftStats.first.bottom THEN numFTs _ numFTs + 1; ftStats _ ftStats.rest; ENDLOOP; IF numFTs > 1 THEN numFTs _ 1; UNTIL pinStats = NIL DO <> IF pinStats.first.position / lambda < minX THEN minX _ pinStats.first.position / lambda; IF pinStats.first.position / lambda > maxX THEN maxX _ pinStats.first.position / lambda; pinStats _ pinStats.rest; ENDLOOP; IF stats.first.channel < minY THEN minY _ stats.first.channel; IF stats.first.channel > maxY THEN maxY _ stats.first.channel; netStat _ Fetch[table, netStats.first.name].netStat; trackLength _ maxX - minX; IF netStat=NIL THEN { netStat _ NEW [NetStatRec _ [name: netStats.first.name, xSpan: [minX, maxX], ySpan: [minY, maxY], trackLength: trackLength, ftHeight: numFTs]]} ELSE { IF netStat.xSpan.min > minX THEN netStat.xSpan.min _ minX; IF netStat.xSpan.max < maxX THEN netStat.xSpan.max _ maxX; IF netStat.ySpan.min > minY THEN netStat.ySpan.min _ minY; IF netStat.ySpan.max < maxY THEN netStat.ySpan.max _ maxY; netStat.ftHeight _ netStat.ftHeight + numFTs; netStat.trackLength _ netStat.trackLength + maxX - minX}; IF netStat.trackLength < 0 THEN netStat.trackLength _ 0; [] _ Store[table, netStats.first.name, netStat]; netStats _ netStats.rest; ENDLOOP; stats _ stats.rest; ENDLOOP; [] _ RefTab.Pairs[structureData.nets, EachNet]; TerminalIO.PutRope[text: "\n End Routing Statistics\n"]; }; WriteDetailNetStats: PUBLIC PROC [table: Table] ~ { EachNetStat: EachNetStatAction ~ { <> TerminalIO.PutF[format: "\n\t\tname: %g, \tnumPins: %g", v1: IO.rope[netStat.name], v2: IO.int[netStat.numPins]]; TerminalIO.PutF[format: "\n\t\t\txSpan: %g, %g, \t\tySpan: %g, %g", v1: IO.int[netStat.xSpan.min], v2: IO.int[netStat.xSpan.max], v3: IO.int[netStat.ySpan.min], v4: IO.int[netStat.ySpan.max]]; TerminalIO.PutF[format: "\n\t\t\ttrackLength: %g, \tftHeight: %g \n", v1: IO.int[netStat.trackLength], v2: IO.int[netStat.ftHeight]]}; [] _ EnumerateNetStats[table, EachNetStat]}; WriteSummaryNetStats: PUBLIC PROC [result: SC.Result, table: Table] ~ { NumNets: EachNetStatAction ~ { <> k: NAT _ netStat.numPins; IF k > maxPinPerNet THEN k _ maxPinPerNet; nets[k] _ nets[k] + 1; }; Avg: EachNetStatAction ~ { <> k: NAT _ netStat.numPins; IF k > maxPinPerNet THEN k _ maxPinPerNet; IF netStat.xSpan.max < netStat.xSpan.min THEN SC.Signal[callingError, "netStat.xSpan is calculated wrong."]; IF netStat.ySpan.max < netStat.ySpan.min THEN SC.Signal[callingError, "netStat.ySpan is calculated wrong."]; IF netStat.trackLength < 0 THEN netStat.trackLength _ 0; IF netStat.ftHeight < 0 THEN netStat.trackLength _ 0; IF nets[k] # 0 THEN { fracL[k] _ fracL[k] + Real.Float[netStat.trackLength] / nets[k]; fracH[k] _ fracH[k] + Real.Float[netStat.ftHeight] / nets[k]; spanX[k] _ spanX[k] + Real.Float[(netStat.xSpan.max - netStat.xSpan.min)] / nets[k]; spanY[k] _ spanY[k] + Real.Float[(netStat.ySpan.max - netStat.ySpan.min + 1)] / nets[k]; }; }; Var: EachNetStatAction ~ { <> k: NAT _ netStat.numPins; IF k > maxPinPerNet THEN k _ maxPinPerNet; IF nets[k] # 0 THEN { varL[k] _ varL[k] + (netStat.trackLength - fracL[k]) * (netStat.trackLength - fracL[k]) / nets[k]; varH[k] _ varH[k] + (netStat.ftHeight - fracH[k]) * (netStat.ftHeight - fracH[k]) / nets[k]; varX[k] _ varX[k] + (netStat.xSpan.max - netStat.xSpan.min - spanX[k]) * (netStat.xSpan.max - netStat.xSpan.min - spanX[k]) / nets[k]; varY[k] _ varY[k] + (netStat.ySpan.max - netStat.ySpan.min + 1 - spanY[k]) * (netStat.ySpan.max - netStat.ySpan.min + 1 - spanY[k]) / nets[k]}; }; maxPinPerNet: NAT _ 25; nets: RowN _ NIL; fracL, fracH, varL, varH, sigmaL, sigmaH: RowR _ NIL; spanX, spanY, varX, varY, sigmaX, sigmaY: RowR _ NIL; technologyKey: ATOM = $cmosB; lambda: INT _ CDSimpleRules.GetTechnology[technologyKey].lambda; layoutData: SCPrivate.LayoutData _ NARROW[result.handle.layoutData]; totWidth: INT _ layoutData.totWidth / lambda; nets _ NEW[VecSeqN[maxPinPerNet+1]]; fracL _ NEW[VecSeqR[maxPinPerNet+1]]; fracH _ NEW[VecSeqR[maxPinPerNet+1]]; varL _ NEW[VecSeqR[maxPinPerNet+1]]; varH _ NEW[VecSeqR[maxPinPerNet+1]]; sigmaL _ NEW[VecSeqR[maxPinPerNet+1]]; sigmaH _ NEW[VecSeqR[maxPinPerNet+1]]; spanX _ NEW[VecSeqR[maxPinPerNet+1]]; spanY _ NEW[VecSeqR[maxPinPerNet+1]]; varX _ NEW[VecSeqR[maxPinPerNet+1]]; varY _ NEW[VecSeqR[maxPinPerNet+1]]; sigmaX _ NEW[VecSeqR[maxPinPerNet+1]]; sigmaY _ NEW[VecSeqR[maxPinPerNet+1]]; FOR i: INT IN [0..maxPinPerNet] DO nets[i] _ 0; fracL[i] _ 0; fracH[i] _ 0; varL[i] _ 0; varH[i] _ 0; sigmaL[i] _ 0; sigmaH[i] _ 0; spanX[i] _ 0; spanY[i] _ 0; varX[i] _ 0; varY[i] _ 0; sigmaX[i] _ 0; sigmaY[i] _ 0; ENDLOOP; [] _ EnumerateNetStats[table, NumNets]; [] _ EnumerateNetStats[table, Avg]; [] _ EnumerateNetStats[table, Var]; FOR i: NAT IN [0..maxPinPerNet] DO fracL[i] _ fracL[i] / totWidth; varL[i] _ varL[i] / totWidth / totWidth; sigmaL[i] _ Real.SqRt[varL[i]]; sigmaH[i] _ Real.SqRt[varH[i]]; spanX[i] _ spanX[i] / totWidth; varX[i] _ varX[i] / totWidth / totWidth; sigmaX[i] _ Real.SqRt[varX[i]]; sigmaY[i] _ Real.SqRt[varY[i]]; ENDLOOP; FOR i: NAT IN [0..maxPinPerNet] DO IF nets[i] # 0 THEN { TerminalIO.PutF[format: "\n\t\tnumPins: %g, \tnumNets: %g", v1: IO.int[i], v2: IO.int[nets[i]]]; TerminalIO.PutF[format: "\n\t\t\tfracL: %g, \tfracH: %g", v1: IO.real[fracL[i]], v2: IO.real[fracH[i]]]; TerminalIO.PutF[format: "\n\t\t\tsigmaL: %g, \tsigmaH: %g", v1: IO.real[sigmaL[i]], v2: IO.real[sigmaH[i]]]; TerminalIO.PutF[format: "\n\t\t\tspanX: %g, \tspanY: %g", v1: IO.real[spanX[i]], v2: IO.real[spanY[i]]]; TerminalIO.PutF[format: "\n\t\t\tsigmaX: %g, \tsigmaY: %g", v1: IO.real[sigmaX[i]], v2: IO.real[sigmaY[i]]];}; ENDLOOP; }; ReadStats: PUBLIC PROC [fileName: Rope.ROPE] RETURNS [stats: LIST OF SC.ChannelStats] ~ { <> }; END.