<> <> <> <> <> <> <<>> DIRECTORY CacheModel, DynaSeer, EditedStream, IO, Random, Real; CacheModelImpl: CEDAR PROGRAM IMPORTS DynaSeer, EditedStream, Random, Real EXPORTS CacheModel ~ BEGIN OPEN CacheModel; CacheState: TYPE = REF CacheStateRec; CacheStateRec: TYPE = RECORD [ requestStatus: {notRequesting, requesting, waitingForReply}, rs: Random.RandomStream, incomingPacket: ARRAY [0..4] OF Cycle _ ALL[NIL], cacheRBRand, cacheWBRand, cacheWSRand: INT ]; maxRand: INT = 1000000; defaultPrRBRqst: REAL _ 0.023*(DynaSeer.busCycle/DynaSeer.procCycle); defaultPrWBRqst: REAL _ defaultPrRBRqst/3.0; defaultPrWSRqst: REAL _ 0.0; prRBRqst, prWBRqst, prWSRqst: REAL; <> Init: PUBLIC PROC [handle: Handle] = { DO ENABLE EditedStream.Rubout => LOOP; prRBRqst _ DynaSeer.GetRealParm[handle.in, handle.out, "\nCache Pr{RBRqst}: ", defaultPrRBRqst]; prWBRqst _ DynaSeer.GetRealParm[handle.in, handle.out, "Cache Pr{WBRqst}: ", defaultPrWBRqst]; prWSRqst _ DynaSeer.GetRealParm[handle.in, handle.out, "Cache Pr{WSRqst}: ", defaultPrWSRqst]; EXIT; ENDLOOP; }; CreateCache: PUBLIC PROC [deviceId: DeviceId] RETURNS [device: Device] = { device _ DynaSeer.CreateDevice[]; device.deviceId _ deviceId; device.state _ NEW [CacheStateRec]; device.init _ InitCache; device.cycle _ CycleCache; }; InitCache: PUBLIC DynaSeer.InitProc = { cs: CacheState _ NARROW[device.state]; cs.requestStatus _ notRequesting; cs.rs _ Random.Create[maxRand, device.deviceId]; cs.cacheRBRand _ Real.Fix[prRBRqst*maxRand]; cs.cacheWBRand _ Real.Fix[(prRBRqst+prWBRqst)*maxRand]; cs.cacheWSRand _ Real.Fix[(prRBRqst+prWBRqst+prWSRqst)*maxRand]; }; CycleCache: PUBLIC DynaSeer.CycleProc = { myState: CacheState _ NARROW[device.state]; myId: DeviceId _ device.deviceId; GenerateCacheLPRequest: PROC [] RETURNS [Request] = { rbRqstCycle: Cycle _ DynaSeer.MakeCycle[RBRqst, myId, myId, Random.NextInt[myState.rs]]; wbRqstCycle: Cycle _ DynaSeer.MakeCycle[WBRqst, myId, myId, Random.NextInt[myState.rs]]; wsRqstCycle: Cycle _ DynaSeer.MakeCycle[WSRqst, myId, myId, Random.NextInt[myState.rs]]; rand: INT _ Random.NextInt[myState.rs]; IF rand <= myState.cacheRBRand THEN RETURN [DynaSeer.MakeRequest[Two, rbRqstCycle, Low]]; IF rand <= myState.cacheWBRand THEN RETURN [DynaSeer.MakeRequest[Five, wbRqstCycle, High]]; IF rand <= myState.cacheWSRand THEN RETURN [DynaSeer.MakeRequest[Two, wsRqstCycle, Low]]; RETURN [NIL]; }; TreatBusCycle: PROC [cycle: Cycle] = { SELECT cycle.cmd FROM RBRply, WBRply, WSRply => IF cycle.deviceId=myId THEN myState.requestStatus _ notRequesting; ENDCASE; }; TreatBusCycle[cycle]; SELECT myState.requestStatus FROM notRequesting => { request: Request _ GenerateCacheLPRequest[]; IF request#NIL THEN { myState.requestStatus _ requesting; IF request.priority=Low THEN handle.cacheLPRequests[myId] _ request ELSE handle.cacheHPRequests[myId] _ request; }; }; requesting => { hpRequest: Request _ handle.cacheHPRequests[myId]; lpRequest: Request _ handle.cacheLPRequests[myId]; IF lpRequest=NIL AND hpRequest=NIL THEN myState.requestStatus _ waitingForReply ELSE { IF lpRequest#NIL THEN lpRequest.cycles.first.grantLatency _ lpRequest.cycles.first.grantLatency+1; IF hpRequest#NIL THEN hpRequest.cycles.first.grantLatency _ hpRequest.cycles.first.grantLatency+1; }; }; ENDCASE; }; END.