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. pMemoryModelImpl.mesa Copyright c 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 Exported Procedures If the arbiter hasn't serviced us as yet, just increment the latency and return Κ»˜codešœ™Kšœ Οmœ1™™>K™2K™>—K™K™šΟk ˜ Kšœžœžœ˜ —K˜KšΠblœžœž˜Kšžœ žœž˜Kšžœ ˜šœžœžœ ˜K˜Kšœ žœžœ˜'šœžœžœ˜K˜+Kšœ žœΟc<˜QJšœ žœžœžœ˜Jšœžœ˜ Jšœ žœ 4˜DK˜—K˜Jšœžœ 5˜BKšœžœ˜—head™šΟnœžœžœ˜&šžœwž˜~KšžœB˜DKšžœ˜—K˜K˜—š‘ œžœžœžœ˜KKšœ!˜!Kšœ˜Kšœžœ˜$K˜K˜K˜—K˜š‘ œžœ˜(Kšœžœ˜'K˜!K˜Kšœžœ ˜Kšœ˜K˜—K˜š‘ œžœ˜*Kšœžœ˜,Kšœ!˜!K˜š‘œžœžœ˜4Kšœ6˜6Kšœžœ#˜,KšœC˜CKšœC˜CKšœC˜CJ˜šžœ ž˜*Jšœ žœ+˜;Jšœ žœ*˜:Jšœ žœ)˜9Jšžœž˜—Kšœ˜—K˜š‘ œžœ˜&šžœ ž˜Kš œžœ žœžœžœ˜mKšžœ˜—Kšœ˜—K˜K˜K˜K™Ošžœ"žœ˜*Kšœ,˜,šžœ ž˜KšžœKžœ˜VKšžœ&˜*—K˜—K˜šžœ˜šžœ )˜0Kšœžœžœ˜AKšžœžœžœ˜>—Kšž˜—šžœ:˜<šžœ˜Kšœ3˜3Kšœ#˜#Kšœ*˜*—Kšž˜—šžœ&˜(šžœ˜Kšœžœžœ˜Ašžœž˜!Kšžœ˜Kšžœ˜——Kšžœ+˜/—K˜K˜——K˜Kšžœ˜—…— 9