DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
AVXPipeline.cpp
Go to the documentation of this file.
1
9
10namespace tpglibs {
11
12__m256i
13AVXPipeline::save_state(const __m256i& processed_signal) {
14 __m256i active = _mm256_cmpgt_epi16(processed_signal, _mm256_setzero_si256());
15 __m256i inactive = _mm256_cmpeq_epi16(processed_signal, _mm256_setzero_si256());
16 __m256i was_inactive = _mm256_cmpeq_epi16(m_samples_over_threshold, _mm256_setzero_si256());
17
18 // If it was *not* inactive and is now inactive, then it must be a new TP.
19 __m256i new_tps = _mm256_andnot_si256(was_inactive, inactive);
20
21 // Get the potentially saturated integral and overflown integral.
22 __m256i adc_integral_sat = _mm256_adds_epu16(m_adc_integral_lo, processed_signal);
23 m_adc_integral_lo = _mm256_add_epi16(m_adc_integral_lo, processed_signal);
24
25 // If it is saturated, then increment the hi. The overflown integral already "reset".
26 __m256i is_saturated = _mm256_cmpeq_epi16(adc_integral_sat, m_max_value_register);
27 // If lo and sat are the same, then it is *not* saturated and happened to exactly sum to 0xFFFF.
28 __m256i exact = _mm256_cmpeq_epi16(m_adc_integral_lo, adc_integral_sat);
29 // So, (!exact) & is_saturated == [truly saturated].
30 is_saturated = _mm256_andnot_si256(exact, is_saturated);
31
32 __m256i to_add = _mm256_and_si256(m_ones_register, is_saturated);
33 m_adc_integral_hi = _mm256_adds_epu16(m_adc_integral_hi, to_add);
34
35 __m256i above_peak = _mm256_cmpgt_epi16(processed_signal, m_adc_peak);
36
37 m_adc_peak = _mm256_max_epi16(m_adc_peak, processed_signal);
38 m_samples_to_peak = _mm256_blendv_epi8(m_samples_to_peak, m_samples_over_threshold, above_peak);
39
40 __m256i time_add = _mm256_blendv_epi8(_mm256_setzero_si256(), m_ones_register, active);
41 m_samples_over_threshold = _mm256_adds_epi16(m_samples_over_threshold, time_add);
42
43 return new_tps;
44}
45
46bool
47AVXPipeline::check_for_tps(const __m256i& tp_mask) {
48 // tp_mask & 0xFFFF = 0 -> tp_mask == 0.
49 // True => tp_mask is all zeros and has no TPs.
50 // Negate!
51 return !_mm256_testz_si256(tp_mask, _mm256_set1_epi16(-1));
52}
53
54std::vector<dunedaq::trgdataformats::TriggerPrimitive>
55AVXPipeline::generate_tps(const __m256i& tp_mask) {
56 // Mask everything that's relevant.
57 __m256i samples_over_threshold = _mm256_blendv_epi8(_mm256_setzero_si256(), m_samples_over_threshold, tp_mask);
58 __m256i adc_integral_lo = _mm256_blendv_epi8(_mm256_setzero_si256(), m_adc_integral_lo, tp_mask);
59 __m256i adc_integral_hi = _mm256_blendv_epi8(_mm256_setzero_si256(), m_adc_integral_hi, tp_mask);
60 __m256i adc_peak = _mm256_blendv_epi8(_mm256_setzero_si256(), m_adc_peak, tp_mask);
61 __m256i samples_to_peak = _mm256_blendv_epi8(_mm256_setzero_si256(), m_samples_to_peak, tp_mask);
62
63 // Convert to uint16_t.
64 uint16_t tp_sot[16], tp_integral_lo[16], tp_integral_hi[16], tp_adc_peak[16], tp_samples_to_peak[16];
65 _mm256_storeu_si256(reinterpret_cast<__m256i*>(tp_sot), samples_over_threshold);
66 _mm256_storeu_si256(reinterpret_cast<__m256i*>(tp_integral_lo), adc_integral_lo);
67 _mm256_storeu_si256(reinterpret_cast<__m256i*>(tp_integral_hi), adc_integral_hi);
68 _mm256_storeu_si256(reinterpret_cast<__m256i*>(tp_adc_peak), adc_peak);
69 _mm256_storeu_si256(reinterpret_cast<__m256i*>(tp_samples_to_peak), samples_to_peak);
70
71 std::vector<dunedaq::trgdataformats::TriggerPrimitive> tps;
72 for (int i = 0; i < 16; i++) {
73 if (tp_sot[i] < m_sot_minima[m_plane_numbers[i]]) continue; // Don't track short TPs.
75 tp.adc_integral = uint32_t(tp_integral_lo[i]) + (uint32_t(tp_integral_hi[i]) << 16);
76 tp.adc_peak = tp_adc_peak[i];
77 tp.channel = m_channels[i];
78 tp.samples_to_peak = tp_samples_to_peak[i];
79 tp.samples_over_threshold = tp_sot[i];
80
81 // time_start is handled at the next level up, since it is aware of the true and relative times.
82 tps.push_back(tp);
83 }
84
85 // Reset the channels that generated tps.
86 m_samples_over_threshold = _mm256_blendv_epi8(m_samples_over_threshold, _mm256_setzero_si256(), tp_mask);
87 m_adc_integral_lo = _mm256_blendv_epi8(m_adc_integral_lo, _mm256_setzero_si256(), tp_mask);
88 m_adc_integral_hi = _mm256_blendv_epi8(m_adc_integral_hi, _mm256_setzero_si256(), tp_mask);
89 m_adc_peak = _mm256_blendv_epi8(m_adc_peak, _mm256_setzero_si256(), tp_mask);
90 m_samples_to_peak = _mm256_blendv_epi8(m_samples_to_peak, _mm256_setzero_si256(), tp_mask);
91
92 // Finalize.
93 return tps;
94}
95
96} // namespace tpglibs
const __m256i m_ones_register
A vector of 1s.
bool check_for_tps(const __m256i &tp_mask) override
Check a channel mask for any TPs that need to be created.
std::vector< dunedaq::trgdataformats::TriggerPrimitive > generate_tps(const __m256i &tp_mask) override
Finalize the details of the completed TPs and send out.
const __m256i m_max_value_register
A vector of uint16_t max.
__m256i save_state(const __m256i &processed_signal) override
Save the state of the processed signals.
dunedaq::trgdataformats::channel_t m_channels[16]
A single energy deposition on a TPC or PDS channel.