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% per-item occupancy [nitems x (lists+1)] from converged access factors (RR/FIFO
40% exact recursion skipped, NaN,
for >10 items); see _kb/09-ldes-and-cache.md
41for ci = 1:length(caches)
42 if ~isempty(cacheinfo.gamma{ci})
43 ni = size(cacheinfo.gamma{ci},1);
44 hi = numel(cacheinfo.m{ci});
45 if cacheinfo.strat{ci} == ReplacementStrategy.LRU
46 itemprob = cache_ttl_lrua(cacheinfo.lambda_cache{ci}, cacheinfo.Rcost{ci}, cacheinfo.m{ci});
48 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);
49 itemprob = NaN(ni, hi+1);
51 itemprob = cache_prob_erec(cacheinfo.gamma{ci}, cacheinfo.m{ci});
53 self.model.nodes{caches(ci)}.setResultItemProb(itemprob);
57 function missrate = miss_exact(gamma, m, lambda_cache, ~)
58 u = size(lambda_cache, 1);
59 [~,~,pij] = cache_mva(gamma, m);
60 pij = [abs(1-sum(pij,2)), pij];
61 missrate = zeros(1, u);
63 missrate(v) = lambda_cache(v,:,1) * pij(:,1);
67 function missrate = miss_fpi(gamma, m, lambda_cache, ~)
68 line_debug('Default method: using FPI approximation for cache\n');
69 line_debug('Using FPI approximation, calling cache_miss_fpi');
70 [~, missrate] = cache_miss_fpi(gamma, m, lambda_cache);
73 function res = netsolve(snit)
76 case {
'aba.upper',
'aba.lower',
'bjb.upper',
'bjb.lower',
'pb.upper',
'pb.lower',
'gb.upper',
'gb.lower',
'sb.upper',
'sb.lower'}
77 [res.Q,res.U,res.R,res.T,res.C,res.X,res.lG,res.runtime] = solver_ba_analyzer(snit, options);
79 if ~isempty(snit.lldscaling) || ~isempty(snit.cdscaling) || ~isempty(snit.jdscaling)
80 [res.Q,res.U,res.R,res.T,res.C,res.X,res.lG,res.runtime] = solver_mvald_analyzer(snit, options);
82 [res.Q,res.U,res.R,res.T,res.C,res.X,res.lG,res.runtime] = solver_mva_analyzer(snit, options);