-- File: HistCommands.mesa last edited by
-- Sandman on September 4, 1980 10:15 AM
-- Karlton on Jun 23, 1980 3:17 PM
DIRECTORY
Inline USING [BITSHIFT, COPY, LongNumber],
MsgSW USING [Post],
PerfCommonOps USING [logSW, msgSW, Number, WriteLongNumber],
PerfOps USING [
GetBase, GetBuckets, GetHistBase, GetHistLeg, GetHistNode, GetLegTable,
GetNodeTable, GetPCR, GetScale, histClass, histType, PutMessage],
PerfPrivate USING [
HistBase, HistIndex, Histogram, HistType, LegTab, MaxLegs, MaxNodes, NodeTab,
NullHist, NullNode, Number, PCR],
Put USING [CR, Decimal, Line, Number, Text],
String USING [AppendChar, AppendDecimal],
UserInput USING [ResetUserAbort, userAbort],
Window USING [Handle];
HistCommands: PROGRAM
IMPORTS Inline, PerfOps, UserInput, String, Put, MsgSW, PerfCommonOps
EXPORTS PerfOps =PUBLIC
BEGIN OPEN PerfCommonOps, PerfOps, PerfPrivate;
handle: Window.Handle ← PerfCommonOps.logSW;
AddHistogram: PUBLIC PROCEDURE =
BEGIN
hIndex: HistIndex;
hist: POINTER TO Histogram;
index: CARDINAL;
size, scale, limit: CARDINAL;
type: HistType ← PerfOps.histType;
histBase: HistBase;
nodeTab: POINTER TO NodeTab ← GetNodeTable[read];
legTab: POINTER TO LegTab ← GetLegTable[read];
pCR: PCR ← GetPCR[read];
SELECT type FROM
node =>
BEGIN
index ← GetHistNode[];
IF index ~IN [0..pCR.nextNode) THEN GOTO invalidNode;
IF (hIndex ← nodeTab[index].hist) # NullHist THEN
BEGIN PutHistError[alreadyOne]; DeleteHist[hIndex]; END;
END;
leg =>
BEGIN
index ← GetHistLeg[];
IF index ~IN [0..pCR.nextLeg) THEN GOTO invalidLeg;
IF (hIndex ← legTab[index].hist) # NullHist THEN
BEGIN PutHistError[alreadyOne]; DeleteHist[hIndex]; END;
END;
ENDCASE => ERROR;
limit ← FindAvailableSpace[pCR.histFree];
IF histClass = log THEN
limit ← IF type = node THEN MIN[16, limit] ELSE MIN[32, limit];
size ← CheckBuckets[limit ! Confused => GOTO return];
scale ← CheckScale[type ! Confused => GOTO return];
hIndex ← GrabHistogramSlot[size];
Put.Text[handle, "Added Histogram for "L];
IF histType = node THEN
BEGIN
[] ← GetNodeTable[write];
nodeTab[index].hist ← hIndex;
Put.Text[handle, "Node "L];
END
ELSE
BEGIN
[] ← GetLegTable[write];
legTab[index].hist ← hIndex;
Put.Text[handle, "Leg "L];
END;
Put.Decimal[handle, index];
Put.CR[handle];
histBase ← GetHistBase[write];
hist ← @histBase[hIndex];
Zero[hist, SIZE[Histogram] + size];
hist.scale ← scale;
hist.type ← type;
hist.class ← histClass;
hist.nBuckets ← size;
hist.base ← GetBase[];
EXITS
return => NULL;
invalidNode => PutHistError[invalidNode];
invalidLeg => PutHistError[invalidLeg];
END;
Zero: PROC [p: POINTER, l: CARDINAL] = {
IF l # 0 THEN {p↑ ← 0; Inline.COPY[from: p, to: p + 1, nwords: l - 1]}};
ValidateIndex: PROCEDURE [type: HistType, index: CARDINAL, pCR: PCR]
RETURNS [hIndex: HistIndex] =
BEGIN
SELECT type FROM
node =>
BEGIN
nodeTab: POINTER TO NodeTab ← GetNodeTable[read];
IF index ~IN [0..pCR.nextNode) THEN SIGNAL Invalid;
IF (hIndex ← nodeTab[index].hist) = NullHist THEN SIGNAL Confused;
END;
leg =>
BEGIN
legTab: POINTER TO LegTab ← GetLegTable[read];
IF index ~IN [0..pCR.nextLeg) THEN SIGNAL Invalid;
IF (hIndex ← legTab[index].hist) = NullHist THEN SIGNAL Confused;
END;
ENDCASE;
RETURN
END;
Confused: SIGNAL = CODE;
Invalid: SIGNAL = CODE;
DeleteHistogram: PROCEDURE =
BEGIN
hIndex: HistIndex;
type: HistType ← histType;
index: CARDINAL;
nodeTab: POINTER TO NodeTab ← GetNodeTable[read];
legTab: POINTER TO LegTab ← GetLegTable[read];
pCR: PCR ← GetPCR[read];
index ← IF type = node THEN GetHistNode[] ELSE GetHistLeg[];
hIndex ← ValidateIndex[
type, index, pCR !
Invalid => IF type = node THEN GOTO invalidNode ELSE GOTO invalidLeg;
Confused => GOTO return];
Put.Text[handle, "Deleted Histogram for "L];
SELECT type FROM
node =>
BEGIN
[] ← GetNodeTable[write];
DeleteHist[hIndex];
nodeTab[index].hist ← NullHist;
Put.Text[handle, "Node "L];
END;
leg =>
BEGIN
[] ← GetLegTable[write];
DeleteHist[hIndex];
legTab[index].hist ← NullHist;
Put.Text[handle, "Leg "L];
END;
ENDCASE;
Put.Decimal[handle, index];
Put.CR[handle];
EXITS
invalidNode => PutHistError[invalidNode];
invalidLeg => PutHistError[invalidLeg];
return => PutHistError[none];
END;
DeleteHist: PROCEDURE [hIndex: HistIndex] =
BEGIN
histBase: HistBase ← GetHistBase[read];
nodeTab: POINTER TO NodeTab ← GetNodeTable[read];
legTab: POINTER TO LegTab ← GetLegTable[read];
pCR: PCR ← GetPCR[write];
count, i: CARDINAL;
from, to: HistIndex;
to ← hIndex;
from ← hIndex + SIZE[Histogram] + histBase[hIndex].nBuckets;
UNTIL from = pCR.histFree DO
FOR i IN [0..MaxNodes) DO
IF nodeTab[i].hist = from THEN
BEGIN [] ← GetNodeTable[write]; nodeTab[i].hist ← to END;
ENDLOOP;
FOR i IN [0..MaxLegs) DO
IF legTab[i].hist = from THEN
BEGIN [] ← GetLegTable[write]; legTab[i].hist ← to END;
ENDLOOP;
[] ← GetHistBase[write];
count ← SIZE[Histogram] + histBase[from].nBuckets;
Inline.COPY[from: @histBase[from], to: @histBase[to], nwords: count];
from ← from + count;
to ← to + SIZE[Histogram] + histBase[to].nBuckets;
ENDLOOP;
pCR.histFree ← to;
END;
PrintHistogram: PROCEDURE =
BEGIN
type: HistType ← PerfOps.histType;
hIndex: HistIndex;
index: CARDINAL ← IF type = node THEN GetHistNode[] ELSE GetHistLeg[];
nodeTab: POINTER TO NodeTab ← GetNodeTable[read];
legTab: POINTER TO LegTab ← GetLegTable[read];
pCR: PCR ← GetPCR[read];
Put.CR[handle];
hIndex ← ValidateIndex[
type, index, pCR !
Invalid => IF type = node THEN GOTO invalidNode ELSE GOTO invalidLeg;
Confused => GOTO return];
ListHist[hIndex, index, type];
EXITS
invalidNode => PutHistError[invalidNode];
invalidLeg => PutHistError[invalidLeg];
return => PutHistError[none];
END;
ListHist: PROCEDURE [hIndex: HistIndex, index: CARDINAL, type: HistType] =
BEGIN
i: CARDINAL;
histBase: HistBase ← GetHistBase[read];
hist: POINTER TO Histogram ← @histBase[hIndex];
Put.CR[handle];
Put.Text[handle, "Histogram for "L];
Put.Text[handle, IF type = node THEN "Node "L ELSE "Leg "L];
Put.Decimal[handle, index];
Put.CR[handle];
Put.Text[handle, "Number of References "L];
WriteLongNumber[hist.count, 15];
Put.CR[handle];
Put.Text[handle, "Sum of Values "L];
WriteLongNumber[hist.sum, 15];
Put.CR[handle];
Put.Text[handle, "Average Value "L];
WriteLongNumber[IF hist.count = 0 THEN 0 ELSE hist.sum/hist.count, 15];
Put.CR[handle];
Put.Text[handle, "Scale Factor"L];
Put.Text[handle, IF type = leg THEN " (2↑n)"L ELSE " "L];
Put.Text[handle, " "L];
WriteLongNumber[hist.scale, 15];
Put.CR[handle];
IF hist.class = linear THEN
BEGIN
Put.Text[handle, "Base "L];
WriteLongNumber[hist.base, 15];
Put.CR[handle];
END;
Put.Line[handle, " Value Count"L];
Put.Line[handle, " -------------- -------"L];
IF hist.class = linear AND hist.base # 0 THEN
BEGIN
Put.Text[handle, " Underflow"L];
WriteLongNumber[hist.underflow, 8];
Put.CR[handle];
END;
FOR i IN [0..hist.nBuckets) DO
IF UserInput.userAbort THEN
BEGIN PutMessage[aborted]; UserInput.ResetUserAbort[]; RETURN END;
WriteLongNumber[ScaleBucket[i, hist], 15];
WriteLongNumber[hist.buckets[i], 8];
Put.CR[handle];
ENDLOOP;
Put.Text[handle, " Overflow"L];
WriteLongNumber[hist.overflow, 8];
Put.CR[handle];
END;
ScaleBucket: PROCEDURE [bucket: CARDINAL, hist: POINTER TO Histogram]
RETURNS [val: Number] =
BEGIN
SELECT hist.type FROM
node =>
SELECT hist.class FROM
linear => val ← LONG[bucket]*hist.scale;
ENDCASE => val ← TimesTwoToN[hist.scale, bucket];
leg =>
SELECT hist.class FROM
linear => val ← TimesTwoToN[bucket, hist.scale];
ENDCASE => val ← TimesTwoToN[1, bucket*(hist.scale + 1)];
ENDCASE;
IF hist.class = linear THEN val ← val + hist.base;
END;
TimesTwoToN: PROCEDURE [z: Number, n: CARDINAL] RETURNS [Number] =
BEGIN OPEN Inline;
y, x: LongNumber;
x.lc ← z;
IF n = 0 THEN RETURN[z];
IF n > 31 THEN RETURN[0];
IF n > 15 THEN
BEGIN
y.lowbits ← 0;
y.highbits ← BITSHIFT[x.lowbits, n - 16];
RETURN[y.lc]
END;
y.lowbits ← BITSHIFT[x.lowbits, n];
y.highbits ← BITSHIFT[x.lowbits, n - 16] + BITSHIFT[x.highbits, n];
RETURN[y.lc]
END;
LegLegal: PROCEDURE [index: CARDINAL] RETURNS [BOOLEAN] =
BEGIN
legTab: POINTER TO LegTab ← GetLegTable[read];
pCR: PCR ← GetPCR[read];
RETURN[index IN [0..pCR.nextLeg) AND legTab[index].from # NullNode];
END;
FindAvailableSpace: PROCEDURE [free: HistIndex] RETURNS [limit: CARDINAL] =
BEGIN
limit ← NullHist - free;
RETURN[IF limit > SIZE[Histogram] THEN limit - SIZE[Histogram] ELSE 0];
END;
GrabHistogramSlot: PROCEDURE [size: CARDINAL] RETURNS [hist: HistIndex] =
BEGIN
pCR: PCR ← GetPCR[write];
hist ← pCR.histFree;
pCR.histFree ← hist + size + SIZE[Histogram];
RETURN
END;
CheckScale: PROCEDURE [type: HistType] RETURNS [n: CARDINAL] =
BEGIN
n ← GetScale[];
SELECT TRUE FROM
type = leg AND n IN [0..31] => RETURN;
type = node AND n # 0 => RETURN;
ENDCASE;
MsgSW.Post[
sw: PerfCommonOps.msgSW, string: "Scale must be"L, endOfMsg: FALSE];
MsgSW.Post[
PerfCommonOps.msgSW,
IF type = leg THEN " (2↑n) [0..31]"L ELSE " [1..65,535]"L];
ERROR Confused;
END;
CheckBuckets: PROCEDURE [top: CARDINAL] RETURNS [n: CARDINAL] =
BEGIN OPEN String;
s: STRING ← [5];
n ← GetBuckets[];
IF n IN [1..top] THEN RETURN;
MsgSW.Post[
sw: PerfCommonOps.msgSW, string: "Number of Buckets must be [1.."L,
endOfMsg: FALSE];
AppendDecimal[s, LOOPHOLE[top]];
AppendChar[s, ']];
MsgSW.Post[PerfCommonOps.msgSW, s];
ERROR Confused;
END;
HistError: TYPE = {invalidLeg, invalidNode, alreadyOne, none};
PutHistError: PROCEDURE [message: HistError] =
BEGIN
MsgSW.Post[
PerfCommonOps.msgSW,
SELECT message FROM
invalidLeg => "!Invalid Leg"L,
invalidNode => "!Invalid Node"L,
alreadyOne => "Old Histogram deleted!"L,
none => "No Histogram exists!"L,
ENDCASE => "?"L];
RETURN
END;
END.