GCC Code Coverage Report


Directory: csrc/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 96.0% 72 / 0 / 75
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 36 size_t EVT4_state_size(void) {
16 36 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 38 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 38 const uint32_t *restrict current = input_buffer->begin;
42 38 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 38 size_t n_events_read = event_buffer->size;
48 38 const size_t events_capacity = event_buffer->capacity;
49 // Guard the size_t subtraction: capacity <= 32 would wrap to a huge offset.
50 38 const size_t events_capacity_offset = events_capacity > 32 ? events_capacity - 32 : 0;
51
52 38 timestamp_t* restrict out_ts = event_buffer->t;
53 38 uint16_t* restrict out_x = event_buffer->x;
54 38 uint16_t* restrict out_y = event_buffer->y;
55 38 uint8_t* restrict out_p = event_buffer->p;
56
57 // Trigger output buffers
58 38 timestamp_t* restrict trigger_ts = trigger_buffer->t;
59 38 uint8_t* restrict trigger_id = trigger_buffer->id;
60 38 uint8_t* restrict trigger_p = trigger_buffer->p;
61
62 38 size_t n_triggers_read = trigger_buffer->size;
63 38 const size_t triggers_capacity = trigger_buffer->capacity;
64
65 // State variables
66 38 uint64_t last_ts_high = state->last_ts_high;
67 38 uint64_t ts_high_high = state->ts_high_high;
68
69 38 parse_status_t status = EVUTILS_PARSE_OK;
70
71 38 while(
72 1035177 current < end &&
73 2070392 n_events_read < events_capacity_offset &&
74 n_triggers_read < triggers_capacity
75 ) {
76
77 1035177 uint32_t packet_type = (*current & 0xF0000000) >> 28;
78 1035177 uint32_t packet_data = *current & 0x0FFFFFFF;
79
80 1035177 switch(packet_type){
81 511042 case EVT4_CD_OFF:
82 case EVT4_CD_ON:
83 // Bits 27..22 low timestamp, 21..11 x, 10..0 y (same as EVT2).
84 511042 out_ts[n_events_read] = ts_high_high | last_ts_high | ((packet_data >> 22) & 0x3F);
85 511042 out_x[n_events_read] = (packet_data >> 11) & 0x7FF;
86 511042 out_y[n_events_read] = packet_data & 0x7FF;
87 511042 out_p[n_events_read] = packet_type & 1; // CD_ON (0xB) -> 1
88 511042 n_events_read++;
89 511042 break;
90 2787 case EVT4_CD_VEC_OFF:
91 case EVT4_CD_VEC_ON: {
92 // Vector CD: this word is the base (x, y, low ts, polarity); the
93 // FOLLOWING word is a 32-bit validity mask. Each set bit `off`
94 // emits an event at x = base_x + off, same y/ts/polarity.
95 // If the mask word is not in this chunk, stop without consuming
96 // the base word so the caller resumes the whole group next time.
97 2787 if (current + 1 >= end) {
98 status = EVUTILS_PARSE_INPUT_EMPTY;
99 goto done;
100 }
101 2787 const uint64_t ts = ts_high_high | last_ts_high | ((packet_data >> 22) & 0x3F);
102 2787 const uint16_t base_x = (packet_data >> 11) & 0x7FF;
103 2787 const uint16_t y = packet_data & 0x7FF;
104 2787 const uint8_t p = packet_type & 1;
105
106 2787 uint32_t mask = *(current + 1);
107 47249 while (mask) {
108 44462 uint32_t off = (uint32_t)__builtin_ctz(mask);
109 44462 out_ts[n_events_read] = ts;
110 44462 out_x[n_events_read] = (uint16_t)(base_x + off);
111 44462 out_y[n_events_read] = y;
112 44462 out_p[n_events_read] = p;
113 44462 n_events_read++;
114 44462 mask &= mask - 1u;
115 }
116 2787 current++; // consume the mask word (base word consumed below)
117 2787 break;
118 }
119 506106 case EVT4_EVT_TIME_HIGH:
120 {
121 // Bits 27..0 are event-time bits 33..6. Track 28-bit wraps.
122 506106 uint64_t new_ts_high = (uint64_t)packet_data << 6;
123 506106 if (new_ts_high < last_ts_high) {
124 707 ts_high_high += EVT4_TS_WRAP;
125 }
126 506106 last_ts_high = new_ts_high;
127 }
128 506106 break;
129 1456 case EVT4_EXT_TRIGGER:
130 // value @ bit 0, id @ bits 8..12 (5 bits), low ts @ bits 22..27.
131 1456 trigger_ts[n_triggers_read] = ts_high_high | last_ts_high | ((packet_data >> 22) & 0x3F);
132 1456 trigger_id[n_triggers_read] = (packet_data >> 8) & 0x1F;
133 1456 trigger_p[n_triggers_read] = packet_data & 0x1;
134 1456 n_triggers_read++;
135 1456 break;
136 13786 case EVT4_OTHERS:
137 case EVT4_CONTINUED:
138 case EVT4_PADDING:
139 default:
140 13786 break;
141 }
142 1035177 current++;
143 }
144
145 38 done:
146 38 event_buffer->size = n_events_read;
147 38 trigger_buffer->size = n_triggers_read;
148 38 state->last_ts_high = last_ts_high;
149 38 state->ts_high_high = ts_high_high;
150
151 /* Report why parsing stopped: output space exhausted vs input drained. */
152 38 if (n_events_read >= events_capacity_offset || n_triggers_read >= triggers_capacity) {
153 status = EVUTILS_PARSE_OUTPUT_FULL;
154 }
155
156 38 return (parser_result_t){
157 .current = (const void *)current,
158 .status = status
159 };
160 }
161