Line data Source code
1 : /**
2 : * @file AVXFrugalPedestalSubtractProcessor.cpp
3 : *
4 : * @copyright This is part of the DUNE DAQ Software Suite, copyright 2020.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 :
9 : #include "tpglibs/AVXFrugalPedestalSubtractProcessor.hpp"
10 :
11 : namespace tpglibs {
12 :
13 15 : REGISTER_AVXPROCESSOR_CREATOR("AVXFrugalPedestalSubtractProcessor", AVXFrugalPedestalSubtractProcessor)
14 :
15 50 : void AVXFrugalPedestalSubtractProcessor::configure(const nlohmann::json& config, const int16_t* /* plane_numbers */) {
16 : // Configure common metric collection parameters
17 : // Register pointers to the ACTUAL member variables, not copies
18 : // Use shared_ptr with no-op deleter to avoid double-free
19 50 : m_internal_state_name_registry.register_internal_state("pedestal",
20 100 : std::shared_ptr<__m256i>(&m_pedestal, [](auto*){}));
21 50 : m_internal_state_name_registry.register_internal_state("accum",
22 100 : std::shared_ptr<__m256i>(&m_accum, [](auto*){}));
23 :
24 50 : configure_internal_state_collection(config);
25 :
26 50 : m_accum_limit = config["accum_limit"];
27 50 : }
28 :
29 650 : __m256i AVXFrugalPedestalSubtractProcessor::process(const __m256i& signal) {
30 : // Update sample counter and write internal states to buffer for harvesting
31 650 : m_samples++;
32 650 : if (m_collect_internal_state_flag && (m_samples % m_sample_period == 0)) {
33 650 : m_internal_state_buffer_manager.write_to_active_buffer();
34 : }
35 :
36 : // Find the channels that are above or below the pedestal.
37 650 : __m256i is_gt = _mm256_cmpgt_epi16(signal, m_pedestal);
38 650 : __m256i is_lt = _mm256_cmpgt_epi16(m_pedestal, signal);
39 :
40 : // Update m_accum.
41 650 : __m256i to_add = _mm256_setzero_si256(); // Assumes equal to pedestal.
42 650 : to_add = _mm256_blendv_epi8(to_add, _mm256_set1_epi16(1), is_gt); // Set the above pedestal case.
43 650 : to_add = _mm256_blendv_epi8(to_add, _mm256_set1_epi16(-1), is_lt); // Set the below pedestal case.
44 :
45 650 : m_accum = _mm256_add_epi16(m_accum, to_add);
46 :
47 : // Check the accum limit condition.
48 650 : is_gt = _mm256_cmpgt_epi16(m_accum, _mm256_set1_epi16(m_accum_limit)); // m_accum > +limit.
49 650 : is_lt = _mm256_cmpgt_epi16(_mm256_set1_epi16(-1*m_accum_limit), m_accum); // m_accum < -limit = -limit > m_accum.
50 :
51 650 : to_add = _mm256_setzero_si256();
52 650 : to_add = _mm256_blendv_epi8(to_add, _mm256_set1_epi16(1), is_gt);
53 650 : to_add = _mm256_blendv_epi8(to_add, _mm256_set1_epi16(-1), is_lt);
54 :
55 : // Update pedestal.
56 650 : m_pedestal = _mm256_adds_epi16(m_pedestal, to_add);
57 :
58 : // Reset too high/low m_accum channels.
59 650 : __m256i need_reset = _mm256_or_si256(is_lt, is_gt);
60 650 : m_accum = _mm256_blendv_epi8(m_accum, _mm256_setzero_si256(), need_reset);
61 :
62 650 : return AVXProcessor::process(_mm256_sub_epi16(signal, m_pedestal));
63 : }
64 :
65 : } // namespace tpglibs
|