docs: cleanup: Rephrase and correct typos
[barectf.git] / barectf / config.py
CommitLineData
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 24import barectf.version as barectf_version
7fffc7d1 25from typing import Optional, Any, FrozenSet, Mapping, Iterator, Set, Union, Callable
2d55dc7d
PP
26import typing
27from barectf.typing import Count, Alignment, _OptStr, Id
4810b707
PP
28import collections.abc
29import collections
30import datetime
31import enum
2d55dc7d 32import uuid as uuidp
e5aa0be3
PP
33
34
4810b707
PP
35@enum.unique
36class ByteOrder(enum.Enum):
37 LITTLE_ENDIAN = 'le'
38 BIG_ENDIAN = 'be'
e5aa0be3
PP
39
40
4810b707
PP
41class _FieldType:
42 @property
2d55dc7d 43 def alignment(self) -> Alignment:
4810b707 44 raise NotImplementedError
a1a610d4 45
1960170e
PP
46 @property
47 def size_is_dynamic(self):
48 return False
49
e5aa0be3 50
4810b707 51class _BitArrayFieldType(_FieldType):
4c91e769 52 def __init__(self, size: Count, alignment: Alignment = Alignment(1)):
4810b707 53 self._size = size
4810b707 54 self._alignment = alignment
e5aa0be3
PP
55
56 @property
2d55dc7d 57 def size(self) -> Count:
4810b707 58 return self._size
e5aa0be3 59
893854db 60 @property
2d55dc7d 61 def alignment(self) -> Alignment:
4810b707
PP
62 return self._alignment
63
64
65class DisplayBase(enum.Enum):
66 BINARY = 2
67 OCTAL = 8
68 DECIMAL = 10
69 HEXADECIMAL = 16
70
71
72class _IntegerFieldType(_BitArrayFieldType):
4c91e769 73 def __init__(self, size: Count, alignment: Optional[Alignment] = None,
2d55dc7d 74 preferred_display_base: DisplayBase = DisplayBase.DECIMAL):
5833e4da
PP
75 if alignment is None:
76 alignment = Alignment(8 if size % 8 == 0 else 1)
4810b707 77
4c91e769 78 super().__init__(size, alignment)
4810b707
PP
79 self._preferred_display_base = preferred_display_base
80
81 @property
2d55dc7d 82 def preferred_display_base(self) -> DisplayBase:
4810b707
PP
83 return self._preferred_display_base
84
85
86class UnsignedIntegerFieldType(_IntegerFieldType):
2c42a1c0
PP
87 def __init__(self, *args, **kwargs):
88 super().__init__(*args, **kwargs)
4810b707 89 self._mapped_clk_type_name = None
2c42a1c0 90 self._is_len = False
4810b707
PP
91
92
93class SignedIntegerFieldType(_IntegerFieldType):
94 pass
95
96
97class EnumerationFieldTypeMappingRange:
2d55dc7d 98 def __init__(self, lower: int, upper: int):
4810b707
PP
99 self._lower = lower
100 self._upper = upper
101
102 @property
2d55dc7d 103 def lower(self) -> int:
4810b707
PP
104 return self._lower
105
106 @property
2d55dc7d 107 def upper(self) -> int:
4810b707
PP
108 return self._upper
109
2d55dc7d 110 def __eq__(self, other: Any) -> bool:
4810b707
PP
111 if type(other) is not type(self):
112 return False
113
114 return (self._lower, self._upper) == (other._lower, other._upper)
115
2d55dc7d 116 def __hash__(self) -> int:
4810b707
PP
117 return hash((self._lower, self._upper))
118
2d55dc7d 119 def contains(self, value: int) -> bool:
4810b707
PP
120 return self._lower <= value <= self._upper
121
122
123class EnumerationFieldTypeMapping:
2d55dc7d 124 def __init__(self, ranges: Set[EnumerationFieldTypeMappingRange]):
4810b707
PP
125 self._ranges = frozenset(ranges)
126
127 @property
2d55dc7d 128 def ranges(self) -> FrozenSet[EnumerationFieldTypeMappingRange]:
4810b707
PP
129 return self._ranges
130
2d55dc7d 131 def ranges_contain_value(self, value: int) -> bool:
4810b707
PP
132 return any([rg.contains(value) for rg in self._ranges])
133
134
2d55dc7d
PP
135_EnumFtMappings = Mapping[str, EnumerationFieldTypeMapping]
136
137
4810b707 138class EnumerationFieldTypeMappings(collections.abc.Mapping):
2d55dc7d 139 def __init__(self, mappings: _EnumFtMappings):
4810b707
PP
140 self._mappings = {label: mapping for label, mapping in mappings.items()}
141
2d55dc7d 142 def __getitem__(self, key: str) -> EnumerationFieldTypeMapping:
4810b707
PP
143 return self._mappings[key]
144
2d55dc7d 145 def __iter__(self) -> Iterator[str]:
4810b707
PP
146 return iter(self._mappings)
147
2d55dc7d 148 def __len__(self) -> int:
4810b707 149 return len(self._mappings)
893854db 150
893854db 151
4810b707 152class _EnumerationFieldType(_IntegerFieldType):
4c91e769 153 def __init__(self, size: Count, alignment: Optional[Alignment] = None,
2d55dc7d
PP
154 preferred_display_base: DisplayBase = DisplayBase.DECIMAL,
155 mappings: Optional[_EnumFtMappings] = None):
4c91e769 156 super().__init__(size, alignment, preferred_display_base)
4810b707
PP
157 self._mappings = EnumerationFieldTypeMappings({})
158
159 if mappings is not None:
160 self._mappings = EnumerationFieldTypeMappings(mappings)
161
162 @property
2d55dc7d 163 def mappings(self) -> EnumerationFieldTypeMappings:
4810b707
PP
164 return self._mappings
165
2d55dc7d 166 def labels_for_value(self, value: int) -> Set[str]:
4810b707
PP
167 labels = set()
168
169 for label, mapping in self._mappings.items():
170 if mapping.ranges_contain_value(value):
171 labels.add(label)
172
173 return labels
174
175
176class UnsignedEnumerationFieldType(_EnumerationFieldType, UnsignedIntegerFieldType):
177 pass
178
179
180class SignedEnumerationFieldType(_EnumerationFieldType, SignedIntegerFieldType):
181 pass
182
183
184class RealFieldType(_BitArrayFieldType):
185 pass
186
187
188class StringFieldType(_FieldType):
189 @property
2d55dc7d
PP
190 def alignment(self) -> Alignment:
191 return Alignment(8)
4810b707 192
1960170e
PP
193 @property
194 def size_is_dynamic(self):
195 return True
196
4810b707
PP
197
198class _ArrayFieldType(_FieldType):
2d55dc7d 199 def __init__(self, element_field_type: _FieldType):
4810b707
PP
200 self._element_field_type = element_field_type
201
202 @property
2d55dc7d 203 def element_field_type(self) -> _FieldType:
4810b707 204 return self._element_field_type
893854db
PP
205
206 @property
2d55dc7d 207 def alignment(self) -> Alignment:
4810b707
PP
208 return self._element_field_type.alignment
209
a19472f2
PP
210 @property
211 def size_is_dynamic(self):
212 return self._element_field_type.size_is_dynamic
213
4810b707
PP
214
215class StaticArrayFieldType(_ArrayFieldType):
2d55dc7d 216 def __init__(self, length: Count, element_field_type: _FieldType):
4810b707
PP
217 super().__init__(element_field_type)
218 self._length = length
893854db 219
893854db 220 @property
2d55dc7d 221 def length(self) -> Count:
4810b707
PP
222 return self._length
223
224
be9f12dc
PP
225class DynamicArrayFieldType(_ArrayFieldType):
226 def __init__(self, length_field_type: UnsignedIntegerFieldType, element_field_type: _FieldType):
227 super().__init__(element_field_type)
228 self._length_field_type = length_field_type
67ec4028 229 self._length_ft_member_name: Optional[str] = None
be9f12dc
PP
230
231 @property
232 def length_field_type(self):
233 return self._length_field_type
234
235 @property
236 def size_is_dynamic(self):
237 return True
238
239
4810b707 240class StructureFieldTypeMember:
2d55dc7d 241 def __init__(self, field_type: _FieldType):
4810b707
PP
242 self._field_type = field_type
243
244 @property
2d55dc7d 245 def field_type(self) -> _FieldType:
4810b707
PP
246 return self._field_type
247
248
2d55dc7d
PP
249_StructFtMembers = Mapping[str, StructureFieldTypeMember]
250
251
4810b707 252class StructureFieldTypeMembers(collections.abc.Mapping):
2d55dc7d 253 def __init__(self, members: _StructFtMembers):
4810b707
PP
254 self._members = collections.OrderedDict()
255
256 for name, member in members.items():
257 assert type(member) is StructureFieldTypeMember
258 self._members[name] = member
259
2d55dc7d 260 def __getitem__(self, key: str) -> StructureFieldTypeMember:
4810b707
PP
261 return self._members[key]
262
2d55dc7d 263 def __iter__(self) -> Iterator[str]:
4810b707
PP
264 return iter(self._members)
265
2d55dc7d 266 def __len__(self) -> int:
4810b707
PP
267 return len(self._members)
268
269
270class StructureFieldType(_FieldType):
2d55dc7d
PP
271 def __init__(self, minimum_alignment: Alignment = Alignment(1),
272 members: Optional[_StructFtMembers] = None):
4810b707
PP
273 self._minimum_alignment = minimum_alignment
274 self._members = StructureFieldTypeMembers({})
275
276 if members is not None:
277 self._members = StructureFieldTypeMembers(members)
278
279 self._set_alignment()
be9f12dc 280 self._set_dyn_array_ft_length_ft_member_names()
4810b707
PP
281
282 def _set_alignment(self):
2d55dc7d 283 self._alignment: Alignment = self._minimum_alignment
4810b707
PP
284
285 for member in self._members.values():
286 if member.field_type.alignment > self._alignment:
287 self._alignment = member.field_type.alignment
288
be9f12dc
PP
289 def _set_dyn_array_ft_length_ft_member_names(self):
290 for member in self._members.values():
291 if type(member.field_type) is DynamicArrayFieldType:
292 # Find length field type member name within the same
293 # structure field type members.
294 for len_name, len_member in self._members.items():
295 if member.field_type.length_field_type is len_member.field_type:
296 member.field_type._length_ft_member_name = len_name
297 len_member.field_type._is_len = True
298 break
299
300 if member.field_type.alignment > self._alignment:
301 self._alignment = member.field_type.alignment
302
4810b707 303 @property
2d55dc7d 304 def minimum_alignment(self) -> Alignment:
4810b707
PP
305 return self._minimum_alignment
306
307 @property
2d55dc7d 308 def alignment(self) -> Alignment:
4810b707
PP
309 return self._alignment
310
1960170e
PP
311 @property
312 def size_is_dynamic(self):
313 return any([member.field_type.size_is_dynamic for member in self.members.values()])
314
4810b707 315 @property
2d55dc7d 316 def members(self) -> StructureFieldTypeMembers:
4810b707
PP
317 return self._members
318
319
320class _UniqueByName:
2d55dc7d
PP
321 _name: str
322
323 def __eq__(self, other: Any) -> bool:
4810b707
PP
324 if type(other) is not type(self):
325 return False
326
327 return self._name == other._name
328
2d55dc7d 329 def __lt__(self, other: '_UniqueByName'):
4810b707
PP
330 assert type(self) is type(other)
331 return self._name < other._name
332
2d55dc7d 333 def __hash__(self) -> int:
4810b707
PP
334 return hash(self._name)
335
336
2d55dc7d
PP
337_OptFt = Optional[_FieldType]
338_OptStructFt = Optional[StructureFieldType]
339LogLevel = typing.NewType('LogLevel', int)
340
341
e8f0d548 342class EventRecordType(_UniqueByName):
2d55dc7d
PP
343 def __init__(self, name: str, log_level: Optional[LogLevel] = None,
344 specific_context_field_type: _OptStructFt = None, payload_field_type: _OptStructFt = None):
345 self._id: Optional[Id] = None
4810b707
PP
346 self._name = name
347 self._log_level = log_level
348 self._specific_context_field_type = specific_context_field_type
349 self._payload_field_type = payload_field_type
350
351 @property
2d55dc7d 352 def id(self) -> Optional[Id]:
4810b707
PP
353 return self._id
354
355 @property
2d55dc7d 356 def name(self) -> str:
4810b707
PP
357 return self._name
358
359 @property
2d55dc7d 360 def log_level(self) -> Optional[LogLevel]:
4810b707
PP
361 return self._log_level
362
363 @property
2d55dc7d 364 def specific_context_field_type(self) -> _OptStructFt:
4810b707
PP
365 return self._specific_context_field_type
366
367 @property
2d55dc7d 368 def payload_field_type(self) -> _OptStructFt:
4810b707
PP
369 return self._payload_field_type
370
371
372class ClockTypeOffset:
2d55dc7d 373 def __init__(self, seconds: int = 0, cycles: Count = Count(0)):
4810b707
PP
374 self._seconds = seconds
375 self._cycles = cycles
376
377 @property
2d55dc7d 378 def seconds(self) -> int:
4810b707
PP
379 return self._seconds
380
381 @property
2d55dc7d 382 def cycles(self) -> Count:
4810b707
PP
383 return self._cycles
384
385
2d55dc7d
PP
386_OptUuid = Optional[uuidp.UUID]
387
388
4810b707 389class ClockType(_UniqueByName):
2d55dc7d
PP
390 def __init__(self, name: str, frequency: Count = Count(int(1e9)), uuid: _OptUuid = None,
391 description: _OptStr = None, precision: Count = Count(0),
392 offset: Optional[ClockTypeOffset] = None, origin_is_unix_epoch: bool = False):
4810b707
PP
393 self._name = name
394 self._frequency = frequency
395 self._uuid = uuid
396 self._description = description
397 self._precision = precision
398 self._offset = ClockTypeOffset()
399
400 if offset is not None:
401 self._offset = offset
402
403 self._origin_is_unix_epoch = origin_is_unix_epoch
404
405 @property
2d55dc7d 406 def name(self) -> str:
4810b707
PP
407 return self._name
408
409 @property
2d55dc7d 410 def frequency(self) -> Count:
4810b707
PP
411 return self._frequency
412
413 @property
2d55dc7d 414 def uuid(self) -> _OptUuid:
4810b707
PP
415 return self._uuid
416
417 @property
2d55dc7d 418 def description(self) -> _OptStr:
4810b707
PP
419 return self._description
420
421 @property
2d55dc7d 422 def precision(self) -> Count:
4810b707
PP
423 return self._precision
424
425 @property
2d55dc7d 426 def offset(self) -> ClockTypeOffset:
4810b707
PP
427 return self._offset
428
429 @property
2d55dc7d 430 def origin_is_unix_epoch(self) -> bool:
4810b707
PP
431 return self._origin_is_unix_epoch
432
433
434DEFAULT_FIELD_TYPE = 'default'
2d55dc7d
PP
435_DefaultableUIntFt = Union[str, UnsignedIntegerFieldType]
436_OptDefaultableUIntFt = Optional[_DefaultableUIntFt]
437_OptUIntFt = Optional[UnsignedIntegerFieldType]
4810b707
PP
438
439
e8f0d548 440class DataStreamTypePacketFeatures:
2d55dc7d
PP
441 def __init__(self, total_size_field_type: _DefaultableUIntFt = DEFAULT_FIELD_TYPE,
442 content_size_field_type: _DefaultableUIntFt = DEFAULT_FIELD_TYPE,
462e49b3
PP
443 beginning_timestamp_field_type: _OptDefaultableUIntFt = None,
444 end_timestamp_field_type: _OptDefaultableUIntFt = None,
af09c4fc
JL
445 discarded_event_records_snapshot_counter_field_type: _OptDefaultableUIntFt = DEFAULT_FIELD_TYPE,
446 sequence_number_field_type: _OptDefaultableUIntFt = None):
2d55dc7d 447 def get_ft(user_ft: _OptDefaultableUIntFt) -> _OptUIntFt:
4810b707 448 if user_ft == DEFAULT_FIELD_TYPE:
4c91e769 449 return UnsignedIntegerFieldType(64)
4810b707 450
2d55dc7d 451 return typing.cast(_OptUIntFt, user_ft)
4810b707
PP
452
453 self._total_size_field_type = get_ft(total_size_field_type)
454 self._content_size_field_type = get_ft(content_size_field_type)
462e49b3
PP
455 self._beginning_timestamp_field_type = get_ft(beginning_timestamp_field_type)
456 self._end_timestamp_field_type = get_ft(end_timestamp_field_type)
e8f0d548 457 self._discarded_event_records_snapshot_counter_field_type = get_ft(discarded_event_records_snapshot_counter_field_type)
af09c4fc
JL
458 self._sequence_number_field_type = get_ft(sequence_number_field_type)
459
460 @property
461 def sequence_number_field_type(self) -> _OptUIntFt:
462 return self._sequence_number_field_type
4810b707
PP
463
464 @property
2d55dc7d 465 def total_size_field_type(self) -> _OptUIntFt:
4810b707
PP
466 return self._total_size_field_type
467
468 @property
2d55dc7d 469 def content_size_field_type(self) -> _OptUIntFt:
4810b707
PP
470 return self._content_size_field_type
471
472 @property
462e49b3
PP
473 def beginning_timestamp_field_type(self) -> _OptUIntFt:
474 return self._beginning_timestamp_field_type
4810b707
PP
475
476 @property
462e49b3
PP
477 def end_timestamp_field_type(self) -> _OptUIntFt:
478 return self._end_timestamp_field_type
4810b707
PP
479
480 @property
e8f0d548
PP
481 def discarded_event_records_snapshot_counter_field_type(self) -> _OptUIntFt:
482 return self._discarded_event_records_snapshot_counter_field_type
4810b707
PP
483
484
e8f0d548 485class DataStreamTypeEventRecordFeatures:
2d55dc7d 486 def __init__(self, type_id_field_type: _OptDefaultableUIntFt = DEFAULT_FIELD_TYPE,
462e49b3 487 timestamp_field_type: _OptDefaultableUIntFt = None):
2d55dc7d
PP
488 def get_ft(user_ft: _OptDefaultableUIntFt) -> _OptUIntFt:
489 if user_ft == DEFAULT_FIELD_TYPE:
4c91e769 490 return UnsignedIntegerFieldType(64)
4810b707 491
2d55dc7d 492 return typing.cast(_OptUIntFt, user_ft)
4810b707
PP
493
494 self._type_id_field_type = get_ft(type_id_field_type)
462e49b3 495 self._timestamp_field_type = get_ft(timestamp_field_type)
4810b707
PP
496
497 @property
2d55dc7d 498 def type_id_field_type(self) -> _OptUIntFt:
4810b707
PP
499 return self._type_id_field_type
500
501 @property
462e49b3
PP
502 def timestamp_field_type(self) -> _OptUIntFt:
503 return self._timestamp_field_type
4810b707
PP
504
505
e8f0d548
PP
506class DataStreamTypeFeatures:
507 def __init__(self, packet_features: Optional[DataStreamTypePacketFeatures] = None,
508 event_record_features: Optional[DataStreamTypeEventRecordFeatures] = None):
7fffc7d1 509 if packet_features is None:
e8f0d548 510 self._packet_features = DataStreamTypePacketFeatures()
7fffc7d1 511 else:
4810b707
PP
512 self._packet_features = packet_features
513
e8f0d548
PP
514 if event_record_features is None:
515 self._event_record_features = DataStreamTypeEventRecordFeatures()
7fffc7d1 516 else:
e8f0d548 517 self._event_record_features = event_record_features
4810b707
PP
518
519 @property
e8f0d548 520 def packet_features(self) -> DataStreamTypePacketFeatures:
4810b707
PP
521 return self._packet_features
522
523 @property
e8f0d548
PP
524 def event_record_features(self) -> DataStreamTypeEventRecordFeatures:
525 return self._event_record_features
4810b707
PP
526
527
e8f0d548
PP
528class DataStreamType(_UniqueByName):
529 def __init__(self, name: str, event_record_types: Set[EventRecordType],
2d55dc7d 530 default_clock_type: Optional[ClockType] = None,
e8f0d548 531 features: Optional[DataStreamTypeFeatures] = None,
2d55dc7d 532 packet_context_field_type_extra_members: Optional[_StructFtMembers] = None,
e8f0d548 533 event_record_common_context_field_type: _OptStructFt = None):
2d55dc7d 534 self._id: Optional[Id] = None
4810b707
PP
535 self._name = name
536 self._default_clock_type = default_clock_type
e8f0d548
PP
537 self._event_record_common_context_field_type = event_record_common_context_field_type
538 self._event_record_types = frozenset(event_record_types)
4810b707
PP
539
540 # assign unique IDs
e8f0d548
PP
541 for index, ert in enumerate(sorted(self._event_record_types, key=lambda evt: evt.name)):
542 assert ert._id is None
543 ert._id = Id(index)
4810b707 544
4c91e769 545 self._set_features(features)
4810b707
PP
546 self._packet_context_field_type_extra_members = StructureFieldTypeMembers({})
547
548 if packet_context_field_type_extra_members is not None:
549 self._packet_context_field_type_extra_members = StructureFieldTypeMembers(packet_context_field_type_extra_members)
550
551 self._set_pkt_ctx_ft()
e8f0d548 552 self._set_er_header_ft()
4810b707 553
e8f0d548 554 def _set_features(self, features: Optional[DataStreamTypeFeatures]):
4810b707
PP
555 if features is not None:
556 self._features = features
2d55dc7d 557 return None
4810b707 558
462e49b3
PP
559 er_ts_ft = None
560 pkt_beginning_ts_ft = None
561 pkt_end_ts_ft = None
4810b707
PP
562
563 if self._default_clock_type is not None:
462e49b3
PP
564 # Automatic timestamp field types because the data stream
565 # type has a default clock type.
566 er_ts_ft = DEFAULT_FIELD_TYPE
567 pkt_beginning_ts_ft = DEFAULT_FIELD_TYPE
568 pkt_end_ts_ft = DEFAULT_FIELD_TYPE
4810b707 569
462e49b3
PP
570 self._features = DataStreamTypeFeatures(DataStreamTypePacketFeatures(beginning_timestamp_field_type=pkt_beginning_ts_ft,
571 end_timestamp_field_type=pkt_end_ts_ft),
572 DataStreamTypeEventRecordFeatures(timestamp_field_type=er_ts_ft))
4810b707 573
2d55dc7d 574 def _set_ft_mapped_clk_type_name(self, ft: Optional[UnsignedIntegerFieldType]):
4810b707
PP
575 if ft is None:
576 return
577
578 if self._default_clock_type is not None:
579 assert isinstance(ft, UnsignedIntegerFieldType)
580 ft._mapped_clk_type_name = self._default_clock_type.name
581
582 def _set_pkt_ctx_ft(self):
2d55dc7d
PP
583 members = None
584
585 def add_member_if_exists(name: str, ft: _FieldType, set_mapped_clk_type_name: bool = False):
4810b707
PP
586 nonlocal members
587
588 if ft is not None:
589 if set_mapped_clk_type_name:
2d55dc7d 590 self._set_ft_mapped_clk_type_name(typing.cast(UnsignedIntegerFieldType, ft))
4810b707
PP
591
592 members[name] = StructureFieldTypeMember(ft)
593
594 members = collections.OrderedDict([
595 (
596 'packet_size',
597 StructureFieldTypeMember(self._features.packet_features.total_size_field_type)
598 ),
599 (
600 'content_size',
601 StructureFieldTypeMember(self._features.packet_features.content_size_field_type)
602 )
603 ])
604
605 add_member_if_exists('timestamp_begin',
462e49b3
PP
606 self._features.packet_features.beginning_timestamp_field_type, True)
607 add_member_if_exists('timestamp_end', self._features.packet_features.end_timestamp_field_type,
4810b707
PP
608 True)
609 add_member_if_exists('events_discarded',
e8f0d548 610 self._features.packet_features.discarded_event_records_snapshot_counter_field_type)
af09c4fc
JL
611 add_member_if_exists('packet_seq_num',
612 self._features.packet_features.sequence_number_field_type)
4810b707
PP
613
614 if self._packet_context_field_type_extra_members is not None:
615 for name, field_type in self._packet_context_field_type_extra_members.items():
616 assert name not in members
617 members[name] = field_type
618
619 self._pkt_ctx_ft = StructureFieldType(8, members)
620
e8f0d548 621 def _set_er_header_ft(self):
4810b707
PP
622 members = collections.OrderedDict()
623
e8f0d548
PP
624 if self._features.event_record_features.type_id_field_type is not None:
625 members['id'] = StructureFieldTypeMember(self._features.event_record_features.type_id_field_type)
4810b707 626
462e49b3
PP
627 if self._features.event_record_features.timestamp_field_type is not None:
628 ft = self._features.event_record_features.timestamp_field_type
4810b707
PP
629 self._set_ft_mapped_clk_type_name(ft)
630 members['timestamp'] = StructureFieldTypeMember(ft)
631
e8f0d548 632 self._er_header_ft = StructureFieldType(8, members)
4810b707
PP
633
634 @property
2d55dc7d 635 def id(self) -> Optional[Id]:
4810b707
PP
636 return self._id
637
638 @property
2d55dc7d 639 def name(self) -> str:
4810b707
PP
640 return self._name
641
642 @property
2d55dc7d 643 def default_clock_type(self) -> Optional[ClockType]:
4810b707
PP
644 return self._default_clock_type
645
646 @property
e8f0d548 647 def features(self) -> DataStreamTypeFeatures:
4810b707
PP
648 return self._features
649
650 @property
2d55dc7d 651 def packet_context_field_type_extra_members(self) -> StructureFieldTypeMembers:
4810b707
PP
652 return self._packet_context_field_type_extra_members
653
654 @property
e8f0d548
PP
655 def event_record_common_context_field_type(self) -> _OptStructFt:
656 return self._event_record_common_context_field_type
4810b707
PP
657
658 @property
e8f0d548
PP
659 def event_record_types(self) -> FrozenSet[EventRecordType]:
660 return self._event_record_types
4810b707
PP
661
662
2d55dc7d
PP
663_OptUuidFt = Optional[Union[str, StaticArrayFieldType]]
664
665
4810b707 666class TraceTypeFeatures:
2d55dc7d
PP
667 def __init__(self, magic_field_type: _OptDefaultableUIntFt = DEFAULT_FIELD_TYPE,
668 uuid_field_type: _OptUuidFt = None,
e8f0d548 669 data_stream_type_id_field_type: _OptDefaultableUIntFt = DEFAULT_FIELD_TYPE):
7fffc7d1
PP
670 def get_field_type(user_ft: Optional[Union[str, _FieldType]],
671 create_default_ft: Callable[[], _FieldType]) -> _OptFt:
2d55dc7d 672 if user_ft == DEFAULT_FIELD_TYPE:
7fffc7d1 673 return create_default_ft()
4810b707 674
2d55dc7d 675 return typing.cast(_OptFt, user_ft)
4810b707 676
7fffc7d1 677 def create_default_magic_ft():
4c91e769 678 return UnsignedIntegerFieldType(32)
7fffc7d1
PP
679
680 def create_default_uuid_ft():
4c91e769 681 return StaticArrayFieldType(Count(16), UnsignedIntegerFieldType(8))
7fffc7d1 682
e8f0d548 683 def create_default_dst_id_ft():
4c91e769 684 return UnsignedIntegerFieldType(64)
7fffc7d1
PP
685
686 self._magic_field_type = typing.cast(_OptUIntFt, get_field_type(magic_field_type, create_default_magic_ft))
687 self._uuid_field_type = typing.cast(Optional[StaticArrayFieldType],
688 get_field_type(uuid_field_type, create_default_uuid_ft))
e8f0d548
PP
689 self._data_stream_type_id_field_type = typing.cast(_OptUIntFt,
690 get_field_type(data_stream_type_id_field_type,
691 create_default_dst_id_ft))
4810b707
PP
692
693 @property
2d55dc7d 694 def magic_field_type(self) -> _OptUIntFt:
4810b707
PP
695 return self._magic_field_type
696
697 @property
2d55dc7d 698 def uuid_field_type(self) -> Optional[StaticArrayFieldType]:
4810b707
PP
699 return self._uuid_field_type
700
701 @property
e8f0d548
PP
702 def data_stream_type_id_field_type(self) -> _OptUIntFt:
703 return self._data_stream_type_id_field_type
4810b707
PP
704
705
a209cf4d
EB
706class _TraceType:
707 def __init__(self, trace_byte_order: ByteOrder, data_stream_types: Set[DataStreamType],
708 uuid: _OptUuid, features: Optional[TraceTypeFeatures]):
709 self._trace_byte_order = trace_byte_order
e8f0d548 710 self._data_stream_types = frozenset(data_stream_types)
4810b707
PP
711
712 # assign unique IDs
e8f0d548
PP
713 for index, dst in enumerate(sorted(self._data_stream_types, key=lambda st: st.name)):
714 assert dst._id is None
715 dst._id = Id(index)
4810b707
PP
716
717 self._uuid = uuid
4c91e769 718 self._set_features(features)
4810b707 719 self._set_pkt_header_ft()
4810b707 720
4c91e769 721 def _set_features(self, features: Optional[TraceTypeFeatures]):
4810b707
PP
722 if features is not None:
723 self._features = features
724 return
725
726 # automatic UUID field type because the trace type has a UUID
727 uuid_ft = None if self._uuid is None else DEFAULT_FIELD_TYPE
4c91e769 728 self._features = TraceTypeFeatures(uuid_field_type=uuid_ft)
4810b707
PP
729
730 def _set_pkt_header_ft(self):
2d55dc7d
PP
731 members = collections.OrderedDict()
732
733 def add_member_if_exists(name: str, ft: _OptFt):
4810b707
PP
734 nonlocal members
735
2d55dc7d
PP
736 if ft is not None:
737 members[name] = StructureFieldTypeMember(ft)
4810b707 738
4810b707
PP
739 add_member_if_exists('magic', self._features.magic_field_type)
740 add_member_if_exists('uuid', self._features.uuid_field_type)
e8f0d548 741 add_member_if_exists('stream_id', self._features.data_stream_type_id_field_type)
4810b707
PP
742 self._pkt_header_ft = StructureFieldType(8, members)
743
b2c06e26 744 @property
a209cf4d
EB
745 def trace_byte_order(self) -> ByteOrder:
746 return self._trace_byte_order
b2c06e26 747
4810b707 748 @property
2d55dc7d 749 def uuid(self) -> _OptUuid:
4810b707
PP
750 return self._uuid
751
752 @property
e8f0d548
PP
753 def data_stream_types(self) -> FrozenSet[DataStreamType]:
754 return self._data_stream_types
4810b707 755
e8f0d548
PP
756 def data_stream_type(self, name: str) -> Optional[DataStreamType]:
757 for cand_dst in self._data_stream_types:
758 if cand_dst.name == name:
759 return cand_dst
4810b707 760
2d55dc7d
PP
761 return None
762
4810b707 763 @property
2d55dc7d 764 def features(self) -> TraceTypeFeatures:
4810b707
PP
765 return self._features
766
de49021e
PP
767 @property
768 def clock_types(self) -> Set[ClockType]:
769 clk_types = set()
770
e8f0d548
PP
771 for dst in self._data_stream_types:
772 if dst.default_clock_type is not None:
773 clk_types.add(dst.default_clock_type)
de49021e
PP
774
775 return clk_types
776
4810b707 777
a209cf4d
EB
778# Standard trace type class for a barectf 3 configuration.
779#
780# The trace byte order property of an instance is the same as the
781# expected native byte order of the target system.
782class TraceType(_TraceType):
783 def __init__(self, trace_byte_order: ByteOrder, data_stream_types: Set[DataStreamType],
784 uuid: _OptUuid = None, features: Optional[TraceTypeFeatures] = None):
785 super().__init__(trace_byte_order, data_stream_types, uuid, features)
786
787 @property
788 def native_byte_order(self) -> ByteOrder:
789 return self._trace_byte_order
790
791
792# This trace type class specifically exists to support barectf 2
793# configurations. Such configurations define the actual trace byte order
794# instead of the expected native byte order of the target system.
795#
796# The user provides the trace byte order property of an instance.
797#
798# IMPORTANT: When possible, prefer the `TraceType` class instead, as
799# enforcing the trace byte order could result in a less efficient
800# generated tracer.
801class TraceTypeWithUnknownNativeByteOrder(_TraceType):
802 def __init__(self, trace_byte_order: ByteOrder, data_stream_types: Set[DataStreamType],
803 uuid: _OptUuid = None, features: Optional[TraceTypeFeatures] = None):
804 super().__init__(trace_byte_order, data_stream_types, uuid, features)
805
806
2d55dc7d
PP
807_EnvEntry = Union[str, int]
808_EnvEntries = Mapping[str, _EnvEntry]
809
810
4810b707 811class TraceEnvironment(collections.abc.Mapping):
2d55dc7d 812 def __init__(self, environment: _EnvEntries):
4810b707
PP
813 self._env = {name: value for name, value in environment.items()}
814
2d55dc7d 815 def __getitem__(self, key: str) -> _EnvEntry:
4810b707
PP
816 return self._env[key]
817
2d55dc7d 818 def __iter__(self) -> Iterator[str]:
4810b707
PP
819 return iter(self._env)
820
2d55dc7d 821 def __len__(self) -> int:
4810b707
PP
822 return len(self._env)
823
824
825class Trace:
a209cf4d 826 def __init__(self, type: _TraceType, environment: Optional[_EnvEntries] = None):
4810b707
PP
827 self._type = type
828 self._set_env(environment)
829
2d55dc7d 830 def _set_env(self, environment: Optional[_EnvEntries]):
4810b707
PP
831 init_env = collections.OrderedDict([
832 ('domain', 'bare'),
833 ('tracer_name', 'barectf'),
834 ('tracer_major', barectf_version.__major_version__),
835 ('tracer_minor', barectf_version.__minor_version__),
836 ('tracer_patch', barectf_version.__patch_version__),
1d3b354e 837 ('tracer_pre', barectf_version.__pre_version__),
4810b707
PP
838 ('barectf_gen_date', str(datetime.datetime.now().isoformat())),
839 ])
840
841 if environment is None:
842 environment = {}
843
844 init_env.update(environment)
2d55dc7d 845 self._env = TraceEnvironment(typing.cast(_EnvEntries, init_env))
4810b707
PP
846
847 @property
a209cf4d 848 def type(self) -> _TraceType:
4810b707
PP
849 return self._type
850
851 @property
2d55dc7d 852 def environment(self) -> TraceEnvironment:
4810b707
PP
853 return self._env
854
855
2d55dc7d
PP
856_ClkTypeCTypes = Mapping[ClockType, str]
857
858
4810b707 859class ClockTypeCTypes(collections.abc.Mapping):
2d55dc7d 860 def __init__(self, c_types: _ClkTypeCTypes):
4810b707
PP
861 self._c_types = {clk_type: c_type for clk_type, c_type in c_types.items()}
862
2d55dc7d 863 def __getitem__(self, key: ClockType) -> str:
4810b707
PP
864 return self._c_types[key]
865
2d55dc7d 866 def __iter__(self) -> Iterator[ClockType]:
4810b707
PP
867 return iter(self._c_types)
868
2d55dc7d 869 def __len__(self) -> int:
4810b707
PP
870 return len(self._c_types)
871
872
873class ConfigurationCodeGenerationHeaderOptions:
2d55dc7d 874 def __init__(self, identifier_prefix_definition: bool = False,
e8f0d548 875 default_data_stream_type_name_definition: bool = False):
4810b707 876 self._identifier_prefix_definition = identifier_prefix_definition
e8f0d548 877 self._default_data_stream_type_name_definition = default_data_stream_type_name_definition
4810b707
PP
878
879 @property
2d55dc7d 880 def identifier_prefix_definition(self) -> bool:
4810b707
PP
881 return self._identifier_prefix_definition
882
883 @property
e8f0d548
PP
884 def default_data_stream_type_name_definition(self) -> bool:
885 return self._default_data_stream_type_name_definition
4810b707
PP
886
887
888class ConfigurationCodeGenerationOptions:
2d55dc7d 889 def __init__(self, identifier_prefix: str = 'barectf_', file_name_prefix: str = 'barectf',
e8f0d548 890 default_data_stream_type: Optional[DataStreamType] = None,
2d55dc7d
PP
891 header_options: Optional[ConfigurationCodeGenerationHeaderOptions] = None,
892 clock_type_c_types: Optional[_ClkTypeCTypes] = None):
4810b707
PP
893 self._identifier_prefix = identifier_prefix
894 self._file_name_prefix = file_name_prefix
e8f0d548 895 self._default_data_stream_type = default_data_stream_type
4810b707
PP
896
897 self._header_options = ConfigurationCodeGenerationHeaderOptions()
898
899 if header_options is not None:
900 self._header_options = header_options
901
902 self._clock_type_c_types = ClockTypeCTypes({})
903
904 if clock_type_c_types is not None:
905 self._clock_type_c_types = ClockTypeCTypes(clock_type_c_types)
906
907 @property
2d55dc7d 908 def identifier_prefix(self) -> str:
4810b707
PP
909 return self._identifier_prefix
910
911 @property
2d55dc7d 912 def file_name_prefix(self) -> str:
4810b707
PP
913 return self._file_name_prefix
914
915 @property
e8f0d548
PP
916 def default_data_stream_type(self) -> Optional[DataStreamType]:
917 return self._default_data_stream_type
4810b707
PP
918
919 @property
2d55dc7d 920 def header_options(self) -> ConfigurationCodeGenerationHeaderOptions:
4810b707
PP
921 return self._header_options
922
923 @property
2d55dc7d 924 def clock_type_c_types(self) -> ClockTypeCTypes:
4810b707
PP
925 return self._clock_type_c_types
926
927
928class ConfigurationOptions:
2d55dc7d
PP
929 def __init__(self,
930 code_generation_options: Optional[ConfigurationCodeGenerationOptions] = None):
4810b707
PP
931 self._code_generation_options = ConfigurationCodeGenerationOptions()
932
933 if code_generation_options is not None:
934 self._code_generation_options = code_generation_options
935
936 @property
2d55dc7d 937 def code_generation_options(self) -> ConfigurationCodeGenerationOptions:
4810b707
PP
938 return self._code_generation_options
939
940
941class Configuration:
b2c06e26 942 def __init__(self, trace: Trace, options: Optional[ConfigurationOptions] = None):
4810b707
PP
943 self._trace = trace
944 self._options = ConfigurationOptions()
945
946 if options is not None:
947 self._options = options
948
949 clk_type_c_types = self._options.code_generation_options.clock_type_c_types
950
e8f0d548
PP
951 for dst in trace.type.data_stream_types:
952 def_clk_type = dst.default_clock_type
4810b707
PP
953
954 if def_clk_type is None:
955 continue
956
957 if def_clk_type not in clk_type_c_types:
958 clk_type_c_types._c_types[def_clk_type] = 'uint32_t'
959
960 @property
2d55dc7d 961 def trace(self) -> Trace:
4810b707
PP
962 return self._trace
963
964 @property
2d55dc7d 965 def options(self) -> ConfigurationOptions:
4810b707 966 return self._options
This page took 0.083906 seconds and 4 git commands to generate.