-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibta.h
377 lines (297 loc) · 9.72 KB
/
libta.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
/** @file libta.h
* The main header file for libta.
*
* This header contains the main classes to be used for interfacing the resource manager with the
* underlying software that computes the WCET timing analysis.
*
* @copyright
* Copyright 2020 Politecnico di Milano
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef LIBTA_H_
#define LIBTA_H_
#include <cassert>
#include <cmath>
#include <memory>
#include <vector>
#include <tuple>
#include <exception>
namespace libta {
//
// ---------------------------------- ENUMERATIONS ----------------------------------
//
/**
* @brief The enumeration for the response type
*
* The TimingAnalyzer returns a general Response class and this
* value represents with child-class actually is.
*/
typedef enum class response_type_e {
PWCET_DISTRIBUTION, /*!< The output is a statistical distribution */
WCET_VALUE /*!< The output is a single WCET value */
} response_type_t;
/**
* @brief The enumeration for type of distribution
*
* If the output is a distribution, this datatype is used to identify the distribution class.
*/
typedef enum class distribution_type_e {
EVT_GEV, /**< Generalized Extreme Value distribution */
EVT_GPD_2PARAM, /**< Generalized Pareto distribution (2-parameters version) */
EVT_GPD_3PARAM /**< Generalized Pareto distribution (3-parameters version) */
} distribution_type_t;
/**
* @brief The enumeration for the error returned by the analyzer
*
*/
typedef enum class error_e {
INVALID_DATA,
INVALID_DISTRIBUTION
} error_t;
//
// ------------------------------------ CLASSES ------------------------------------
//
/**
* @brief The class returned by the timing analysis tool.
*
* @note This class is not abstract but intended to be used with sub-classes only.
*/
class Response {
public:
/**
* @brief The Response class constructor
* @param res_type The type of response
*/
Response(response_type_t resp_type) noexcept : resp_type(resp_type) {
}
/**
* @brief The Response class default destructor
*/
virtual ~Response() = default;
/** @brief Getter for reponse type */
inline response_type_t get_response_type() const noexcept {
return this->resp_type;
}
private:
const response_type_t resp_type;
};
/**
* @brief The class returned by the timing analysis tool when the output is the EVT distribution
*
*/
class ResponseEVTDistribution : public Response {
public:
/**
* @brief The type for EVT distribution parameters
*
* GEV distribution has three parameters \mu, \sigma and \xi. The same for the 3-parameters
* version of GPD. In case of 2-parameters version GPD the first value (\mu) is not present and
* ignored.
*/
typedef std::tuple<double, double, double, double> parameters_t;
static constexpr int P_MU = 0; /**< */
static constexpr int P_SIGMA = 1; /**< */
static constexpr int P_XI = 2; /**< */
static constexpr int P_THRSH = 3;
/**
* @brief The ResponseEVTDistribution class constructor
* @param dist_type The subtype of EVT distribution (GEV/GPD)
*/
ResponseEVTDistribution(distribution_type_t dist_type) noexcept
: Response(response_type_t::PWCET_DISTRIBUTION),
dist_type(dist_type) {
}
/**
* @brief The ResponseEVTDistribution class default destructor
*/
virtual ~ResponseEVTDistribution() = default;
/*/** @brief Setter for distribution parameters */
void set_parameters(double mu, double sigma, double xi) noexcept {
set_parameters(std::make_tuple(mu, sigma, xi,0));
}
/** @brief Setter for distribution parameters */
void set_parameters(double mu, double sigma, double xi,double threshold ) noexcept {
set_parameters(std::make_tuple(mu, sigma, xi, threshold));
}
/** @brief Setter for distribution parameters */
void set_parameters(parameters_t params) noexcept {
assert(std::get<P_MU>(params) >= 0); // A negative mu has no sense for pWCET purposes
assert(std::get<P_SIGMA>(params) > 0); // Must be positive
this->params = params;
}
/** @brief Getter for \mu parameter */
inline double get_mu() const noexcept {
return std::get<P_MU>(params);
}
/** @brief Getter for \sg parameter */
inline double get_sigma() const noexcept {
return std::get<P_SIGMA>(params);
}
/** @brief Getter for \xi parameter */
inline double get_xi() const noexcept {
return std::get<P_XI>(params);
}
/** @brief Getter for \xi parameter */
inline double get_threshold() const noexcept {
return std::get<P_THRSH>(params);
}
/** @brief Getter for the paramters tuple */
inline parameters_t get_parameters() const noexcept {
return this->params;
}
/** @brief Getter for the distribution type */
inline distribution_type_t get_dist_type() const noexcept {
return this->dist_type;
}
double get_quantile(double p) const {
switch(this->dist_type) {
case distribution_type_t::EVT_GEV:
return get_gev_quantile(p);
case distribution_type_t::EVT_GPD_2PARAM:
case distribution_type_t::EVT_GPD_3PARAM:
return get_gpd_quantile(p);
default:
assert(false);
}
return 0; // Cannot be reached
}
private:
const distribution_type_t dist_type;
parameters_t params;
double get_gev_quantile(double p) const {
if (p <= 0. || p >= 1.) {
throw std::invalid_argument("The probability value is not valid.");
}
auto mu = std::get<P_MU>(params);
auto sg = std::get<P_SIGMA>(params);
auto xi = std::get<P_XI>(params);
if (xi == 0.) {
return mu - sg * std::log(-std::log(p));
} else {
return mu + sg * (1.-std::pow((-std::log(p)),(-xi)))/(-xi);
}
}
double get_gpd_quantile(double p) const {
auto mu = std::get<P_MU>(params);
auto sg = std::get<P_SIGMA>(params);
auto xi = std::get<P_XI>(params);
if (p <= 0. || p >= 1.) {
throw std::invalid_argument("The probability value is not valid.");
}
double quantile;
if (xi != 0.) {
quantile = mu + sg * (1. - std::pow(1. - p, -xi)) / (-xi);
} else {
quantile = mu - sg * std::log(1. - p);
}
return quantile;
}
};
/**
* @brief The class returned by the timing analysis tool when the output is a WCET value. The
* class is a template class because the WCET can be a float, an integer, etc. depending on
* the context.
*
*/
template <typename T>
class ResponseWCET : public Response {
public:
/**
* @brief The ResponseWCET class constructor
*/
ResponseWCET() noexcept : Response(response_type_t::WCET_VALUE)
{
}
/**
* @brief The ResponseWCET class default destructor
*/
virtual ~ResponseWCET() = default;
/** @brief Getter for the WCET value */
inline T get_wcet_value() const {
return this->wcet_value;
}
/** @brief Setter for the WCET value */
inline void set_wcet_value(T value) {
this->wcet_value = value;
}
private:
T wcet_value;
};
/**
* @brief The class representing the objects sent to the timing analysis tool
*
*/
template <typename T>
class Request {
public:
/**
* @brief The ResponseWCET class constructor
*/
Request() noexcept {}
virtual ~Request() = default;
/** @brief Begin iterator for for-range-loops */
inline typename std::vector<T>::iterator begin() noexcept {
return this->execution_times.begin();
}
/** @brief Const begin iterator for for-range-loops */
inline typename std::vector<T>::const_iterator cbegin() const noexcept {
return this->execution_times.cbegin();
}
/** @brief End iterator for for-range-loops */
inline typename std::vector<T>::iterator end() noexcept {
return this->execution_times.end();
}
/** @brief Const end iterator for for-range-loops */
inline typename std::vector<T>::const_iterator cend() const noexcept {
return this->execution_times.cend();
}
/** @brief Getter for the whole timing array. Do not try to edit the returned value. */
inline const std::vector<T> &get_all() const noexcept {
return this->execution_times;
}
/** @brief Add new values to the timing array */
inline void add_value(const T& time) {
this->execution_times.push_back(time);
}
private:
std::vector<T> execution_times;
};
class TimingAnalyzerError : public std::runtime_error {
public:
TimingAnalyzerError(const std::string& what_arg, error_t err_type) noexcept
: std::runtime_error(what_arg), err(err_type) {}
virtual ~TimingAnalyzerError() = default;
inline error_t get_type() const noexcept {
return this->err;
}
private:
error_t err;
};
/**
* @brief The main class to be inherited and implemented by the Timing Analysis tool.
*
* @note This class is abstract and must be inherited to be instanced.
*/
template <typename T>
class TimingAnalyzer {
public:
virtual ~TimingAnalyzer() = default;
/**
* @brief The main method to be implemented that will perform the analysis.
*/
virtual std::shared_ptr<Response> perform_analysis(std::shared_ptr<Request<T>> req) = 0;
};
} // libta
#endif // LIBTA_H_