Commit | Line | Data |
---|---|---|
e5aa0be3 PP |
1 | # The MIT License (MIT) |
2 | # | |
4a90140d | 3 | # Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com> |
e5aa0be3 | 4 | # |
1378f213 PP |
5 | # Permission is hereby granted, free of charge, to any person obtaining |
6 | # a copy of this software and associated documentation files (the | |
7 | # "Software"), to deal in the Software without restriction, including | |
8 | # without limitation the rights to use, copy, modify, merge, publish, | |
9 | # distribute, sublicense, and/or sell copies of the Software, and to | |
10 | # permit persons to whom the Software is furnished to do so, subject to | |
11 | # the following conditions: | |
e5aa0be3 | 12 | # |
1378f213 PP |
13 | # The above copyright notice and this permission notice shall be |
14 | # included in all copies or substantial portions of the Software. | |
e5aa0be3 | 15 | # |
1378f213 PP |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
19 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
20 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
21 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
22 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
e5aa0be3 | 23 | |
4810b707 PP |
24 | import barectf.config_parse as barectf_config_parse |
25 | import barectf.version as barectf_version | |
26 | import collections.abc | |
27 | import collections | |
28 | import datetime | |
29 | import enum | |
e5aa0be3 PP |
30 | |
31 | ||
4810b707 PP |
32 | @enum.unique |
33 | class ByteOrder(enum.Enum): | |
34 | LITTLE_ENDIAN = 'le' | |
35 | BIG_ENDIAN = 'be' | |
e5aa0be3 PP |
36 | |
37 | ||
4810b707 PP |
38 | class _FieldType: |
39 | @property | |
40 | def alignment(self): | |
41 | raise NotImplementedError | |
a1a610d4 | 42 | |
e5aa0be3 | 43 | |
4810b707 PP |
44 | class _BitArrayFieldType(_FieldType): |
45 | def __init__(self, size, byte_order=None, alignment=1): | |
46 | self._size = size | |
47 | self._byte_order = byte_order | |
48 | self._alignment = alignment | |
e5aa0be3 PP |
49 | |
50 | @property | |
4810b707 PP |
51 | def size(self): |
52 | return self._size | |
e5aa0be3 | 53 | |
e5aa0be3 | 54 | @property |
4810b707 PP |
55 | def byte_order(self): |
56 | return self._byte_order | |
e5aa0be3 | 57 | |
893854db | 58 | @property |
4810b707 PP |
59 | def alignment(self): |
60 | return self._alignment | |
61 | ||
62 | ||
63 | class DisplayBase(enum.Enum): | |
64 | BINARY = 2 | |
65 | OCTAL = 8 | |
66 | DECIMAL = 10 | |
67 | HEXADECIMAL = 16 | |
68 | ||
69 | ||
70 | class _IntegerFieldType(_BitArrayFieldType): | |
71 | def __init__(self, size, byte_order=None, alignment=None, | |
72 | preferred_display_base=DisplayBase.DECIMAL): | |
73 | effective_alignment = 1 | |
74 | ||
75 | if alignment is None and size % 8 == 0: | |
76 | effective_alignment = 8 | |
77 | ||
78 | super().__init__(size, byte_order, effective_alignment) | |
79 | self._preferred_display_base = preferred_display_base | |
80 | ||
81 | @property | |
82 | def preferred_display_base(self): | |
83 | return self._preferred_display_base | |
84 | ||
85 | ||
86 | class UnsignedIntegerFieldType(_IntegerFieldType): | |
87 | def __init__(self, *args): | |
88 | super().__init__(*args) | |
89 | self._mapped_clk_type_name = None | |
90 | ||
91 | ||
92 | class SignedIntegerFieldType(_IntegerFieldType): | |
93 | pass | |
94 | ||
95 | ||
96 | class EnumerationFieldTypeMappingRange: | |
97 | def __init__(self, lower, upper): | |
98 | self._lower = lower | |
99 | self._upper = upper | |
100 | ||
101 | @property | |
102 | def lower(self): | |
103 | return self._lower | |
104 | ||
105 | @property | |
106 | def upper(self): | |
107 | return self._upper | |
108 | ||
109 | def __eq__(self, other): | |
110 | if type(other) is not type(self): | |
111 | return False | |
112 | ||
113 | return (self._lower, self._upper) == (other._lower, other._upper) | |
114 | ||
115 | def __hash__(self): | |
116 | return hash((self._lower, self._upper)) | |
117 | ||
118 | def contains(self, value): | |
119 | return self._lower <= value <= self._upper | |
120 | ||
121 | ||
122 | class EnumerationFieldTypeMapping: | |
123 | def __init__(self, ranges): | |
124 | self._ranges = frozenset(ranges) | |
125 | ||
126 | @property | |
127 | def ranges(self): | |
128 | return self._ranges | |
129 | ||
130 | def ranges_contain_value(self, value): | |
131 | return any([rg.contains(value) for rg in self._ranges]) | |
132 | ||
133 | ||
134 | class EnumerationFieldTypeMappings(collections.abc.Mapping): | |
135 | def __init__(self, mappings): | |
136 | self._mappings = {label: mapping for label, mapping in mappings.items()} | |
137 | ||
138 | def __getitem__(self, key): | |
139 | return self._mappings[key] | |
140 | ||
141 | def __iter__(self): | |
142 | return iter(self._mappings) | |
143 | ||
144 | def __len__(self): | |
145 | return len(self._mappings) | |
893854db | 146 | |
893854db | 147 | |
4810b707 PP |
148 | class _EnumerationFieldType(_IntegerFieldType): |
149 | def __init__(self, size, byte_order=None, alignment=None, | |
150 | preferred_display_base=DisplayBase.DECIMAL, mappings=None): | |
151 | super().__init__(size, byte_order, alignment, preferred_display_base) | |
152 | self._mappings = EnumerationFieldTypeMappings({}) | |
153 | ||
154 | if mappings is not None: | |
155 | self._mappings = EnumerationFieldTypeMappings(mappings) | |
156 | ||
157 | @property | |
158 | def mappings(self): | |
159 | return self._mappings | |
160 | ||
161 | def labels_for_value(self, value): | |
162 | labels = set() | |
163 | ||
164 | for label, mapping in self._mappings.items(): | |
165 | if mapping.ranges_contain_value(value): | |
166 | labels.add(label) | |
167 | ||
168 | return labels | |
169 | ||
170 | ||
171 | class UnsignedEnumerationFieldType(_EnumerationFieldType, UnsignedIntegerFieldType): | |
172 | pass | |
173 | ||
174 | ||
175 | class SignedEnumerationFieldType(_EnumerationFieldType, SignedIntegerFieldType): | |
176 | pass | |
177 | ||
178 | ||
179 | class RealFieldType(_BitArrayFieldType): | |
180 | pass | |
181 | ||
182 | ||
183 | class StringFieldType(_FieldType): | |
184 | @property | |
185 | def alignment(self): | |
186 | return 8 | |
187 | ||
188 | ||
189 | class _ArrayFieldType(_FieldType): | |
190 | def __init__(self, element_field_type): | |
191 | self._element_field_type = element_field_type | |
192 | ||
193 | @property | |
194 | def element_field_type(self): | |
195 | return self._element_field_type | |
893854db PP |
196 | |
197 | @property | |
4810b707 PP |
198 | def alignment(self): |
199 | return self._element_field_type.alignment | |
200 | ||
201 | ||
202 | class StaticArrayFieldType(_ArrayFieldType): | |
203 | def __init__(self, length, element_field_type): | |
204 | super().__init__(element_field_type) | |
205 | self._length = length | |
893854db | 206 | |
893854db | 207 | @property |
4810b707 PP |
208 | def length(self): |
209 | return self._length | |
210 | ||
211 | ||
212 | class StructureFieldTypeMember: | |
213 | def __init__(self, field_type): | |
214 | self._field_type = field_type | |
215 | ||
216 | @property | |
217 | def field_type(self): | |
218 | return self._field_type | |
219 | ||
220 | ||
221 | class StructureFieldTypeMembers(collections.abc.Mapping): | |
222 | def __init__(self, members): | |
223 | self._members = collections.OrderedDict() | |
224 | ||
225 | for name, member in members.items(): | |
226 | assert type(member) is StructureFieldTypeMember | |
227 | self._members[name] = member | |
228 | ||
229 | def __getitem__(self, key): | |
230 | return self._members[key] | |
231 | ||
232 | def __iter__(self): | |
233 | return iter(self._members) | |
234 | ||
235 | def __len__(self): | |
236 | return len(self._members) | |
237 | ||
238 | ||
239 | class StructureFieldType(_FieldType): | |
240 | def __init__(self, minimum_alignment=1, members=None): | |
241 | self._minimum_alignment = minimum_alignment | |
242 | self._members = StructureFieldTypeMembers({}) | |
243 | ||
244 | if members is not None: | |
245 | self._members = StructureFieldTypeMembers(members) | |
246 | ||
247 | self._set_alignment() | |
248 | ||
249 | def _set_alignment(self): | |
250 | self._alignment = self._minimum_alignment | |
251 | ||
252 | for member in self._members.values(): | |
253 | if member.field_type.alignment > self._alignment: | |
254 | self._alignment = member.field_type.alignment | |
255 | ||
256 | @property | |
257 | def minimum_alignment(self): | |
258 | return self._minimum_alignment | |
259 | ||
260 | @property | |
261 | def alignment(self): | |
262 | return self._alignment | |
263 | ||
264 | @property | |
265 | def members(self): | |
266 | return self._members | |
267 | ||
268 | ||
269 | class _UniqueByName: | |
270 | def __eq__(self, other): | |
271 | if type(other) is not type(self): | |
272 | return False | |
273 | ||
274 | return self._name == other._name | |
275 | ||
276 | def __lt__(self, other): | |
277 | assert type(self) is type(other) | |
278 | return self._name < other._name | |
279 | ||
280 | def __hash__(self): | |
281 | return hash(self._name) | |
282 | ||
283 | ||
284 | class EventType(_UniqueByName): | |
285 | def __init__(self, name, log_level=None, specific_context_field_type=None, | |
286 | payload_field_type=None): | |
287 | self._id = None | |
288 | self._name = name | |
289 | self._log_level = log_level | |
290 | self._specific_context_field_type = specific_context_field_type | |
291 | self._payload_field_type = payload_field_type | |
292 | ||
293 | @property | |
294 | def id(self): | |
295 | return self._id | |
296 | ||
297 | @property | |
298 | def name(self): | |
299 | return self._name | |
300 | ||
301 | @property | |
302 | def log_level(self): | |
303 | return self._log_level | |
304 | ||
305 | @property | |
306 | def specific_context_field_type(self): | |
307 | return self._specific_context_field_type | |
308 | ||
309 | @property | |
310 | def payload_field_type(self): | |
311 | return self._payload_field_type | |
312 | ||
313 | ||
314 | class ClockTypeOffset: | |
315 | def __init__(self, seconds=0, cycles=0): | |
316 | self._seconds = seconds | |
317 | self._cycles = cycles | |
318 | ||
319 | @property | |
320 | def seconds(self): | |
321 | return self._seconds | |
322 | ||
323 | @property | |
324 | def cycles(self): | |
325 | return self._cycles | |
326 | ||
327 | ||
328 | class ClockType(_UniqueByName): | |
329 | def __init__(self, name, frequency=int(1e9), uuid=None, description=None, precision=0, | |
330 | offset=None, origin_is_unix_epoch=False): | |
331 | self._name = name | |
332 | self._frequency = frequency | |
333 | self._uuid = uuid | |
334 | self._description = description | |
335 | self._precision = precision | |
336 | self._offset = ClockTypeOffset() | |
337 | ||
338 | if offset is not None: | |
339 | self._offset = offset | |
340 | ||
341 | self._origin_is_unix_epoch = origin_is_unix_epoch | |
342 | ||
343 | @property | |
344 | def name(self): | |
345 | return self._name | |
346 | ||
347 | @property | |
348 | def frequency(self): | |
349 | return self._frequency | |
350 | ||
351 | @property | |
352 | def uuid(self): | |
353 | return self._uuid | |
354 | ||
355 | @property | |
356 | def description(self): | |
357 | return self._description | |
358 | ||
359 | @property | |
360 | def precision(self): | |
361 | return self._precision | |
362 | ||
363 | @property | |
364 | def offset(self): | |
365 | return self._offset | |
366 | ||
367 | @property | |
368 | def origin_is_unix_epoch(self): | |
369 | return self._origin_is_unix_epoch | |
370 | ||
371 | ||
372 | DEFAULT_FIELD_TYPE = 'default' | |
373 | ||
374 | ||
375 | class StreamTypePacketFeatures: | |
376 | def __init__(self, total_size_field_type=DEFAULT_FIELD_TYPE, | |
377 | content_size_field_type=DEFAULT_FIELD_TYPE, beginning_time_field_type=None, | |
378 | end_time_field_type=None, discarded_events_counter_field_type=None): | |
379 | def get_ft(user_ft): | |
380 | if user_ft == DEFAULT_FIELD_TYPE: | |
381 | return UnsignedIntegerFieldType(64) | |
382 | ||
383 | return user_ft | |
384 | ||
385 | self._total_size_field_type = get_ft(total_size_field_type) | |
386 | self._content_size_field_type = get_ft(content_size_field_type) | |
387 | self._beginning_time_field_type = get_ft(beginning_time_field_type) | |
388 | self._end_time_field_type = get_ft(end_time_field_type) | |
389 | self._discarded_events_counter_field_type = get_ft(discarded_events_counter_field_type) | |
390 | ||
391 | @property | |
392 | def total_size_field_type(self): | |
393 | return self._total_size_field_type | |
394 | ||
395 | @property | |
396 | def content_size_field_type(self): | |
397 | return self._content_size_field_type | |
398 | ||
399 | @property | |
400 | def beginning_time_field_type(self): | |
401 | return self._beginning_time_field_type | |
402 | ||
403 | @property | |
404 | def end_time_field_type(self): | |
405 | return self._end_time_field_type | |
406 | ||
407 | @property | |
408 | def discarded_events_counter_field_type(self): | |
409 | return self._discarded_events_counter_field_type | |
410 | ||
411 | ||
412 | class StreamTypeEventFeatures: | |
413 | def __init__(self, type_id_field_type=DEFAULT_FIELD_TYPE, time_field_type=None): | |
414 | def get_ft(user_field_type): | |
415 | if user_field_type == DEFAULT_FIELD_TYPE: | |
416 | return UnsignedIntegerFieldType(64) | |
417 | ||
418 | return user_field_type | |
419 | ||
420 | self._type_id_field_type = get_ft(type_id_field_type) | |
421 | self._time_field_type = get_ft(time_field_type) | |
422 | ||
423 | @property | |
424 | def type_id_field_type(self): | |
425 | return self._type_id_field_type | |
426 | ||
427 | @property | |
428 | def time_field_type(self): | |
429 | return self._time_field_type | |
430 | ||
431 | ||
432 | class StreamTypeFeatures: | |
433 | def __init__(self, packet_features=None, event_features=None): | |
434 | self._packet_features = StreamTypePacketFeatures() | |
435 | ||
436 | if packet_features is not None: | |
437 | self._packet_features = packet_features | |
438 | ||
439 | self._event_features = StreamTypeEventFeatures() | |
440 | ||
441 | if event_features is not None: | |
442 | self._event_features = event_features | |
443 | ||
444 | @property | |
445 | def packet_features(self): | |
446 | return self._packet_features | |
447 | ||
448 | @property | |
449 | def event_features(self): | |
450 | return self._event_features | |
451 | ||
452 | ||
453 | class StreamType(_UniqueByName): | |
454 | def __init__(self, name, event_types, default_clock_type=None, features=None, | |
455 | packet_context_field_type_extra_members=None, | |
456 | event_common_context_field_type=None): | |
457 | self._id = None | |
458 | self._name = name | |
459 | self._default_clock_type = default_clock_type | |
460 | self._event_common_context_field_type = event_common_context_field_type | |
461 | self._event_types = frozenset(event_types) | |
462 | ||
463 | # assign unique IDs | |
464 | for index, ev_type in enumerate(sorted(self._event_types, key=lambda evt: evt.name)): | |
465 | assert ev_type._id is None | |
466 | ev_type._id = index | |
467 | ||
468 | self._set_features(features) | |
469 | self._packet_context_field_type_extra_members = StructureFieldTypeMembers({}) | |
470 | ||
471 | if packet_context_field_type_extra_members is not None: | |
472 | self._packet_context_field_type_extra_members = StructureFieldTypeMembers(packet_context_field_type_extra_members) | |
473 | ||
474 | self._set_pkt_ctx_ft() | |
475 | self._set_ev_header_ft() | |
476 | ||
477 | def _set_features(self, features): | |
478 | if features is not None: | |
479 | self._features = features | |
480 | return | |
481 | ||
482 | ev_time_ft = None | |
483 | pkt_beginning_time_ft = None | |
484 | pkt_end_time_ft = None | |
485 | ||
486 | if self._default_clock_type is not None: | |
487 | # Automatic time field types because the stream type has a | |
488 | # default clock type. | |
489 | ev_time_ft = DEFAULT_FIELD_TYPE | |
490 | pkt_beginning_time_ft = DEFAULT_FIELD_TYPE | |
491 | pkt_end_time_ft = DEFAULT_FIELD_TYPE | |
492 | ||
493 | self._features = StreamTypeFeatures(StreamTypePacketFeatures(beginning_time_field_type=pkt_beginning_time_ft, | |
494 | end_time_field_type=pkt_end_time_ft), | |
495 | StreamTypeEventFeatures(time_field_type=ev_time_ft)) | |
496 | ||
497 | def _set_ft_mapped_clk_type_name(self, ft): | |
498 | if ft is None: | |
499 | return | |
500 | ||
501 | if self._default_clock_type is not None: | |
502 | assert isinstance(ft, UnsignedIntegerFieldType) | |
503 | ft._mapped_clk_type_name = self._default_clock_type.name | |
504 | ||
505 | def _set_pkt_ctx_ft(self): | |
506 | def add_member_if_exists(name, ft, set_mapped_clk_type_name=False): | |
507 | nonlocal members | |
508 | ||
509 | if ft is not None: | |
510 | if set_mapped_clk_type_name: | |
511 | self._set_ft_mapped_clk_type_name(ft) | |
512 | ||
513 | members[name] = StructureFieldTypeMember(ft) | |
514 | ||
515 | members = collections.OrderedDict([ | |
516 | ( | |
517 | 'packet_size', | |
518 | StructureFieldTypeMember(self._features.packet_features.total_size_field_type) | |
519 | ), | |
520 | ( | |
521 | 'content_size', | |
522 | StructureFieldTypeMember(self._features.packet_features.content_size_field_type) | |
523 | ) | |
524 | ]) | |
525 | ||
526 | add_member_if_exists('timestamp_begin', | |
527 | self._features.packet_features.beginning_time_field_type, True) | |
528 | add_member_if_exists('timestamp_end', self._features.packet_features.end_time_field_type, | |
529 | True) | |
530 | add_member_if_exists('events_discarded', | |
531 | self._features.packet_features.discarded_events_counter_field_type) | |
532 | ||
533 | if self._packet_context_field_type_extra_members is not None: | |
534 | for name, field_type in self._packet_context_field_type_extra_members.items(): | |
535 | assert name not in members | |
536 | members[name] = field_type | |
537 | ||
538 | self._pkt_ctx_ft = StructureFieldType(8, members) | |
539 | ||
540 | def _set_ev_header_ft(self): | |
541 | members = collections.OrderedDict() | |
542 | ||
543 | if self._features.event_features.type_id_field_type is not None: | |
544 | members['id'] = StructureFieldTypeMember(self._features.event_features.type_id_field_type) | |
545 | ||
546 | if self._features.event_features.time_field_type is not None: | |
547 | ft = self._features.event_features.time_field_type | |
548 | self._set_ft_mapped_clk_type_name(ft) | |
549 | members['timestamp'] = StructureFieldTypeMember(ft) | |
550 | ||
551 | self._ev_header_ft = StructureFieldType(8, members) | |
552 | ||
553 | @property | |
554 | def id(self): | |
555 | return self._id | |
556 | ||
557 | @property | |
558 | def name(self): | |
559 | return self._name | |
560 | ||
561 | @property | |
562 | def default_clock_type(self): | |
563 | return self._default_clock_type | |
564 | ||
565 | @property | |
566 | def features(self): | |
567 | return self._features | |
568 | ||
569 | @property | |
570 | def packet_context_field_type_extra_members(self): | |
571 | return self._packet_context_field_type_extra_members | |
572 | ||
573 | @property | |
574 | def event_common_context_field_type(self): | |
575 | return self._event_common_context_field_type | |
576 | ||
577 | @property | |
578 | def event_types(self): | |
579 | return self._event_types | |
580 | ||
581 | ||
582 | class TraceTypeFeatures: | |
583 | def __init__(self, magic_field_type=DEFAULT_FIELD_TYPE, uuid_field_type=None, | |
584 | stream_type_id_field_type=DEFAULT_FIELD_TYPE): | |
585 | def get_field_type(user_field_type, default_field_type): | |
586 | if user_field_type == DEFAULT_FIELD_TYPE: | |
587 | return default_field_type | |
588 | ||
589 | return user_field_type | |
590 | ||
591 | self._magic_field_type = get_field_type(magic_field_type, UnsignedIntegerFieldType(32)) | |
592 | self._uuid_field_type = get_field_type(uuid_field_type, | |
593 | StaticArrayFieldType(16, UnsignedIntegerFieldType(8))) | |
594 | self._stream_type_id_field_type = get_field_type(stream_type_id_field_type, | |
595 | UnsignedIntegerFieldType(64)) | |
596 | ||
597 | @property | |
598 | def magic_field_type(self): | |
599 | return self._magic_field_type | |
600 | ||
601 | @property | |
602 | def uuid_field_type(self): | |
603 | return self._uuid_field_type | |
604 | ||
605 | @property | |
606 | def stream_type_id_field_type(self): | |
607 | return self._stream_type_id_field_type | |
608 | ||
609 | ||
610 | class TraceType: | |
611 | def __init__(self, stream_types, default_byte_order, uuid=None, features=None): | |
612 | self._default_byte_order = default_byte_order | |
613 | self._stream_types = frozenset(stream_types) | |
614 | ||
615 | # assign unique IDs | |
616 | for index, stream_type in enumerate(sorted(self._stream_types, key=lambda st: st.name)): | |
617 | assert stream_type._id is None | |
618 | stream_type._id = index | |
619 | ||
620 | self._uuid = uuid | |
621 | self._set_features(features) | |
622 | self._set_pkt_header_ft() | |
623 | self._set_fts_effective_byte_order() | |
624 | ||
625 | def _set_features(self, features): | |
626 | if features is not None: | |
627 | self._features = features | |
628 | return | |
629 | ||
630 | # automatic UUID field type because the trace type has a UUID | |
631 | uuid_ft = None if self._uuid is None else DEFAULT_FIELD_TYPE | |
632 | self._features = TraceTypeFeatures(uuid_field_type=uuid_ft) | |
633 | ||
634 | def _set_pkt_header_ft(self): | |
635 | def add_member_if_exists(name, field_type): | |
636 | nonlocal members | |
637 | ||
638 | if field_type is not None: | |
639 | members[name] = StructureFieldTypeMember(field_type) | |
640 | ||
641 | members = collections.OrderedDict() | |
642 | add_member_if_exists('magic', self._features.magic_field_type) | |
643 | add_member_if_exists('uuid', self._features.uuid_field_type) | |
644 | add_member_if_exists('stream_id', self._features.stream_type_id_field_type) | |
645 | self._pkt_header_ft = StructureFieldType(8, members) | |
646 | ||
647 | def _set_fts_effective_byte_order(self): | |
648 | def set_ft_effective_byte_order(ft): | |
649 | if ft is None: | |
650 | return | |
651 | ||
652 | if isinstance(ft, _BitArrayFieldType): | |
653 | if ft._byte_order is None: | |
654 | assert self._default_byte_order is not None | |
655 | ft._byte_order = self._default_byte_order | |
656 | elif isinstance(ft, StaticArrayFieldType): | |
657 | set_ft_effective_byte_order(ft.element_field_type) | |
658 | elif isinstance(ft, StructureFieldType): | |
659 | for member in ft.members.values(): | |
660 | set_ft_effective_byte_order(member.field_type) | |
661 | ||
662 | # packet header field type | |
663 | set_ft_effective_byte_order(self._pkt_header_ft) | |
664 | ||
665 | # stream type field types | |
666 | for stream_type in self._stream_types: | |
667 | set_ft_effective_byte_order(stream_type._pkt_ctx_ft) | |
668 | set_ft_effective_byte_order(stream_type._ev_header_ft) | |
669 | set_ft_effective_byte_order(stream_type._event_common_context_field_type) | |
670 | ||
671 | # event type field types | |
672 | for ev_type in stream_type.event_types: | |
673 | set_ft_effective_byte_order(ev_type._specific_context_field_type) | |
674 | set_ft_effective_byte_order(ev_type._payload_field_type) | |
675 | ||
676 | @property | |
677 | def default_byte_order(self): | |
678 | return self._default_byte_order | |
679 | ||
680 | @property | |
681 | def uuid(self): | |
682 | return self._uuid | |
683 | ||
684 | @property | |
685 | def stream_types(self): | |
686 | return self._stream_types | |
687 | ||
688 | def stream_type(self, name): | |
689 | for cand_stream_type in self._stream_types: | |
690 | if cand_stream_type.name == name: | |
691 | return cand_stream_type | |
692 | ||
693 | @property | |
694 | def features(self): | |
695 | return self._features | |
696 | ||
697 | ||
698 | class TraceEnvironment(collections.abc.Mapping): | |
699 | def __init__(self, environment): | |
700 | self._env = {name: value for name, value in environment.items()} | |
701 | ||
702 | def __getitem__(self, key): | |
703 | return self._env[key] | |
704 | ||
705 | def __iter__(self): | |
706 | return iter(self._env) | |
707 | ||
708 | def __len__(self): | |
709 | return len(self._env) | |
710 | ||
711 | ||
712 | class Trace: | |
713 | def __init__(self, type, environment=None): | |
714 | self._type = type | |
715 | self._set_env(environment) | |
716 | ||
717 | def _set_env(self, environment): | |
718 | init_env = collections.OrderedDict([ | |
719 | ('domain', 'bare'), | |
720 | ('tracer_name', 'barectf'), | |
721 | ('tracer_major', barectf_version.__major_version__), | |
722 | ('tracer_minor', barectf_version.__minor_version__), | |
723 | ('tracer_patch', barectf_version.__patch_version__), | |
724 | ('barectf_gen_date', str(datetime.datetime.now().isoformat())), | |
725 | ]) | |
726 | ||
727 | if environment is None: | |
728 | environment = {} | |
729 | ||
730 | init_env.update(environment) | |
731 | self._env = TraceEnvironment(init_env) | |
732 | ||
733 | @property | |
734 | def type(self): | |
735 | return self._type | |
736 | ||
737 | @property | |
738 | def environment(self): | |
739 | return self._env | |
740 | ||
741 | ||
742 | class ClockTypeCTypes(collections.abc.Mapping): | |
743 | def __init__(self, c_types): | |
744 | self._c_types = {clk_type: c_type for clk_type, c_type in c_types.items()} | |
745 | ||
746 | def __getitem__(self, key): | |
747 | return self._c_types[key] | |
748 | ||
749 | def __iter__(self): | |
750 | return iter(self._c_types) | |
751 | ||
752 | def __len__(self): | |
753 | return len(self._c_types) | |
754 | ||
755 | ||
756 | class ConfigurationCodeGenerationHeaderOptions: | |
757 | def __init__(self, identifier_prefix_definition=False, | |
758 | default_stream_type_name_definition=False): | |
759 | self._identifier_prefix_definition = identifier_prefix_definition | |
760 | self._default_stream_type_name_definition = default_stream_type_name_definition | |
761 | ||
762 | @property | |
763 | def identifier_prefix_definition(self): | |
764 | return self._identifier_prefix_definition | |
765 | ||
766 | @property | |
767 | def default_stream_type_name_definition(self): | |
768 | return self._default_stream_type_name_definition | |
769 | ||
770 | ||
771 | class ConfigurationCodeGenerationOptions: | |
772 | def __init__(self, identifier_prefix='barectf_', file_name_prefix='barectf', | |
773 | default_stream_type=None, header_options=None, clock_type_c_types=None): | |
774 | self._identifier_prefix = identifier_prefix | |
775 | self._file_name_prefix = file_name_prefix | |
776 | self._default_stream_type = default_stream_type | |
777 | ||
778 | self._header_options = ConfigurationCodeGenerationHeaderOptions() | |
779 | ||
780 | if header_options is not None: | |
781 | self._header_options = header_options | |
782 | ||
783 | self._clock_type_c_types = ClockTypeCTypes({}) | |
784 | ||
785 | if clock_type_c_types is not None: | |
786 | self._clock_type_c_types = ClockTypeCTypes(clock_type_c_types) | |
787 | ||
788 | @property | |
789 | def identifier_prefix(self): | |
790 | return self._identifier_prefix | |
791 | ||
792 | @property | |
793 | def file_name_prefix(self): | |
794 | return self._file_name_prefix | |
795 | ||
796 | @property | |
797 | def default_stream_type(self): | |
798 | return self._default_stream_type | |
799 | ||
800 | @property | |
801 | def header_options(self): | |
802 | return self._header_options | |
803 | ||
804 | @property | |
805 | def clock_type_c_types(self): | |
806 | return self._clock_type_c_types | |
807 | ||
808 | ||
809 | class ConfigurationOptions: | |
810 | def __init__(self, code_generation_options=None): | |
811 | self._code_generation_options = ConfigurationCodeGenerationOptions() | |
812 | ||
813 | if code_generation_options is not None: | |
814 | self._code_generation_options = code_generation_options | |
815 | ||
816 | @property | |
817 | def code_generation_options(self): | |
818 | return self._code_generation_options | |
819 | ||
820 | ||
821 | class Configuration: | |
822 | def __init__(self, trace, options=None): | |
823 | self._trace = trace | |
824 | self._options = ConfigurationOptions() | |
825 | ||
826 | if options is not None: | |
827 | self._options = options | |
828 | ||
829 | clk_type_c_types = self._options.code_generation_options.clock_type_c_types | |
830 | ||
831 | for stream_type in trace.type.stream_types: | |
832 | def_clk_type = stream_type.default_clock_type | |
833 | ||
834 | if def_clk_type is None: | |
835 | continue | |
836 | ||
837 | if def_clk_type not in clk_type_c_types: | |
838 | clk_type_c_types._c_types[def_clk_type] = 'uint32_t' | |
839 | ||
840 | @property | |
841 | def trace(self): | |
842 | return self._trace | |
843 | ||
844 | @property | |
845 | def options(self): | |
846 | return self._options | |
847 | ||
848 | ||
7cd4634e PP |
849 | def effective_configuration_file(file, with_package_inclusion_directory=True, |
850 | inclusion_directories=None, ignore_inclusion_not_found=False, | |
4810b707 | 851 | indent_space_count=2): |
7cd4634e PP |
852 | if inclusion_directories is None: |
853 | inclusion_directories = [] | |
854 | ||
855 | return barectf_config_parse._effective_config_file(file, with_package_inclusion_directory, | |
856 | inclusion_directories, | |
4810b707 PP |
857 | ignore_inclusion_not_found, |
858 | indent_space_count) | |
893854db | 859 | |
e5aa0be3 | 860 | |
7cd4634e PP |
861 | def configuration_from_file(file, with_package_inclusion_directory=True, inclusion_directories=None, |
862 | ignore_inclusion_not_found=False): | |
863 | if inclusion_directories is None: | |
864 | inclusion_directories = [] | |
865 | ||
866 | return barectf_config_parse._from_file(file, with_package_inclusion_directory, | |
867 | inclusion_directories, ignore_inclusion_not_found) | |
e5aa0be3 | 868 | |
f58be68f | 869 | |
4810b707 PP |
870 | def configuration_file_major_version(file): |
871 | return barectf_config_parse._config_file_major_version(file) |