MemoryModelImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Written By: Pradeep Sindhu, September 20, 1986 11:53:20 am PDT
Pradeep Sindhu, September 26, 1986 11:18:03 pm PDT
Last Edited by: Louis Monier September 24, 1986 4:28:18 pm PDT
DIRECTORY
MemoryModel, DynaSeer, FIFO, IO;
MemoryModelImpl: CEDAR PROGRAM
IMPORTS DynaSeer, FIFO, IO
EXPORTS MemoryModel
~ BEGIN OPEN MemoryModel;
MemoryState: TYPE = REF MemoryStateRec;
MemoryStateRec: TYPE = RECORD [
requestStatus: {notRequesting, requesting},
memCounter: INT ← 0, -- counts cycles for each request; 0 => nothing being served
inputFIFO: FIFO.FIFONIL,
requestBeingServed: Cycle ← NIL,
memLatency: INT--delay from address in on bus to address out on bus
];
memLat: INT; -- delay from address in on bus to address out on bus
defaultMemLat: INT ← 15;
Exported Procedures
Init: PUBLIC PROC [handle: Handle] = {
WHILE (memLat ← DynaSeer.GetIntParm[handle.in, handle.out, "\nMemory latency (cycles)", defaultMemLat]) < handle.arbLatency DO
IO.PutRope[handle.out, "memLatency must be larger than arbLatency"];
ENDLOOP;
};
CreateMemory: PUBLIC PROC [deviceId: DeviceId] RETURNS [device: Device] = {
device ← DynaSeer.CreateDevice[];
device.deviceId ← deviceId;
device.state ← NEW [MemoryStateRec];
device.init ← InitMemory;
device.cycle ← CycleMemory;
};
InitMemory: PUBLIC DynaSeer.InitProc = {
ms: MemoryState ← NARROW[device.state];
ms.requestStatus ← notRequesting;
ms.memCounter ← 0;
ms.inputFIFO ← FIFO.Create[];
ms.memLatency ← memLat
};
CycleMemory: PUBLIC DynaSeer.CycleProc = {
myState: MemoryState ← NARROW[device.state];
myId: DeviceId ← device.deviceId;
GenerateMemoryRequest: PROC [] RETURNS [Request] = {
hisId: DeviceId ← myState.requestBeingServed.deviceId;
data: INT ← myState.requestBeingServed.data;
rbRplyCycle: Cycle ← DynaSeer.MakeCycle[RBRply, hisId, myId, data];
wbRplyCycle: Cycle ← DynaSeer.MakeCycle[WBRply, hisId, myId, data];
wsRplyCycle: Cycle ← DynaSeer.MakeCycle[WSRply, hisId, myId, data];
SELECT myState.requestBeingServed.cmd FROM
RBRqst => RETURN [DynaSeer.MakeRequest[Five, rbRplyCycle]];
WBRqst => RETURN [DynaSeer.MakeRequest[Two, wbRplyCycle]];
WSRqst => RETURN [DynaSeer.MakeRequest[Two, wsRplyCycle]]
ENDCASE => ERROR
};
TreatBusCycle: PROC [cycle: Cycle] = {
SELECT cycle.cmd FROM
RBRqst, WBRqst, WSRqst => IF cycle.data MOD (handle.lastmem+1) = myId THEN FIFO.Put[myState.inputFIFO, cycle]
ENDCASE;
};
TreatBusCycle[cycle];
If the arbiter hasn't serviced us as yet, just increment the latency and return
IF myState.requestStatus=requesting THEN {
request: Request ← handle.memRequests[myId];
IF request#NIL
THEN {request.cycles.first.grantLatency ← request.cycles.first.grantLatency+1; RETURN}
ELSE myState.requestStatus ← notRequesting
};
IF myState.memCounter=0
THEN { -- nothing is being serviced at this time
myState.requestBeingServed ← NARROW[FIFO.Get[myState.inputFIFO]];
IF myState.requestBeingServed#NIL THEN myState.memCounter ← 1}
ELSE
IF myState.memCounter=(myState.memLatency-handle.arbLatency)
THEN {
handle.memRequests[myId] ← GenerateMemoryRequest[];
myState.requestStatus ← requesting;
myState.memCounter ← myState.memCounter+1}
ELSE
IF myState.memCounter=myState.memLatency
THEN {
myState.requestBeingServed ← NARROW[FIFO.Get[myState.inputFIFO]];
IF myState.requestBeingServed#NIL
THEN myState.memCounter ← 1
ELSE myState.memCounter ← 0}
ELSE myState.memCounter ← myState.memCounter+1;
};
END.