Line data Source code
1 : /**
2 : * @file toolbox.cpp
3 : *
4 : * This is part of the DUNE DAQ Software Suite, copyright 2020.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 :
9 : #include "timing/toolbox.hpp"
10 :
11 : // PDT Headers
12 : #include "timing/TimingIssues.hpp"
13 :
14 : // uHAL Headers
15 : #include "uhal/ValMem.hpp"
16 :
17 : // Boost Headers
18 : #include "boost/foreach.hpp"
19 : #include <boost/filesystem/operations.hpp>
20 : #include <boost/filesystem/path.hpp>
21 :
22 : // C++ Headers
23 : #include <cstdarg>
24 : #include <cstdint>
25 : #include <cstdio>
26 : #include <cstdlib>
27 : #include <ctime>
28 : #include <map>
29 : #include <stdexcept>
30 : #include <string>
31 : #include <utility>
32 : #include <vector>
33 : #include <wordexp.h>
34 :
35 : using namespace std;
36 :
37 : namespace dunedaq {
38 : namespace timing {
39 :
40 : //-----------------------------------------------------------------------------
41 : Snapshot
42 0 : snapshot(const uhal::Node& node)
43 : {
44 : /// snapshot( node ) -> { subnode:value }
45 0 : std::map<string, uhal::ValWord<uint32_t>> value_words; // NOLINT(build/unsigned)
46 :
47 0 : for (string n : node.getNodes()) {
48 0 : value_words.insert(make_pair(n, node.getNode(n).read()));
49 0 : }
50 0 : node.getClient().dispatch();
51 :
52 0 : Snapshot vals;
53 0 : std::map<string, uhal::ValWord<uint32_t>>::iterator it; // NOLINT(build/unsigned)
54 0 : for (it = value_words.begin(); it != value_words.end(); ++it)
55 0 : vals.insert(make_pair(it->first, it->second.value()));
56 :
57 0 : return vals;
58 0 : }
59 : //-----------------------------------------------------------------------------
60 :
61 : //-----------------------------------------------------------------------------
62 : Snapshot
63 0 : snapshot(const uhal::Node& node, const std::string& regex)
64 : {
65 0 : std::map<string, uhal::ValWord<uint32_t>> value_words; // NOLINT(build/unsigned)
66 :
67 0 : for (string n : node.getNodes(regex)) {
68 0 : value_words.insert(make_pair(n, node.getNode(n).read()));
69 0 : }
70 0 : node.getClient().dispatch();
71 :
72 0 : Snapshot vals;
73 0 : std::map<string, uhal::ValWord<uint32_t>>::iterator it; // NOLINT(build/unsigned)
74 0 : for (it = value_words.begin(); it != value_words.end(); ++it)
75 0 : vals.insert(make_pair(it->first, it->second.value()));
76 :
77 0 : return vals;
78 0 : }
79 : //-----------------------------------------------------------------------------
80 :
81 : //-----------------------------------------------------------------------------
82 : void
83 0 : millisleep(const double& time_in_milliseconds)
84 : {
85 : // using namespace uhal;
86 : // logging();
87 0 : double time_in_seconds(time_in_milliseconds / 1e3);
88 0 : int integer_part(static_cast<int>(time_in_seconds));
89 0 : double fractional_part(time_in_seconds - static_cast<double>(integer_part));
90 0 : struct timespec sleep_time, return_time;
91 0 : sleep_time.tv_sec = integer_part;
92 0 : sleep_time.tv_nsec = static_cast<long>(fractional_part * 1e9); // NOLINT
93 0 : nanosleep(&sleep_time, &return_time);
94 0 : }
95 : //-----------------------------------------------------------------------------
96 :
97 : //-----------------------------------------------------------------------------
98 : std::string
99 0 : strprintf(const char* fmt, ...) // NOLINT
100 : {
101 0 : char* ret;
102 0 : va_list ap;
103 0 : va_start(ap, fmt);
104 0 : vasprintf(&ret, fmt, ap); // NOLINT
105 0 : va_end(ap);
106 0 : std::string str(ret);
107 0 : free(ret);
108 0 : return str;
109 : }
110 : //-----------------------------------------------------------------------------
111 :
112 : //-----------------------------------------------------------------------------
113 : std::vector<std::string>
114 0 : shell_expand_paths(const std::string& path)
115 : {
116 :
117 0 : std::vector<std::string> paths;
118 0 : wordexp_t substituted_path;
119 0 : int code = wordexp(path.c_str(), &substituted_path, WRDE_NOCMD);
120 0 : if (code)
121 0 : throw runtime_error("Failed expanding path: " + path);
122 :
123 0 : for (std::size_t i = 0; i != substituted_path.we_wordc; i++)
124 0 : paths.push_back(substituted_path.we_wordv[i]);
125 :
126 0 : wordfree(&substituted_path);
127 :
128 0 : return paths;
129 0 : }
130 : //-----------------------------------------------------------------------------
131 :
132 : //-----------------------------------------------------------------------------
133 : std::string
134 0 : shellExpandPath(const std::string& path)
135 : {
136 0 : std::vector<std::string> paths = shell_expand_paths(path);
137 :
138 0 : if (paths.size() > 1)
139 0 : throw runtime_error("Failed to expand: multiple matches found");
140 :
141 0 : return paths[0];
142 0 : }
143 : //-----------------------------------------------------------------------------
144 :
145 : //-----------------------------------------------------------------------------
146 : void
147 0 : throw_if_not_file(const std::string& path)
148 : {
149 :
150 : // FIXME: Review the implementation. The function never returns
151 0 : namespace fs = boost::filesystem;
152 :
153 : // Check that the path exists and that it's not a directory
154 0 : fs::path cfgFile(path);
155 0 : if (!fs::exists(cfgFile)) {
156 0 : throw FileNotFound(ERS_HERE, path);
157 0 : } else if (fs::is_directory(cfgFile)) {
158 0 : throw FileIsDirectory(ERS_HERE, path);
159 : }
160 :
161 : // return true;
162 0 : }
163 : //-----------------------------------------------------------------------------
164 :
165 : //-----------------------------------------------------------------------------
166 : uint8_t // NOLINT(build/unsigned)
167 0 : dec_rng(uint8_t word, uint8_t ibit, uint8_t nbits) // NOLINT(build/unsigned)
168 : {
169 0 : return (word >> ibit) & ((1 << nbits) - 1);
170 : }
171 : //-----------------------------------------------------------------------------
172 :
173 : //-----------------------------------------------------------------------------
174 : uint64_t // NOLINT(build/unsigned)
175 0 : tstamp2int(uhal::ValVector<uint32_t> raw_timestamp) // NOLINT(build/unsigned)
176 : {
177 0 : return (uint64_t)raw_timestamp[0] + ((uint64_t)raw_timestamp[1] << 32); // NOLINT(build/unsigned)
178 : }
179 : //-----------------------------------------------------------------------------
180 :
181 : //-----------------------------------------------------------------------------
182 : int64_t
183 0 : get_seconds_since_epoch()
184 : {
185 : // get the current time
186 0 : const auto now = std::chrono::system_clock::now();
187 :
188 : // transform the time into a duration since the epoch
189 0 : const auto epoch = now.time_since_epoch();
190 :
191 : // cast the duration into seconds
192 0 : const auto seconds = std::chrono::duration_cast<std::chrono::seconds>(epoch);
193 :
194 : // return the number of seconds
195 0 : return seconds.count();
196 : }
197 : //-----------------------------------------------------------------------------
198 :
199 : //-----------------------------------------------------------------------------
200 : int64_t
201 0 : get_milliseconds_since_epoch()
202 : {
203 : // get the current time
204 0 : const auto now = std::chrono::system_clock::now();
205 :
206 : // transform the time into a duration since the epoch
207 0 : const auto epoch = now.time_since_epoch();
208 :
209 : // cast the duration into milliseconds
210 0 : const auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
211 :
212 : // return the number of milliseconds
213 0 : return milliseconds.count();
214 : }
215 : //-----------------------------------------------------------------------------
216 :
217 : //-----------------------------------------------------------------------------
218 : std::string
219 0 : format_timestamp(uint64_t raw_timestamp, uint32_t clock_frequency_hz) // NOLINT(build/unsigned)
220 : {
221 0 : std::time_t sec_from_epoch = raw_timestamp / clock_frequency_hz;
222 :
223 0 : struct tm* time = localtime(&sec_from_epoch); // NOLINT
224 0 : char time_buffer[32];
225 :
226 0 : strftime(time_buffer, sizeof time_buffer, "%a, %d %b %Y %H:%M:%S +0000", time);
227 0 : return time_buffer;
228 : }
229 : //-----------------------------------------------------------------------------
230 :
231 : //-----------------------------------------------------------------------------
232 : std::string
233 0 : format_timestamp(uhal::ValVector<uint32_t> raw_timestamp, uint32_t clock_frequency_hz) // NOLINT(build/unsigned)
234 : {
235 0 : uint64_t timestamp = tstamp2int(raw_timestamp); // NOLINT(build/unsigned)
236 0 : return format_timestamp(timestamp, clock_frequency_hz);
237 : }
238 : //-----------------------------------------------------------------------------
239 :
240 : //-----------------------------------------------------------------------------
241 : double
242 0 : convert_bits_to_float(uint64_t bits, bool is_double_precision) // NOLINT(build/unsigned)
243 : {
244 0 : uint32_t mantissa_shift = is_double_precision ? 52 : 23; // NOLINT(build/unsigned)
245 0 : uint64_t exponent_mask = is_double_precision ? 0x7FF0000000000000 : 0x7f800000; // NOLINT(build/unsigned)
246 0 : uint32_t bias = is_double_precision ? 1023 : 127; // NOLINT(build/unsigned)
247 0 : uint32_t sign_shift = is_double_precision ? 63 : 31; // NOLINT(build/unsigned)
248 :
249 0 : int32_t sign = (bits >> sign_shift) & 0x01;
250 0 : uint32_t exponent_biased = ((bits & exponent_mask) >> mantissa_shift); // NOLINT(build/unsigned)
251 0 : int32_t exponent = exponent_biased - bias;
252 :
253 0 : int32_t power = -1;
254 0 : double mantissa = 0.0;
255 0 : for (uint32_t i = 0; i < mantissa_shift; ++i) { // NOLINT(build/unsigned)
256 0 : uint64_t mantissa_bit = (bits >> (mantissa_shift - i - 1)) & 0x01; // NOLINT(build/unsigned)
257 0 : mantissa += mantissa_bit * pow(2.0, power);
258 0 : --power;
259 : }
260 :
261 0 : if (exponent_biased == 0) {
262 0 : ++exponent;
263 0 : if (mantissa == 0)
264 : return 0;
265 : } else {
266 0 : mantissa += 1.0;
267 : }
268 0 : return (sign ? -1 : 1) * pow(2.0, exponent) * mantissa;
269 : }
270 : //-----------------------------------------------------------------------------
271 :
272 : //-----------------------------------------------------------------------------
273 : BoardType
274 0 : convert_value_to_board_type(uint32_t board_type) // NOLINT(build/unsigned)
275 : {
276 : // not pleasnt, but works for now
277 0 : if (board_type >= kBoardUnknown) {
278 0 : throw UnknownBoardType(ERS_HERE, format_reg_value(board_type));
279 : } else {
280 0 : return static_cast<BoardType>(board_type);
281 : }
282 : }
283 : //-----------------------------------------------------------------------------
284 :
285 : //-----------------------------------------------------------------------------
286 : CarrierType
287 0 : convert_value_to_carrier_type(uint32_t carrier_type) // NOLINT(build/unsigned)
288 : {
289 : // not pleasnt, but works for now
290 0 : if (carrier_type >= kCarrierUnknown) {
291 0 : throw UnknownCarrierType(ERS_HERE, format_reg_value(carrier_type));
292 : } else {
293 0 : return static_cast<CarrierType>(carrier_type);
294 : }
295 : }
296 : //-----------------------------------------------------------------------------
297 :
298 : //-----------------------------------------------------------------------------
299 : DesignType
300 0 : convert_value_to_design_type(uint32_t design_type) // NOLINT(build/unsigned)
301 : {
302 : // not pleasnt, but works for now
303 0 : if (design_type >= kDesignUnknown) {
304 0 : throw UnknownDesignType(ERS_HERE, format_reg_value(design_type));
305 : } else {
306 0 : return static_cast<DesignType>(design_type);
307 : }
308 : }
309 : //-----------------------------------------------------------------------------
310 :
311 : template std::string
312 : timing::vec_fmt<uint32_t>(const std::vector<uint32_t>& vec); // NOLINT(build/unsigned)
313 : template std::string
314 : timing::short_vec_fmt<uint32_t>(const std::vector<uint32_t>& vec); // NOLINT(build/unsigned)
315 :
316 : //-----------------------------------------------------------------------------
317 : uint32_t // NOLINT(build/unsigned)
318 0 : locate(float xx[], unsigned long n, float x) // NOLINT
319 : {
320 0 : uint32_t j, ju, jm, jl; // NOLINT(build/unsigned)
321 0 : int ascnd;
322 0 : jl = 0; // Initialize lower
323 0 : ju = n + 1; // and upper limits.
324 0 : ascnd = (xx[n] >= xx[1]); // NOLINT
325 :
326 0 : while (ju - jl > 1) // If we are not yet done,
327 : {
328 0 : jm = (ju + jl) >> 1; // compute a midpoint,
329 :
330 0 : if ((x >= xx[jm]) == ascnd) // added additional parenthesis
331 : {
332 : jl = jm; // and replace either the lower limit
333 : } else {
334 0 : ju = jm; // or the upper limit, as appropriate.
335 : }
336 : } // Repeat until the test condition is satisfied.
337 :
338 0 : if (x == xx[1]) { // NOLINT
339 : j = 1; // Then set the output
340 0 : } else if (x == xx[n]) { // NOLINT
341 0 : j = n - 1;
342 : } else {
343 : j = jl;
344 : }
345 :
346 0 : return j;
347 : }
348 : //-----------------------------------------------------------------------------
349 :
350 : //-----------------------------------------------------------------------------
351 : std::string
352 0 : format_firmware_version(uint32_t firmware_version) // NOLINT(build/unsigned)
353 : {
354 0 : int major_firmware_version = (firmware_version >> 16) & 0xff;
355 0 : int minor_firmware_version = (firmware_version >> 8) & 0xff;
356 0 : int patch_firmware_version = (firmware_version >> 0) & 0xff;
357 :
358 0 : std::stringstream firmware_version_stream;
359 0 : firmware_version_stream << "v" << major_firmware_version << "." << minor_firmware_version << "." << patch_firmware_version;
360 0 : return firmware_version_stream.str();
361 0 : }
362 : //-----------------------------------------------------------------------------
363 :
364 : } // namespace timing
365 : } // namespace dunedaq
|