<> <> <> <> <> <<>> <<>> 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.FIFO _ NIL, 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; <> 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 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.