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
.template
as barectf_template
27 import barectf
.codegen
as barectf_codegen
28 import barectf
.config
as barectf_config
29 import barectf
.version
as barectf_version
36 def __init__(self
, name
, contents
):
38 self
._contents
= contents
50 def __init__(self
, configuration
):
51 self
._config
= configuration
52 self
._file
_name
_prefix
= configuration
.options
.code_generation_options
.file_name_prefix
53 self
._ccode
_gen
= _CCodeGenerator(configuration
)
54 self
._c
_headers
= None
55 self
._c
_sources
= None
56 self
._metadata
_stream
= None
59 def _barectf_header_name(self
):
60 return f
'{self._file_name_prefix}.h'
63 def _bitfield_header_name(self
):
64 return f
'{self._file_name_prefix}-bitfield.h'
66 def generate_c_headers(self
):
67 if self
._c
_headers
is None:
69 _GeneratedFile(self
._barectf
_header
_name
, self
._ccode
_gen
.generate_header()),
70 _GeneratedFile(self
._bitfield
_header
_name
, self
._ccode
_gen
.generate_bitfield_header()),
73 return self
._c
_headers
75 def generate_c_sources(self
):
76 if self
._c
_sources
is None:
77 bitfield_header_name
= f
'{self._file_name_prefix}-bitfield.h'
79 _GeneratedFile(f
'{self._file_name_prefix}.c',
80 self
._ccode
_gen
.generate_c_src(self
._barectf
_header
_name
,
81 self
._bitfield
_header
_name
))
84 return self
._c
_sources
86 def generate_metadata_stream(self
):
87 if self
._metadata
_stream
is None:
88 self
._metadata
_stream
= _GeneratedFile('metadata',
89 barectf_tsdl182gen
._from
_config
(self
._config
))
91 return self
._metadata
_stream
95 return (v
+ (align
- 1)) & -align
98 class _SerializationAction
:
99 def __init__(self
, offset_in_byte
, ft
, names
):
100 assert(offset_in_byte
>= 0 and offset_in_byte
< 8)
101 self
._offset
_in
_byte
= offset_in_byte
103 self
._names
= copy
.deepcopy(names
)
106 def offset_in_byte(self
):
107 return self
._offset
_in
_byte
118 class _AlignSerializationAction(_SerializationAction
):
119 def __init__(self
, offset_in_byte
, ft
, names
, value
):
120 super().__init
__(offset_in_byte
, ft
, names
)
128 class _SerializeSerializationAction(_SerializationAction
):
132 class _SerializationActions
:
137 self
._last
_alignment
= None
138 self
._last
_bit
_array
_size
= None
141 self
._offset
_in
_byte
= 0
143 def append_root_scope_ft(self
, ft
, name
):
147 assert(type(ft
) is barectf_config
.StructureFieldType
)
155 def align(self
, alignment
):
156 do_align
= self
._must
_align
(alignment
)
157 self
._last
_alignment
= alignment
158 self
._last
_bit
_array
_size
= alignment
159 self
._try
_append
_align
_action
(alignment
, do_align
)
161 def _must_align(self
, align_req
):
162 return self
._last
_alignment
!= align_req
or self
._last
_bit
_array
_size
% align_req
!= 0
164 def _append_ft(self
, ft
):
165 if isinstance(ft
, (barectf_config
.StringFieldType
, barectf_config
._ArrayFieldType
)):
166 assert(type(ft
) is barectf_config
.StringFieldType
or self
._names
[-1] == 'uuid')
167 do_align
= self
._must
_align
(8)
168 self
._last
_alignment
= 8
169 self
._last
_bit
_array
_size
= 8
170 self
._try
_append
_align
_action
(8, do_align
, ft
)
171 self
._append
_serialize
_action
(ft
)
173 do_align
= self
._must
_align
(ft
.alignment
)
174 self
._last
_alignment
= ft
.alignment
176 if type(ft
) is barectf_config
.StructureFieldType
:
177 self
._last
_bit
_array
_size
= ft
.alignment
179 self
._last
_bit
_array
_size
= ft
.size
181 self
._try
_append
_align
_action
(ft
.alignment
, do_align
, ft
)
183 if type(ft
) is barectf_config
.StructureFieldType
:
184 for member_name
, member
in ft
.members
.items():
185 self
._names
.append(member_name
)
186 self
._append
_ft
(member
.field_type
)
189 self
._append
_serialize
_action
(ft
)
191 def _try_append_align_action(self
, alignment
, do_align
, ft
=None):
192 offset_in_byte
= self
._offset
_in
_byte
193 self
._offset
_in
_byte
= _align(self
._offset
_in
_byte
, alignment
) % 8
195 if do_align
and alignment
> 1:
196 self
._actions
.append(_AlignSerializationAction(offset_in_byte
, ft
, self
._names
,
199 def _append_serialize_action(self
, ft
):
200 assert(type(ft
) is not barectf_config
.StructureFieldType
)
201 offset_in_byte
= self
._offset
_in
_byte
203 if isinstance(ft
, barectf_config
._BitArrayFieldType
):
204 self
._offset
_in
_byte
+= ft
.size
205 self
._offset
_in
_byte
%= 8
207 self
._actions
.append(_SerializeSerializationAction(offset_in_byte
, ft
, self
._names
))
217 _PREFIX_TPH
: 'trace packet header',
218 _PREFIX_SPC
: 'stream packet context',
219 _PREFIX_SEH
: 'stream event header',
220 _PREFIX_SEC
: 'stream event context',
221 _PREFIX_EC
: 'event context',
222 _PREFIX_EP
: 'event payload',
226 class _CCodeGenerator
:
227 def __init__(self
, cfg
):
229 code_gen_opts
= cfg
.options
.code_generation_options
230 self
._iden
_prefix
= code_gen_opts
.identifier_prefix
231 self
._cg
= barectf_codegen
._CodeGenerator
('\t')
232 self
._saved
_serialization
_actions
= {}
234 def _create_template(self
, name
: str) -> barectf_template
._Template
:
235 return barectf_template
._Template
(name
, cfg
=self
._cfg
)
237 def _create_file_template(self
, name
: str) -> barectf_template
._Template
:
238 return barectf_template
._Template
(name
, True, self
._cfg
)
241 def _trace_type(self
):
242 return self
._cfg
.trace
.type
244 def _clk_type_c_type(self
, clk_type
):
245 return self
._cfg
.options
.code_generation_options
.clock_type_c_types
[clk_type
]
247 def _generate_ctx_parent(self
):
248 tmpl
= barectf_templates
._CTX
_PARENT
249 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
))
251 def _generate_ctx(self
, stream_type
):
252 tmpl
= barectf_templates
._CTX
_BEGIN
253 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
))
255 pkt_header_ft
= self
._trace
_type
._pkt
_header
_ft
257 if pkt_header_ft
is not None:
258 for member_name
in pkt_header_ft
.members
:
259 self
._cg
.add_lines(f
'uint32_t off_tph_{member_name};')
261 for member_name
in stream_type
._pkt
_ctx
_ft
.members
:
262 self
._cg
.add_lines(f
'uint32_t off_spc_{member_name};')
264 if stream_type
.default_clock_type
is not None:
265 self
._cg
.add_line(f
'{self._clk_type_c_type(stream_type.default_clock_type)} cur_last_event_ts;')
268 tmpl
= barectf_templates
._CTX
_END
269 self
._cg
.add_lines(tmpl
)
271 def _generate_ctxs(self
):
272 for stream_type
in self
._trace
_type
.stream_types
:
273 self
._generate
_ctx
(stream_type
)
275 def _generate_clock_cb(self
, clk_type
):
276 tmpl
= barectf_templates
._CLOCK
_CB
277 self
._cg
.add_lines(tmpl
.format(return_ctype
=self
._clk
_type
_c
_type
(clk_type
),
278 cname
=clk_type
.name
))
280 def _generate_clock_cbs(self
):
283 for stream_type
in self
._trace
_type
.stream_types
:
284 def_clk_type
= stream_type
.default_clock_type
286 if def_clk_type
is not None and def_clk_type
not in clk_names
:
287 self
._generate
_clock
_cb
(def_clk_type
)
288 clk_names
.add(def_clk_type
)
290 def _generate_platform_callbacks(self
):
291 tmpl
= barectf_templates
._PLATFORM
_CALLBACKS
_BEGIN
292 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
))
294 self
._generate
_clock
_cbs
()
296 tmpl
= barectf_templates
._PLATFORM
_CALLBACKS
_END
297 self
._cg
.add_lines(tmpl
)
299 def generate_bitfield_header(self
):
300 return self
._create
_file
_template
('bitfield.h.j2').render()
302 def _generate_func_init_proto(self
):
303 tmpl
= barectf_templates
._FUNC
_INIT
_PROTO
304 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
))
306 def _get_ft_c_type(self
, ft
):
307 if isinstance(ft
, barectf_config
._IntegerFieldType
):
308 sign_prefix
= 'u' if isinstance(ft
, barectf_config
.UnsignedIntegerFieldType
) else ''
320 return f
'{sign_prefix}int{sz}_t'
321 elif type(ft
) is barectf_config
.RealFieldType
:
322 if ft
.size
== 32 and ft
.alignment
== 32:
324 elif ft
.size
== 64 and ft
.alignment
== 64:
329 assert type(ft
) is barectf_config
.StringFieldType
330 return 'const char *'
332 def _generate_ft_c_type(self
, ft
):
333 c_type
= self
._get
_ft
_c
_type
(ft
)
334 self
._cg
.append_to_last_line(c_type
)
336 def _generate_proto_param(self
, ft
, name
):
337 self
._generate
_ft
_c
_type
(ft
)
338 self
._cg
.append_to_last_line(' ')
339 self
._cg
.append_to_last_line(name
)
341 def _generate_proto_params(self
, ft
, name_prefix
, exclude_set
=None):
342 if exclude_set
is None:
347 for member_name
, member
in ft
.members
.items():
348 if member_name
in exclude_set
:
351 self
._cg
.append_to_last_line(',')
352 self
._cg
.add_line('')
353 self
._generate
_proto
_param
(member
.field_type
, name_prefix
+ member_name
)
357 def _generate_func_open_proto(self
, stream_type
):
358 tmpl
= barectf_templates
._FUNC
_OPEN
_PROTO
_BEGIN
359 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
))
361 if self
._trace
_type
._pkt
_header
_ft
is not None:
362 self
._generate
_proto
_params
(self
._trace
_type
._pkt
_header
_ft
, _PREFIX_TPH
,
363 {'magic', 'stream_id', 'uuid'})
372 self
._generate
_proto
_params
(stream_type
._pkt
_ctx
_ft
, _PREFIX_SPC
, exclude_set
)
373 tmpl
= barectf_templates
._FUNC
_OPEN
_PROTO
_END
374 self
._cg
.add_lines(tmpl
)
376 def _generate_func_close_proto(self
, stream_type
):
377 tmpl
= barectf_templates
._FUNC
_CLOSE
_PROTO
378 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
))
380 def _generate_func_trace_proto_params(self
, stream_type
, ev_type
):
381 if stream_type
._ev
_header
_ft
is not None:
382 self
._generate
_proto
_params
(stream_type
._ev
_header
_ft
, _PREFIX_SEH
, {'id', 'timestamp'})
384 if stream_type
.event_common_context_field_type
is not None:
385 self
._generate
_proto
_params
(stream_type
.event_common_context_field_type
, _PREFIX_SEC
)
387 if ev_type
.specific_context_field_type
is not None:
388 self
._generate
_proto
_params
(ev_type
.specific_context_field_type
, _PREFIX_EC
)
390 if ev_type
.payload_field_type
is not None:
391 self
._generate
_proto
_params
(ev_type
.payload_field_type
, _PREFIX_EP
)
393 def _generate_func_trace_proto(self
, stream_type
, ev_type
):
394 tmpl
= barectf_templates
._FUNC
_TRACE
_PROTO
_BEGIN
395 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
,
396 evname
=ev_type
.name
))
397 self
._generate
_func
_trace
_proto
_params
(stream_type
, ev_type
)
398 tmpl
= barectf_templates
._FUNC
_TRACE
_PROTO
_END
399 self
._cg
.add_lines(tmpl
)
401 def _punctuate_proto(self
):
402 self
._cg
.append_to_last_line(';')
404 def generate_header(self
):
406 dt
= datetime
.datetime
.now().isoformat()
408 def_stream_type_name_def
= ''
409 cg_opts
= self
._cfg
.options
.code_generation_options
410 header_opts
= cg_opts
.header_options
412 if header_opts
.identifier_prefix_definition
:
413 prefix_def
= f
'#define _BARECTF_PREFIX {self._iden_prefix}'
415 def_stream_type
= cg_opts
.default_stream_type
417 if header_opts
.default_stream_type_name_definition
and def_stream_type
is not None:
418 def_stream_type_name_def
= f
'#define _BARECTF_DEFAULT_STREAM {def_stream_type.name}'
420 def_stream_type_trace_defs
= ''
422 if def_stream_type
is not None:
425 for ev_type
in def_stream_type
.event_types
:
426 tmpl
= barectf_templates
._DEFINE
_DEFAULT
_STREAM
_TRACE
427 define
= tmpl
.format(prefix
=self
._iden
_prefix
, sname
=def_stream_type
.name
,
431 def_stream_type_trace_defs
= '\n'.join(lines
)
433 tmpl
= barectf_templates
._HEADER
_BEGIN
434 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
,
435 ucprefix
=self
._iden
_prefix
.upper(),
436 version
=barectf_version
.__version
__, date
=dt
,
437 prefix_def
=prefix_def
,
438 default_stream_def
=def_stream_type_name_def
,
439 default_stream_trace_defs
=def_stream_type_trace_defs
))
440 self
._cg
.add_empty_line()
442 # platform callbacks structure
443 self
._generate
_platform
_callbacks
()
444 self
._cg
.add_empty_line()
447 self
._generate
_ctx
_parent
()
448 self
._cg
.add_empty_line()
451 self
._generate
_ctxs
()
452 self
._cg
.add_empty_line()
454 # initialization function prototype
455 self
._generate
_func
_init
_proto
()
456 self
._punctuate
_proto
()
457 self
._cg
.add_empty_line()
459 for stream_type
in self
._trace
_type
.stream_types
:
460 self
._generate
_func
_open
_proto
(stream_type
)
461 self
._punctuate
_proto
()
462 self
._cg
.add_empty_line()
463 self
._generate
_func
_close
_proto
(stream_type
)
464 self
._punctuate
_proto
()
465 self
._cg
.add_empty_line()
467 for ev_type
in stream_type
.event_types
:
468 self
._generate
_func
_trace
_proto
(stream_type
, ev_type
)
469 self
._punctuate
_proto
()
470 self
._cg
.add_empty_line()
472 tmpl
= barectf_templates
._HEADER
_END
473 self
._cg
.add_lines(tmpl
.format(ucprefix
=self
._iden
_prefix
.upper()))
476 def _get_call_event_param_list_from_struct_ft(self
, ft
, prefix
, exclude_set
=None):
477 if exclude_set
is None:
482 for member_name
in ft
.members
:
483 if member_name
in exclude_set
:
486 lst
+= f
', {prefix}{member_name}'
490 def _get_call_event_param_list(self
, stream_type
, ev_type
):
493 if stream_type
._ev
_header
_ft
is not None:
494 lst
+= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(stream_type
._ev
_header
_ft
,
495 _PREFIX_SEH
, {'id', 'timestamp'})
497 if stream_type
.event_common_context_field_type
is not None:
498 lst
+= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(stream_type
.event_common_context_field_type
,
501 if ev_type
.specific_context_field_type
is not None:
502 lst
+= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(ev_type
.specific_context_field_type
,
505 if ev_type
.payload_field_type
is not None:
506 lst
+= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(ev_type
.payload_field_type
,
511 def _generate_align(self
, at
, align
):
512 self
._cg
.add_line(f
'_ALIGN({at}, {align});')
514 def _generate_incr_pos(self
, var
, value
):
515 self
._cg
.add_line(f
'{var} += {value};')
517 def _generate_incr_pos_bytes(self
, var
, value
):
518 self
._generate
_incr
_pos
(var
, f
'_BYTES_TO_BITS({value})')
520 def _generate_func_get_event_size_proto(self
, stream_type
, ev_type
):
521 tmpl
= barectf_templates
._FUNC
_GET
_EVENT
_SIZE
_PROTO
_BEGIN
522 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
,
523 evname
=ev_type
.name
))
524 self
._generate
_func
_trace
_proto
_params
(stream_type
, ev_type
)
525 tmpl
= barectf_templates
._FUNC
_GET
_EVENT
_SIZE
_PROTO
_END
526 self
._cg
.add_lines(tmpl
)
528 def _generate_func_get_event_size(self
, stream_type
, ev_type
):
529 self
._generate
_func
_get
_event
_size
_proto
(stream_type
, ev_type
)
530 tmpl
= barectf_templates
._FUNC
_GET
_EVENT
_SIZE
_BODY
_BEGIN
531 lines
= tmpl
.format(prefix
=self
._iden
_prefix
)
532 self
._cg
.add_lines(lines
)
533 self
._cg
.add_empty_line()
535 ser_actions
= _SerializationActions()
536 ser_actions
.append_root_scope_ft(stream_type
._ev
_header
_ft
, _PREFIX_SEH
)
537 ser_actions
.append_root_scope_ft(stream_type
.event_common_context_field_type
, _PREFIX_SEC
)
538 ser_actions
.append_root_scope_ft(ev_type
.specific_context_field_type
, _PREFIX_EC
)
539 ser_actions
.append_root_scope_ft(ev_type
.payload_field_type
, _PREFIX_EP
)
541 for action
in ser_actions
.actions
:
542 if type(action
) is _AlignSerializationAction
:
544 if len(action
.names
) == 1:
545 line
= f
'align {_PREFIX_TO_NAME[action.names[0]]} structure'
547 line
= f
'align field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})'
549 self
._cg
.add_cc_line(line
)
551 self
._generate
_align
('at', action
.value
)
552 self
._cg
.add_empty_line()
554 assert type(action
) is _SerializeSerializationAction
555 assert(len(action
.names
) >= 2)
556 line
= f
'add size of field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})'
557 self
._cg
.add_cc_line(line
)
559 if type(action
.ft
) is barectf_config
.StringFieldType
:
560 param
= ''.join(action
.names
)
561 self
._generate
_incr
_pos
_bytes
('at', f
'strlen({param}) + 1')
563 self
._generate
_incr
_pos
('at', action
.ft
.size
)
565 self
._cg
.add_empty_line()
568 tmpl
= barectf_templates
._FUNC
_GET
_EVENT
_SIZE
_BODY
_END
569 self
._cg
.add_lines(tmpl
)
571 def _generate_func_serialize_event_proto(self
, stream_type
, ev_type
):
572 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_EVENT
_PROTO
_BEGIN
573 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
,
574 evname
=ev_type
.name
))
575 self
._generate
_func
_trace
_proto
_params
(stream_type
, ev_type
)
576 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_EVENT
_PROTO
_END
577 self
._cg
.add_lines(tmpl
)
579 def _generate_serialize_from_action(self
, var
, ctx
, action
):
580 def gen_bitfield_write(c_type
, var
, ctx
, action
):
581 ptr
= f
'&{ctx}->buf[_BITS_TO_BYTES({ctx}->at)]'
582 start
= action
.offset_in_byte
583 suffix
= 'le' if action
.ft
.byte_order
is barectf_config
.ByteOrder
.LITTLE_ENDIAN
else 'be'
584 func
= f
'{self._iden_prefix}bt_bitfield_write_{suffix}'
585 call
= f
'{func}({ptr}, uint8_t, {start}, {action.ft.size}, {c_type}, ({c_type}) {var});'
586 self
._cg
.add_line(call
)
588 def gen_serialize_int(var
, ctx
, action
):
589 c_type
= self
._get
_ft
_c
_type
(action
.ft
)
590 gen_bitfield_write(c_type
, var
, ctx
, action
)
591 self
._generate
_incr
_pos
(f
'{ctx}->at', action
.ft
.size
)
593 def gen_serialize_real(var
, ctx
, action
):
594 c_type
= self
._get
_ft
_c
_type
(action
.ft
)
597 if c_type
== 'float' or c_type
== 'double':
600 if c_type
== 'float':
602 int_c_type
= 'uint32_t'
604 assert c_type
== 'double'
606 int_c_type
= 'uint64_t'
608 # union for reading the bytes of the floating point number
609 self
._cg
.add_empty_line()
610 self
._cg
.add_line('{')
612 self
._cg
.add_line(f
'union {union_name} {union_name};')
613 self
._cg
.add_empty_line()
614 self
._cg
.add_line(f
'{union_name}.f = {var};')
615 bf_var
= f
'{union_name}.u'
617 bf_var
= f
'({c_type}) {var}'
620 gen_bitfield_write(int_c_type
, bf_var
, ctx
, action
)
624 self
._cg
.add_line('}')
625 self
._cg
.add_empty_line()
627 self
._generate
_incr
_pos
(f
'{ctx}->at', action
.ft
.size
)
629 def gen_serialize_string(var
, ctx
, action
):
630 self
._cg
.add_lines(f
'_write_cstring({ctx}, {var});')
632 if isinstance(action
.ft
, barectf_config
._IntegerFieldType
):
633 return gen_serialize_int(var
, ctx
, action
)
634 elif type(action
.ft
) is barectf_config
.RealFieldType
:
635 return gen_serialize_real(var
, ctx
, action
)
637 assert type(action
.ft
) is barectf_config
.StringFieldType
638 return gen_serialize_string(var
, ctx
, action
)
640 def _generate_serialize_statements_from_actions(self
, prefix
, action_iter
, spec_src
=None):
641 for action
in action_iter
:
642 if type(action
) is _AlignSerializationAction
:
644 if len(action
.names
) == 1:
645 line
= f
'align {_PREFIX_TO_NAME[action.names[0]]} structure'
647 line
= f
'align field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})'
649 self
._cg
.add_cc_line(line
)
651 self
._generate
_align
('ctx->at', action
.value
)
652 self
._cg
.add_empty_line()
654 assert type(action
) is _SerializeSerializationAction
655 assert(len(action
.names
) >= 2)
656 member_name
= action
.names
[-1]
657 line
= f
'serialize field `{member_name}` ({_PREFIX_TO_NAME[action.names[0]]})'
658 self
._cg
.add_cc_line(line
)
659 src
= prefix
+ member_name
661 if spec_src
is not None and member_name
in spec_src
:
662 src
= spec_src
[member_name
]
664 self
._generate
_serialize
_from
_action
(src
, 'ctx', action
)
665 self
._cg
.add_empty_line()
667 def _generate_func_serialize_event(self
, stream_type
, ev_type
, orig_ser_actions
):
668 self
._generate
_func
_serialize
_event
_proto
(stream_type
, ev_type
)
669 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_EVENT
_BODY
_BEGIN
670 lines
= tmpl
.format(prefix
=self
._iden
_prefix
)
671 self
._cg
.add_lines(lines
)
673 self
._cg
.add_empty_line()
675 if stream_type
._ev
_header
_ft
is not None:
676 params
= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(stream_type
._ev
_header
_ft
,
679 self
._cg
.add_cc_line('stream event header')
680 line
= f
'_serialize_stream_event_header_{stream_type.name}(ctx, {ev_type.id}{params});'
681 self
._cg
.add_line(line
)
682 self
._cg
.add_empty_line()
684 if stream_type
.event_common_context_field_type
is not None:
685 params
= self
._get
_call
_event
_param
_list
_from
_struct
_ft
(stream_type
.event_common_context_field_type
,
687 self
._cg
.add_cc_line('stream event context')
688 line
= f
'_serialize_stream_event_context_{stream_type.name}(ctx{params});'
689 self
._cg
.add_line(line
)
690 self
._cg
.add_empty_line()
692 if ev_type
.specific_context_field_type
is not None or ev_type
.payload_field_type
is not None:
693 ser_actions
= copy
.deepcopy(orig_ser_actions
)
695 if ev_type
.specific_context_field_type
is not None:
696 ser_action_index
= len(ser_actions
.actions
)
697 ser_actions
.append_root_scope_ft(ev_type
.specific_context_field_type
, _PREFIX_EC
)
698 ser_action_iter
= itertools
.islice(ser_actions
.actions
, ser_action_index
, None)
699 self
._generate
_serialize
_statements
_from
_actions
(_PREFIX_EC
, ser_action_iter
)
701 if ev_type
.payload_field_type
is not None:
702 ser_action_index
= len(ser_actions
.actions
)
703 ser_actions
.append_root_scope_ft(ev_type
.payload_field_type
, _PREFIX_EP
)
704 ser_action_iter
= itertools
.islice(ser_actions
.actions
, ser_action_index
, None)
705 self
._generate
_serialize
_statements
_from
_actions
(_PREFIX_EP
, ser_action_iter
)
708 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_EVENT
_BODY
_END
709 self
._cg
.add_lines(tmpl
)
711 def _generate_func_serialize_event_header_proto(self
, stream_type
):
712 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_PROTO
_BEGIN
713 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
))
715 if stream_type
._ev
_header
_ft
is not None:
716 self
._generate
_proto
_params
(stream_type
._ev
_header
_ft
, _PREFIX_SEH
,
719 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_PROTO
_END
720 self
._cg
.add_lines(tmpl
)
722 def _generate_func_serialize_event_common_context_proto(self
, stream_type
):
723 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_PROTO
_BEGIN
724 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
))
726 if stream_type
.event_common_context_field_type
is not None:
727 self
._generate
_proto
_params
(stream_type
.event_common_context_field_type
, _PREFIX_SEC
)
729 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_PROTO
_END
730 self
._cg
.add_lines(tmpl
)
732 def _generate_func_serialize_event_header(self
, stream_type
, ser_action_iter
):
733 self
._generate
_func
_serialize
_event
_header
_proto
(stream_type
)
734 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_BODY
_BEGIN
735 lines
= tmpl
.format(prefix
=self
._iden
_prefix
, sname
=stream_type
.name
)
736 self
._cg
.add_lines(lines
)
739 if stream_type
.default_clock_type
is not None:
740 line
= f
'struct {self._iden_prefix}{stream_type.name}_ctx *s_ctx = FROM_VOID_PTR(struct {self._iden_prefix}{stream_type.name}_ctx, vctx);'
741 self
._cg
.add_line(line
)
742 line
= f
'const {self._clk_type_c_type(stream_type.default_clock_type)} ts = s_ctx->cur_last_event_ts;'
743 self
._cg
.add_line(line
)
745 self
._cg
.add_empty_line()
747 if stream_type
._ev
_header
_ft
is not None:
750 member
= stream_type
._ev
_header
_ft
.members
.get(member_name
)
752 if member
is not None:
753 spec_src
[member_name
] = f
'({self._get_ft_c_type(member.field_type)}) event_id'
755 member_name
= 'timestamp'
756 member
= stream_type
._ev
_header
_ft
.members
.get(member_name
)
758 if member
is not None:
759 spec_src
[member_name
] = f
'({self._get_ft_c_type(member.field_type)}) ts'
761 self
._generate
_serialize
_statements
_from
_actions
(_PREFIX_SEH
, ser_action_iter
,
765 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_BODY
_END
766 self
._cg
.add_lines(tmpl
)
768 def _generate_func_serialize_event_common_context(self
, stream_type
, ser_action_iter
):
769 self
._generate
_func
_serialize
_event
_common
_context
_proto
(stream_type
)
770 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_BODY
_BEGIN
771 lines
= tmpl
.format(prefix
=self
._iden
_prefix
)
772 self
._cg
.add_lines(lines
)
775 if stream_type
.event_common_context_field_type
is not None:
776 self
._generate
_serialize
_statements
_from
_actions
(_PREFIX_SEC
, ser_action_iter
)
779 tmpl
= barectf_templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_BODY
_END
780 self
._cg
.add_lines(tmpl
)
782 def _generate_func_trace(self
, stream_type
, ev_type
):
783 self
._generate
_func
_trace
_proto
(stream_type
, ev_type
)
784 params
= self
._get
_call
_event
_param
_list
(stream_type
, ev_type
)
785 def_clk_type
= stream_type
.default_clock_type
787 if def_clk_type
is not None:
788 save_ts_line
= f
'ctx->cur_last_event_ts = ctx->parent.cbs.{def_clk_type.name}_clock_get_value(ctx->parent.data);'
790 save_ts_line
= '/* (no clock) */'
792 tmpl
= barectf_templates
._FUNC
_TRACE
_BODY
793 self
._cg
.add_lines(tmpl
.format(sname
=stream_type
.name
, evname
=ev_type
.name
, params
=params
,
794 save_ts
=save_ts_line
))
796 def _generate_func_init(self
):
797 self
._generate
_func
_init
_proto
()
798 tmpl
= barectf_templates
._FUNC
_INIT
_BODY
799 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
))
801 def _generate_member_name_cc_line(self
, member_name
):
802 self
._cg
.add_cc_line(f
'`{member_name}` field')
804 def _save_serialization_action(self
, name
, action
):
805 self
._saved
_serialization
_actions
[name
] = action
807 def _get_open_close_ts_line(self
, stream_type
):
808 def_clk_type
= stream_type
.default_clock_type
810 if def_clk_type
is None:
813 c_type
= self
._clk
_type
_c
_type
(def_clk_type
)
814 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);'
816 def _generate_func_open(self
, stream_type
):
817 def generate_save_offset(name
, action
):
818 self
._cg
.add_line(f
'ctx->off_spc_{name} = ctx->parent.at;')
819 self
._save
_serialization
_action
(name
, action
)
821 self
._generate
_func
_open
_proto
(stream_type
)
822 tmpl
= barectf_templates
._FUNC
_OPEN
_BODY
_BEGIN
823 pkt_ctx_ft
= stream_type
._pkt
_ctx
_ft
824 ts_line
= self
._get
_open
_close
_ts
_line
(stream_type
)
825 lines
= tmpl
.format(ts
=ts_line
)
826 self
._cg
.add_lines(lines
)
828 self
._cg
.add_cc_line('do not open a packet that is already open')
829 self
._cg
.add_line('if (ctx->parent.packet_is_open) {')
831 self
._cg
.add_line('ctx->parent.in_tracing_section = saved_in_tracing_section;')
832 self
._cg
.add_line('return;')
834 self
._cg
.add_line('}')
835 self
._cg
.add_empty_line()
836 self
._cg
.add_line('ctx->parent.at = 0;')
837 pkt_header_ft
= self
._trace
_type
._pkt
_header
_ft
838 ser_actions
= _SerializationActions()
840 if pkt_header_ft
is not None:
841 self
._cg
.add_empty_line()
842 self
._cg
.add_cc_line('trace packet header')
843 self
._cg
.add_line('{')
845 ser_actions
.append_root_scope_ft(pkt_header_ft
, _PREFIX_TPH
)
847 for action
in ser_actions
.actions
:
848 if type(action
) is _AlignSerializationAction
:
850 if len(action
.names
) == 1:
851 line
= 'align trace packet header structure'
853 line
= f
'align field `{action.names[-1]}`'
855 self
._cg
.add_cc_line(line
)
857 self
._generate
_align
('ctx->parent.at', action
.value
)
858 self
._cg
.add_empty_line()
860 assert type(action
) is _SerializeSerializationAction
861 assert(len(action
.names
) >= 2)
862 member_name
= action
.names
[-1]
863 line
= f
'serialize field `{member_name}`'
864 self
._cg
.add_cc_line(line
)
865 src
= _PREFIX_TPH
+ member_name
867 if member_name
== 'magic':
869 elif member_name
== 'stream_id':
870 src
= f
'({self._get_ft_c_type(action.ft)}) {stream_type.id}'
871 elif member_name
== 'uuid':
872 self
._cg
.add_line('{')
874 self
._cg
.add_line('static uint8_t uuid[] = {')
877 for b
in self
._trace
_type
.uuid
.bytes
:
878 self
._cg
.add_line(f
'{b},')
881 self
._cg
.add_line('};')
882 self
._cg
.add_empty_line()
883 self
._generate
_align
('ctx->parent.at', 8)
884 line
= 'memcpy(&ctx->parent.buf[_BITS_TO_BYTES(ctx->parent.at)], uuid, 16);'
885 self
._cg
.add_line(line
)
886 self
._generate
_incr
_pos
_bytes
('ctx->parent.at', 16)
888 self
._cg
.add_line('}')
889 self
._cg
.add_empty_line()
892 self
._generate
_serialize
_from
_action
(src
, '(&ctx->parent)', action
)
893 self
._cg
.add_empty_line()
896 self
._cg
.add_lines('}')
898 spc_action_index
= len(ser_actions
.actions
)
899 self
._cg
.add_empty_line()
900 self
._cg
.add_cc_line('stream packet context')
901 self
._cg
.add_line('{')
903 ser_actions
.append_root_scope_ft(pkt_ctx_ft
, _PREFIX_SPC
)
905 for action
in itertools
.islice(ser_actions
.actions
, spc_action_index
, None):
906 if type(action
) is _AlignSerializationAction
:
908 if len(action
.names
) == 1:
909 line
= 'align stream packet context structure'
911 line
= f
'align field `{action.names[-1]}`'
913 self
._cg
.add_cc_line(line
)
915 self
._generate
_align
('ctx->parent.at', action
.value
)
916 self
._cg
.add_empty_line()
918 assert type(action
) is _SerializeSerializationAction
919 assert(len(action
.names
) >= 2)
920 member_name
= action
.names
[-1]
921 line
= f
'serialize field `{member_name}`'
922 self
._cg
.add_cc_line(line
)
923 src
= _PREFIX_SPC
+ member_name
926 if member_name
== 'timestamp_begin':
927 src
= f
'({self._get_ft_c_type(action.ft)}) ts'
928 elif member_name
in {'timestamp_end', 'content_size', 'events_discarded'}:
930 elif member_name
== 'packet_size':
931 src
= f
'({self._get_ft_c_type(action.ft)}) ctx->parent.packet_size'
934 generate_save_offset(member_name
, action
)
935 self
._generate
_incr
_pos
('ctx->parent.at', action
.ft
.size
)
937 self
._generate
_serialize
_from
_action
(src
, '(&ctx->parent)', action
)
939 self
._cg
.add_empty_line()
942 self
._cg
.add_lines('}')
944 tmpl
= barectf_templates
._FUNC
_OPEN
_BODY
_END
945 self
._cg
.add_lines(tmpl
)
947 def _generate_func_close(self
, stream_type
):
948 def generate_goto_offset(name
):
949 self
._cg
.add_line(f
'ctx->parent.at = ctx->off_spc_{name};')
951 self
._generate
_func
_close
_proto
(stream_type
)
952 tmpl
= barectf_templates
._FUNC
_CLOSE
_BODY
_BEGIN
953 pkt_ctx_ft
= stream_type
._pkt
_ctx
_ft
954 ts_line
= self
._get
_open
_close
_ts
_line
(stream_type
)
955 lines
= tmpl
.format(ts
=ts_line
)
956 self
._cg
.add_lines(lines
)
958 self
._cg
.add_cc_line('do not close a packet that is not open')
959 self
._cg
.add_line('if (!ctx->parent.packet_is_open) {')
961 self
._cg
.add_line('ctx->parent.in_tracing_section = saved_in_tracing_section;')
962 self
._cg
.add_line('return;')
964 self
._cg
.add_line('}')
965 self
._cg
.add_empty_line()
966 self
._cg
.add_cc_line('save content size')
967 self
._cg
.add_line('ctx->parent.content_size = ctx->parent.at;')
968 member_name
= 'timestamp_end'
969 member
= pkt_ctx_ft
.members
.get(member_name
)
971 if member
is not None:
972 self
._cg
.add_empty_line()
973 self
._generate
_member
_name
_cc
_line
(member_name
)
974 generate_goto_offset(member_name
)
975 action
= self
._saved
_serialization
_actions
[member_name
]
976 c_type
= self
._get
_ft
_c
_type
(member
.field_type
)
977 self
._generate
_serialize
_from
_action
(f
'({c_type}) ts', '(&ctx->parent)', action
)
979 member_name
= 'content_size'
980 member
= pkt_ctx_ft
.members
.get(member_name
)
982 if member
is not None:
983 self
._cg
.add_empty_line()
984 self
._generate
_member
_name
_cc
_line
(member_name
)
985 generate_goto_offset(member_name
)
986 action
= self
._saved
_serialization
_actions
[member_name
]
987 c_type
= self
._get
_ft
_c
_type
(member
.field_type
)
988 self
._generate
_serialize
_from
_action
(f
'({c_type}) ctx->parent.content_size',
989 '(&ctx->parent)', action
)
991 member_name
= 'events_discarded'
992 member
= pkt_ctx_ft
.members
.get(member_name
)
994 if member
is not None:
995 self
._cg
.add_empty_line()
996 self
._generate
_member
_name
_cc
_line
(member_name
)
997 generate_goto_offset(member_name
)
998 action
= self
._saved
_serialization
_actions
[member_name
]
999 c_type
= self
._get
_ft
_c
_type
(member
.field_type
)
1000 self
._generate
_serialize
_from
_action
(f
'({c_type}) ctx->parent.events_discarded',
1001 '(&ctx->parent)', action
)
1004 tmpl
= barectf_templates
._FUNC
_CLOSE
_BODY
_END
1005 self
._cg
.add_lines(tmpl
)
1007 def generate_c_src(self
, header_name
, bitfield_header_name
):
1009 dt
= datetime
.datetime
.now().isoformat()
1010 tmpl
= barectf_templates
._C
_SRC
1011 self
._cg
.add_lines(tmpl
.format(prefix
=self
._iden
_prefix
, header_filename
=header_name
,
1012 bitfield_header_filename
=bitfield_header_name
,
1013 version
=barectf_version
.__version
__, date
=dt
))
1014 self
._cg
.add_empty_line()
1016 # initialization function
1017 self
._generate
_func
_init
()
1018 self
._cg
.add_empty_line()
1020 for stream_type
in self
._trace
_type
.stream_types
:
1021 self
._generate
_func
_open
(stream_type
)
1022 self
._cg
.add_empty_line()
1023 self
._generate
_func
_close
(stream_type
)
1024 self
._cg
.add_empty_line()
1025 ser_actions
= _SerializationActions()
1027 if stream_type
._ev
_header
_ft
is not None:
1028 ser_actions
.append_root_scope_ft(stream_type
._ev
_header
_ft
, _PREFIX_SEH
)
1029 self
._generate
_func
_serialize
_event
_header
(stream_type
, iter(ser_actions
.actions
))
1030 self
._cg
.add_empty_line()
1032 if stream_type
.event_common_context_field_type
is not None:
1033 ser_action_index
= len(ser_actions
.actions
)
1034 ser_actions
.append_root_scope_ft(stream_type
.event_common_context_field_type
,
1036 ser_action_iter
= itertools
.islice(ser_actions
.actions
, ser_action_index
, None)
1037 self
._generate
_func
_serialize
_event
_common
_context
(stream_type
, ser_action_iter
)
1038 self
._cg
.add_empty_line()
1040 for ev_type
in stream_type
.event_types
:
1041 self
._generate
_func
_get
_event
_size
(stream_type
, ev_type
)
1042 self
._cg
.add_empty_line()
1043 self
._generate
_func
_serialize
_event
(stream_type
, ev_type
, ser_actions
)
1044 self
._cg
.add_empty_line()
1045 self
._generate
_func
_trace
(stream_type
, ev_type
)
1046 self
._cg
.add_empty_line()
1048 return self
._cg
.code