MonitorSmallCachePmCodeImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Created: Sindhu July 27, 1987 2:00:51 pm PDT
Pradeep Sindhu February 7, 1988 12:26:34 pm PST
Implements monitoring of mcode to check if all paths have been traversed.
DIRECTORY
Core, CoreClasses, CoreCreate, CoreFlat, FS, AMatrix, IO, MonitorSmallCachePmCode, Ports, Rope, Rosemary, SmallCacheLogic, SmallCacheUtils, TerminalIO;
MonitorSmallCachePmCodeImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreCreate, CoreFlat, FS, IO, AMatrix, Ports, Rope, Rosemary, SmallCacheLogic, SmallCacheUtils, TerminalIO
EXPORTS MonitorSmallCachePmCode
~ BEGIN OPEN MonitorSmallCachePmCode;
Type Defs
State: TYPE = REF StateRec;
StateRec: TYPE = RECORD [
pc: LevelSequence,
prevClock: Level
];
Signal Defs
PC, Reset, Clock: NAT;
Public Procs
LabelToPC: PUBLIC PROC [h: Handle, label: ROPE] RETURNS [INT] = {
FOR i: INT IN [0..h.size) DO
IF Rope.Equal[label, h.labelTable[i]] THEN RETURN [i]
ENDLOOP;
RETURN [-1];
};
PCToLabel: PUBLIC PROC [h: Handle, pc: NAT] RETURNS [ROPE] = {
RETURN [h.labelTable[pc]];
};
Parses mCode file and creates the labelTable and AMatrix
ParseMCode: PUBLIC PROC [fileName: ROPE, wDir: ROPE] RETURNS [h: Handle] = {
s: IO.STREAM ← FS.StreamOpen[fileName: fileName, wDir: SmallCacheUtils.workingDirectory];
tk: IO.TokenKind;
token: ROPE;
First build the labelTable:
BEGIN
GetLabel: PROC [] RETURNS [label: ROPE] = {
DO
[tk, label, ] ← IO.GetCedarTokenRope[s];
WHILE tk#tokenID DO [tk, label, ] ← IO.GetCedarTokenRope[s] ENDLOOP;
[tk, token, ] ← IO.GetCedarTokenRope[s];
IF Rope.Equal[token, ":"] THEN RETURN
ENDLOOP;
};
label: ROPE;
labelList: LIST OF ROPENIL;
numLabels: NAT ← 0;
Find the start of the microcode labels
[tk , token, ] ← IO.GetCedarTokenRope[s, FALSE];
WHILE NOT (tk=tokenCOMMENT AND Rope.Equal[token, "-- Begin Labels"]) DO
[tk , token, ] ← IO.GetCedarTokenRope[s, FALSE];
ENDLOOP;
Read the labels and put them into labelList
numLabels ← 0; label ← GetLabel[];
WHILE NOT Rope.Equal[label, "MaxPC"] DO
labelList ← CONS [label, labelList];
numLabels ← numLabels+1;
label ← GetLabel[];
ENDLOOP;
Create handle, and then copy labelList into labelTable
h ← NEW [HandleRec[numLabels]];
FOR i: NAT DECREASING IN [0..numLabels) DO
h.labelTable[i] ← labelList.first; labelList ← labelList.rest;
ENDLOOP;
END;
Next build the AMatrix
BEGIN
fromPC: ROPENIL;
toPCs: LIST OF ROPENIL;
This proc reads the transitions from one pc to all the others it jumps to
GetTransitions: PROC [] RETURNS [done: BOOLFALSE] = {
curlyCount: INT;
toPCs ← NIL;
Ignore stuff till we get to "=" or "-- End Transitions"
[tk, token, ] ← IO.GetCedarTokenRope[s, FALSE];
WHILE NOT (tk=tokenSINGLE AND Rope.Equal[token, "="]) AND NOT (tk=tokenCOMMENT AND Rope.Equal[token, "-- End Transitions"]) DO
[tk, token, ] ← IO.GetCedarTokenRope[s, FALSE]
ENDLOOP;
IF tk=tokenCOMMENT AND Rope.Equal[token, "-- End Transitions"]
THEN RETURN [TRUE];
[tk, fromPC, ] ← IO.GetCedarTokenRope[s];
[tk, token, ] ← IO.GetCedarTokenRope[s];
IF NOT Rope.Equal[token, "=>"] THEN ERROR;
[tk, token, ] ← IO.GetCedarTokenRope[s];
IF NOT Rope.Equal[token, "{"] THEN ERROR;
curlyCount ← -1; -- to indicate one "{" has been seen
WHILE curlyCount#0 DO
[tk, token, ] ← IO.GetCedarTokenRope[s];
SELECT tk FROM
= tokenID => IF Rope.Equal[token, "Jmp"] THEN {
[tk, token, ] ← IO.GetCedarTokenRope[s];
IF NOT (tk=tokenSINGLE AND Rope.Equal[token, "["]) THEN ERROR;
[tk, token, ] ← IO.GetCedarTokenRope[s];
IF NOT tk=tokenID THEN ERROR;
toPCs ← CONS[token, toPCs];
};
= tokenSINGLE => {
IF Rope.Equal[token, "{"] THEN curlyCount ← curlyCount-1;
IF Rope.Equal[token, "}"] THEN curlyCount ← curlyCount+1;
};
ENDCASE;
ENDLOOP;
};
Find the start of the section that defines the transitions
[tk , token, ] ← IO.GetCedarTokenRope[s, FALSE];
WHILE NOT (tk=tokenCOMMENT AND Rope.Equal[token, "-- Begin Transitions"]) DO
[tk , token, ] ← IO.GetCedarTokenRope[s, FALSE];
ENDLOOP;
Read the transitions and put them into AMatrix
h.am ← AMatrix.Create[h.size];
WHILE NOT GetTransitions[] DO
FOR l: LIST OF ROPE ← toPCs, l.rest WHILE l#NIL DO
h.am[LabelToPC[h, fromPC]][LabelToPC[h, l.first]] ← 1;
ENDLOOP;
ENDLOOP;
END;
Finally, compute the sequence of AMatrices
h.amSeq ← AMatrix.CreateAMSeq[h.am]
};
RecordPC: PUBLIC PROC [h: Handle, pc: NAT] = {
ENABLE AMatrix.DisallowedPath => {
TerminalIO.PutF["\n*** Got disallowed path from %g to %g ***", IO.rope[PCToLabel[h, from]], IO.rope[PCToLabel[h, to]]];
RESUME
};
AMatrix.UpdateAMSeq[h.amSeq, pc];
IF tracingEnabled THEN TerminalIO.PutF["\n= %g", IO.rope[PCToLabel[h, pc]]];
};
PrintUnVisitedPaths: PUBLIC PROC [h: Handle, maxLength: NAT] = {
seqSize: NAT ← h.amSeq.size;
size: NAT ← h.amSeq.ams[0].size;
existUnvisitedPaths: BOOLFALSE;
TerminalIO.PutF["\n\n-- Printing unvisited paths up to length %g --", IO.int[MIN[maxLength, seqSize]]];
FOR p: NAT IN [0..seqSize) DO
IF p+1 <= maxLength
THEN TerminalIO.PutF["\n\n Unvisited paths of length %g:", IO.int[p+1]];
FOR i: NAT IN [0..size) DO
FOR j: NAT IN [0..size) DO
IF h.amSeq.ams[p][i][j] = 1 THEN {
existUnvisitedPaths ← TRUE;
IF p+1 <= maxLength
THEN TerminalIO.PutF["\n %g-->%g", IO.rope[PCToLabel[h, i]], IO.rope[PCToLabel[h, j]]]
}
ENDLOOP;
ENDLOOP;
ENDLOOP;
IF existUnvisitedPaths THEN TerminalIO.PutF["\n\n*** Warning: Unvisited paths exist ***\n"];
};
PCMonitor: PUBLIC PROC [] RETURNS [ct: CellType] = {
public: Wire ← CoreCreate.WireList[LIST[CoreCreate.Seq["PC", SmallCacheLogic.NumPCBits], "Reset", "Clock"]];
ct ← CoreClasses.CreateUnspecified[public: public];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: pcMonitorName];
[] ← CoreFlat.CellTypeCutLabels[ct, "Logic"];
Ports.InitPorts[ct, ls, none, "PC"];
Ports.InitPorts[ct, l, none, "Reset", "Clock"];
};
Internal Procs
Init: Rosemary.InitProc = {
s: State;
IF oldStateAny=NIL
THEN {
s ← NEW [StateRec];
s.pc ← NEW [LevelSequenceRec[SmallCacheLogic.NumPCBits]];
}
ELSE s ← NARROW[oldStateAny, State];
s.prevClock ← X;
[PC, Reset, Clock] ← Ports.PortIndexes[cellType.public, "PC", "Reset", "Clock"];
stateAny ← s;
};
Simple: Rosemary.EvalProc = {
s: State ← NARROW[stateAny];
IF clockEval OR handle=NIL THEN RETURN;
IF p[Clock].l=L THEN Ports.CopyLS[p[PC].ls, s.pc];
IF s.prevClock=L AND p[Clock].l=H THEN {
IF p[Reset].l=H THEN AMatrix.InitAMSeq[handle.amSeq];
IF p[Reset].l=L THEN RecordPC[handle, Ports.LSToC[s.pc]]
};
s.prevClock ← p[Clock].l;
};
pcMonitorName: ROPE = Rosemary.Register[roseClassName: "PCMonitor", init: Init, evalSimple: Simple, scheduleIfClockEval: TRUE];
tracingEnabled: BOOLTRUE;
handle: Handle ← NIL;
END.