GCC Code Coverage Report


Directory: csrc/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 94.5% 69 / 0 / 73
Functions: 100.0% 1 / 0 / 1
Branches: -% 0 / 0 / 0

evt4.c
Line Branch Exec Source
1 #include "evutils/evt4.h"
2
3 /* EVT4 timestamp reconstruction is identical to EVT2: the 28-bit TIME_HIGH
4 * field carries time-base bits 6..33 (so it is shifted left by 6), and the CD /
5 * trigger words carry the low 6 bits. The field wraps at 2^34; bump the overflow
6 * accumulator each time it does. */
7 typedef struct evt4_state_s {
8 uint64_t last_ts_high; /* current TIME_HIGH << 6 (bits 6..33) */
9 uint64_t ts_high_high; /* accumulated overflow of the 28-bit field (34+) */
10 } evt4_state_t;
11
12 #define EVT4_TS_WRAP (1ULL << 34)
13
14
15 11 size_t EVT4_state_size(void) {
16 11 return sizeof(evt4_state_t);
17 }
18
19
20 /* 4-bit type field in bits 28..31 of each 32-bit word. */
21 enum EVT4_PacketType {
22 EVT4_OTHERS = 0x6,
23 EVT4_CONTINUED = 0x7,
24 EVT4_EXT_TRIGGER = 0x9,
25 EVT4_CD_OFF = 0xA, /* single CD event, polarity 0 */
26 EVT4_CD_ON = 0xB, /* single CD event, polarity 1 */
27 EVT4_CD_VEC_OFF = 0xC, /* vector CD base, polarity 0; next word = mask */
28 EVT4_CD_VEC_ON = 0xD, /* vector CD base, polarity 1; next word = mask */
29 EVT4_EVT_TIME_HIGH = 0xE,
30 EVT4_PADDING = 0xF
31 };
32
33
34 EVUTILS_TARGET_CLONES
35 11 parser_result_t EVT4_parse_chunk_soa(
36 evt4_state_t *state,
37 const evt4_input_buffer_t *input_buffer,
38 event_buffer_soa_t *event_buffer,
39 trigger_buffer_soa_t *trigger_buffer) {
40
41 11 const uint32_t *restrict current = input_buffer->begin;
42 11 const uint32_t *restrict end = input_buffer->end;
43
44 // Event output buffers. A single vector word expands to at most 32 events
45 // (one per set bit of the 32-bit mask), so stop early enough to always have
46 // room for a full expansion without a per-bit capacity check.
47 11 size_t n_events_read = event_buffer->size;
48 11 const size_t events_capacity = event_buffer->capacity;
49 11 const size_t events_capacity_offset = events_capacity - 32;
50
51 11 timestamp_t* restrict out_ts = event_buffer->t;
52 11 uint16_t* restrict out_x = event_buffer->x;
53 11 uint16_t* restrict out_y = event_buffer->y;
54 11 uint8_t* restrict out_p = event_buffer->p;
55
56 // Trigger output buffers
57 11 timestamp_t* restrict trigger_ts = trigger_buffer->t;
58 11 uint8_t* restrict trigger_id = trigger_buffer->id;
59 11 uint8_t* restrict trigger_p = trigger_buffer->p;
60
61 11 size_t n_triggers_read = trigger_buffer->size;
62 11 const size_t triggers_capacity = trigger_buffer->capacity;
63
64 // State variables
65 11 uint64_t last_ts_high = state->last_ts_high;
66 11 uint64_t ts_high_high = state->ts_high_high;
67
68 11 parse_status_t status = EVUTILS_PARSE_OK;
69
70 11 while(
71 4033 current < end &&
72 8077 n_events_read < events_capacity_offset &&
73 n_triggers_read < triggers_capacity
74 ) {
75
76 4033 uint32_t packet_type = (*current & 0xF0000000) >> 28;
77 4033 uint32_t packet_data = *current & 0x0FFFFFFF;
78
79 4033 switch(packet_type){
80 3222 case EVT4_CD_OFF:
81 case EVT4_CD_ON:
82 // Bits 27..22 low timestamp, 21..11 x, 10..0 y (same as EVT2).
83 3222 out_ts[n_events_read] = ts_high_high | last_ts_high | ((packet_data >> 22) & 0x3F);
84 3222 out_x[n_events_read] = (packet_data >> 11) & 0x7FF;
85 3222 out_y[n_events_read] = packet_data & 0x7FF;
86 3222 out_p[n_events_read] = packet_type & 1; // CD_ON (0xB) -> 1
87 3222 n_events_read++;
88 3222 break;
89 5 case EVT4_CD_VEC_OFF:
90 case EVT4_CD_VEC_ON: {
91 // Vector CD: this word is the base (x, y, low ts, polarity); the
92 // FOLLOWING word is a 32-bit validity mask. Each set bit `off`
93 // emits an event at x = base_x + off, same y/ts/polarity.
94 // If the mask word is not in this chunk, stop without consuming
95 // the base word so the caller resumes the whole group next time.
96 5 if (current + 1 >= end) {
97 status = EVUTILS_PARSE_INPUT_EMPTY;
98 goto done;
99 }
100 5 const uint64_t ts = ts_high_high | last_ts_high | ((packet_data >> 22) & 0x3F);
101 5 const uint16_t base_x = (packet_data >> 11) & 0x7FF;
102 5 const uint16_t y = packet_data & 0x7FF;
103 5 const uint8_t p = packet_type & 1;
104
105 5 uint32_t mask = *(current + 1);
106 43 while (mask) {
107 38 uint32_t off = (uint32_t)__builtin_ctz(mask);
108 38 out_ts[n_events_read] = ts;
109 38 out_x[n_events_read] = (uint16_t)(base_x + off);
110 38 out_y[n_events_read] = y;
111 38 out_p[n_events_read] = p;
112 38 n_events_read++;
113 38 mask &= mask - 1u;
114 }
115 5 current++; // consume the mask word (base word consumed below)
116 5 break;
117 }
118 801 case EVT4_EVT_TIME_HIGH:
119 {
120 // Bits 27..0 are event-time bits 33..6. Track 28-bit wraps.
121 801 uint64_t new_ts_high = (uint64_t)packet_data << 6;
122 801 if (new_ts_high < last_ts_high) {
123 2 ts_high_high += EVT4_TS_WRAP;
124 }
125 801 last_ts_high = new_ts_high;
126 }
127 801 break;
128 5 case EVT4_EXT_TRIGGER:
129 // value @ bit 0, id @ bits 8..12 (5 bits), low ts @ bits 22..27.
130 5 trigger_ts[n_triggers_read] = ts_high_high | last_ts_high | ((packet_data >> 22) & 0x3F);
131 5 trigger_id[n_triggers_read] = (packet_data >> 8) & 0x1F;
132 5 trigger_p[n_triggers_read] = packet_data & 0x1;
133 5 n_triggers_read++;
134 5 break;
135 case EVT4_OTHERS:
136 case EVT4_CONTINUED:
137 case EVT4_PADDING:
138 default:
139 break;
140 }
141 4033 current++;
142 }
143
144 11 done:
145 11 event_buffer->size = n_events_read;
146 11 trigger_buffer->size = n_triggers_read;
147 11 state->last_ts_high = last_ts_high;
148 11 state->ts_high_high = ts_high_high;
149
150 11 return (parser_result_t){
151 .current = (const void *)current,
152 .status = status
153 };
154 }
155