1function [Q,U,R,T,C,X,lG,hitprob,missprob,runtime,it] = solver_mva_cacheqn_analyzer(self, options)
2% [Q,U,R,T,C,X,LG,RUNTIME,ITER] = SOLVER_MVA_CACHEQN_ANALYZER(SELF, OPTIONS)
4% Integrated cache-queueing analyzer: delegates
the decomposition-
5% aggregation alternation between
the isolated caches and
the queueing
6% network to da_cacheqn, supplying
the MVA-specific isolated-cache miss
7% algorithm (exact cache_mva or FPI approximation) and network solver.
9% Copyright (c) 2012-2026, Imperial College London
12snorig = self.model.getStruct;
16line_debug(
'MVA cacheqn analyzer starting: method=%s, nclasses=%d', options.method, K);
18caches = find(sn.nodetype == NodeType.Cache);
22 missfun = @miss_exact;
27[res, hitprob_pc, missprob_pc, it, ~, cacheinfo] = da_cacheqn(sn, missfun, @netsolve, options);
28Q = res.Q; U = res.U; R = res.R; T = res.T; C = res.C; X = res.X;
29lG = res.lG; runtime = res.runtime;
31% legacy contract: hit/miss probabilities indexed by node row
32hitprob = zeros(length(caches), K);
33missprob = zeros(length(caches), K);
34for ci = 1:length(caches)
35 hitprob(caches(ci),:) = hitprob_pc(ci,:);
36 missprob(caches(ci),:) = missprob_pc(ci,:);
39% Report
the per-item occupancy [nitems x (lists+1)] (col 1 = miss) from
the
40% converged access factors, so getAvgItemTable
is populated
for integrated
41% cache-queueing models too. LRU uses
the scalable TTL algorithm; RR/FIFO use
the
42% exact product-form recursion, which
is only tractable
for small item sets and
43%
is therefore skipped (NaN, with a warning) when there are more than 10 items.
44for ci = 1:length(caches)
45 if ~isempty(cacheinfo.gamma{ci})
46 ni = size(cacheinfo.gamma{ci},1);
47 hi = numel(cacheinfo.m{ci});
48 if cacheinfo.strat{ci} == ReplacementStrategy.LRU
49 itemprob = cache_ttl_lrua(cacheinfo.lambda_cache{ci}, cacheinfo.Rcost{ci}, cacheinfo.m{ci});
51 line_warning(mfilename,
'Per-item cache occupancy (getAvgItemTable) requires the exact algorithm for RR/FIFO and is skipped for caches with more than 10 items (%d items); reporting NaN.', ni);
52 itemprob = NaN(ni, hi+1);
54 itemprob = cache_prob_erec(cacheinfo.gamma{ci}, cacheinfo.m{ci});
56 self.model.nodes{caches(ci)}.setResultItemProb(itemprob);
60 function missrate = miss_exact(gamma, m, lambda_cache, ~)
61 u = size(lambda_cache, 1);
62 [~,~,pij] = cache_mva(gamma, m);
63 pij = [abs(1-sum(pij,2)), pij];
64 missrate = zeros(1, u);
66 missrate(v) = lambda_cache(v,:,1) * pij(:,1);
70 function missrate = miss_fpi(gamma, m, lambda_cache, ~)
71 line_debug('Default method: using FPI approximation for cache\n');
72 line_debug('Using FPI approximation, calling cache_miss_fpi');
73 [~, missrate] = cache_miss_fpi(gamma, m, lambda_cache);
76 function res = netsolve(snit)
79 case {
'aba.upper',
'aba.lower',
'bjb.upper',
'bjb.lower',
'pb.upper',
'pb.lower',
'gb.upper',
'gb.lower',
'sb.upper',
'sb.lower'}
80 [res.Q,res.U,res.R,res.T,res.C,res.X,res.lG,res.runtime] = solver_ba_analyzer(snit, options);
82 if ~isempty(snit.lldscaling) || ~isempty(snit.cdscaling)
83 [res.Q,res.U,res.R,res.T,res.C,res.X,res.lG,res.runtime] = solver_mvald_analyzer(snit, options);
85 [res.Q,res.U,res.R,res.T,res.C,res.X,res.lG,res.runtime] = solver_mva_analyzer(snit, options);