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;
queue: FIFOQueue.Queue ← NIL;
thisCmd: Cmd;
thisResponse: ResponseRec;
cycleCount: CARDINAL ← 0;
dataIndex: CARDINAL ← 0;
prevClock: BOOLFALSE;
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];
InitPortIndicies[ct];
[] ← 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]--
queue ← FIFOQueue.Create[];
cycleCount ← 0;
dataIndex ← 0;
prevClock ← FALSE;
};
Simple: Rosemary.EvalProc = {
--PROC [p: Ports.Port, stateAny: REF ANY]--
IF prevClock=p[Clock].b THEN RETURN; --edge sensitive
prevClock ← p[Clock].b;
IF NOT p[Clock].b THEN RETURN; --filter falling edge
IF cycleCount#0 AND ~p[DGrant].b THEN ERROR; --DGrant disappeared in middle of packet
IF p[HeaderCycle].b AND p[DGrant].b THEN { --begin new packet
IF cycleCount#0 THEN ERROR; --bogus HeaderCycle in middle of packet
thisResponse ← NARROW[FIFOQueue.Remove[queue], REF ResponseRec]^;
thisCmd ← DynaBusInterface.ExtractCmd[p[DataOut].q];
cycleCount ← IF thisCmd=RBRply OR thisCmd=CWSRply THEN 5 ELSE 2;
dataIndex ← 0;
IF NOT QuadEqual[p[DataOut].q, thisResponse.header] THEN ERROR; --bad header
};
IF cycleCount#0 AND NOT p[HeaderCycle].b THEN {
SELECT thisCmd FROM
RBRply => {
IF thisResponse.doubleError[dataIndex] THEN
{IF NOT p[ErrorOut].b THEN ERROR}
ELSE IF NOT QuadEqual[thisResponse.data[dataIndex], p[DataOut].q] THEN ERROR;
};
WBRply, FBRply, WSRply, BIOWRply, DeMapRply, IOWRply, IORRply => {
IF p[ErrorOut].b THEN ERROR;
IF NOT QuadEqual[thisResponse.data[dataIndex], p[DataOut].q] THEN ERROR;
};
CWSRply => {
IF p[ErrorOut].b THEN ERROR;
IF NOT QuadEqual[thisResponse.data[0], p[DataOut].q] THEN ERROR;
};
ENDCASE => ERROR;
dataIndex ← dataIndex+1;
};
IF cycleCount#0 THEN cycleCount ← 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 [header: Quad, data: ARRAY[0..4) OF Quad, doubleError: ARRAY [0..4) OF BOOLALL[FALSE]] ~ {
FIFOQueue.Include[queue, NEW[ResponseRec ← [header, data, doubleError]]];
};
IsEmpty: PUBLIC PROC RETURNS [empty: BOOL] ~ {
RETURN[FIFOQueue.IsEmpty[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];
END.