Line data Source code
1 : /**
2 : * @file TPGenerator.hpp
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/TPGenerator.hpp"
10 :
11 : namespace tpglibs {
12 :
13 : void
14 3 : TPGenerator::configure(const std::vector<std::pair<std::string, nlohmann::json>>& configs,
15 : const std::vector<std::pair<dunedaq::trgdataformats::channel_t, int16_t>> channel_plane_numbers,
16 : const float sample_tick_difference) {
17 3 : if (m_configured) {
18 0 : reset();
19 : }
20 :
21 3 : m_num_pipelines = channel_plane_numbers.size() / m_num_channels_per_pipeline;
22 3 : m_sample_tick_difference = sample_tick_difference;
23 :
24 15 : for (int p = 0; p < m_num_pipelines; p++) {
25 12 : AVXPipeline new_pipe = AVXPipeline();
26 12 : auto begin_channel_plane = channel_plane_numbers.begin() + p*m_num_channels_per_pipeline;
27 12 : auto end_channel_plane = begin_channel_plane + m_num_channels_per_pipeline;
28 12 : new_pipe.configure(configs, std::vector<std::pair<dunedaq::trgdataformats::channel_t, int16_t>>(begin_channel_plane, end_channel_plane));
29 12 : new_pipe.set_sot_minima(m_sot_minima);
30 12 : m_tpg_pipelines.push_back(new_pipe);
31 12 : }
32 :
33 3 : m_configured = true;
34 3 : }
35 :
36 0 : std::vector<std::pair<std::shared_ptr<AbstractProcessor<__m256i>>, int>> TPGenerator::get_all_processor_references_with_pipeline_index() {
37 0 : std::vector<std::pair<std::shared_ptr<AbstractProcessor<__m256i>>, int>> processor_references;
38 :
39 0 : for (int pipeline_id = 0; pipeline_id < m_num_pipelines; ++pipeline_id) {
40 0 : for (auto& processor : m_tpg_pipelines[pipeline_id].get_all_processor_references()) {
41 0 : processor_references.push_back(std::make_pair(processor, pipeline_id));
42 0 : }
43 : }
44 0 : return processor_references;
45 0 : }
46 :
47 : void
48 2 : TPGenerator::reset() {
49 2 : m_num_pipelines = 0;
50 2 : m_tpg_pipelines.clear();
51 2 : m_sample_tick_difference = 0;
52 2 : m_sot_minima = {1, 1, 1};
53 2 : m_configured = false;
54 2 : }
55 :
56 : void
57 0 : TPGenerator::set_sot_minima(const std::vector<uint16_t>& sot_minima) {
58 0 : m_sot_minima = sot_minima;
59 0 : }
60 :
61 :
62 : __m256i
63 768 : TPGenerator::expand_frame(const __m256i& regi) {
64 : // Refer to the diagram and documentation on frame expansion for details.
65 :
66 : // Prepare even (2,4,6,8), odd (1,3,5,7) rows in 64-bit sense.
67 768 : __m256i odd = _mm256_permutevar8x32_epi32(regi, _mm256_setr_epi32(1, 0, 1, 2, 3, 4, 5, 6));
68 :
69 : // Shift into place.
70 768 : __m256i even = _mm256_sllv_epi64(regi, _mm256_setr_epi64x(6, 14, 22, 30));
71 768 : odd = _mm256_srlv_epi64(odd, _mm256_setr_epi64x(30, 22, 14, 6));
72 :
73 : // Everything is center aligned in 32-bit. Mask and right-align the right side.
74 768 : __m256i both = _mm256_blend_epi32(even, odd, 0b01010101);
75 768 : __m256i right = _mm256_and_si256(_mm256_set1_epi32(0xFFFFu), both);
76 768 : __m256i left = _mm256_and_si256(_mm256_set1_epi32(0x3FFF0000u), both);
77 :
78 768 : right = _mm256_srli_epi32(right, 2);
79 768 : return _mm256_or_si256(left, right);
80 : }
81 :
82 : __m256i
83 0 : TPGenerator::old_expand_frame(const __m256i& regi) {
84 : // Refer to the diagram and documentation on frame expansion for details.
85 :
86 : // Rearrange original with row 3 doubled.
87 0 : __m256i idx = _mm256_set_epi32(6, 5, 4, 3, 3, 2, 1, 0);
88 0 : __m256i shuf1 = _mm256_permutevar8x32_epi32(regi, idx);
89 :
90 : // Left shift each row.
91 0 : __m256i count = _mm256_set_epi32(12, 8, 4, 0, 14, 10, 6, 2);
92 0 : __m256i high_half = _mm256_sllv_epi32(shuf1, count);
93 0 : high_half = _mm256_and_si256(high_half, _mm256_set1_epi32(0x3FFF0000u)); // Mask out the low half.
94 :
95 : // Left shift for low half later.
96 0 : count = _mm256_set_epi32(10, 6, 2, 0, 12, 8, 4, 0);
97 0 : __m256i shift2 = _mm256_sllv_epi32(shuf1, count);
98 :
99 : // Rearrange original and doubled rows 2 and 0.
100 0 : idx = _mm256_set_epi32(5, 4, 3, 2, 2, 1, 0, 0);
101 0 : __m256i shuf2 = _mm256_permutevar8x32_epi32(regi, idx);
102 :
103 : // Right shift each row.
104 0 : count = _mm256_set_epi32(22, 26, 30, 0, 20, 24, 28, 0);
105 0 : __m256i shift3 = _mm256_srlv_epi32(shuf2, count);
106 :
107 : // "Complete" the low half. Still more.
108 0 : __m256i low_half = _mm256_or_si256(shift2, shift3);
109 0 : low_half = _mm256_and_si256(low_half, _mm256_set1_epi32(0x3FFFu)); // Mask out the high half.
110 :
111 : // Combine halves and clear space for an odd entry.
112 0 : __m256i both = _mm256_or_si256(low_half, high_half);
113 0 : both = _mm256_andnot_si256(_mm256_set_epi32(0, 0, 0, 0xFFFFu, 0, 0, 0, 0), both);
114 :
115 : // There is a specific 16-bit entry that needs special handling.
116 : // Align it.
117 0 : __m256i shift4 = _mm256_srli_epi32(regi, 18);
118 : // Mask it.
119 0 : shift4 = _mm256_and_si256(_mm256_set_epi32(0, 0x3FFFu, 0, 0, 0, 0, 0, 0), shift4);
120 :
121 : // Permute into the right spot
122 0 : idx = _mm256_set_epi32(0, 0, 0, 6, 0, 0, 0, 0);
123 0 : __m256i shuf3 = _mm256_permutevar8x32_epi32(shift4, idx);
124 :
125 : // Add it in.
126 0 : both = _mm256_or_si256(both, shuf3);
127 0 : return both;
128 : }
129 :
130 :
131 : } // namespace tpglibs
|