1function [QNn,UNn,RNn,TNn,ANn,WNn] = getAvgNode(self, Q, U, R, T, A, W)
2% [QNN,UNN,RNN,TNN,ANn,WNn] = GETNODEAVG(Q, U, R, T, A, W)
4% Compute average utilizations at steady-state
for all
nodes
6if nargin == 1 % no parameter
7 if isempty(self.model.handles) || ~isfield(self.model.handles,
'Q') || ...
8 ~isfield(self.model.handles,
'U') || ~isfield(self.model.handles,
'R') || ...
9 ~isfield(self.model.handles,
'T') || ~isfield(self.model.handles,
'A') || ...
10 ~isfield(self.model.handles,
'W')
11 reset(self); % reset in case there are partial results saved
13 [Q,U,R,T,A,W] = self.getAvgHandles;
16 [Q,U,R,T,A,W] = deal(handlers{:}); % set Q=handlers{1}, U=handlers{2}, ...
19[QN,UN,RN,TN,AN,WN] = self.getAvg(Q,U,R,T,A,W);
21 [QNn, UNn, RNn, TNn, ANn, WNn] = deal([]); % set each to []
25sn = self.model.getStruct; % must be called after getAvg eg
for caches
27% Resync each Cache node
's hit/miss/delayed-hit split into the local struct
28% before reconstructing node throughputs. self.model.sn may be cached
29% (hasStruct=true) and still hold the split written by a PREVIOUSLY run solver,
30% which makes the cache node throughputs order-dependent (e.g. an exact CTMC run
31% after LDES would otherwise report LDES's residual hit ratio). The authoritative
32% result of the solver that just ran
is on the node
's server (set via
33% setResultHitProb); copy it into the local sn so the throughput reconstruction
34% below always reflects THIS solver. Mirrors refreshLocalVars.m.
36 if sn.nodetype(ind) == NodeType.Cache
37 node = self.model.nodes{ind};
38 if isprop(node.server, 'actualHitProb
') && ~isempty(node.server.actualHitProb)
39 sn.nodeparam{ind}.actualhitprob = full(node.server.actualHitProb);
40 sn.nodeparam{ind}.actualmissprob = full(node.server.actualMissProb);
42 if isprop(node.server, 'actualDelayedHitProb
') && ~isempty(node.server.actualDelayedHitProb)
43 sn.nodeparam{ind}.actualdelayedhitprob = full(node.server.actualDelayedHitProb);
48I = sn.nnodes; % Physical nodes only
51F = sn.nregions; % Number of FCR virtual nodes
53% Total nodes includes physical nodes + FCR virtual nodes
56% get average metrics that are zero at non-station nodes
57QNn = zeros(totalNodes, R);
58UNn = zeros(totalNodes, R);
59RNn = zeros(totalNodes, R);
60WNn = zeros(totalNodes, R);
62% Map station metrics to node metrics
64 ind = sn.stationToNode(ist);
65 QNn(ind,:) = QN(ist,:);
66 UNn(ind,:) = UN(ist,:);
67 RNn(ind,:) = RN(ist,:);
68 WNn(ind,:) = WN(ist,:);
71% get the remaining node average metrics
72ANn = sn_get_node_arvr_from_tput(sn, TN(1:M,:), T, AN);
73TNn = sn_get_node_tput_from_tput(sn, TN(1:M,:), T, ANn);
75% Fix arrival rates for ClassSwitch and Sink nodes for cache hit/miss classes
76% The arrival rate at these nodes for hit/miss classes equals the Cache throughput
78 if sn.nodetype(cacheInd) == NodeType.Cache
79 hitclass = sn.nodeparam{cacheInd}.hitclass;
80 missclass = sn.nodeparam{cacheInd}.missclass;
81 % Update arrival rates at ClassSwitch and Sink nodes for hit/miss classes
83 if sn.nodetype(ind) == NodeType.ClassSwitch || sn.nodetype(ind) == NodeType.Sink
85 % Check if this class is a hit class from the cache
86 if any(classIdx == hitclass(hitclass > 0))
87 ANn(ind, classIdx) = TNn(cacheInd, classIdx);
89 % Check if this class is a miss class from the cache
90 if any(classIdx == missclass(missclass > 0))
91 ANn(ind, classIdx) = TNn(cacheInd, classIdx);
99% Extend ANn and TNn to include FCR rows
101 ANn = [ANn; NaN(F, R)]; % FCR A is NaN (JMT doesn't provide)
102 TNn = [TNn; zeros(F, R)];
105% Map FCR pseudo-station metrics to FCR node indices
106% FCR metrics are stored at station indices M+1 to M+F in self.result.Avg
107% FCR node indices are I+1 to I+F in node-level matrices
108% Note: getAvg() only returns station-level metrics (1:M), so we access FCR
109% metrics directly from self.result.Avg
110if F > 0 && isfield(self.result, 'Avg') && size(self.result.Avg.Q, 1) > M
112 fcrStationIdx = M + f; % FCR pseudo-station index in result matrices
113 fcrNodeIdx = I + f; % FCR node index in nodenames
114 QNn(fcrNodeIdx,:) = self.result.Avg.Q(fcrStationIdx,:);
115 UNn(fcrNodeIdx,:) = self.result.Avg.U(fcrStationIdx,:);
116 RNn(fcrNodeIdx,:) = self.result.Avg.R(fcrStationIdx,:);
117 WNn(fcrNodeIdx,:) = self.result.Avg.W(fcrStationIdx,:);
118 TNn(fcrNodeIdx,:) = self.result.Avg.T(fcrStationIdx,:);
119 % ANn for FCR
is NaN (already set above)