1function [outspace, outrate, outprob, eventCache] = afterEventCache(sn, ind, event,
class, isSimulation, eventCache, R, space_buf, space_srv, space_var, key)
2% job arrives in
class, then reads and moves into hit or miss
10 space_srv(:,class) = space_srv(:,class) + 1;
11 outspace = [space_srv, space_var]; % buf
is empty
12 outrate = -1*ones(size(outspace,1)); % passive action, rate
is unspecified
15 % A retrieval-
class job departs the cache only to BEGIN a retrieval
16 % (cache -> queue); record the item in the per-item occupancy bitmap.
18 if isfield(sn.nodeparam{ind},
'retrievalClassIndices')
19 rciDep = sn.nodeparam{ind}.retrievalClassIndices;
23 if any(rciDep ==
class)
24 if isfield(sn.nodeparam{ind},
'totalCacheCapacity')
25 tccDep = sn.nodeparam{ind}.totalCacheCapacity;
27 tccDep = sum(sn.nodeparam{ind}.itemcap);
29 pDep = sn.nodeparam{ind}.pread{
class};
30 item = find(pDep == 1, 1,
'first'); % retrieval
class reads its one-hot item
31 if ~isempty(item) && (tccDep + item <= size(space_var,2))
32 if any(space_var(:, tccDep + item) ~= 0)
33 beginBlocked = true; % already retrieving
this item -> no transition
35 space_var(:, tccDep + item) = 1;
40 space_srv(:,class) = space_srv(:,class) - 1;
41 switch sn.routing(ind,
class)
42 case RoutingStrategy.RROBIN
43 idx = find(space_var(sum(sn.nvars(ind,1:(R+class)))) == sn.nodeparam{ind}{
class}.outlinks);
44 if idx < length(sn.nodeparam{ind}{class}.outlinks)
45 space_var(sum(sn.nvars(ind,1:(R+class)))) = sn.nodeparam{ind}{
class}.outlinks(idx+1);
47 space_var(sum(sn.nvars(ind,1:(R+class)))) = sn.nodeparam{ind}{
class}.outlinks(1);
50 outspace = [space_srv, space_var]; % buf
is empty
51 outrate = GlobalConstants.Immediate*ones(size(outspace,1)); % immediate action
55 n = sn.nodeparam{ind}.nitems; % n items
56 m = sn.nodeparam{ind}.itemcap; % capacity
57 ac = sn.nodeparam{ind}.accost; % access cost
58 hitclass = sn.nodeparam{ind}.hitclass;
59 missclass = sn.nodeparam{ind}.missclass;
61 replacement_id = sn.nodeparam{ind}.replacestrat;
62 % retrieval-system parameters (set by Cache.setRetrievalSystem; defaults below)
63 if isfield(sn.nodeparam{ind},
'totalCacheCapacity')
64 totalCacheCapacity = sn.nodeparam{ind}.totalCacheCapacity;
66 totalCacheCapacity = sum(m);
68 if isfield(sn.nodeparam{ind},
'retrievalClasses')
69 retrievalClasses = sn.nodeparam{ind}.retrievalClasses;
71 retrievalClasses = [];
73 if isfield(sn.nodeparam{ind},
'retrievalClassIndices')
74 retrievalClassIndices = sn.nodeparam{ind}.retrievalClassIndices;
76 retrievalClassIndices = [];
78 if space_srv(
class)>0 && sum(space_srv)==1 % a job of
class is in
79 p = sn.nodeparam{ind}.pread{
class};
80 en = space_srv(:,class) > 0;
86 isFromRetrieval = any(retrievalClassIndices == class);
87 if isSimulation || isFromRetrieval
88 % pick one item (a returning retrieval reads exactly its own item)
89 kset = 1 + max([0,find( rand > cumsum(p) )]);
90 % pick one entry list for cache miss
91 % do not move this entry
92 l = 1 + max([0,find( rand > cumsum(ac{class,kset}(1,:)) )]);
96 for k=kset % request to item k
97 space_srv_e = space_srv(e,:);
98 space_srv_e(class) = space_srv_e(class) - 1;
100 % posk is searched only in the cache-contents region (1..totalCacheCapacity).
101 % The trailing retrieval-system slots (if any) are out of scope here.
102 posk = find(k==var(1:totalCacheCapacity),1,'first
');
103 % A retrieval-complete READ always completes the miss that started
104 % the retrieval, so it must take the cache-miss branch even if the
105 % state-space enumeration produced a (then unreachable) state in
106 % which item k is already cached. This also avoids indexing the
107 % undefined hitClass of a retrieval-complete class.
112 if isempty(posk) % CACHE MISS or RETRIEVAL begin/return
113 % Retrieval-system occupancy bitmap: column (totalCacheCapacity+k)
114 % is non-zero iff item k is currently being retrieved.
115 inRetrieval = (totalCacheCapacity + k <= size(var,2)) && var(totalCacheCapacity + k) ~= 0;
117 if ~isempty(retrievalClasses) && ...
118 class <= size(retrievalClasses,2) && ...
119 k <= size(retrievalClasses,1)
120 rClass = retrievalClasses(k, class);
123 % A returning retrieval that is not recorded in the bitmap is an
124 % unreachable event-loop artifact; do not continue it.
125 if isFromRetrieval && ~inRetrieval
129 % Begin a retrieval: the job switches to the retrieval class for
130 % item k. The occupancy bitmap is set on the subsequent DEP (when
131 % the job departs the cache for the queue), so the cache contents
132 % are unchanged here. A concurrent request for an item already
133 % being retrieved is served by the in-flight retrieval and exits
134 % (its class is not incremented, so the job is absorbed).
135 if ~isFromRetrieval && rClass ~= -1
137 space_srv_e(rClass) = space_srv_e(rClass) + 1;
139 space_srv_k = [space_srv_k; space_srv_e];
140 space_var_k = [space_var_k; var];
142 outrate(end+1,1) = GlobalConstants.Immediate;
143 outprob(end+1,1) = p(k);
145 outrate(end+1,1) = p(k) * GlobalConstants.Immediate;
150 % Item has now been retrieved (or there is no retrieval system):
151 % mark it as a miss and clear its retrieval-system bit.
152 space_srv_e(missclass(class)) = space_srv_e(missclass(class)) + 1;
153 if totalCacheCapacity + k <= size(var,2)
154 var(totalCacheCapacity + k) = 0;
156 switch replacement_id
157 case {ReplacementStrategy.FIFO, ReplacementStrategy.LRU, ReplacementStrategy.SFIFO}
159 listidx = l - 1; % l is accessCost column index, listidx is actual list (1-indexed)
160 if listidx > 0 % only cache if listidx is valid (l >= 2)
162 varp(cpos(listidx,2):cpos(listidx,m(listidx))) = var(cpos(listidx,1):cpos(listidx,m(listidx)-1));
163 varp(cpos(listidx,1)) = k; % head of list listidx
164 space_srv_k = [space_srv_k; space_srv_e];
165 space_var_k = [space_var_k; varp];
166 %% no p(k) weighting since that goes in the outprob vec
167 outrate(end+1,1) = GlobalConstants.Immediate;
168 outprob(end+1,1) = ac{class,k}(1,l) * p(k);
170 % Cache reject (l=1): pass through without caching
171 space_srv_k = [space_srv_k; space_srv_e];
172 space_var_k = [space_var_k; var];
173 outrate(end+1,1) = GlobalConstants.Immediate;
174 outprob(end+1,1) = ac{class,k}(1,l) * p(k);
177 for l=2:(h+1) % iterate over all possible target lists (columns 2 to h+1)
178 listidx = l - 1; % l is accessCost column index, listidx is actual list (1-indexed)
180 varp(cpos(listidx,2):cpos(listidx,m(listidx))) = var(cpos(listidx,1):cpos(listidx,m(listidx)-1));
181 varp(cpos(listidx,1)) = k; % head of list listidx
182 space_srv_k = [space_srv_k; space_srv_e];
183 space_var_k = [space_var_k; varp];
184 outrate(end+1,1) = ac{class,k}(1,l) * p(k) * GlobalConstants.Immediate;
185 outprob(end+1,1) = 1;
188 case ReplacementStrategy.RR
190 listidx = l - 1; % l is accessCost column index, listidx is actual list (1-indexed)
191 if listidx > 0 % only cache if listidx is valid (l >= 2)
193 r = randi(m(listidx),1,1);
194 varp(cpos(listidx,r)) = k;
195 space_srv_k = [space_srv_k; space_srv_e];
196 space_var_k = [space_var_k; (varp)];
197 outrate(end+1,1) = GlobalConstants.Immediate;
198 outprob(end+1,1) = ac{
class,k}(1,l) * p(k);
200 % Cache reject (l=1): pass through without caching
201 space_srv_k = [space_srv_k; space_srv_e];
202 space_var_k = [space_var_k; var];
203 outrate(end+1,1) = GlobalConstants.Immediate;
204 outprob(end+1,1) = ac{
class,k}(1,l) * p(k);
207 for l=2:(h+1) % iterate over all possible target lists
208 listidx = l - 1; % l
is accessCost column index, listidx
is actual list (1-indexed)
209 for r=1:m(listidx) % random position in list listidx
211 varp(cpos(listidx,r)) = k;
212 space_srv_k = [space_srv_k; space_srv_e];
213 space_var_k = [space_var_k; (varp)];
214 outrate(end+1,1) = ac{
class,k}(1,l) * p(k)/m(listidx) * GlobalConstants.Immediate;
219 elseif posk <= sum(m(1:h-1)) % CACHE HIT in list i < h, move to list i+1
220 space_srv_e(hitclass(class)) = space_srv_e(hitclass(class)) + 1;
221 i = min(find(posk <= cumsum(m)));
222 j = posk - sum(m(1:i-1));
224 switch replacement_id
225 case ReplacementStrategy.FIFO
228 inew = i+probchoose(ac{
class,k}(1+i,(1+i):end)/sum(ac{class,k}(1+i,(1+i):end)))-1; % can choose i
230 varp(cpos(i,j)) = var(cpos(inew,m(inew)));
231 varp(cpos(inew,2):cpos(inew,m(inew))) = var(cpos(inew,1):cpos(inew,m(inew)-1));
232 varp(cpos(inew,1)) = k;
234 %varp(cpos(i,j)) = var(cpos(i+1,m(i+1)));
235 %varp(cpos(i+1,2):cpos(i+1,m(i+1))) = var(cpos(i+1,1):cpos(i+1,m(i+1)-1));
236 %varp(cpos(i+1,1)) = k;
238 space_srv_k = [space_srv_k; space_srv_e];
239 space_var_k = [space_var_k; varp];
240 outrate(end+1,1) = GlobalConstants.Immediate;
241 outprob(end+1,1) = ac{
class,k}(1+i,1+inew) * p(k);
245 varp(cpos(i,j)) = var(cpos(inew,m(inew)));
246 varp(cpos(inew,2):cpos(inew,m(inew))) = var(cpos(inew,1):cpos(inew,m(inew)-1));
247 varp(cpos(inew,1)) = k;
248 space_srv_k = [space_srv_k; space_srv_e];
249 space_var_k = [space_var_k; varp];
250 outrate(end+1,1) = ac{
class,k}(1+i,1+inew) * p(k) * GlobalConstants.Immediate;
253 case ReplacementStrategy.RR
255 inew = i+probchoose(ac{
class,k}(1+i,(1+i):end)/sum(ac{class,k}(1+i,(1+i):end)))-1; % can choose i
257 r = randi(m(inew),1,1);
258 varp(cpos(i,j)) = var(cpos(inew,r));
259 varp(cpos(inew,r)) = k;
260 space_srv_k = [space_srv_k; space_srv_e];
261 space_var_k = [space_var_k; varp];
262 outrate(end+1,1) = GlobalConstants.Immediate;
263 outprob(end+1,1) = ac{
class,k}(1+i,1+inew) * p(k)/m(inew);
266 for r=1:m(inew) % random position in
new list
268 varp(cpos(i,j)) = var(cpos(inew,r));
269 varp(cpos(inew,r)) = k;
270 space_srv_k = [space_srv_k; space_srv_e];
271 space_var_k = [space_var_k; varp];
272 outrate(end+1,1) = ac{
class,k}(1+i,1+inew) * p(k)/m(inew) * GlobalConstants.Immediate;
276 case {ReplacementStrategy.LRU, ReplacementStrategy.SFIFO}
279 inew = i+probchoose(ac{
class,k}(1+i,(1+i):end)/sum(ac{class,k}(1+i,(1+i):end)))-1; % can choose i
280 varp(cpos(i,2):cpos(i,j)) = var(cpos(i,1):cpos(i,j-1));
281 varp(cpos(i,1)) = var(cpos(inew,m(inew)));
282 varp(cpos(inew,2):cpos(inew,m(inew))) = var(cpos(inew,1):cpos(inew,m(inew)-1));
283 varp(cpos(inew,1)) = k;
284 space_srv_k = [space_srv_k; space_srv_e];
285 space_var_k = [space_var_k; varp];
286 outrate(end+1,1) = GlobalConstants.Immediate;
287 outprob(end+1,1) = ac{
class,k}(1+i,1+inew) * p(k);
291 varp(cpos(i,2):cpos(i,j)) = var(cpos(i,1):cpos(i,j-1));
292 varp(cpos(i,1)) = var(cpos(inew,m(inew)));
293 varp(cpos(inew,2):cpos(inew,m(inew))) = var(cpos(inew,1):cpos(inew,m(inew)-1));
294 varp(cpos(inew,1)) = k;
295 space_srv_k = [space_srv_k; space_srv_e];
296 space_var_k = [space_var_k; varp];
297 outrate(end+1,1) = ac{
class,k}(1+i,1+inew) * p(k) * GlobalConstants.Immediate;
301 else % CACHE HIT in list h
302 space_srv_e(hitclass(
class)) = space_srv_e(hitclass(
class)) + 1;
304 j = posk - sum(m(1:i-1));
305 switch replacement_id
306 case {ReplacementStrategy.RR, ReplacementStrategy.FIFO, ReplacementStrategy.SFIFO}
307 space_srv_k = [space_srv_k; space_srv_e];
308 space_var_k = [space_var_k; var];
310 outrate(end+1,1) = GlobalConstants.Immediate;
311 outprob(end+1,1) = p(k);
313 outrate(end+1,1) = p(k) * GlobalConstants.Immediate;
315 case ReplacementStrategy.LRU
317 varp(cpos(h,2):cpos(h,j)) = var(cpos(h,1):cpos(h,j-1));
318 varp(cpos(h,1)) = var(cpos(h,j));
319 space_srv_k = [space_srv_k; space_srv_e];
320 space_var_k = [space_var_k; varp];
322 outrate(end+1,1) = GlobalConstants.Immediate;
323 outprob(end+1,1) = p(k);
325 outrate(end+1,1) = p(k) * GlobalConstants.Immediate;
331 %
if state
is unchanged, still add with rate 0
332 outspace = [space_srv_k, space_var_k];
336 function pos = cpos(i,j)
339 pos = sum(m(1:i-1)) + j;