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 ROPE ← NIL;
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: ROPE ← NIL;
toPCs: LIST OF ROPE ← NIL;
This proc reads the transitions from one pc to all the others it jumps to
GetTransitions:
PROC []
RETURNS [done:
BOOL ←
FALSE] = {
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: BOOL ← FALSE;
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: BOOL ← TRUE;
handle: Handle ← NIL;
END.