SCStatsImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Last Edited by: Preas, September 5, 1985 10:39:21 am PDT
Massoud Pedram March 23, 1989 10:29:42 am PST
To print stats from SC placement and routing;
set SCNewRouteImpl.keepStats ← TRUE to gather statistics
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
outer list is of the channels
netStats: LIST OF SC.NetEntry ← stats.first.netStats;
TerminalIO.PutF[format: "\n\tchannel: %g", v1: IO.int[stats.first.channel]];
UNTIL netStats = NIL DO
next inner list is of the nets within this channel
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
inner list is of the pins within the net within this channel
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
inner list is of the pins within the net within this channel
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
outer list is of the channels
netStats: LIST OF SC.NetEntry ← stats.first.netStats;
netStat: NetStat;
minY ← LAST[INT];
maxY ← FIRST[INT];
UNTIL netStats = NIL DO
next inner list is of the nets within this channel
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
inner list is of the pins within the net within this channel
IF ftStats.first.bottom THEN numFTs ← numFTs + 1;
ftStats ← ftStats.rest;
ENDLOOP;
IF numFTs > 1 THEN numFTs ← 1;
UNTIL pinStats = NIL DO
inner list is of the pins within the net within this channel
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 ~ {
PROC [key: Key, netStat: NetStat] RETURNS [quit: BOOLEANFALSE]
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 ~ {
PROC [key: Key, netStat: NetStat] RETURNS [quit: BOOLEANFALSE]
k: NAT ← netStat.numPins;
IF k > maxPinPerNet THEN k ← maxPinPerNet;
nets[k] ← nets[k] + 1;
};
Avg: EachNetStatAction ~ {
PROC [key: Key, netStat: NetStat] RETURNS [quit: BOOLEANFALSE]
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 ~ {
PROC [key: Key, netStat: NetStat] RETURNS [quit: BOOLEANFALSE]
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] ~ {
read as stats file and make a data structure
};
END.