ResponseCheckerImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Gasbarro April 3, 1987 9:43:46 am PST
DIRECTORY
BitOps, Core, CoreClasses, CoreCreate, CoreProperties, DynaBusInterface, FIFOQueue, Ports, ResponseChecker, Rosemary, RosemaryUser;
ResponseCheckerImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreCreate, DynaBusInterface, FIFOQueue, Ports, Rosemary
EXPORTS ResponseChecker
= BEGIN
DGrant, ErrorOut, DataOut, HeaderCycle, Reset, Clock, Vdd, Gnd: NATLAST[NAT];
ROPE: TYPE = Core.ROPE;
Port: TYPE = Ports.Port;
Quad: TYPE = DynaBusInterface.Quad;
Cmd: TYPE = DynaBusInterface.Cmd;
dataBits: CARDINAL = 64;
qZero: Quad = BitOps.BitQWordZero;
State: TYPE = REF StateRec;
StateRec: TYPE = RECORD [
queue: FIFOQueue.Queue ← NIL,
thisCmd: Cmd,
thisResponse: ResponseRec,
cycleCount: CARDINAL ← 0,
dataIndex: CARDINAL ← 0,
grantM, grantS: BOOL,
alreadyChecked: BOOL
];
ResponseRec: TYPE = RECORD [header: Quad, data: ARRAY[0..4) OF Quad, doubleError: ARRAY[0..4) OF BOOL];
Create: PUBLIC PROC RETURNS [ct: Core.CellType] = {
ct ← CoreClasses.CreateUnspecified[
public: CoreCreate.WireList[LIST["DGrant", "ErrorOut", CoreCreate.Seq["DataOut", dataBits], "HeaderCycle", "Reset", "Clock", "Vdd", "Gnd"], "ResponseChecker", NIL],
name: checkerName
];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: checkerName];
[] ← Ports.InitPorts[ct, b, none, "DGrant", "ErrorOut", "HeaderCycle", "Reset", "Clock"];
[] ← Ports.InitPorts[ct, q, none, "DataOut"];
};
Init: Rosemary.InitProc = {
--PROC [cellType: Core.CellType, p: Ports.Port] RETURNS [stateAny: REF ANY ← NIL]--
state: State ← IF oldStateAny=NIL THEN NEW[StateRec] ELSE NARROW[oldStateAny];
InitPortIndicies[cellType];
state.queue ← FIFOQueue.Create[];
state.cycleCount ← 0;
state.dataIndex ← 0;
state.grantM ← FALSE;
state.grantS ← FALSE;
state.alreadyChecked ← FALSE;
stateAny ← state;
};
Simple: Rosemary.EvalProc = {
--PROC [p: Ports.Port, stateAny: REF ANY]--
state: State ← NARROW[stateAny];
--delay DGrant one clock cycle to make it easier to compare with header and data cycles
IF ~clockEval THEN {
SELECT p[Clock].b FROM
FALSE => state.grantM ← p[DGrant].b;
TRUE => state.grantS ← state.grantM;
ENDCASE => ERROR;
};
IF clockEval THEN state.alreadyChecked ← FALSE;
IF clockEval OR p[Clock].b OR state.alreadyChecked THEN RETURN ELSE state.alreadyChecked ← TRUE;
IF state.cycleCount#0 AND ~state.grantS THEN ERROR; --DGrant disappeared in middle of packet
IF p[HeaderCycle].b AND state.grantS THEN { --begin new packet
IF state.cycleCount#0 THEN ERROR; --bogus HeaderCycle in middle of packet
state.thisResponse ← NARROW[FIFOQueue.Remove[state.queue], REF ResponseRec]^;
state.thisCmd ← DynaBusInterface.ExtractCmd[p[DataOut].q];
state.cycleCount ← IF state.thisCmd=RBRply OR state.thisCmd=CWSRply THEN 5 ELSE 2;
state.dataIndex ← 0;
IF NOT QuadEqual[p[DataOut].q, state.thisResponse.header] THEN ERROR; --bad header
};
IF state.cycleCount#0 AND NOT p[HeaderCycle].b THEN {
SELECT state.thisCmd FROM
RBRply => {
IF state.thisResponse.doubleError[state.dataIndex] THEN
{IF NOT p[ErrorOut].b THEN ERROR}
ELSE IF NOT QuadEqual[state.thisResponse.data[state.dataIndex], p[DataOut].q] THEN ERROR;
};
WBRply, FBRply, WSRply, BIOWRply, DeMapRply, IOWRply, IORRply => {
IF p[ErrorOut].b THEN ERROR;
IF NOT QuadEqual[state.thisResponse.data[state.dataIndex], p[DataOut].q] THEN ERROR;
};
CWSRply => {
IF p[ErrorOut].b THEN ERROR;
IF NOT QuadEqual[state.thisResponse.data[0], p[DataOut].q] THEN ERROR;
};
ENDCASE => ERROR;
state.dataIndex ← state.dataIndex+1;
};
IF state.cycleCount#0 THEN state.cycleCount ← state.cycleCount-1;
};
InitPortIndicies: PROC [ct: Core.CellType] = {
[DGrant, ErrorOut, DataOut, HeaderCycle, Reset, Clock, Vdd, Gnd] ← Ports.PortIndexes[ct.public, "DGrant", "ErrorOut", "DataOut", "HeaderCycle", "Reset", "Clock", "Vdd", "Gnd"];
};
ExpectReply: PUBLIC PROC [rcState: REF ANY, header: Quad, data: ARRAY[0..4) OF Quad, doubleError: ARRAY [0..4) OF BOOLALL[FALSE]] ~ {
state: State ← NARROW[rcState];
FIFOQueue.Include[state.queue, NEW[ResponseRec ← [header, data, doubleError]]];
};
IsEmpty: PUBLIC PROC [rcState: REF ANY] RETURNS [empty: BOOL] ~ {
state: State ← NARROW[rcState];
RETURN[FIFOQueue.IsEmpty[state.queue]];
};
QuadEqual: PROC [q1, q2: Quad] RETURNS [BOOL] ~ {
FOR i: INT IN[0..4) DO
IF q1[i]#q2[i] THEN RETURN[FALSE];
ENDLOOP;
RETURN[TRUE];
};
checkerName: ROPE = Rosemary.Register[roseClassName: "ResponseChecker", init: Init, evalSimple: Simple, scheduleIfClockEval: TRUE];
END.