1 # The MIT License (MIT)
3 # Copyright (c) 2014-2020 Philippe Proulx <pproulx@efficios.com>
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:
13 # The above copyright notice and this permission notice shall be
14 # included in all copies or substantial portions of the Software.
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.
24 import barectf
.tsdl182gen
as barectf_tsdl182gen
25 import barectf
.templates
as barectf_templates
26 import barectf
.codegen
as barectf_codegen
27 import barectf
.config
as barectf_config
28 import barectf
.version
as barectf_version
35 def __init__(self
, name
, contents
):
37 self
._contents
= contents
49 def __init__(self
, configuration
):
50 self
._config
= configuration
51 self
._file
_name
_prefix
= configuration
.options
.code_generation_options
.file_name_prefix
52 self
._ccode
_gen
= _CCodeGenerator(configuration
)
53 self
._c
_headers
= None
54 self
._c
_sources
= None
55 self
._metadata
_stream
= None
58 def _barectf_header_name(self
):
59 return f
'{self._file_name_prefix}.h'
61 def generate_c_headers(self
):
62 if self
._c
_headers
is None:
63 bitfield_header_name
= f
'{self._file_name_prefix}-bitfield.h'
65 _GeneratedFile(self
._barectf
_header
_name
,
66 self
._ccode
_gen
.generate_header(bitfield_header_name
)),
67 _GeneratedFile(bitfield_header_name
,
68 self
._ccode
_gen
.generate_bitfield_header()),
71 return self
._c
_headers
73 def generate_c_sources(self
):
74 if self
._c
_sources
is None:
76 _GeneratedFile(f
'{self._file_name_prefix}.c',
77 self
._ccode
_gen
.generate_c_src(self
._barectf
_header
_name
))
80 return self
._c
_sources
82 def generate_metadata_stream(self
):
83 if self
._metadata
_stream
is None:
84 self
._metadata
_stream
= _GeneratedFile('metadata',
85 barectf_tsdl182gen
._from
_config
(self
._config
))
87 return self
._metadata
_stream
91 return (v
+ (align
- 1)) & -align
94 class _SerializationAction
:
95 def __init__(self
, offset_in_byte
, ft
, names
):
96 assert(offset_in_byte
>= 0 and offset_in_byte
< 8)
97 self
._offset
_in
_byte
= offset_in_byte
99 self
._names
= copy
.deepcopy(names
)
102 def offset_in_byte(self
):
103 return self
._offset
_in
_byte
114 class _AlignSerializationAction(_SerializationAction
):
115 def __init__(self
, offset_in_byte
, ft
, names
, value
):
116 super().__init
__(offset_in_byte
, ft
, names
)
124 class _SerializeSerializationAction(_SerializationAction
):
128 class _SerializationActions
:
133 self
._last
_alignment
= None
134 self
._last
_bit
_array
_size
= None
137 self
._offset
_in
_byte
= 0
139 def append_root_scope_ft(self
, ft
, name
):
143 assert(type(ft
) is barectf_config
.StructureFieldType
)
151 def align(self
, alignment
):
152 do_align
= self
._must
_align
(alignment
)
153 self
._last
_alignment
= alignment
154 self
._last
_bit
_array
_size
= alignment
155 self
._try
_append
_align
_action
(alignment
, do_align
)
157 def _must_align(self
, align_req
):
158 return self
._last
_alignment
!= align_req
or self
._last
_bit
_array
_size
% align_req
!= 0
160 def _append_ft(self
, ft
):
161 if isinstance(ft
, (barectf_config
.StringFieldType
, barectf_config
._ArrayFieldType
)):
162 assert(type(ft
) is barectf_config
.StringFieldType
or self
._names
[-1] == 'uuid')
163 do_align
= self
._must
_align
(8)
164 self
._last
_alignment
= 8
165 self
._last
_bit
_array
_size
= 8
166 self
._try
_append
_align
_action
(8, do_align
, ft
)
167 self
._append
_serialize
_action
(ft
)
169 do_align
= self
._must
_align
(ft
.alignment
)
170 self
._last
_alignment
= ft
.alignment
172 if type(ft
) is barectf_config
.StructureFieldType
:
173 self
._last
_bit
_array
_size
= ft
.alignment
175 self
._last
_bit
_array
_size
= ft
.size
177 self
._try
_append
_align
_action
(ft
.alignment
, do_align
, ft
)
179 if type(ft
) is barectf_config
.StructureFieldType
:
180 for member_name
, member
in ft
.members
.items():
181 self
._names
.append(member_name
)
182 self
._append
_ft
(member
.field_type
)
185 self
._append
_serialize
_action
(ft
)
187 def _try_append_align_action(self
, alignment
, do_align
, ft
=None):
188 offset_in_byte
= self
._offset
_in
_byte
189 self
._offset
_in
_byte
= _align(self
._offset
_in
_byte
, alignment
) % 8
191 if do_align
and alignment
> 1:
192 self
._actions
.append(_AlignSerializationAction(offset_in_byte
, ft
, self
._names
,
195 def _append_serialize_action(self
, ft
):
196 assert(type(ft
) is not barectf_config
.StructureFieldType
)
197 offset_in_byte
= self
._offset
_in
_byte
199 if isinstance(ft
, barectf_config
._BitArrayFieldType
):
200 self
._offset
_in
_byte
+= ft
.size
201 self
._offset
_in
_byte
%= 8
203 self
._actions
.append(_SerializeSerializationAction(offset_in_byte
, ft
, self
._names
))
213 _PREFIX_TPH
: 'trace packet header',
214 _PREFIX_SPC
: 'stream packet context',
215 _PREFIX_SEH
: 'stream event header',
216 _PREFIX_SEC
: 'stream event context',
217 _PREFIX_EC
: 'event context',
218 _PREFIX_EP
: 'event payload',
222 class _CCodeGenerator
:
223 def __init__(self
, cfg
):
225 code_gen_opts
= cfg
.options
.code_generation_options
226 self
._iden
_prefix
= code_gen_opts
.identifier_prefix
227 self
._cg
= barectf_codegen
._CodeGenerator
('\t')
228 self
._saved
_serialization
_actions
= {}
231 def _trace_type(self
):
232 return self
._cfg
.trace
.type
234 def _clk_type_c_type(self
, clk_type
):
235 return self
._cfg
.options
.code_generation_options
.clock_type_c_types
[clk_type
]
237 def _generate_ctx_parent(self
):
238 tmpl
= barectf_templates
._CTX
_PARENT
239 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
))
241 def _generate_ctx(self
, stream_type
):
242 tmpl
= barectf_templates
._CTX
_BEGIN
243 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
))
245 pkt_header_ft
= self
._trace
_type
._pkt
_header
_ft
247 if pkt_header_ft
is not None:
248 for member_name
in pkt_header_ft
.members
:
249 self
._cg
.add_lines(f
'uint32_t off_tph_{member_name};')
251 for member_name
in stream_type
._pkt
_ctx
_ft
.members
:
252 self
._cg
.add_lines(f
'uint32_t off_spc_{member_name};')
254 if stream_type
.default_clock_type
is not None:
255 self
._cg
.add_line(f
'{self._clk_type_c_type(stream_type.default_clock_type)} cur_last_event_ts;')
258 tmpl
= barectf_templates
._CTX
_END
259 self
._cg
.add_lines(tmpl
)
261 def _generate_ctxs(self
):
262 for stream_type
in self
._trace
_type
.stream_types
:
263 self
._generate
_ctx
(stream_type
)
265 def _generate_clock_cb(self
, clk_type
):
266 tmpl
= barectf_templates
._CLOCK
_CB
267 self
._cg
.add_lines(tmpl
.format(return_ctype
=self
._clk
_type
_c
_type
(clk_type
),
268 cname
=clk_type
.name
))
270 def _generate_clock_cbs(self
):
273 for stream_type
in self
._trace
_type
.stream_types
:
274 def_clk_type
= stream_type
.default_clock_type
276 if def_clk_type
is not None and def_clk_type
not in clk_names
:
277 self
._generate
_clock
_cb
(def_clk_type
)
278 clk_names
.add(def_clk_type
)
280 def _generate_platform_callbacks(self
):
281 tmpl
= barectf_templates
._PLATFORM
_CALLBACKS
_BEGIN
282 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
))
284 self
._generate
_clock
_cbs
()
286 tmpl
= barectf_templates
._PLATFORM
_CALLBACKS
_END
287 self
._cg
.add_lines(tmpl
)
289 def generate_bitfield_header(self
):
291 tmpl
= barectf_templates
._BITFIELD
292 tmpl
= tmpl
.replace('$prefix$', self
._iden
_prefix
)
293 tmpl
= tmpl
.replace('$PREFIX$', self
._iden
_prefix
.upper())
295 if self
._trace
_type
.default_byte_order
== barectf_config
.ByteOrder
.BIG_ENDIAN
:
296 endian_def
= 'BIG_ENDIAN'
298 endian_def
= 'LITTLE_ENDIAN'
300 tmpl
= tmpl
.replace('$ENDIAN_DEF$', endian_def
)
301 self
._cg
.add_lines(tmpl
)
305 def _generate_func_init_proto(self
):
306 tmpl
= barectf_templates
._FUNC
_INIT
_PROTO
307 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
))
309 def _get_ft_c_type(self
, ft
):
310 if isinstance(ft
, barectf_config
._IntegerFieldType
):
311 sign_prefix
= 'u' if isinstance(ft
, barectf_config
.UnsignedIntegerFieldType
) else ''
323 return f
'{sign_prefix}int{sz}_t'
324 elif type(ft
) is barectf_config
.RealFieldType
:
325 if ft
.size
== 32 and ft
.alignment
== 32:
327 elif ft
.size
== 64 and ft
.alignment
== 64:
332 assert type(ft
) is barectf_config
.StringFieldType
333 return 'const char *'
335 def _generate_ft_c_type(self
, ft
):
336 c_type
= self
._get
_ft
_c
_type
(ft
)
337 self
._cg
.append_to_last_line(c_type
)
339 def _generate_proto_param(self
, ft
, name
):
340 self
._generate
_ft
_c
_type
(ft
)
341 self
._cg
.append_to_last_line(' ')
342 self
._cg
.append_to_last_line(name
)
344 def _generate_proto_params(self
, ft
, name_prefix
, exclude_set
=None):
345 if exclude_set
is None:
350 for member_name
, member
in ft
.members
.items():
351 if member_name
in exclude_set
:
354 self
._cg
.append_to_last_line(',')
355 self
._cg
.add_line('')
356 self
._generate
_proto
_param
(member
.field_type
, name_prefix
+ member_name
)
360 def _generate_func_open_proto(self
, stream_type
):
361 tmpl
= barectf_templates
._FUNC
_OPEN
_PROTO
_BEGIN
362 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
))
364 if self
._trace
_type
._pkt
_header
_ft
is not None:
365 self
._generate
_proto
_params
(self
._trace
_type
._pkt
_header
_ft
, _PREFIX_TPH
,
366 {'magic', 'stream_id', 'uuid'})
375 self
._generate
_proto
_params
(stream_type
._pkt
_ctx
_ft
, _PREFIX_SPC
, exclude_set
)
376 tmpl
= barectf_templates
._FUNC
_OPEN
_PROTO
_END
377 self
._cg
.add_lines(tmpl
)
379 def _generate_func_close_proto(self
, stream_type
):
380 tmpl
= barectf_templates
._FUNC
_CLOSE
_PROTO
381 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
))
383 def _generate_func_trace_proto_params(self
, stream_type
, ev_type
):
384 if stream_type
._ev
_header
_ft
is not None:
385 self
._generate
_proto
_params
(stream_type
._ev
_header
_ft
, _PREFIX_SEH
, {'id', 'timestamp'})
387 if stream_type
.event_common_context_field_type
is not None:
388 self
._generate
_proto
_params
(stream_type
.event_common_context_field_type
, _PREFIX_SEC
)
390 if ev_type
.specific_context_field_type
is not None:
391 self
._generate
_proto
_params
(ev_type
.specific_context_field_type
, _PREFIX_EC
)
393 if ev_type
.payload_field_type
is not None:
394 self
._generate
_proto
_params
(ev_type
.payload_field_type
, _PREFIX_EP
)
396 def _generate_func_trace_proto(self
, stream_type
, ev_type
):
397 tmpl
= barectf_templates
._FUNC
_TRACE
_PROTO
_BEGIN
398 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
,
399 evname
=ev_type
.name
))
400 self
._generate
_func
_trace
_proto
_params
(stream_type
, ev_type
)
401 tmpl
= barectf_templates
._FUNC
_TRACE
_PROTO
_END
402 self
._cg
.add_lines(tmpl
)
404 def _punctuate_proto(self
):
405 self
._cg
.append_to_last_line(';')
407 def generate_header(self
, bitfield_header_name
):
409 dt
= datetime
.datetime
.now().isoformat()
411 def_stream_type_name_def
= ''
412 cg_opts
= self
._cfg
.options
.code_generation_options
413 header_opts
= cg_opts
.header_options
415 if header_opts
.identifier_prefix_definition
:
416 prefix_def
= f
'#define _BARECTF_PREFIX {self._iden_prefix}'
418 def_stream_type
= cg_opts
.default_stream_type
420 if header_opts
.default_stream_type_name_definition
and def_stream_type
is not None:
421 def_stream_type_name_def
= f
'#define _BARECTF_DEFAULT_STREAM {def_stream_type.name}'
423 def_stream_type_trace_defs
= ''
425 if def_stream_type
is not None:
428 for ev_type
in def_stream_type
.event_types
:
429 tmpl
= barectf_templates
._DEFINE
_DEFAULT
_STREAM
_TRACE
430 define
= tmpl
.format(prefix
=self
._iden
_prefix
, sname
=def_stream_type
.name
,
434 def_stream_type_trace_defs
= '\n'.join(lines
)
436 tmpl
= barectf_templates
._HEADER
_BEGIN
437 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
,
438 ucprefix
=self
._iden
_prefix
.upper(),
439 bitfield_header_filename
=bitfield_header_name
,
440 version
=barectf_version
.__version
__, date
=dt
,
441 prefix_def
=prefix_def
,
442 default_stream_def
=def_stream_type_name_def
,
443 default_stream_trace_defs
=def_stream_type_trace_defs
))
444 self
._cg
.add_empty_line()
446 # platform callbacks structure
447 self
._generate
_platform
_callbacks
()
448 self
._cg
.add_empty_line()
451 self
._generate
_ctx
_parent
()
452 self
._cg
.add_empty_line()
455 self
._generate
_ctxs
()
456 self
._cg
.add_empty_line()
458 # initialization function prototype
459 self
._generate
_func
_init
_proto
()
460 self
._punctuate
_proto
()
461 self
._cg
.add_empty_line()
463 for stream_type
in self
._trace
_type
.stream_types
:
464 self
._generate
_func
_open
_proto
(stream_type
)
465 self
._punctuate
_proto
()
466 self
._cg
.add_empty_line()
467 self
._generate
_func
_close
_proto
(stream_type
)
468 self
._punctuate
_proto
()
469 self
._cg
.add_empty_line()
471 for ev_type
in stream_type
.event_types
:
472 self
._generate
_func
_trace
_proto
(stream_type
, ev_type
)
473 self
._punctuate
_proto
()
474 self
._cg
.add_empty_line()
476 tmpl
= barectf_templates
._HEADER
_END
477 self
._cg
.add_lines(tmpl
.format(ucprefix
=self
._iden
_prefix
.upper()))
480 def _get_call_event_param_list_from_struct_ft(self
, ft
, prefix
, exclude_set
=None):
481 if exclude_set
is None:
486 for member_name
in ft
.members
:
487 if member_name
in exclude_set
:
490 lst
+= f
', {prefix}{member_name}'
494 def _get_call_event_param_list(self
, stream_type
, ev_type
):
497 if stream_type
._ev
_header
_ft
is not None:
498 lst
+= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(stream_type
._ev
_header
_ft
,
499 _PREFIX_SEH
, {'id', 'timestamp'})
501 if stream_type
.event_common_context_field_type
is not None:
502 lst
+= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(stream_type
.event_common_context_field_type
,
505 if ev_type
.specific_context_field_type
is not None:
506 lst
+= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(ev_type
.specific_context_field_type
,
509 if ev_type
.payload_field_type
is not None:
510 lst
+= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(ev_type
.payload_field_type
,
515 def _generate_align(self
, at
, align
):
516 self
._cg
.add_line(f
'_ALIGN({at}, {align});')
518 def _generate_incr_pos(self
, var
, value
):
519 self
._cg
.add_line(f
'{var} += {value};')
521 def _generate_incr_pos_bytes(self
, var
, value
):
522 self
._generate
_incr
_pos
(var
, f
'_BYTES_TO_BITS({value})')
524 def _generate_func_get_event_size_proto(self
, stream_type
, ev_type
):
525 tmpl
= barectf_templates
._FUNC
_GET
_EVENT
_SIZE
_PROTO
_BEGIN
526 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
,
527 evname
=ev_type
.name
))
528 self
._generate
_func
_trace
_proto
_params
(stream_type
, ev_type
)
529 tmpl
= barectf_templates
._FUNC
_GET
_EVENT
_SIZE
_PROTO
_END
530 self
._cg
.add_lines(tmpl
)
532 def _generate_func_get_event_size(self
, stream_type
, ev_type
):
533 self
._generate
_func
_get
_event
_size
_proto
(stream_type
, ev_type
)
534 tmpl
= barectf_templates
._FUNC
_GET
_EVENT
_SIZE
_BODY
_BEGIN
535 lines
= tmpl
.format(prefix
=self
._iden
_prefix
)
536 self
._cg
.add_lines(lines
)
537 self
._cg
.add_empty_line()
539 ser_actions
= _SerializationActions()
540 ser_actions
.append_root_scope_ft(stream_type
._ev
_header
_ft
, _PREFIX_SEH
)
541 ser_actions
.append_root_scope_ft(stream_type
.event_common_context_field_type
, _PREFIX_SEC
)
542 ser_actions
.append_root_scope_ft(ev_type
.specific_context_field_type
, _PREFIX_EC
)
543 ser_actions
.append_root_scope_ft(ev_type
.payload_field_type
, _PREFIX_EP
)
545 for action
in ser_actions
.actions
:
546 if type(action
) is _AlignSerializationAction
:
548 if len(action
.names
) == 1:
549 line
= f
'align {_PREFIX_TO_NAME[action.names[0]]} structure'
551 line
= f
'align field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})'
553 self
._cg
.add_cc_line(line
)
555 self
._generate
_align
('at', action
.value
)
556 self
._cg
.add_empty_line()
558 assert type(action
) is _SerializeSerializationAction
559 assert(len(action
.names
) >= 2)
560 line
= f
'add size of field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})'
561 self
._cg
.add_cc_line(line
)
563 if type(action
.ft
) is barectf_config
.StringFieldType
:
564 param
= ''.join(action
.names
)
565 self
._generate
_incr
_pos
_bytes
('at', f
'strlen({param}) + 1')
567 self
._generate
_incr
_pos
('at', action
.ft
.size
)
569 self
._cg
.add_empty_line()
572 tmpl
= barectf_templates
._FUNC
_GET
_EVENT
_SIZE
_BODY
_END
573 self
._cg
.add_lines(tmpl
)
575 def _generate_func_serialize_event_proto(self
, stream_type
, ev_type
):
576 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_EVENT
_PROTO
_BEGIN
577 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
,
578 evname
=ev_type
.name
))
579 self
._generate
_func
_trace
_proto
_params
(stream_type
, ev_type
)
580 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_EVENT
_PROTO
_END
581 self
._cg
.add_lines(tmpl
)
583 def _generate_serialize_from_action(self
, var
, ctx
, action
):
584 def gen_bitfield_write(c_type
, var
, ctx
, action
):
585 ptr
= f
'&{ctx}->buf[_BITS_TO_BYTES({ctx}->at)]'
586 start
= action
.offset_in_byte
587 suffix
= 'le' if action
.ft
.byte_order
is barectf_config
.ByteOrder
.LITTLE_ENDIAN
else 'be'
588 func
= f
'{self._iden_prefix}bt_bitfield_write_{suffix}'
589 call
= f
'{func}({ptr}, uint8_t, {start}, {action.ft.size}, {c_type}, ({c_type}) {var});'
590 self
._cg
.add_line(call
)
592 def gen_serialize_int(var
, ctx
, action
):
593 c_type
= self
._get
_ft
_c
_type
(action
.ft
)
594 gen_bitfield_write(c_type
, var
, ctx
, action
)
595 self
._generate
_incr
_pos
(f
'{ctx}->at', action
.ft
.size
)
597 def gen_serialize_real(var
, ctx
, action
):
598 c_type
= self
._get
_ft
_c
_type
(action
.ft
)
601 if c_type
== 'float' or c_type
== 'double':
604 if c_type
== 'float':
606 int_c_type
= 'uint32_t'
608 assert c_type
== 'double'
610 int_c_type
= 'uint64_t'
612 # union for reading the bytes of the floating point number
613 self
._cg
.add_empty_line()
614 self
._cg
.add_line('{')
616 self
._cg
.add_line(f
'union {union_name} {union_name};')
617 self
._cg
.add_empty_line()
618 self
._cg
.add_line(f
'{union_name}.f = {var};')
619 bf_var
= f
'{union_name}.u'
621 bf_var
= f
'({c_type}) {var}'
624 gen_bitfield_write(int_c_type
, bf_var
, ctx
, action
)
628 self
._cg
.add_line('}')
629 self
._cg
.add_empty_line()
631 self
._generate
_incr
_pos
(f
'{ctx}->at', action
.ft
.size
)
633 def gen_serialize_string(var
, ctx
, action
):
634 self
._cg
.add_lines(f
'_write_cstring({ctx}, {var});')
636 if isinstance(action
.ft
, barectf_config
._IntegerFieldType
):
637 return gen_serialize_int(var
, ctx
, action
)
638 elif type(action
.ft
) is barectf_config
.RealFieldType
:
639 return gen_serialize_real(var
, ctx
, action
)
641 assert type(action
.ft
) is barectf_config
.StringFieldType
642 return gen_serialize_string(var
, ctx
, action
)
644 def _generate_serialize_statements_from_actions(self
, prefix
, action_iter
, spec_src
=None):
645 for action
in action_iter
:
646 if type(action
) is _AlignSerializationAction
:
648 if len(action
.names
) == 1:
649 line
= f
'align {_PREFIX_TO_NAME[action.names[0]]} structure'
651 line
= f
'align field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})'
653 self
._cg
.add_cc_line(line
)
655 self
._generate
_align
('ctx->at', action
.value
)
656 self
._cg
.add_empty_line()
658 assert type(action
) is _SerializeSerializationAction
659 assert(len(action
.names
) >= 2)
660 member_name
= action
.names
[-1]
661 line
= f
'serialize field `{member_name}` ({_PREFIX_TO_NAME[action.names[0]]})'
662 self
._cg
.add_cc_line(line
)
663 src
= prefix
+ member_name
665 if spec_src
is not None and member_name
in spec_src
:
666 src
= spec_src
[member_name
]
668 self
._generate
_serialize
_from
_action
(src
, 'ctx', action
)
669 self
._cg
.add_empty_line()
671 def _generate_func_serialize_event(self
, stream_type
, ev_type
, orig_ser_actions
):
672 self
._generate
_func
_serialize
_event
_proto
(stream_type
, ev_type
)
673 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_EVENT
_BODY
_BEGIN
674 lines
= tmpl
.format(prefix
=self
._iden
_prefix
)
675 self
._cg
.add_lines(lines
)
677 self
._cg
.add_empty_line()
679 if stream_type
._ev
_header
_ft
is not None:
680 params
= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(stream_type
._ev
_header
_ft
,
683 self
._cg
.add_cc_line('stream event header')
684 line
= f
'_serialize_stream_event_header_{stream_type.name}(ctx, {ev_type.id}{params});'
685 self
._cg
.add_line(line
)
686 self
._cg
.add_empty_line()
688 if stream_type
.event_common_context_field_type
is not None:
689 params
= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(stream_type
.event_common_context_field_type
,
691 self
._cg
.add_cc_line('stream event context')
692 line
= f
'_serialize_stream_event_context_{stream_type.name}(ctx{params});'
693 self
._cg
.add_line(line
)
694 self
._cg
.add_empty_line()
696 if ev_type
.specific_context_field_type
is not None or ev_type
.payload_field_type
is not None:
697 ser_actions
= copy
.deepcopy(orig_ser_actions
)
699 if ev_type
.specific_context_field_type
is not None:
700 ser_action_index
= len(ser_actions
.actions
)
701 ser_actions
.append_root_scope_ft(ev_type
.specific_context_field_type
, _PREFIX_EC
)
702 ser_action_iter
= itertools
.islice(ser_actions
.actions
, ser_action_index
, None)
703 self
._generate
_serialize
_statements
_from
_actions
(_PREFIX_EC
, ser_action_iter
)
705 if ev_type
.payload_field_type
is not None:
706 ser_action_index
= len(ser_actions
.actions
)
707 ser_actions
.append_root_scope_ft(ev_type
.payload_field_type
, _PREFIX_EP
)
708 ser_action_iter
= itertools
.islice(ser_actions
.actions
, ser_action_index
, None)
709 self
._generate
_serialize
_statements
_from
_actions
(_PREFIX_EP
, ser_action_iter
)
712 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_EVENT
_BODY
_END
713 self
._cg
.add_lines(tmpl
)
715 def _generate_func_serialize_event_header_proto(self
, stream_type
):
716 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_PROTO
_BEGIN
717 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
))
719 if stream_type
._ev
_header
_ft
is not None:
720 self
._generate
_proto
_params
(stream_type
._ev
_header
_ft
, _PREFIX_SEH
,
723 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_PROTO
_END
724 self
._cg
.add_lines(tmpl
)
726 def _generate_func_serialize_event_common_context_proto(self
, stream_type
):
727 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_PROTO
_BEGIN
728 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
))
730 if stream_type
.event_common_context_field_type
is not None:
731 self
._generate
_proto
_params
(stream_type
.event_common_context_field_type
, _PREFIX_SEC
)
733 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_PROTO
_END
734 self
._cg
.add_lines(tmpl
)
736 def _generate_func_serialize_event_header(self
, stream_type
, ser_action_iter
):
737 self
._generate
_func
_serialize
_event
_header
_proto
(stream_type
)
738 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_BODY
_BEGIN
739 lines
= tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
)
740 self
._cg
.add_lines(lines
)
743 if stream_type
.default_clock_type
is not None:
744 line
= f
'struct {self._iden_prefix}{stream_type.name}_ctx *s_ctx = FROM_VOID_PTR(struct {self._iden_prefix}{stream_type.name}_ctx, vctx);'
745 self
._cg
.add_line(line
)
746 line
= f
'const {self._clk_type_c_type(stream_type.default_clock_type)} ts = s_ctx->cur_last_event_ts;'
747 self
._cg
.add_line(line
)
749 self
._cg
.add_empty_line()
751 if stream_type
._ev
_header
_ft
is not None:
754 member
= stream_type
._ev
_header
_ft
.members
.get(member_name
)
756 if member
is not None:
757 spec_src
[member_name
] = f
'({self._get_ft_c_type(member.field_type)}) event_id'
759 member_name
= 'timestamp'
760 member
= stream_type
._ev
_header
_ft
.members
.get(member_name
)
762 if member
is not None:
763 spec_src
[member_name
] = f
'({self._get_ft_c_type(member.field_type)}) ts'
765 self
._generate
_serialize
_statements
_from
_actions
(_PREFIX_SEH
, ser_action_iter
,
769 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_BODY
_END
770 self
._cg
.add_lines(tmpl
)
772 def _generate_func_serialize_event_common_context(self
, stream_type
, ser_action_iter
):
773 self
._generate
_func
_serialize
_event
_common
_context
_proto
(stream_type
)
774 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_BODY
_BEGIN
775 lines
= tmpl
.format(prefix
=self
._iden
_prefix
)
776 self
._cg
.add_lines(lines
)
779 if stream_type
.event_common_context_field_type
is not None:
780 self
._generate
_serialize
_statements
_from
_actions
(_PREFIX_SEC
, ser_action_iter
)
783 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_BODY
_END
784 self
._cg
.add_lines(tmpl
)
786 def _generate_func_trace(self
, stream_type
, ev_type
):
787 self
._generate
_func
_trace
_proto
(stream_type
, ev_type
)
788 params
= self
._get
_call
_event
_param
_list
(stream_type
, ev_type
)
789 def_clk_type
= stream_type
.default_clock_type
791 if def_clk_type
is not None:
792 save_ts_line
= f
'ctx->cur_last_event_ts = ctx->parent.cbs.{def_clk_type.name}_clock_get_value(ctx->parent.data);'
794 save_ts_line
= '/* (no clock) */'
796 tmpl
= barectf_templates
._FUNC
_TRACE
_BODY
797 self
._cg
.add_lines(tmpl
.format(sname
=stream_type
.name
, evname
=ev_type
.name
, params
=params
,
798 save_ts
=save_ts_line
))
800 def _generate_func_init(self
):
801 self
._generate
_func
_init
_proto
()
802 tmpl
= barectf_templates
._FUNC
_INIT
_BODY
803 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
))
805 def _generate_member_name_cc_line(self
, member_name
):
806 self
._cg
.add_cc_line(f
'`{member_name}` field')
808 def _save_serialization_action(self
, name
, action
):
809 self
._saved
_serialization
_actions
[name
] = action
811 def _get_open_close_ts_line(self
, stream_type
):
812 def_clk_type
= stream_type
.default_clock_type
814 if def_clk_type
is None:
817 c_type
= self
._clk
_type
_c
_type
(def_clk_type
)
818 return f
'\tconst {c_type} ts = ctx->parent.use_cur_last_event_ts ? ctx->cur_last_event_ts : ctx->parent.cbs.{def_clk_type.name}_clock_get_value(ctx->parent.data);'
820 def _generate_func_open(self
, stream_type
):
821 def generate_save_offset(name
, action
):
822 self
._cg
.add_line(f
'ctx->off_spc_{name} = ctx->parent.at;')
823 self
._save
_serialization
_action
(name
, action
)
825 self
._generate
_func
_open
_proto
(stream_type
)
826 tmpl
= barectf_templates
._FUNC
_OPEN
_BODY
_BEGIN
827 pkt_ctx_ft
= stream_type
._pkt
_ctx
_ft
828 ts_line
= self
._get
_open
_close
_ts
_line
(stream_type
)
829 lines
= tmpl
.format(ts
=ts_line
)
830 self
._cg
.add_lines(lines
)
832 self
._cg
.add_cc_line('do not open a packet that is already open')
833 self
._cg
.add_line('if (ctx->parent.packet_is_open) {')
835 self
._cg
.add_line('ctx->parent.in_tracing_section = saved_in_tracing_section;')
836 self
._cg
.add_line('return;')
838 self
._cg
.add_line('}')
839 self
._cg
.add_empty_line()
840 self
._cg
.add_line('ctx->parent.at = 0;')
841 pkt_header_ft
= self
._trace
_type
._pkt
_header
_ft
842 ser_actions
= _SerializationActions()
844 if pkt_header_ft
is not None:
845 self
._cg
.add_empty_line()
846 self
._cg
.add_cc_line('trace packet header')
847 self
._cg
.add_line('{')
849 ser_actions
.append_root_scope_ft(pkt_header_ft
, _PREFIX_TPH
)
851 for action
in ser_actions
.actions
:
852 if type(action
) is _AlignSerializationAction
:
854 if len(action
.names
) == 1:
855 line
= 'align trace packet header structure'
857 line
= f
'align field `{action.names[-1]}`'
859 self
._cg
.add_cc_line(line
)
861 self
._generate
_align
('ctx->parent.at', action
.value
)
862 self
._cg
.add_empty_line()
864 assert type(action
) is _SerializeSerializationAction
865 assert(len(action
.names
) >= 2)
866 member_name
= action
.names
[-1]
867 line
= f
'serialize field `{member_name}`'
868 self
._cg
.add_cc_line(line
)
869 src
= _PREFIX_TPH
+ member_name
871 if member_name
== 'magic':
873 elif member_name
== 'stream_id':
874 src
= f
'({self._get_ft_c_type(action.ft)}) {stream_type.id}'
875 elif member_name
== 'uuid':
876 self
._cg
.add_line('{')
878 self
._cg
.add_line('static uint8_t uuid[] = {')
881 for b
in self
._trace
_type
.uuid
.bytes
:
882 self
._cg
.add_line(f
'{b},')
885 self
._cg
.add_line('};')
886 self
._cg
.add_empty_line()
887 self
._generate
_align
('ctx->parent.at', 8)
888 line
= 'memcpy(&ctx->parent.buf[_BITS_TO_BYTES(ctx->parent.at)], uuid, 16);'
889 self
._cg
.add_line(line
)
890 self
._generate
_incr
_pos
_bytes
('ctx->parent.at', 16)
892 self
._cg
.add_line('}')
893 self
._cg
.add_empty_line()
896 self
._generate
_serialize
_from
_action
(src
, '(&ctx->parent)', action
)
897 self
._cg
.add_empty_line()
900 self
._cg
.add_lines('}')
902 spc_action_index
= len(ser_actions
.actions
)
903 self
._cg
.add_empty_line()
904 self
._cg
.add_cc_line('stream packet context')
905 self
._cg
.add_line('{')
907 ser_actions
.append_root_scope_ft(pkt_ctx_ft
, _PREFIX_SPC
)
909 for action
in itertools
.islice(ser_actions
.actions
, spc_action_index
, None):
910 if type(action
) is _AlignSerializationAction
:
912 if len(action
.names
) == 1:
913 line
= 'align stream packet context structure'
915 line
= f
'align field `{action.names[-1]}`'
917 self
._cg
.add_cc_line(line
)
919 self
._generate
_align
('ctx->parent.at', action
.value
)
920 self
._cg
.add_empty_line()
922 assert type(action
) is _SerializeSerializationAction
923 assert(len(action
.names
) >= 2)
924 member_name
= action
.names
[-1]
925 line
= f
'serialize field `{member_name}`'
926 self
._cg
.add_cc_line(line
)
927 src
= _PREFIX_SPC
+ member_name
930 if member_name
== 'timestamp_begin':
931 src
= f
'({self._get_ft_c_type(action.ft)}) ts'
932 elif member_name
in {'timestamp_end', 'content_size', 'events_discarded'}:
934 elif member_name
== 'packet_size':
935 src
= f
'({self._get_ft_c_type(action.ft)}) ctx->parent.packet_size'
938 generate_save_offset(member_name
, action
)
939 self
._generate
_incr
_pos
('ctx->parent.at', action
.ft
.size
)
941 self
._generate
_serialize
_from
_action
(src
, '(&ctx->parent)', action
)
943 self
._cg
.add_empty_line()
946 self
._cg
.add_lines('}')
948 tmpl
= barectf_templates
._FUNC
_OPEN
_BODY
_END
949 self
._cg
.add_lines(tmpl
)
951 def _generate_func_close(self
, stream_type
):
952 def generate_goto_offset(name
):
953 self
._cg
.add_line(f
'ctx->parent.at = ctx->off_spc_{name};')
955 self
._generate
_func
_close
_proto
(stream_type
)
956 tmpl
= barectf_templates
._FUNC
_CLOSE
_BODY
_BEGIN
957 pkt_ctx_ft
= stream_type
._pkt
_ctx
_ft
958 ts_line
= self
._get
_open
_close
_ts
_line
(stream_type
)
959 lines
= tmpl
.format(ts
=ts_line
)
960 self
._cg
.add_lines(lines
)
962 self
._cg
.add_cc_line('do not close a packet that is not open')
963 self
._cg
.add_line('if (!ctx->parent.packet_is_open) {')
965 self
._cg
.add_line('ctx->parent.in_tracing_section = saved_in_tracing_section;')
966 self
._cg
.add_line('return;')
968 self
._cg
.add_line('}')
969 self
._cg
.add_empty_line()
970 self
._cg
.add_cc_line('save content size')
971 self
._cg
.add_line('ctx->parent.content_size = ctx->parent.at;')
972 member_name
= 'timestamp_end'
973 member
= pkt_ctx_ft
.members
.get(member_name
)
975 if member
is not None:
976 self
._cg
.add_empty_line()
977 self
._generate
_member
_name
_cc
_line
(member_name
)
978 generate_goto_offset(member_name
)
979 action
= self
._saved
_serialization
_actions
[member_name
]
980 c_type
= self
._get
_ft
_c
_type
(member
.field_type
)
981 self
._generate
_serialize
_from
_action
(f
'({c_type}) ts', '(&ctx->parent)', action
)
983 member_name
= 'content_size'
984 member
= pkt_ctx_ft
.members
.get(member_name
)
986 if member
is not None:
987 self
._cg
.add_empty_line()
988 self
._generate
_member
_name
_cc
_line
(member_name
)
989 generate_goto_offset(member_name
)
990 action
= self
._saved
_serialization
_actions
[member_name
]
991 c_type
= self
._get
_ft
_c
_type
(member
.field_type
)
992 self
._generate
_serialize
_from
_action
(f
'({c_type}) ctx->parent.content_size',
993 '(&ctx->parent)', action
)
995 member_name
= 'events_discarded'
996 member
= pkt_ctx_ft
.members
.get(member_name
)
998 if member
is not None:
999 self
._cg
.add_empty_line()
1000 self
._generate
_member
_name
_cc
_line
(member_name
)
1001 generate_goto_offset(member_name
)
1002 action
= self
._saved
_serialization
_actions
[member_name
]
1003 c_type
= self
._get
_ft
_c
_type
(member
.field_type
)
1004 self
._generate
_serialize
_from
_action
(f
'({c_type}) ctx->parent.events_discarded',
1005 '(&ctx->parent)', action
)
1008 tmpl
= barectf_templates
._FUNC
_CLOSE
_BODY
_END
1009 self
._cg
.add_lines(tmpl
)
1011 def generate_c_src(self
, header_name
):
1013 dt
= datetime
.datetime
.now().isoformat()
1014 tmpl
= barectf_templates
._C
_SRC
1015 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, header_filename
=header_name
,
1016 version
=barectf_version
.__version
__, date
=dt
))
1017 self
._cg
.add_empty_line()
1019 # initialization function
1020 self
._generate
_func
_init
()
1021 self
._cg
.add_empty_line()
1023 for stream_type
in self
._trace
_type
.stream_types
:
1024 self
._generate
_func
_open
(stream_type
)
1025 self
._cg
.add_empty_line()
1026 self
._generate
_func
_close
(stream_type
)
1027 self
._cg
.add_empty_line()
1028 ser_actions
= _SerializationActions()
1030 if stream_type
._ev
_header
_ft
is not None:
1031 ser_actions
.append_root_scope_ft(stream_type
._ev
_header
_ft
, _PREFIX_SEH
)
1032 self
._generate
_func
_serialize
_event
_header
(stream_type
, iter(ser_actions
.actions
))
1033 self
._cg
.add_empty_line()
1035 if stream_type
.event_common_context_field_type
is not None:
1036 ser_action_index
= len(ser_actions
.actions
)
1037 ser_actions
.append_root_scope_ft(stream_type
.event_common_context_field_type
,
1039 ser_action_iter
= itertools
.islice(ser_actions
.actions
, ser_action_index
, None)
1040 self
._generate
_func
_serialize
_event
_common
_context
(stream_type
, ser_action_iter
)
1041 self
._cg
.add_empty_line()
1043 for ev_type
in stream_type
.event_types
:
1044 self
._generate
_func
_get
_event
_size
(stream_type
, ev_type
)
1045 self
._cg
.add_empty_line()
1046 self
._generate
_func
_serialize
_event
(stream_type
, ev_type
, ser_actions
)
1047 self
._cg
.add_empty_line()
1048 self
._generate
_func
_trace
(stream_type
, ev_type
)
1049 self
._cg
.add_empty_line()
1051 return self
._cg
.code