O-RAN E Maintenance Release contribution for ODULOW
[o-du/phy.git] / fhi_lib / lib / src / xran_compression.cpp
1 /******************************************************************************
2 *
3 *   Copyright (c) 2020 Intel.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19 /**
20  * @brief xRAN BFP compression/decompression U-plane implementation and interface functions
21  *
22  * @file xran_compression.cpp
23  * @ingroup group_source_xran
24  * @author Intel Corporation
25  **/
26
27 #include "xran_compression.hpp"
28 #include "xran_compression.h"
29 #include "xran_mod_compression.h"
30 #include "xran_fh_o_du.h"
31 #include <complex>
32 #include <algorithm>
33 #include <immintrin.h>
34 #include <limits.h>
35 #include <cstring>
36
37 using namespace BlockFloatCompander;
38
39 /** callback function type for Symbol packet */
40 typedef void (*xran_bfp_compress_fn)(const BlockFloatCompander::ExpandedData& dataIn,
41                                      BlockFloatCompander::CompressedData* dataOut);
42
43 /** callback function type for Symbol packet */
44 typedef void (*xran_bfp_decompress_fn)(const BlockFloatCompander::CompressedData& dataIn, BlockFloatCompander::ExpandedData* dataOut);
45
46 int32_t
47 xranlib_compress(const struct xranlib_compress_request *request,
48                         struct xranlib_compress_response *response)
49   {
50     if (request->compMethod == XRAN_COMPMETHOD_MODULATION)
51     {
52         struct xranlib_5gnr_mod_compression_request mod_request;
53         struct xranlib_5gnr_mod_compression_response mod_response;
54         mod_request.data_in = request->data_in;
55         mod_request.unit = request->ScaleFactor;
56         mod_request.modulation = (enum xran_modulation_order)(request->iqWidth * 2);
57         mod_request.num_symbols = request->numRBs * XRAN_NUM_OF_SC_PER_RB;
58         mod_request.re_mask = request->reMask;
59         mod_response.data_out = response->data_out;
60         response->len = (request->numRBs * XRAN_NUM_OF_SC_PER_RB * request->iqWidth * 2) >> 3;
61
62         return xranlib_5gnr_mod_compression(&mod_request, &mod_response);
63   }
64     else{
65         if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) {
66             return xranlib_compress_avxsnc(request,response);
67         } else {
68             return xranlib_compress_avx512(request,response);
69     }
70   }
71   }
72
73 int32_t
74 xranlib_decompress(const struct xranlib_decompress_request *request,
75     struct xranlib_decompress_response *response)
76   {
77     if (request->compMethod == XRAN_COMPMETHOD_MODULATION)
78     {
79         struct xranlib_5gnr_mod_decompression_request mod_request;
80         struct xranlib_5gnr_mod_decompression_response mod_response;
81         mod_request.data_in = request->data_in;
82         mod_request.unit = request->ScaleFactor;
83         mod_request.modulation = (enum xran_modulation_order)(request->iqWidth * 2);
84         mod_request.num_symbols = request->numRBs * XRAN_NUM_OF_SC_PER_RB;
85         mod_request.re_mask = request->reMask;
86         mod_response.data_out = response->data_out;
87         response->len = request->numRBs * XRAN_NUM_OF_SC_PER_RB * 4;
88
89         return xranlib_5gnr_mod_decompression(&mod_request, &mod_response);
90       }
91     else{
92         if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) {
93             return xranlib_decompress_avxsnc(request,response);
94         } else {
95             return xranlib_decompress_avx512(request,response);
96     }
97   }
98   }
99
100 int32_t
101 xranlib_compress_bfw(const struct xranlib_compress_request *request,
102                         struct xranlib_compress_response *response)
103     {
104     if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) {
105         return xranlib_compress_avxsnc_bfw(request,response);
106     } else {
107         return xranlib_compress_avx512_bfw(request,response);
108     }
109   }
110
111 int32_t
112 xranlib_decompress_bfw(const struct xranlib_decompress_request *request,
113     struct xranlib_decompress_response *response)
114   {
115     if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) {
116         return xranlib_decompress_avxsnc_bfw(request,response);
117     } else {
118         return xranlib_decompress_avx512_bfw(request,response);
119   }
120 }
121
122 int32_t
123 xranlib_compress_avx512(const struct xranlib_compress_request *request,
124                         struct xranlib_compress_response *response)
125 {
126     BlockFloatCompander::ExpandedData expandedDataInput;
127     BlockFloatCompander::CompressedData compressedDataOut;
128     xran_bfp_compress_fn com_fn = NULL;
129     uint16_t totalRBs = request->numRBs;
130     uint16_t remRBs   = totalRBs;
131     int16_t len = 0;
132     int16_t block_idx_bytes = 0;
133
134     switch (request->iqWidth) {
135         case 8:
136         case 9:
137         case 10:
138         case 12:
139             com_fn = BlockFloatCompander::BFPCompressUserPlaneAvx512;
140             break;
141         default:
142             com_fn = BlockFloatCompander::BFPCompressRef;
143             break;
144     }
145
146     expandedDataInput.iqWidth = request->iqWidth;
147     expandedDataInput.numDataElements =  24;
148
149     while (remRBs){
150         expandedDataInput.dataExpanded   = &request->data_in[block_idx_bytes];
151         compressedDataOut.dataCompressed = (uint8_t*)&response->data_out[len];
152         if(remRBs >= 16){
153             expandedDataInput.numBlocks = 16;
154             com_fn(expandedDataInput, &compressedDataOut);
155             len  += ((3 * expandedDataInput.iqWidth) + 1) * std::min((int16_t)BlockFloatCompander::k_maxNumBlocks,(int16_t)16);
156             block_idx_bytes += 16*expandedDataInput.numDataElements;
157             remRBs -= 16;
158         }else if(remRBs >= 4){
159             expandedDataInput.numBlocks = 4;
160             com_fn(expandedDataInput, &compressedDataOut);
161             len  += ((3 * expandedDataInput.iqWidth) + 1) * std::min((int16_t)BlockFloatCompander::k_maxNumBlocks,(int16_t)4);
162             block_idx_bytes +=4*expandedDataInput.numDataElements;
163             remRBs -=4;
164         }else if (remRBs >= 1){
165             expandedDataInput.numBlocks = 1;
166             com_fn(expandedDataInput, &compressedDataOut);
167             len  += ((3 * expandedDataInput.iqWidth) + 1) * std::min((int16_t)BlockFloatCompander::k_maxNumBlocks,(int16_t)1);
168             block_idx_bytes +=1*expandedDataInput.numDataElements;
169             remRBs = remRBs - 1;
170         }
171     }
172
173     response->len =  ((3 * expandedDataInput.iqWidth) + 1) * totalRBs;
174
175     return 0;
176 }
177
178 int32_t
179 xranlib_decompress_avx512(const struct xranlib_decompress_request *request,
180     struct xranlib_decompress_response *response)
181 {
182     BlockFloatCompander::CompressedData compressedDataInput;
183     BlockFloatCompander::ExpandedData expandedDataOut;
184
185     xran_bfp_decompress_fn decom_fn = NULL;
186     uint16_t totalRBs = request->numRBs;
187     uint16_t remRBs   = totalRBs;
188     int16_t len = 0;
189     int16_t block_idx_bytes = 0;
190
191     switch (request->iqWidth) {
192     case 8:
193     case 9:
194     case 10:
195     case 12:
196         decom_fn = BlockFloatCompander::BFPExpandUserPlaneAvx512;
197         break;
198     default:
199         decom_fn = BlockFloatCompander::BFPExpandRef;
200         break;
201     }
202
203     compressedDataInput.iqWidth         =  request->iqWidth;
204     compressedDataInput.numDataElements =  24;
205
206     while(remRBs) {
207         compressedDataInput.dataCompressed = (uint8_t*)&request->data_in[block_idx_bytes];
208         expandedDataOut.dataExpanded       = &response->data_out[len];
209         if(remRBs >= 16){
210             compressedDataInput.numBlocks = 16;
211             decom_fn(compressedDataInput, &expandedDataOut);
212             len  += 16*compressedDataInput.numDataElements;
213             block_idx_bytes  += ((3 * compressedDataInput.iqWidth) + 1) * std::min((int16_t)BlockFloatCompander::k_maxNumBlocks,(int16_t)16);
214             remRBs -= 16;
215         }else if(remRBs >= 4){
216             compressedDataInput.numBlocks = 4;
217             decom_fn(compressedDataInput, &expandedDataOut);
218             len  += 4*compressedDataInput.numDataElements;
219             block_idx_bytes  += ((3 * compressedDataInput.iqWidth) + 1) * std::min((int16_t)BlockFloatCompander::k_maxNumBlocks,(int16_t)4);
220             remRBs -=4;
221         }else if (remRBs >= 1){
222             compressedDataInput.numBlocks = 1;
223             decom_fn(compressedDataInput, &expandedDataOut);
224             len  += 1*compressedDataInput.numDataElements;
225             block_idx_bytes  += ((3 * compressedDataInput.iqWidth) + 1) * std::min((int16_t)BlockFloatCompander::k_maxNumBlocks,(int16_t)1);
226             remRBs = remRBs - 1;
227         }
228     }
229
230     response->len = totalRBs * compressedDataInput.numDataElements * sizeof(int16_t);
231
232     return 0;
233 }
234
235 int32_t
236 xranlib_compress_avx512_bfw(const struct xranlib_compress_request *request,
237                         struct xranlib_compress_response *response)
238 {
239     BlockFloatCompander::ExpandedData expandedDataInput;
240     BlockFloatCompander::CompressedData compressedDataOut;
241     xran_bfp_compress_fn com_fn = NULL;
242
243     if (request->numRBs != 1){
244         printf("Unsupported numRBs %d\n", request->numRBs);
245         return -1;
246     }
247
248     switch (request->iqWidth) {
249         case 8:
250         case 9:
251         case 10:
252         case 12:
253         switch (request->numDataElements) {
254             case 16:
255                 com_fn = BlockFloatCompander::BFPCompressCtrlPlane8Avx512;
256                 break;
257             case 32:
258                 com_fn = BlockFloatCompander::BFPCompressCtrlPlane16Avx512;
259                 break;
260             case 64:
261                 com_fn = BlockFloatCompander::BFPCompressCtrlPlane32Avx512;
262                 break;
263             case 128:
264                 com_fn = BlockFloatCompander::BFPCompressCtrlPlane64Avx512;
265                 break;
266             case 24:
267             default:
268                 printf("Unsupported numDataElements %d\n", request->numDataElements);
269                 return -1;
270                 break;
271         }
272         break;
273     default:
274         printf("Unsupported iqWidth %d\n", request->iqWidth);
275         return -1;
276         break;
277     }
278
279     expandedDataInput.iqWidth         = request->iqWidth;
280     expandedDataInput.numDataElements = request->numDataElements;
281     expandedDataInput.numBlocks       = 1;
282     expandedDataInput.dataExpanded    = &request->data_in[0];
283     compressedDataOut.dataCompressed  = (uint8_t*)&response->data_out[0];
284
285     com_fn(expandedDataInput, &compressedDataOut);
286
287     response->len =  (((expandedDataInput.numDataElements  * expandedDataInput.iqWidth) >> 3) + 1)
288                             * request->numRBs;
289
290     return 0;
291 }
292
293 int32_t
294 xranlib_decompress_avx512_bfw(const struct xranlib_decompress_request *request,
295                         struct xranlib_decompress_response *response)
296 {
297     BlockFloatCompander::CompressedData compressedDataInput;
298     BlockFloatCompander::ExpandedData expandedDataOut;
299     xran_bfp_decompress_fn decom_fn = NULL;
300
301     if (request->numRBs != 1){
302         printf("Unsupported numRBs %d\n", request->numRBs);
303         return -1;
304     }
305
306     switch (request->iqWidth) {
307         case 8:
308         case 9:
309         case 10:
310         case 12:
311         switch (request->numDataElements) {
312             case 16:
313                 decom_fn = BlockFloatCompander::BFPExpandCtrlPlane8Avx512;
314                 break;
315             case 32:
316                 decom_fn = BlockFloatCompander::BFPExpandCtrlPlane16Avx512;
317                 break;
318             case 64:
319                 decom_fn = BlockFloatCompander::BFPExpandCtrlPlane32Avx512;
320                 break;
321             case 128:
322                 decom_fn = BlockFloatCompander::BFPExpandCtrlPlane64Avx512;
323                 break;
324             case 24:
325             default:
326                 printf("Unsupported numDataElements %d\n", request->numDataElements);
327                 return -1;
328                 break;
329         }
330         break;
331     default:
332         printf("Unsupported iqWidth %d\n", request->iqWidth);
333         return -1;
334         break;
335     }
336
337     compressedDataInput.iqWidth         = request->iqWidth;
338     compressedDataInput.numDataElements = request->numDataElements;
339     compressedDataInput.numBlocks       = 1;
340     compressedDataInput.dataCompressed  = (uint8_t*)&request->data_in[0];
341     expandedDataOut.dataExpanded        = &response->data_out[0];
342
343     decom_fn(compressedDataInput, &expandedDataOut);
344
345     response->len = request->numRBs * compressedDataInput.numDataElements * sizeof(int16_t);
346
347     return 0;
348 }
349