templates: use Jinja 2's `true`, not Python's `True`
[deliverable/barectf.git] / barectf / templates / c / barectf.c.j2
CommitLineData
fdbf8740
PP
1{#
2 # The MIT License (MIT)
3 #
4 # Copyright (c) 2020 Philippe Proulx <pproulx@efficios.com>
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining
7 # a copy of this software and associated documentation files (the
8 # "Software"), to deal in the Software without restriction, including
9 # without limitation the rights to use, copy, modify, merge, publish,
10 # distribute, sublicense, and/or sell copies of the Software, and to
11 # permit persons to whom the Software is furnished to do so, subject to
12 # the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be
15 # included in all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #}
d6483c83
PP
25{% import 'common.j2' as common %}
26{% import 'c/common.j2' as c_common %}
27{% import 'c/barectf.c-macros.j2' as macros %}
28{% set prefix = common.prefix %}
29{% set ucprefix = common.ucprefix %}
30{% set ctx_struct_name = c_common.ctx_struct_name %}
31{% set cg_opts = cfg.options.code_generation_options %}
e18cf9d6 32{% set const_params = true %}
e72875eb
PP
33{% include 'licence-header.j2' %}
34
d6483c83
PP
35
36#include <stdint.h>
37#include <string.h>
38#include <assert.h>
39
40#include "{{ header_file_name }}"
41#include "{{ bitfield_header_file_name }}"
42
629cfd44
PP
43#define _ALIGN(_at_var, _align) \
44 do { \
45 (_at_var) = ((_at_var) + ((_align) - 1)) & -(_align); \
d6483c83
PP
46 } while (0)
47
48#ifdef __cplusplus
49# define _TO_VOID_PTR(_value) static_cast<void *>(_value)
50# define _FROM_VOID_PTR(_type, _value) static_cast<_type *>(_value)
51#else
52# define _TO_VOID_PTR(_value) ((void *) (_value))
53# define _FROM_VOID_PTR(_type, _value) ((_type *) (_value))
54#endif
55
56#define _BITS_TO_BYTES(_x) ((_x) >> 3)
57#define _BYTES_TO_BITS(_x) ((_x) << 3)
58
59union _f2u {
60 float f;
61 uint32_t u;
62};
63
64union _d2u {
65 double f;
66 uint64_t u;
67};
68
e18cf9d6 69uint32_t {{ prefix }}packet_size(const void * const ctx)
d6483c83 70{
e18cf9d6 71 return _FROM_VOID_PTR(const struct {{ ctx_struct_name }}, ctx)->packet_size;
d6483c83
PP
72}
73
e18cf9d6 74int {{ prefix }}packet_is_full(const void * const vctx)
d6483c83 75{
e18cf9d6 76 const struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(const struct {{ ctx_struct_name }}, vctx);
d6483c83
PP
77
78 return ctx->at == ctx->packet_size;
79}
80
e18cf9d6 81int {{ prefix }}packet_is_empty(const void * const vctx)
d6483c83 82{
e18cf9d6 83 const struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(const struct {{ ctx_struct_name }}, vctx);
d6483c83
PP
84
85 return ctx->at <= ctx->off_content;
86}
87
e18cf9d6 88uint32_t {{ prefix }}packet_events_discarded(const void * const vctx)
d6483c83 89{
e18cf9d6 90 return _FROM_VOID_PTR(const struct {{ ctx_struct_name }}, vctx)->events_discarded;
d6483c83
PP
91}
92
e18cf9d6 93uint8_t *{{ prefix }}packet_buf(const void * const vctx)
d6483c83 94{
e18cf9d6 95 return _FROM_VOID_PTR(const struct {{ ctx_struct_name }}, vctx)->buf;
d6483c83
PP
96}
97
e18cf9d6 98uint32_t {{ prefix }}packet_buf_size(const void * const vctx)
d6483c83 99{
e18cf9d6 100 const struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(const struct {{ ctx_struct_name }}, vctx);
d6483c83
PP
101
102 return _BITS_TO_BYTES(ctx->packet_size);
103}
104
e18cf9d6
PP
105void {{ prefix }}packet_set_buf(void * const vctx, uint8_t * const buf,
106 const uint32_t buf_size)
d6483c83 107{
e18cf9d6 108 struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
d6483c83
PP
109
110 ctx->buf = buf;
111 ctx->packet_size = _BYTES_TO_BITS(buf_size);
112}
113
e18cf9d6 114int {{ prefix }}packet_is_open(const void * const vctx)
d6483c83 115{
e18cf9d6 116 return _FROM_VOID_PTR(const struct {{ ctx_struct_name }}, vctx)->packet_is_open;
d6483c83
PP
117}
118
e18cf9d6 119int {{ prefix }}is_in_tracing_section(const void * const vctx)
d6483c83 120{
e18cf9d6 121 return _FROM_VOID_PTR(const struct {{ ctx_struct_name }}, vctx)->in_tracing_section;
d6483c83
PP
122}
123
e18cf9d6 124volatile const int *{{ prefix }}is_in_tracing_section_ptr(const void * const vctx)
d6483c83 125{
e18cf9d6 126 return &_FROM_VOID_PTR(const struct {{ ctx_struct_name }}, vctx)->in_tracing_section;
d6483c83
PP
127}
128
e18cf9d6 129int {{ prefix }}is_tracing_enabled(const void * const vctx)
d6483c83 130{
e18cf9d6 131 return _FROM_VOID_PTR(const struct {{ ctx_struct_name }}, vctx)->is_tracing_enabled;
d6483c83
PP
132}
133
e18cf9d6 134void {{ prefix }}enable_tracing(void * const vctx, const int enable)
d6483c83
PP
135{
136 _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->is_tracing_enabled = enable;
137}
138
139static
e18cf9d6 140void _write_c_str(struct {{ ctx_struct_name }} * const ctx, const char * const src)
d6483c83 141{
e18cf9d6 142 const uint32_t sz = strlen(src) + 1;
d6483c83
PP
143
144 memcpy(&ctx->buf[_BITS_TO_BYTES(ctx->at)], src, sz);
145 ctx->at += _BYTES_TO_BITS(sz);
146}
147
148static
e18cf9d6 149int _reserve_ev_space(void * const vctx, const uint32_t ev_size)
d6483c83 150{
e18cf9d6 151 struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
d6483c83
PP
152
153 /* event _cannot_ fit? */
154 if (ev_size > (ctx->packet_size - ctx->off_content)) {
155 ctx->events_discarded++;
156 return 0;
157 }
158
159 /* packet is full? */
160 if ({{ prefix }}packet_is_full(ctx)) {
161 /* yes: is back-end full? */
162 if (ctx->cbs.is_backend_full(ctx->data)) {
163 /* yes: discard event */
164 ctx->events_discarded++;
165 return 0;
166 }
167
168 /* back-end is not full: open new packet */
169 ctx->use_cur_last_event_ts = 1;
170 ctx->cbs.open_packet(ctx->data);
171 ctx->use_cur_last_event_ts = 0;
172 }
173
174 /* event fits the current packet? */
175 if (ev_size > (ctx->packet_size - ctx->at)) {
176 /* no: close packet now */
177 ctx->use_cur_last_event_ts = 1;
178 ctx->cbs.close_packet(ctx->data);
179 ctx->use_cur_last_event_ts = 0;
180
181 /* is back-end full? */
182 if (ctx->cbs.is_backend_full(ctx->data)) {
183 /* yes: discard event */
184 ctx->events_discarded++;
185 return 0;
186 }
187
188 /* back-end is not full: open new packet */
189 ctx->use_cur_last_event_ts = 1;
190 ctx->cbs.open_packet(ctx->data);
191 ctx->use_cur_last_event_ts = 0;
192 assert(ev_size <= (ctx->packet_size - ctx->at));
193 }
194
195 return 1;
196}
197
198static
e18cf9d6 199void _commit_ev(void * const vctx)
d6483c83 200{
e18cf9d6 201 struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
d6483c83
PP
202
203 /* is packet full? */
204 if ({{ prefix }}packet_is_full(ctx)) {
205 /* yes: close it now */
206 ctx->cbs.close_packet(ctx->data);
207 }
208}
209
210{% include 'c/ctx-init-func-proto.j2' %}
211
212{
e18cf9d6 213 struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
d6483c83
PP
214 ctx->cbs = cbs;
215 ctx->data = data;
216 ctx->buf = buf;
217 ctx->packet_size = _BYTES_TO_BITS(buf_size);
218 ctx->at = 0;
219 ctx->events_discarded = 0;
220 ctx->packet_is_open = 0;
221 ctx->in_tracing_section = 0;
222 ctx->is_tracing_enabled = 1;
223 ctx->use_cur_last_event_ts = 0;
224}
225
226{% for stream_type in cfg.trace.type.stream_types | sort %}
227 {% set def_clk_type = stream_type.default_clock_type %}
228 {% set sctx_name %}{{ prefix }}{{ stream_type.name }}{% endset %}
229 {% set this_stream_ops = stream_ops[stream_type] %}
230 {% include 'c/open-func-proto.j2' %}
231
232{
233 {{ macros.open_close_func_preamble(stream_type) | indent_tab }}
234
235 /*
236 * This function is either called by a tracing function, or
237 * directly by the platform.
238 *
239 * If it's called by a tracing function, then
240 * `ctx->in_tracing_section` is 1, so it's safe to open
241 * the packet here (alter the packet), even if tracing was
242 * disabled in the meantime because we're already in a tracing
243 * section (which finishes at the end of the tracing function
244 * call).
245 *
246 * If it's called directly by the platform, then if tracing is
247 * disabled, we don't want to alter the packet, and return
248 * immediately.
249 */
250 if (!ctx->is_tracing_enabled && !saved_in_tracing_section) {
251 ctx->in_tracing_section = 0;
252 return;
253 }
254
255 /* we can alter the packet */
256 ctx->in_tracing_section = 1;
257
258 /* do not open a packet that is already open */
259 if (ctx->packet_is_open) {
260 ctx->in_tracing_section = saved_in_tracing_section;
261 return;
262 }
263
264 ctx->at = 0;
265 {% set pkt_header_ops = this_stream_ops.pkt_header_ops %}
266 {% if pkt_header_ops %}
267
268 /* serialize packet header */
269 {
270 {% for op in pkt_header_ops %}
271 {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
272
273 {% endfor %}
274 }
275 {% endif %}
276
277 /* serialize packet context */
278 {
279 {% for op in this_stream_ops.pkt_ctx_ops %}
280 {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
281
282 {% endfor %}
283 }
284
285 /* save content beginning's offset */
286 ctx->off_content = ctx->at;
287
288 /* mark current packet as open */
289 ctx->packet_is_open = 1;
290
291 /* not tracing anymore */
292 ctx->in_tracing_section = saved_in_tracing_section;
293}
294
295 {% include 'c/close-func-proto.j2' %}
296
297{
298 {{ macros.open_close_func_preamble(stream_type) | indent_tab }}
299
300 /*
301 * This function is either called by a tracing function, or
302 * directly by the platform.
303 *
304 * If it's called by a tracing function, then
305 * `ctx->in_tracing_section` is 1, so it's safe to close
306 * the packet here (alter the packet), even if tracing was
307 * disabled in the meantime, because we're already in a tracing
308 * section (which finishes at the end of the tracing function
309 * call).
310 *
311 * If it's called directly by the platform, then if tracing is
312 * disabled, we don't want to alter the packet, and return
313 * immediately.
314 */
315 if (!ctx->is_tracing_enabled && !saved_in_tracing_section) {
316 ctx->in_tracing_section = 0;
317 return;
318 }
319
320 /* we can alter the packet */
321 ctx->in_tracing_section = 1;
322
323 /* do not close a packet that is not open */
324 if (!ctx->packet_is_open) {
325 ctx->in_tracing_section = saved_in_tracing_section;
326 return;
327 }
328
329 /* save content size */
330 ctx->content_size = ctx->at;
03088329
PP
331 {% set name = 'timestamp_end' %}
332 {% if name in stream_type._pkt_ctx_ft.members %}
333 {% set op = stream_op_pkt_ctx_op(stream_type, name) %}
d6483c83
PP
334
335 /* go back to `timestamp_end` field offset */
336 ctx->at = sctx->off_{{ c_common.op_src(op) }};
337
338 {% set src = 'ts' %}
adb5316b 339 {% filter indent_tab(indent_first=true) %}
d6483c83
PP
340 {% include 'c/serialize-write-saved-int-statements.j2' %}
341
342 {% endfilter %}
343 {% endif %}
03088329
PP
344 {% set name = 'content_size' %}
345 {% if name in stream_type._pkt_ctx_ft.members %}
346 {% set op = stream_op_pkt_ctx_op(stream_type, name) %}
d6483c83
PP
347
348 /* go back to `content_size` field offset */
349 ctx->at = sctx->off_{{ c_common.op_src(op) }};
350
03088329 351 {% set src %}ctx->{{ name }}{% endset %}
adb5316b 352 {% filter indent_tab(indent_first=true) %}
d6483c83
PP
353 {% include 'c/serialize-write-saved-int-statements.j2' %}
354
355 {% endfilter %}
356 {% endif %}
03088329
PP
357 {% set name = 'events_discarded' %}
358 {% if name in stream_type._pkt_ctx_ft.members %}
359 {% set op = stream_op_pkt_ctx_op(stream_type, name) %}
d6483c83
PP
360
361 /* go back to `events_discarded` field offset */
362 ctx->at = sctx->off_{{ c_common.op_src(op) }};
363
03088329 364 {% set src %}ctx->{{ name }}{% endset %}
adb5316b 365 {% filter indent_tab(indent_first=true) %}
d6483c83
PP
366 {% include 'c/serialize-write-saved-int-statements.j2' %}
367
368 {% endfilter %}
369 {% endif %}
370
371 /* go back to end of packet */
372 ctx->at = ctx->packet_size;
373
374 /* mark packet as closed */
375 ctx->packet_is_open = 0;
376
377 /* not tracing anymore */
378 ctx->in_tracing_section = saved_in_tracing_section;
379}
380 {% if stream_type._ev_header_ft %}
381
e18cf9d6
PP
382static void _serialize_ev_header_{{ stream_type.name }}(void * const vctx,
383 const uint32_t ev_type_id)
d6483c83 384{
e18cf9d6 385 struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
d6483c83 386 {% if def_clk_type %}
e18cf9d6 387 struct {{ sctx_name }}_ctx * const sctx = _FROM_VOID_PTR(struct {{ sctx_name }}_ctx, vctx);
d6483c83
PP
388 const {{ cg_opts.clock_type_c_types[def_clk_type] }} ts = sctx->cur_last_event_ts;
389 {% endif %}
390
391 /* serialize event header */
392 {
393 {% for op in this_stream_ops.ev_header_ops %}
394 {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
395
396 {% endfor %}
397 }
398}
399 {% endif %}
400 {% if stream_type.event_common_context_field_type %}
401
e18cf9d6 402static void _serialize_ev_common_ctx_{{ stream_type.name }}(void * const vctx{{ stream_type | serialize_ev_common_ctx_func_params_str(const_params) }})
d6483c83 403{
e18cf9d6 404 struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
d6483c83
PP
405
406 /* serialize event common context */
407 {
408 {% for op in this_stream_ops.ev_common_ctx_ops %}
409 {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
410
411 {% endfor %}
412 }
413}
414 {% endif %}
415 {# internal serialization functions #}
416 {% for ev_type in stream_type.event_types | sort %}
417
e18cf9d6 418static void _serialize_ev_{{ stream_type.name }}_{{ ev_type.name }}(void * const vctx{{ (stream_type, ev_type) | trace_func_params_str(const_params) }})
d6483c83 419{
e18cf9d6 420 struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
d6483c83
PP
421 {% if stream_type._ev_header_ft %}
422
423 /* serialize header */
424 _serialize_ev_header_{{ stream_type.name }}(ctx, {{ ev_type.id }});
425 {% endif %}
426 {% if stream_type.event_common_context_field_type %}
427
428 /* serialize common context */
1c650e47 429 {% set params = macros.ft_call_params(root_ft_prefixes.ECC, stream_type.event_common_context_field_type) %}
d6483c83
PP
430 _serialize_ev_common_ctx_{{ stream_type.name }}(ctx{{ params }});
431 {% endif %}
432 {% set this_ev_ops = this_stream_ops.ev_ops[ev_type] %}
433 {% if this_ev_ops.spec_ctx_ops %}
434
435 /* serialize specific context */
436 {
437 {% for op in this_ev_ops.spec_ctx_ops %}
438 {{ op.serialize_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
439
440 {% endfor %}
441 }
442 {% endif %}
443 {% if this_ev_ops.payload_ops %}
444
445 /* serialize payload */
446 {
447 {% for op in this_ev_ops.payload_ops %}
448 {{ op.serialize_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
449
450 {% endfor %}
451 }
452 {% endif %}
453}
454 {% endfor %}
455 {# internal size functions #}
456 {% for ev_type in stream_type.event_types | sort %}
457 {% set this_ev_ops = this_stream_ops.ev_ops[ev_type] %}
458
e18cf9d6 459static uint32_t _ev_size_{{ stream_type.name }}_{{ ev_type.name }}(void * const vctx{{ (stream_type, ev_type) | trace_func_params_str(const_params) }})
d6483c83 460{
e18cf9d6 461 struct {{ ctx_struct_name }} * const ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
d6483c83
PP
462 uint32_t at = ctx->at;
463 {% if this_stream_ops.ev_header_ops %}
464
465 /* add header size */
466 {
467 {% for op in this_stream_ops.ev_header_ops %}
468 {{ op.size_str(stream_type=stream_type) | indent_tab(2) }}
469
470 {% endfor %}
471 }
472 {% endif %}
473 {% if this_stream_ops.ev_common_ctx_ops %}
474
475 /* add common context size */
476 {
477 {% for op in this_stream_ops.ev_common_ctx_ops %}
478 {{ op.size_str(stream_type=stream_type) | indent_tab(2) }}
479
480 {% endfor %}
481 }
482 {% endif %}
483 {% if this_ev_ops.spec_ctx_ops %}
484
485 /* add specific context size */
486 {
487 {% for op in this_ev_ops.spec_ctx_ops %}
488 {{ op.size_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
489
490 {% endfor %}
491 }
492 {% endif %}
493 {% if this_ev_ops.payload_ops %}
494
495 /* add payload size */
496 {
497 {% for op in this_ev_ops.payload_ops %}
498 {{ op.size_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
499
500 {% endfor %}
501 }
502 {% endif %}
503
504 return at - ctx->at;
505}
506 {% endfor %}
507 {# public tracing functions #}
508 {% for ev_type in stream_type.event_types | sort %}
509
510 {% include 'c/trace-func-proto.j2' %}
511
512{
e18cf9d6 513 struct {{ ctx_struct_name }} * const ctx = &sctx->parent;
d6483c83
PP
514 uint32_t ev_size;
515
516 {% if def_clk_type %}
517 /* save time */
518 sctx->cur_last_event_ts = ctx->cbs.{{ def_clk_type.name }}_clock_get_value(ctx->data);
519
520 {% endif %}
521
522 if (!ctx->is_tracing_enabled) {
523 return;
524 }
525
526 /* we can alter the packet */
527 ctx->in_tracing_section = 1;
528
529 /* compute event size */
1c650e47
PP
530 {% set ev_common_ctx_params = macros.ft_call_params(root_ft_prefixes.ECC, stream_type.event_common_context_field_type) %}
531 {% set spec_ctx_params = macros.ft_call_params(root_ft_prefixes.SC, ev_type.specific_context_field_type) %}
532 {% set payload_params = macros.ft_call_params(root_ft_prefixes.P, ev_type.payload_field_type) %}
d6483c83
PP
533 {% set params %}{{ ev_common_ctx_params }}{{ spec_ctx_params }}{{ payload_params }}{% endset %}
534 ev_size = _ev_size_{{ stream_type.name }}_{{ ev_type.name }}(_TO_VOID_PTR(ctx){{ params }});
535
536 /* do we have enough space to serialize? */
537 if (!_reserve_ev_space(_TO_VOID_PTR(ctx), ev_size)) {
538 /* no: forget this */
539 ctx->in_tracing_section = 0;
540 return;
541 }
542
543 /* serialize event */
544 _serialize_ev_{{ stream_type.name }}_{{ ev_type.name }}(_TO_VOID_PTR(ctx){{ params }});
545
546 /* commit event */
547 _commit_ev(_TO_VOID_PTR(ctx));
548
549 /* not tracing anymore */
550 ctx->in_tracing_section = 0;
551}
552 {% endfor %}
553{% endfor %}
This page took 0.04373 seconds and 4 git commands to generate.