1 # The MIT License (MIT)
3 # Copyright (c) 2014-2015 Philippe Proulx <pproulx@efficios.com>
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 from barectf
import templates
24 from barectf
import metadata
25 import barectf
.codegen
35 class _StaticAlignSizeAutomaton
:
38 self
._type
_to
_update
_byte
_offset
_func
= {
39 metadata
.Integer
: self
.write_static_size
,
40 metadata
.FloatingPoint
: self
.write_static_size
,
41 metadata
.Enum
: self
.write_static_size
,
42 metadata
.String
: self
.reset
,
46 def byte_offset(self
):
47 return self
._byte
_offset
50 def byte_offset(self
, value
):
51 self
._byte
_offset
= value
53 def _wrap_byte_offset(self
):
54 self
._byte
_offset
%= 8
56 def align(self
, align
):
58 self
._byte
_offset
= (self
._byte
_offset
+ (align
- 1)) & -align
60 # wrap on current byte
61 self
._wrap
_byte
_offset
()
63 def write_type(self
, t
):
64 self
._type
_to
_update
_byte
_offset
_func
[type(t
)](t
)
66 def write_static_size(self
, t
):
67 # increment byte offset
68 self
._byte
_offset
+= t
.size
70 # wrap on current byte
71 self
._wrap
_byte
_offset
()
73 def reset(self
, t
=None):
74 # reset byte offset (strings are always byte-aligned)
77 def set_unknown(self
):
78 self
._byte
_offset
= None
90 def __init__(self
, cfg
):
92 self
._cg
= barectf
.codegen
.CodeGenerator('\t')
93 self
._type
_to
_get
_ctype
_func
= {
94 metadata
.Integer
: self
._get
_int
_ctype
,
95 metadata
.FloatingPoint
: self
._get
_float
_ctype
,
96 metadata
.Enum
: self
._get
_enum
_ctype
,
97 metadata
.String
: self
._get
_string
_ctype
,
99 self
._type
_to
_generate
_serialize
_func
= {
100 metadata
.Integer
: self
._generate
_serialize
_int
,
101 metadata
.FloatingPoint
: self
._generate
_serialize
_float
,
102 metadata
.Enum
: self
._generate
_serialize
_enum
,
103 metadata
.String
: self
._generate
_serialize
_string
,
105 self
._saved
_byte
_offsets
= {}
106 self
._uf
_written
= False
107 self
._ud
_written
= False
108 self
._sasa
= _StaticAlignSizeAutomaton()
110 def _generate_ctx_parent(self
):
111 tmpl
= templates
._CTX
_PARENT
112 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
))
114 def _generate_ctx(self
, stream
):
115 tmpl
= templates
._CTX
_BEGIN
116 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
,
118 tmpl
= 'uint32_t off_tph_{fname};'
120 trace_packet_header_type
= self
._cfg
.metadata
.trace
.packet_header_type
122 if trace_packet_header_type
is not None:
123 for field_name
in trace_packet_header_type
.fields
:
124 self
._cg
.add_lines(tmpl
.format(fname
=field_name
))
126 tmpl
= 'uint32_t off_spc_{fname};'
128 if stream
.packet_context_type
is not None:
129 for field_name
in stream
.packet_context_type
.fields
:
130 self
._cg
.add_lines(tmpl
.format(fname
=field_name
))
133 tmpl
= templates
._CTX
_END
134 self
._cg
.add_lines(tmpl
)
136 def _generate_ctxs(self
):
137 for stream
in self
._cfg
.metadata
.streams
.values():
138 self
._generate
_ctx
(stream
)
140 def _generate_clock_cb(self
, clock
):
141 tmpl
= templates
._CLOCK
_CB
142 self
._cg
.add_lines(tmpl
.format(return_ctype
=clock
.return_ctype
,
145 def _generate_clock_cbs(self
):
146 for clock
in self
._cfg
.metadata
.clocks
.values():
147 self
._generate
_clock
_cb
(clock
)
149 def _generate_platform_callbacks(self
):
150 tmpl
= templates
._PLATFORM
_CALLBACKS
_BEGIN
151 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
))
153 self
._generate
_clock
_cbs
()
155 tmpl
= templates
._PLATFORM
_CALLBACKS
_END
156 self
._cg
.add_lines(tmpl
)
158 def generate_bitfield_header(self
):
160 tmpl
= templates
._BITFIELD
161 tmpl
= tmpl
.replace('$prefix$', self
._cfg
.prefix
)
162 tmpl
= tmpl
.replace('$PREFIX$', self
._cfg
.prefix
.upper())
164 if self
._cfg
.metadata
.trace
.byte_order
== metadata
.ByteOrder
.BE
:
165 endian_def
= 'BIG_ENDIAN'
167 endian_def
= 'LITTLE_ENDIAN'
169 tmpl
= tmpl
.replace('$ENDIAN_DEF$', endian_def
)
170 self
._cg
.add_lines(tmpl
)
174 def _generate_func_init_proto(self
):
175 tmpl
= templates
._FUNC
_INIT
_PROTO
176 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
))
178 def _get_int_ctype(self
, t
):
179 signed
= 'u' if not t
.signed
else ''
190 return '{}int{}_t'.format(signed
, sz
)
192 def _get_float_ctype(self
, t
):
193 if t
.exp_size
== 8 and t
.mant_size
== 24 and t
.align
== 32:
195 elif t
.exp_size
== 11 and t
.mant_size
== 53 and t
.align
== 64:
202 def _get_enum_ctype(self
, t
):
203 return self
._get
_int
_ctype
(t
.value_type
)
205 def _get_string_ctype(self
, t
):
206 return 'const char *'
208 def _get_type_ctype(self
, t
):
209 return self
._type
_to
_get
_ctype
_func
[type(t
)](t
)
211 def _generate_type_ctype(self
, t
):
212 ctype
= self
._get
_type
_ctype
(t
)
213 self
._cg
.append_to_last_line(ctype
)
215 def _generate_proto_param(self
, t
, name
):
216 self
._generate
_type
_ctype
(t
)
217 self
._cg
.append_to_last_line(' ')
218 self
._cg
.append_to_last_line(name
)
220 def _generate_proto_params(self
, t
, name_prefix
, exclude_list
):
223 for field_name
, field_type
in t
.fields
.items():
224 if field_name
in exclude_list
:
227 name
= name_prefix
+ field_name
228 self
._cg
.append_to_last_line(',')
229 self
._cg
.add_line('')
230 self
._generate
_proto
_param
(field_type
, name
)
234 def _generate_func_open_proto(self
, stream
):
235 tmpl
= templates
._FUNC
_OPEN
_PROTO
_BEGIN
236 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
,
238 trace_packet_header_type
= self
._cfg
.metadata
.trace
.packet_header_type
240 if trace_packet_header_type
is not None:
241 exclude_list
= ['magic', 'stream_id', 'uuid']
242 self
._generate
_proto
_params
(trace_packet_header_type
, _PREFIX_TPH
,
245 if stream
.packet_context_type
is not None:
253 self
._generate
_proto
_params
(stream
.packet_context_type
,
254 _PREFIX_SPC
, exclude_list
)
256 tmpl
= templates
._FUNC
_OPEN
_PROTO
_END
257 self
._cg
.add_lines(tmpl
)
259 def _generate_func_close_proto(self
, stream
):
260 tmpl
= templates
._FUNC
_CLOSE
_PROTO
261 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
,
264 def _generate_func_trace_proto_params(self
, stream
, event
):
265 if stream
.event_header_type
is not None:
270 self
._generate
_proto
_params
(stream
.event_header_type
,
271 _PREFIX_SEH
, exclude_list
)
273 if stream
.event_context_type
is not None:
274 self
._generate
_proto
_params
(stream
.event_context_type
,
277 if event
.context_type
is not None:
278 self
._generate
_proto
_params
(event
.context_type
,
281 if event
.payload_type
is not None:
282 self
._generate
_proto
_params
(event
.payload_type
,
285 def _generate_func_trace_proto(self
, stream
, event
):
286 tmpl
= templates
._FUNC
_TRACE
_PROTO
_BEGIN
287 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
,
288 sname
=stream
.name
, evname
=event
.name
))
289 self
._generate
_func
_trace
_proto
_params
(stream
, event
)
290 tmpl
= templates
._FUNC
_TRACE
_PROTO
_END
291 self
._cg
.add_lines(tmpl
)
293 def _punctuate_proto(self
):
294 self
._cg
.append_to_last_line(';')
296 def generate_header(self
):
298 dt
= datetime
.datetime
.now().isoformat()
299 bh_filename
= self
.get_bitfield_header_filename()
300 tmpl
= templates
._HEADER
_BEGIN
301 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
,
302 ucprefix
=self
._cfg
.prefix
.upper(),
303 bitfield_header_filename
=bh_filename
,
304 version
=barectf
.__version
__, date
=dt
))
305 self
._cg
.add_empty_line()
307 # platform callbacks structure
308 self
._generate
_platform
_callbacks
()
309 self
._cg
.add_empty_line()
312 self
._generate
_ctx
_parent
()
313 self
._cg
.add_empty_line()
316 self
._generate
_ctxs
()
317 self
._cg
.add_empty_line()
319 # initialization function prototype
320 self
._generate
_func
_init
_proto
()
321 self
._punctuate
_proto
()
322 self
._cg
.add_empty_line()
324 for stream
in self
._cfg
.metadata
.streams
.values():
325 self
._generate
_func
_open
_proto
(stream
)
326 self
._punctuate
_proto
()
327 self
._cg
.add_empty_line()
328 self
._generate
_func
_close
_proto
(stream
)
329 self
._punctuate
_proto
()
330 self
._cg
.add_empty_line()
332 for ev
in stream
.events
.values():
333 self
._generate
_func
_trace
_proto
(stream
, ev
)
334 self
._punctuate
_proto
()
335 self
._cg
.add_empty_line()
337 tmpl
= templates
._HEADER
_END
338 self
._cg
.add_lines(tmpl
.format(ucprefix
=self
._cfg
.prefix
.upper()))
342 def _get_call_event_param_list_from_struct(self
, t
, prefix
, exclude_list
):
345 for field_name
in t
.fields
:
346 if field_name
in exclude_list
:
349 lst
+= ', {}{}'.format(prefix
, field_name
)
353 def _get_call_event_param_list(self
, stream
, event
):
355 gcp_func
= self
._get
_call
_event
_param
_list
_from
_struct
357 if stream
.event_header_type
is not None:
362 lst
+= gcp_func(stream
.event_header_type
, _PREFIX_SEH
, exclude_list
)
364 if stream
.event_context_type
is not None:
365 lst
+= gcp_func(stream
.event_context_type
, _PREFIX_SEC
, [])
367 if event
.context_type
is not None:
368 lst
+= gcp_func(event
.context_type
, _PREFIX_EC
, [])
370 if event
.payload_type
is not None:
371 lst
+= gcp_func(event
.payload_type
, _PREFIX_EP
, [])
375 def _generate_align(self
, at
, align
):
376 self
._cg
.add_line('_ALIGN({}, {});'.format(at
, align
))
377 self
._sasa
.align(align
)
379 def _generate_align_type(self
, at
, t
):
383 self
._generate
_align
(at
, t
.align
)
385 def _generate_incr_pos(self
, var
, value
):
386 self
._cg
.add_line('{} += {};'.format(var
, value
))
388 def _generate_incr_pos_bytes(self
, var
, value
):
389 self
._generate
_incr
_pos
(var
, '_BYTES_TO_BITS({})'.format(value
))
391 def _generate_func_get_event_size_proto(self
, stream
, event
):
392 tmpl
= templates
._FUNC
_GET
_EVENT
_SIZE
_PROTO
_BEGIN
393 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
,
394 sname
=stream
.name
, evname
=event
.name
))
395 self
._generate
_func
_trace
_proto
_params
(stream
, event
)
396 tmpl
= templates
._FUNC
_GET
_EVENT
_SIZE
_PROTO
_END
397 self
._cg
.add_lines(tmpl
)
399 def _generate_func_get_event_size_from_entity(self
, prefix
, t
):
400 self
._cg
.add_line('{')
402 self
._cg
.add_cc_line('align structure')
403 self
._generate
_align
_type
('at', t
)
405 for field_name
, field_type
in t
.fields
.items():
406 self
._cg
.add_empty_line()
407 self
._generate
_field
_name
_cc
_line
(field_name
)
408 self
._generate
_align
_type
('at', field_type
)
410 if type(field_type
) is metadata
.String
:
411 param
= prefix
+ field_name
412 self
._generate
_incr
_pos
_bytes
('at',
413 'strlen({}) + 1'.format(param
))
415 self
._generate
_incr
_pos
('at', field_type
.size
)
418 self
._cg
.add_line('}')
419 self
._cg
.add_empty_line()
421 def _generate_func_get_event_size(self
, stream
, event
):
422 self
._reset
_per
_func
_state
()
423 self
._generate
_func
_get
_event
_size
_proto
(stream
, event
)
424 tmpl
= templates
._FUNC
_GET
_EVENT
_SIZE
_BODY
_BEGIN
425 self
._cg
.add_lines(tmpl
)
426 self
._cg
.add_empty_line()
428 func
= self
._generate
_func
_get
_event
_size
_from
_entity
430 if stream
.event_header_type
is not None:
431 self
._cg
.add_cc_line('stream event header')
432 func(_PREFIX_SEH
, stream
.event_header_type
)
434 if stream
.event_context_type
is not None:
435 self
._cg
.add_cc_line('stream event context')
436 func(_PREFIX_SEC
, stream
.event_context_type
)
438 if event
.context_type
is not None:
439 self
._cg
.add_cc_line('event context')
440 func(_PREFIX_EC
, event
.context_type
)
442 if event
.payload_type
is not None:
443 self
._cg
.add_cc_line('event payload')
444 func(_PREFIX_EP
, event
.payload_type
)
447 tmpl
= templates
._FUNC
_GET
_EVENT
_SIZE
_BODY
_END
448 self
._cg
.add_lines(tmpl
)
450 def _generate_func_serialize_event_proto(self
, stream
, event
):
451 tmpl
= templates
._FUNC
_SERIALIZE
_EVENT
_PROTO
_BEGIN
452 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
,
453 sname
=stream
.name
, evname
=event
.name
))
454 self
._generate
_func
_trace
_proto
_params
(stream
, event
)
455 tmpl
= templates
._FUNC
_SERIALIZE
_EVENT
_PROTO
_END
456 self
._cg
.add_lines(tmpl
)
458 def _generate_bitfield_write(self
, var
, ctx
, t
):
459 ptr
= '&{ctx}->buf[_BITS_TO_BYTES({ctx}->at)]'.format(ctx
=ctx
)
460 start
= self
._sasa
.byte_offset
461 suffix
= 'le' if t
.byte_order
is metadata
.ByteOrder
.LE
else 'be'
462 func
= '{}bt_bitfield_write_{}'.format(self
._cfg
.prefix
, suffix
)
463 call
= '{}({}, uint8_t, {}, {}, {});'.format(func
, ptr
, start
, t
.size
,
465 self
._cg
.add_line(call
)
467 def _generate_serialize_int(self
, var
, ctx
, t
):
468 self
._generate
_bitfield
_write
(var
, ctx
, t
)
469 self
._generate
_incr
_pos
('{}->at'.format(ctx
), t
.size
)
471 def _generate_serialize_float(self
, var
, ctx
, t
):
472 ctype
= self
._get
_type
_ctype
(t
)
474 if ctype
== 'float' or ctype
== 'double':
475 gen_union_var
= False
478 if not self
._uf
_written
:
479 self
._uf
_written
= True
483 elif ctype
== 'double':
484 if not self
._ud
_written
:
485 self
._ud
_written
= True
491 # union for reading the bytes of the floating point number
493 self
._cg
.add_line('union {name} {name};'.format(name
=union_name
))
494 self
._cg
.add_empty_line()
496 self
._cg
.add_line('{}.f = {};'.format(union_name
, var
))
497 bf_var
= '{}.u'.format(union_name
)
499 bf_var
= '({}) {}'.format(ctype
, var
)
501 self
._generate
_bitfield
_write
(bf_var
, ctx
, t
)
502 self
._generate
_incr
_pos
('{}->at'.format(ctx
), t
.size
)
504 def _generate_serialize_enum(self
, var
, ctx
, t
):
505 self
._generate
_serialize
_type
(var
, ctx
, t
.value_type
)
507 def _generate_serialize_string(self
, var
, ctx
, t
):
508 tmpl
= '_write_cstring({}, {});'.format(ctx
, var
)
509 self
._cg
.add_lines(tmpl
)
511 def _generate_serialize_type(self
, var
, ctx
, t
):
512 self
._type
_to
_generate
_serialize
_func
[type(t
)](var
, ctx
, t
)
513 self
._sasa
.write_type(t
)
515 def _generate_func_serialize_event_from_entity(self
, prefix
, t
,
517 self
._cg
.add_line('{')
519 self
._cg
.add_cc_line('align structure')
521 self
._generate
_align
_type
('ctx->at', t
)
523 for field_name
, field_type
in t
.fields
.items():
524 src
= prefix
+ field_name
526 if spec_src
is not None:
527 if field_name
in spec_src
:
528 src
= spec_src
[field_name
]
530 self
._cg
.add_empty_line()
531 self
._generate
_field
_name
_cc
_line
(field_name
)
532 self
._generate
_align
_type
('ctx->at', field_type
)
533 self
._generate
_serialize
_type
(src
, 'ctx', field_type
)
536 self
._cg
.add_line('}')
537 self
._cg
.add_empty_line()
539 def _generate_func_serialize_event(self
, stream
, event
):
540 self
._reset
_per
_func
_state
()
541 self
._generate
_func
_serialize
_event
_proto
(stream
, event
)
542 tmpl
= templates
._FUNC
_SERIALIZE
_EVENT
_BODY
_BEGIN
543 self
._cg
.add_lines(tmpl
)
546 if stream
.event_header_type
is not None:
547 t
= stream
.event_header_type
548 exclude_list
= ['timestamp', 'id']
549 params
= self
._get
_call
_event
_param
_list
_from
_struct
(t
, _PREFIX_SEH
,
551 tmpl
= '_serialize_stream_event_header_{sname}(ctx, {evid}{params});'
552 self
._cg
.add_cc_line('stream event header')
553 self
._cg
.add_line(tmpl
.format(sname
=stream
.name
, evid
=event
.id,
555 self
._cg
.add_empty_line()
557 if stream
.event_context_type
is not None:
558 t
= stream
.event_context_type
559 params
= self
._get
_call
_event
_param
_list
_from
_struct
(t
, _PREFIX_SEH
,
561 tmpl
= '_serialize_stream_event_context_{sname}(ctx{params});'
562 self
._cg
.add_cc_line('stream event context')
563 self
._cg
.add_line(tmpl
.format(sname
=stream
.name
, params
=params
))
564 self
._cg
.add_empty_line()
566 if event
.context_type
is not None:
567 self
._cg
.add_cc_line('event context')
568 self
._generate
_func
_serialize
_event
_from
_entity
(_PREFIX_EC
,
571 if event
.payload_type
is not None:
572 self
._cg
.add_cc_line('event payload')
573 self
._generate
_func
_serialize
_event
_from
_entity
(_PREFIX_EP
,
577 tmpl
= templates
._FUNC
_SERIALIZE
_EVENT
_BODY
_END
578 self
._cg
.add_lines(tmpl
)
580 def _generate_func_serialize_stream_event_header_proto(self
, stream
):
581 tmpl
= templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_PROTO
_BEGIN
582 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
,
585 if stream
.event_header_type
is not None:
590 self
._generate
_proto
_params
(stream
.event_header_type
,
591 _PREFIX_SEH
, exclude_list
)
593 tmpl
= templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_PROTO
_END
594 self
._cg
.add_lines(tmpl
)
596 def _generate_func_serialize_stream_event_context_proto(self
, stream
):
597 tmpl
= templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_PROTO
_BEGIN
598 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
,
601 if stream
.event_context_type
is not None:
602 self
._generate
_proto
_params
(stream
.event_context_type
,
605 tmpl
= templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_PROTO
_END
606 self
._cg
.add_lines(tmpl
)
608 def _generate_func_serialize_stream_event_header(self
, stream
):
609 self
._reset
_per
_func
_state
()
610 self
._generate
_func
_serialize
_stream
_event
_header
_proto
(stream
)
611 tmpl
= templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_BODY
_BEGIN
612 self
._cg
.add_lines(tmpl
)
615 if stream
.event_header_type
is not None:
616 if 'timestamp' in stream
.event_header_type
.fields
:
617 timestamp
= stream
.event_header_type
.fields
['timestamp']
618 ts_ctype
= self
._get
_int
_ctype
(timestamp
)
619 clock
= timestamp
.property_mappings
[0].object
620 clock_name
= clock
.name
621 clock_ctype
= clock
.return_ctype
622 tmpl
= '{} ts = ctx->cbs.{}_clock_get_value(ctx->data);'
623 self
._cg
.add_line(tmpl
.format(clock_ctype
, clock_name
))
625 self
._cg
.add_empty_line()
626 func
= self
._generate
_func
_serialize
_event
_from
_entity
628 if stream
.event_header_type
is not None:
631 if 'id' in stream
.event_header_type
.fields
:
632 id_t
= stream
.event_header_type
.fields
['id']
633 id_t_ctype
= self
._get
_int
_ctype
(id_t
)
634 spec_src
['id'] = '({}) event_id'.format(id_t_ctype
)
636 if 'timestamp' in stream
.event_header_type
.fields
:
637 spec_src
['timestamp'] = '({}) ts'.format(ts_ctype
)
639 func(_PREFIX_SEH
, stream
.event_header_type
, spec_src
)
642 tmpl
= templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_HEADER
_BODY
_END
643 self
._cg
.add_lines(tmpl
)
645 def _generate_func_serialize_stream_event_context(self
, stream
):
646 self
._reset
_per
_func
_state
()
647 self
._generate
_func
_serialize
_stream
_event
_context
_proto
(stream
)
648 tmpl
= templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_BODY
_BEGIN
649 self
._cg
.add_lines(tmpl
)
651 func
= self
._generate
_func
_serialize
_event
_from
_entity
653 if stream
.event_context_type
is not None:
654 func(_PREFIX_SEC
, stream
.event_context_type
)
657 tmpl
= templates
._FUNC
_SERIALIZE
_STREAM
_EVENT
_CONTEXT
_BODY
_END
658 self
._cg
.add_lines(tmpl
)
660 def _generate_func_trace(self
, stream
, event
):
661 self
._reset
_per
_func
_state
()
662 self
._generate
_func
_trace
_proto
(stream
, event
)
663 params
= self
._get
_call
_event
_param
_list
(stream
, event
)
664 tmpl
= templates
._FUNC
_TRACE
_BODY
665 self
._cg
.add_lines(tmpl
.format(sname
=stream
.name
, evname
=event
.name
,
668 def _generate_func_init(self
):
669 self
._reset
_per
_func
_state
()
670 self
._generate
_func
_init
_proto
()
671 tmpl
= templates
._FUNC
_INIT
_BODY
672 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
))
674 def _generate_field_name_cc_line(self
, field_name
):
675 self
._cg
.add_cc_line('"{}" field'.format(field_name
))
677 def _save_byte_offset(self
, name
):
678 self
._saved
_byte
_offsets
[name
] = self
._sasa
.byte_offset
680 def _restore_byte_offset(self
, name
):
681 self
._sasa
.byte_offset
= self
._saved
_byte
_offsets
[name
]
683 def _reset_per_func_state(self
):
684 self
._uf
_written
= False
685 self
._ud
_written
= False
687 def _generate_func_open(self
, stream
):
688 def generate_save_offset(name
):
689 tmpl
= 'ctx->off_spc_{} = ctx->parent.at;'.format(name
)
690 self
._cg
.add_line(tmpl
)
691 self
._save
_byte
_offset
(name
)
693 self
._reset
_per
_func
_state
()
694 self
._generate
_func
_open
_proto
(stream
)
695 tmpl
= templates
._FUNC
_OPEN
_BODY
_BEGIN
696 self
._cg
.add_lines(tmpl
)
698 tph_type
= self
._cfg
.metadata
.trace
.packet_header_type
699 spc_type
= stream
.packet_context_type
701 if spc_type
is not None and 'timestamp_begin' in spc_type
.fields
:
702 field
= spc_type
.fields
['timestamp_begin']
703 tmpl
= '{} ts = ctx->parent.cbs.{}_clock_get_value(ctx->parent.data);'
704 clock
= field
.property_mappings
[0].object
705 clock_ctype
= clock
.return_ctype
706 clock_name
= clock
.name
707 self
._cg
.add_line(tmpl
.format(clock_ctype
, clock_name
))
708 self
._cg
.add_empty_line()
710 self
._cg
.add_cc_line('do not open a packet that is already open')
711 self
._cg
.add_line('if (ctx->parent.packet_is_open) {')
713 self
._cg
.add_line('return;')
715 self
._cg
.add_line('}')
716 self
._cg
.add_empty_line()
717 self
._cg
.add_line('ctx->parent.at = 0;')
719 if tph_type
is not None:
720 self
._cg
.add_empty_line()
721 self
._cg
.add_cc_line('trace packet header')
722 self
._cg
.add_line('{')
724 self
._cg
.add_cc_line('align structure')
726 self
._generate
_align
_type
('ctx->parent.at', tph_type
)
728 for field_name
, field_type
in tph_type
.fields
.items():
729 src
= _PREFIX_TPH
+ field_name
731 if field_name
== 'magic':
733 elif field_name
== 'stream_id':
734 stream_id_ctype
= self
._get
_int
_ctype
(field_type
)
735 src
= '({}) {}'.format(stream_id_ctype
, stream
.id)
736 elif field_name
== 'uuid':
737 self
._cg
.add_empty_line()
738 self
._generate
_field
_name
_cc
_line
(field_name
)
739 self
._cg
.add_line('{')
741 self
._cg
.add_line('static uint8_t uuid[] = {')
744 for b
in self
._cfg
.metadata
.trace
.uuid
.bytes
:
745 self
._cg
.add_line('{},'.format(b
))
748 self
._cg
.add_line('};')
749 self
._cg
.add_empty_line()
750 self
._generate
_align
('ctx->parent.at', 8)
751 line
= 'memcpy(&ctx->parent.buf[_BITS_TO_BYTES(ctx->parent.at)], uuid, 16);'
752 self
._cg
.add_line(line
)
753 self
._generate
_incr
_pos
_bytes
('ctx->parent.at', 16)
755 self
._cg
.add_line('}')
759 self
._cg
.add_empty_line()
760 self
._generate
_field
_name
_cc
_line
(field_name
)
761 self
._generate
_align
_type
('ctx->parent.at', field_type
)
762 self
._generate
_serialize
_type
(src
, '(&ctx->parent)', field_type
)
765 self
._cg
.add_lines('}')
767 if spc_type
is not None:
768 self
._cg
.add_empty_line()
769 self
._cg
.add_cc_line('stream packet context')
770 self
._cg
.add_line('{')
772 self
._cg
.add_cc_line('align structure')
774 self
._generate
_align
_type
('ctx->parent.at', spc_type
)
775 tmpl_off
= 'off_spc_{fname}'
777 for field_name
, field_type
in spc_type
.fields
.items():
778 src
= _PREFIX_SPC
+ field_name
780 self
._cg
.add_empty_line()
781 self
._generate
_field
_name
_cc
_line
(field_name
)
783 if field_name
== 'timestamp_begin':
784 ctype
= self
._get
_type
_ctype
(field_type
)
785 src
= '({}) ts'.format(ctype
)
786 elif field_name
in ['timestamp_end', 'content_size',
789 elif field_name
== 'packet_size':
790 ctype
= self
._get
_type
_ctype
(field_type
)
791 src
= '({}) ctx->parent.packet_size'.format(ctype
)
793 self
._generate
_align
_type
('ctx->parent.at', field_type
)
796 generate_save_offset(field_name
)
797 self
._generate
_incr
_pos
('ctx->parent.at', field_type
.size
)
798 self
._sasa
.write_type(field_type
)
800 self
._generate
_serialize
_type
(src
, '(&ctx->parent)',
804 self
._cg
.add_lines('}')
807 tmpl
= templates
._FUNC
_OPEN
_BODY
_END
808 self
._cg
.add_lines(tmpl
)
810 def _generate_func_close(self
, stream
):
811 def generate_goto_offset(name
):
812 tmpl
= 'ctx->parent.at = ctx->off_spc_{};'.format(name
)
813 self
._cg
.add_line(tmpl
)
815 self
._reset
_per
_func
_state
()
816 self
._generate
_func
_close
_proto
(stream
)
817 tmpl
= templates
._FUNC
_CLOSE
_BODY
_BEGIN
818 self
._cg
.add_lines(tmpl
)
820 spc_type
= stream
.packet_context_type
822 if spc_type
is not None:
823 if 'timestamp_end' in spc_type
.fields
:
824 tmpl
= '{} ts = ctx->parent.cbs.{}_clock_get_value(ctx->parent.data);'
825 field
= spc_type
.fields
['timestamp_end']
826 clock
= field
.property_mappings
[0].object
827 clock_ctype
= clock
.return_ctype
828 clock_name
= clock
.name
829 self
._cg
.add_line(tmpl
.format(clock_ctype
, clock_name
))
830 self
._cg
.add_empty_line()
832 self
._cg
.add_cc_line('do not close a packet that is not open')
833 self
._cg
.add_line('if (!ctx->parent.packet_is_open) {')
835 self
._cg
.add_line('return;')
837 self
._cg
.add_line('}')
838 self
._cg
.add_empty_line()
839 self
._cg
.add_cc_line('save content size')
840 self
._cg
.add_line('ctx->parent.content_size = ctx->parent.at;')
842 if spc_type
is not None:
843 field_name
= 'timestamp_end'
845 if field_name
in spc_type
.fields
:
846 t
= spc_type
.fields
[field_name
]
847 ctype
= self
._get
_type
_ctype
(t
)
848 src
= '({}) ts'.format(ctype
)
849 self
._cg
.add_empty_line()
850 self
._generate
_field
_name
_cc
_line
(field_name
)
851 generate_goto_offset(field_name
)
852 self
._restore
_byte
_offset
(field_name
)
853 self
._generate
_serialize
_type
(src
, '(&ctx->parent)', t
)
855 field_name
= 'content_size'
857 if 'content_size' in spc_type
.fields
:
858 t
= spc_type
.fields
[field_name
]
859 ctype
= self
._get
_type
_ctype
(t
)
860 src
= '({}) ctx->parent.content_size'.format(ctype
)
861 self
._cg
.add_empty_line()
862 self
._generate
_field
_name
_cc
_line
(field_name
)
863 generate_goto_offset(field_name
)
864 self
._restore
_byte
_offset
(field_name
)
865 self
._generate
_serialize
_type
(src
, '(&ctx->parent)', t
)
867 field_name
= 'events_discarded'
869 if field_name
in spc_type
.fields
:
870 t
= spc_type
.fields
[field_name
]
871 ctype
= self
._get
_type
_ctype
(t
)
872 src
= '({}) ctx->parent.events_discarded'.format(ctype
)
873 self
._cg
.add_empty_line()
874 self
._generate
_field
_name
_cc
_line
(field_name
)
875 generate_goto_offset(field_name
)
876 self
._restore
_byte
_offset
(field_name
)
877 self
._generate
_serialize
_type
(src
, '(&ctx->parent)', t
)
880 tmpl
= templates
._FUNC
_CLOSE
_BODY
_END
881 self
._cg
.add_lines(tmpl
)
884 def generate_c_src(self
):
886 dt
= datetime
.datetime
.now().isoformat()
887 header_filename
= self
.get_header_filename()
888 tmpl
= templates
._C
_SRC
889 self
._cg
.add_lines(tmpl
.format(prefix
=self
._cfg
.prefix
,
890 header_filename
=header_filename
,
891 version
=barectf
.__version
__, date
=dt
))
892 self
._cg
.add_empty_line()
894 # initialization function
895 self
._generate
_func
_init
()
896 self
._cg
.add_empty_line()
898 for stream
in self
._cfg
.metadata
.streams
.values():
899 self
._generate
_func
_open
(stream
)
900 self
._cg
.add_empty_line()
901 self
._generate
_func
_close
(stream
)
902 self
._cg
.add_empty_line()
904 if stream
.event_header_type
is not None:
905 self
._generate
_func
_serialize
_stream
_event
_header
(stream
)
906 self
._cg
.add_empty_line()
908 if stream
.event_context_type
is not None:
909 self
._generate
_func
_serialize
_stream
_event
_context
(stream
)
910 self
._cg
.add_empty_line()
912 for ev
in stream
.events
.values():
913 self
._generate
_func
_get
_event
_size
(stream
, ev
)
914 self
._cg
.add_empty_line()
915 self
._generate
_func
_serialize
_event
(stream
, ev
)
916 self
._cg
.add_empty_line()
917 self
._generate
_func
_trace
(stream
, ev
)
918 self
._cg
.add_empty_line()
923 def get_header_filename(self
):
924 return '{}.h'.format(self
._cfg
.prefix
.rstrip('_'))
926 def get_bitfield_header_filename(self
):
927 return '{}-bitfield.h'.format(self
._cfg
.prefix
.rstrip('_'))