PLAOpsImplE.mesa
Copyright c 1984 by Xerox Corporation. All rights reserved.
Last edited by Curry, October 5, 1985 8:29:39 am PDT
Don Curry August 16, 1987 12:49:50 pm PDT
DIRECTORY
Commander,
Convert,
FS,
IO,
IOClasses,
Menus,
PLAOps,
Process,
REFBit,
Rope,
TypeScript,
ViewerClasses,
ViewerOps,
ViewerIO;
PLAOpsImplE: CEDAR MONITOR
IMPORTS Commander, Convert, FS, IO, IOClasses, Menus, PLAOps, Process, REFBit, Rope, TypeScript, ViewerIO, ViewerOps =
BEGIN
OPEN PLAOps;
UseFlag: CONDITION;
InUse: BOOLFALSE;
AcquireUseFlag: ENTRY PROC[] = {WHILE InUse DO WAIT UseFlag ENDLOOP; InUse←TRUE};
ReleaseUseFlag: ENTRY PROC = {InUse ← FALSE; NOTIFY UseFlag};
PLACompress: Commander.CommandProc = {
log, traceV: IO.STREAM;
DO
ENABLE {
UNWIND => {FinishUp[log, traceV]; };
FS.Error => IF error.group = user THEN {
cmd.err.PutRope[error.explanation]; EXIT }};
source, dest:  IO.ROPE;
first, last, time: CARDINAL;
comSum, mult: BOOL;
[source, first, last, time, comSum, mult] ← GetCommandLineParams[cmd];
IF source=NIL OR source.Length[]=0 THEN
{cmd.err.PutF["\n%g\n", IO.rope[plaOpsDoc]]; RETURN};
source ← source.Substr[len: source.Index[s2: ".ttt"]];
source ← FS.ExpandName[source].fullFName;
IF InUse THEN cmd.err.PutRope[" . . . waiting for PLA Compressor . . . \n"];
AcquireUseFlag[];
[traceV, log] ← OpenTraceAndLogStreams[source,
IF mult THEN "field" ELSE "composite"];
dest ← source.Cat[IF mult THEN ".fld.ttt" ELSE ".com.ttt"];
source ← source.Cat[".ttt"];
IF mult
THENCompressPLAFields [source, dest, first, last, comSum, time, log, traceV]
ELSECompressPLA   [source, dest, first, last, comSum, time, log, traceV];
cmd.out.PutF["%g ← %g\n", IO.rope[dest], IO.rope[source]];
EXIT ENDLOOP};
PLACompress: Commander.CommandProc = {
log, traceV: IO.STREAM;
DO
ENABLE {
UNWIND => {log.Close[]; traceV.Close[]};
FS.Error => IF error.group = user THEN {
cmd.err.PutRope[error.explanation]; EXIT }};
source, dest:  IO.ROPE;
first, last, time: CARDINAL;
comSum, mult: BOOL;
[source, first, last, time, comSum, mult] ← GetCommandLineParams[cmd];
IF source=NIL OR source.Length[]=0 THEN
{cmd.err.PutF["\n%g\n", IO.rope[plaOpsDoc]]; RETURN};
source ← source.Substr[len: source.Index[s2: ".ttt"]];
source ← FS.ExpandName[source].fullFName;
IF InUse THEN cmd.err.PutRope[" . . . waiting for PLA Compressor . . . \n"];
AcquireUseFlag[];
[traceV, log] ← OpenTraceAndLogStreams[source,
IF mult THEN "field" ELSE "composite"];
dest ← source.Cat[IF mult THEN ".fld.ttt" ELSE ".com.ttt"];
source ← source.Cat[".ttt"];
IF mult
THEN TRUSTED {Process.Detach[FORK CompressPLAFields
[source, dest, first, last, comSum, time, log, traceV]]}
ELSE TRUSTED {Process.Detach[FORK CompressPLA
[source, dest, first, last, comSum, time, log, traceV]]};
EXIT ENDLOOP};
OpenTraceAndLogStreams: PROC[source, msg: IO.ROPE]
RETURNS [traceV, log: IO.STREAM] = {
logF, logV: IO.STREAM;
name: IO.ROPEIO.PutFR["Trace of %g.pla %g compression", IO.rope[source], IO.rope[msg]];
traceV← BuildControlPanel[name];
logF ← FS.StreamOpen[fileName: source.Cat[".log"], accessOptions: $append, keep: 2];
logV ← ViewerIO.CreateViewerStreams[name: source.Cat[".log"]].out;
log ← IOClasses.CreateDribbleOutputStream[ output1: logV, output2: logF];
TypeScript.ChangeLooks[ViewerIO.GetViewerFromStream[logV], 'f];
TypeScript.ChangeLooks[ViewerIO.GetViewerFromStream[logV], 's]};
FinishUp: PROC[log, traceV: IO.STREAM] = {
logViewer: ViewerClasses.Viewer ← ViewerIO.GetViewerFromStream[log];
traceViewer: ViewerClasses.Viewer ← ViewerIO.GetViewerFromStream[traceV];
log.Close;
traceV.Close;
ViewerOps.CloseViewer  [traceViewer];
ViewerOps.DestroyViewer [logViewer];
ReleaseUseFlag[]};
BuildControlPanel: PROC[name: IO.ROPE] RETURNS [out: IO.STREAM] = {
viewer: ViewerClasses.Viewer;
out  ← ViewerIO.CreateViewerStreams[name].out;
viewer ← ViewerIO.GetViewerFromStream[out];
TypeScript.ChangeLooks[viewer, 'f];
TypeScript.ChangeLooks[viewer, 's];
Menus.AppendMenuEntry[
menu: viewer.menu,
entry: Menus.CreateEntry[name: "Trace",  clientData: out, proc: TraceProc]];
Menus.AppendMenuEntry[
menu: viewer.menu,
entry: Menus.CreateEntry[name: "FinishCS", clientData: out, proc: FinishCSProc]];
Menus.AppendMenuEntry[
menu: viewer.menu,
entry: Menus.CreateEntry[name: "FinishMin", clientData: out, proc: FinishMinProc]];
Menus.AppendMenuEntry[
menu: viewer.menu,
entry: Menus.CreateEntry[name: "Abort",  clientData: out, proc: AbortProc]] };
FinishCSProc: Menus.ClickProc = {
out: IO.STREAM  ← NARROW[clientData];
FinishCS ← TRUE;
out.PutRope["\nTruncate complete sum"]};
FinishMinProc: Menus.ClickProc = {
out: IO.STREAM  ← NARROW[clientData];
FinishMin ← TRUE;
out.PutRope["\nTruncate minimum sum search"]};
AbortProc:  Menus.ClickProc = {
out: IO.STREAM  ← NARROW[clientData];
FinishCS𡤏inishMin�ort ← TRUE;
out.PutRope["\nAbort"]};
TraceProc:  Menus.ClickProc = {
out: IO.STREAM  ← NARROW[clientData];
Trace  ← NOT Trace;
out.PutF["\nTrace %g", IO.rope[(IF Trace THEN "ON" ELSE "OFF")]]};
GetCommandLineParams: PROC[cmd: Commander.Handle] RETURNS
[source: IO.ROPE, begin, end, time: CARDINAL, comSum, mult: BOOL] = {
cls: IO.STREAMIO.RIS[cmd.commandLine];
token: IO.ROPE;
source ← NIL;
time ← 177777B; -- delay in minutes ~ 45 days
begin ← end ← 177777B;
comSum ← mult ← FALSE;
token ← IO.GetTokenRope[cls ! IO.EndOfStream => {token ← NIL; CONTINUE}].token;
IF token # NIL THEN DO
ENABLE IO.EndOfStream => EXIT;
Next: PROC = {token←IO.GetTokenRope[cls].token};
SELECT token.Fetch[0] FROM
'/, IN ['a..'z], IN ['A..'Z ] => {source ← source.Cat[token];  Next[]; LOOP};
'-  => {
Next[];
SELECT token.Fetch[0] FROM
'm, 'M => {mult←TRUE; --Multiple plas--     Next[]; LOOP};
'c, 'C => {comSum←TRUE; --complete sum--    Next[]; LOOP};
't, 'T => {time𡤌onvert.CardFromRope[token.Substr[1]]; Next[]; LOOP};
'f, 'F => {     -- field or field range
IF token.Length[] > 1 -- field
THEN {
token ← token.Substr[1];
begin ← end ← Convert.CardFromRope[token];   Next[]; LOOP};
Next[];     -- field range
SELECT token.Fetch[0] FROM
'[   => {begin ← 0};
'(   => {begin ← 1};
ENDCASE => LOOP;
Next[];
begin ← Convert.CardFromRope[token.Substr[len: token.Index[s2:".."]]] + begin;
token ← token.Substr[token.Index[s2:".."]+2];
end ← Convert.CardFromRope[token];
Next[];
SELECT token.Fetch[0] FROM
']   => {};
')   => {end ← end-1};
ENDCASE =>
{cmd.err.PutF["\n**I don't understand '%g'. I was expecting an end of range\n", IO.rope[token]]; RETURN};
Next[]; LOOP};
ENDCASE =>
{cmd.err.PutF["\n**Unknown switch: %g\n", IO.rope[token]]; RETURN} };
ENDCASE =>
{cmd.err.PutF["\n**I don't understand '%g'. I was expecting a switch or filename\n", IO.rope[token]]; RETURN};
ENDLOOP;
cls.Close[]};
TOD: PROC RETURNS[IO.Value] = {
time: IO.ROPEIO.PutFR["%g", IO.time[]];
time ← time.Substr[time.Index[s2:"198"]+5];
time ← time.Substr[len: time.Index[s2:" "]];
IF time.Length[] = 7 THEN time ← Rope.Cat[" ", time];
RETURN[IO.rope[time]]};
CompressPLA: PROC[
source, dest: IO.ROPE,
first:   CARDINAL,
last:   CARDINAL,
comSum:  BOOL,
time:   CARDINAL,
log, traceV: IO.STREAMIO.noWhereStream] = {
refPLA:   PLA;
newPLA:   PLA;
dfList:   TermList;
iForm:   Format;
oForm:   Format;
index:    CARDINAL ← 0;
dfLength:  CARDINAL ← 0;
csLength:   CARDINAL ← 0;
initEssential:  CARDINAL ← 0;
initDelete:  CARDINAL ← 0;
cover:    CARDINAL ← 0;
insTot,   outsTot:   CARDINAL ← 0;
finishCS,   finishMin:  BOOLFALSE;
Process.SetPriority[Process.priorityBackground];
log.PutF["\n\n%g ← %g - %g", IO.rope[dest], IO.rope[source], IO.time[]];
refPLA ← ReadPLAFile[source];
log.PutF["\n%g\n", IO.rope[PLAHeader[refPLA]]]; log.Flush[];
newPLA ← NewPLA[refPLA.data, refPLA.out, refPLA.name];
iForm ← REFBit.Desc[refPLA.data].fieldForm;
oForm ← REFBit.Desc[refPLA.out].fieldForm;
IF first=177777B THEN {first ← 0; last ← oForm.size-1};
Trace ← FinishCS ← FinishMin ← Abort ← FALSE;
dfList ← CopyTermListForField[
list:  refPLA.termList, -- Size Effect is removing null terms
firstBit: oForm[first].firstBit,
bitSize: oForm[last].firstBit + oForm[last].bitSize - oForm[first].firstBit ];
DO
ENABLE {
UNWIND => GOTO AbortExit;
ABORTED => GOTO AbortExit };
log.PutRope["\n"];
IF Abort THEN {log.PutRope["\n<<<<ABORT>>>>\n"]; log.Flush[]; EXIT};
dfLength ← dfList.length;
log.PutF["\nConsolidated DEF Terms: %3g %g", IO.card[dfLength], TOD[] ];
IF dfLength=0 THEN {log.Flush[]; LOOP};
IF Abort THEN GOTO AbortExit;
finishCS ← ConvertTermListToCompleteSum
[list: dfList, addMerges: comSum, addConsensus: comSum, log: traceV];
csLength ← dfList.length;
log.PutF["\nConsolidated SUM Terms: %3g %g", IO.card[csLength], TOD[] ];
IF finishCS THEN log.PutRope[" ~finished"];
IF Abort THEN GOTO AbortExit;
[initEssential, initDelete, cover, finishMin]
← FindAMinimalCover[list: dfList, time: time, log: traceV];
log.PutF["\nConsolidated MIN Terms: %3g %g", IO.card[cover], TOD[] ];
IF finishMin THEN log.PutRope[" ~finished"];
newPLA.termList ← dfList;
log.PutF["\n\nConsolidated RES Def:%3g %g:%3g",
IO.card[dfLength],
IO.rope[(IF comSum THEN "CS" ELSE "Sum")],
IO.card[csLength] ];
log.PutF[" Ess:%3g Del:%3g Cov:%3g",
IO.card[initEssential ],
IO.card[initDelete ],
IO.card[cover   ] ];
log.PutF[" %g", TOD[]];
IF finishCS OR finishMin THEN {
IF finishCS THEN log.PutRope[" CS"];
IF finishMin THEN log.PutRope[" Min"];
log.PutRope[" ~finished"]};
log.Flush[];
EXIT REPEAT AbortExit => {log.PutRope["\n<<<<ABORT>>>>\n"]; log.Flush[] } ENDLOOP;
FOR index IN [0..iForm.size) DO
insTot ← insTot + iForm[index].bitSize ENDLOOP;
FOR index IN [0..oForm.size) DO
outsTotoutsTot + oForm[index].bitSize ENDLOOP;
IF ~Abort THEN {
log.PutF["\n\nSummary:"];
log.PutF["\n Inputs Bits:%4g", IO.card[insTot]];
log.PutF["\n Total Outputs Bits:%4g", IO.card[outsTot]];
log.PutF["\n Definition Terms:%4g", IO.card[dfLength]];
log.PutF["\n Complete Sum Terms:%4g", IO.card[csLength]];
log.PutF["\n Essential Terms:%4g", IO.card[initEssential]];
log.PutF["\n Init Deletes Terms:%4g", IO.card[initDelete]];
log.PutF["\n Cover Terms:%4g", IO.card[cover]];
IF finishCS THEN log.PutRope["\n CS Unfinished"];
IF finishMin THEN log.PutRope["\n Min Unfinished"];
log.PutF["\n\n"];
WritePLAFile[newPLA, dest, log] };
log.PutChar[IO.FF];
Trace ← FinishCS ← FinishMin ← Abort ← FALSE;
FinishUp[log, traceV]};
CompressPLAFields: PROC[
source, dest: IO.ROPE,
first:   CARDINAL,
last:   CARDINAL,
comSum:  BOOL,
time:   CARDINAL,
log, traceV: IO.STREAMIO.noWhereStream] = {
iForm:   Format;
oForm:   Format;
refPLA:   PLA;
newPLA:   PLA;
dfList:   TermList;
index:         CARDINAL ← 0;
dfLength,  dfSeqTot:   CARDINAL ← 0;
csLength,  csSeqTot:   CARDINAL ← 0;
initEssential,  initEssentialTot: CARDINAL ← 0;
initDelete,  initDeleteTot: CARDINAL ← 0;
cover,    coverTot:   CARDINAL ← 0;
     finishCSTot:  CARDINAL ← 0;
     finishMinTot: CARDINAL ← 0;
     insUsed:   CARDINAL ← 0;
insTot,   outsTot:   CARDINAL ← 0;
finishCS,   finishMin:  BOOLFALSE;
max:         CARDINAL ← 0;
msgLineForm:      IO.ROPENIL;
MSGLine: PROC[msg: IO.ROPE, card: CARDINAL] = {
traceV.PutF[msgLineForm,
IO.rope[msg], IO.card[index], IO.rope[oForm[index].name] ];
traceV.PutF[" [%2g] Terms: %3g %g",
IO.card[oForm[index].bitSize], IO.card[card], TOD[]] };
Process.SetPriority[Process.priorityBackground];
log.PutF["\n\n%g ← %g - %g", IO.rope[dest], IO.rope[source], IO.time[]];
refPLA ← ReadPLAFile[source];
IF refPLA=NIL THEN {FinishUp[log, traceV]; RETURN};
log.PutF["\n%g\n", IO.rope[PLAHeader[refPLA]]]; log.Flush[];
newPLA ← NewPLA[refPLA.data, refPLA.out, refPLA.name];
iForm ← REFBit.Desc[refPLA.data].fieldForm;
oForm ← REFBit.Desc[refPLA.out].fieldForm;
IF first=177777B THEN {first ← 0; last ← oForm.size-1};
Trace ← FinishCS ← FinishMin ← Abort ← FALSE;
max ← 0;
FOR index IN [first..last] DO
len: CARDINAL ← oForm[index].name.Length[];
max ← MAX[max, len] ENDLOOP;
msgLineForm ← IO.PutFR["%g%g%g",
IO.rope["\n%gField:%3g %"], IO.card[max], IO.rope["g"] ];
FOR index IN [first..last] DO
ENABLE {
UNWIND => GOTO AbortExit;
ABORTED => GOTO AbortExit };
traceV.PutRope["\n"];
IF Abort THEN {log.PutRope["\n<<<<ABORT>>>>\n"]; log.Flush[]; EXIT};
dfList ← CopyTermListForField[
list:  refPLA.termList,
firstBit: oForm[index].firstBit,
bitSize: oForm[index].bitSize ];
dfLength ← dfList.length;
MSGLine["DEF ", dfLength];
IF dfLength=0 THEN {log.Flush[]; LOOP};
IF Abort THEN GOTO AbortExit;
finishCS ← ConvertTermListToCompleteSum
[list: dfList, addMerges: comSum, addConsensus: comSum, log: traceV];
csLength ← dfList.length;
MSGLine["SUM ", csLength];
IF finishCS THEN traceV.PutRope[" ~finished"];
IF Abort THEN GOTO AbortExit;
[initEssential, initDelete, cover, finishMin]
← FindAMinimalCover[list: dfList, time: time, log: traceV];
MSGLine["MIN ", cover];
IF finishMin THEN traceV.PutRope[" ~finished"];
insUsed    ← InsUsed[dfList];
newPLA.termList ← Add[newPLA.termList, dfList];
outsTot   ← outsTot   + oForm[index].bitSize;
dfSeqTot   ← dfSeqTot  + dfLength;
csSeqTot   ← csSeqTot  + csLength;
initEssentialTot ← initEssentialTot+ initEssential;
initDeleteTot  ← initDeleteTot + initDelete;
coverTot   ← coverTot  + cover;
finishCSTot  ← finishCSTot + (IF finishCS THEN 1 ELSE 0);
finishMinTot ← finishMinTot + (IF finishMin THEN 1 ELSE 0);
log.PutF[msgLineForm,
IO.rope[""], IO.card[index], IO.rope[oForm[index].name ] ];
log.PutF[" [%2gx%2g]",IO.card[insUsed], IO.card[oForm[index].bitSize]];
log.PutF[" Def:%3g %g:%3g",
IO.card[dfLength],
IO.rope[(IF comSum THEN "CS" ELSE "Sum")],
IO.card[csLength] ];
log.PutF[" Ess:%3g Del:%3g Cov:%3g",
IO.card[initEssential ],
IO.card[initDelete ],
IO.card[cover   ] ];
log.PutF[" %g", TOD[]];
IF finishCS OR finishMin THEN {
IF finishCS THEN log.PutRope[" CS"];
IF finishMin THEN log.PutRope[" Min"];
log.PutRope[" ~finished"]};
log.Flush[];
REPEAT AbortExit => {log.PutRope["\n<<<<ABORT>>>>\n"]; log.Flush[] } ENDLOOP;
FOR index IN [0..iForm.size) DO
insTot ← insTot + iForm[index].bitSize ENDLOOP;
IF ~Abort THEN {
traceV.PutRope["\n\nFinal Consolidation"];
finishCS ← ConvertTermListToCompleteSum
[list: newPLA.termList, addMerges: FALSE, addConsensus: FALSE, log: traceV];
csLength ← newPLA.termList.length;
traceV.PutF[msgLineForm, IO.rope["RES "], IO.rope["ALL"], IO.rope["Consolidated"] ];
traceV.PutF[" Terms: %3g %g", IO.card[csLength], TOD[]];
IF finishCS THEN traceV.PutRope[" ~finished"];
log.PutF["\n\nSummary:"];
log.PutF["\n Inputs Bits:%4g", IO.card[insTot]];
log.PutF["\n Total Outputs Bits:%4g", IO.card[outsTot]];
log.PutF["\n SourcePLA Terms:%4g", IO.card[refPLA.termList.length]];
log.PutF["\n Definition Terms:%4g", IO.card[dfSeqTot]];
log.PutF["\n Complete Sum Terms:%4g", IO.card[csSeqTot]];
log.PutF["\n Essential Terms:%4g", IO.card[initEssentialTot]];
log.PutF["\n Init Deletes Terms:%4g", IO.card[initDeleteTot]];
log.PutF["\n Cover Terms:%4g", IO.card[coverTot]];
log.PutF["\n Consolidation Terms:%4g", IO.card[csLength]];
log.PutF["\n CS Unfinished Srchs:%4g", IO.card[finishCSTot]];
log.PutF["\n Min Unfinished Srchs:%4g", IO.card[finishMinTot]];
log.PutF["\n\n"];
WritePLAFile[newPLA, dest, log] };
log.PutChar[IO.FF];
Trace ← FinishCS ← FinishMin ← Abort ← FALSE;
FinishUp[log, traceV]};
plaOpsDoc: IO.ROPE = "PLAOpsCompress filename.ttt
 -c  => complete sum
 -f  => field or field range
 -m => multiple plas, one for each field
 -t  => timeout minutes ";
Commander.Register[key:"PLAOpsCompress", proc: PLACompress, doc: plaOpsDoc];
END.