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