Update to odulow per maintenance bronze
[o-du/phy.git] / fhi_lib / lib / src / xran_bfp_ref.cpp
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 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 [C-code version, no AVX512 optimization]
21  *
22  * @file xran_bfp_ref.cpp
23  * @ingroup group_source_xran
24  * @author Intel Corporation
25  **/
26
27 #include "xran_compression.hpp"
28 #include "xran_bfp_utils.hpp"
29 #include <complex>
30 #include <algorithm>
31 #include <limits.h>
32
33 static int16_t saturateAbs(int16_t inVal)
34 {
35   int16_t result;
36   if (inVal == std::numeric_limits<int16_t>::min())
37   {
38     result = std::numeric_limits<int16_t>::max();
39   }
40   else
41   {
42     result = (int16_t)std::abs(inVal);
43   }
44   return result;
45 }
46
47
48 /// Reference compression
49 void
50 BlockFloatCompander::BFPCompressRef(const ExpandedData& dataIn, CompressedData* dataOut)
51 {
52   int dataOutIdx = 0;
53   int16_t iqMask = (int16_t)((1 << dataIn.iqWidth) - 1);
54   int byteShiftUnits = dataIn.iqWidth - 8;
55
56   for (int rb = 0; rb < dataIn.numBlocks; ++rb)
57   {
58     /// Find max abs value for this RB
59     int16_t maxAbs = 0;
60     for (int re = 0; re < dataIn.numDataElements; ++re)
61     {
62       auto dataIdx = rb * dataIn.numDataElements + re;
63       auto dataAbs = saturateAbs(dataIn.dataExpanded[dataIdx]);
64       maxAbs = std::max(maxAbs, dataAbs);
65     }
66
67     /// Find exponent and insert into byte stream
68     auto thisExp = (uint8_t)(std::max(0,(16 - dataIn.iqWidth + 1 - __lzcnt16(maxAbs))));
69     dataOut->dataCompressed[dataOutIdx++] = thisExp;
70
71     /// ARS data by exponent and pack bytes in Network order
72     /// This uses a sliding buffer where one or more bytes are
73     /// extracted after the insertion of each compressed sample
74     static constexpr int k_byteMask = 0xFF;
75     int byteShiftVal = -8;
76     int byteBuffer = { 0 };
77     for (int re = 0; re < dataIn.numDataElements; ++re)
78     {
79       auto dataIdxIn = rb * dataIn.numDataElements + re;
80       auto thisRE = dataIn.dataExpanded[dataIdxIn] >> thisExp;
81       byteBuffer = (byteBuffer << dataIn.iqWidth) + (int)(thisRE & iqMask);
82
83       byteShiftVal += (8 + byteShiftUnits);
84       while (byteShiftVal >= 0)
85       {
86         auto thisByte = (uint8_t)((byteBuffer >> byteShiftVal) & k_byteMask);
87         dataOut->dataCompressed[dataOutIdx++] = thisByte;
88         byteShiftVal -= 8;
89       }
90     }
91   }
92   dataOut->iqWidth = dataIn.iqWidth;
93   dataOut->numBlocks = dataIn.numBlocks;
94   dataOut->numDataElements = dataIn.numDataElements;
95 }
96
97
98 /// Reference expansion
99 void
100 BlockFloatCompander::BFPExpandRef(const CompressedData& dataIn, ExpandedData* dataOut)
101 {
102   uint32_t iqMask = (uint32_t)(UINT_MAX - ((1 << (32 - dataIn.iqWidth)) - 1));
103   uint32_t byteBuffer = { 0 };
104   int numBytesPerRB = ((dataIn.numDataElements * dataIn.iqWidth) >> 3) + 1;
105   int bitPointer = 0;
106   int dataIdxOut = 0;
107
108   for (int rb = 0; rb < dataIn.numBlocks; ++rb)
109   {
110     auto expIdx = rb * numBytesPerRB;
111     auto signExtShift = 32 - dataIn.iqWidth - dataIn.dataCompressed[expIdx];
112
113     for (int b = 0; b < numBytesPerRB - 1; ++b)
114     {
115       auto dataIdxIn = (expIdx + 1) + b;
116       auto thisByte = (uint16_t)dataIn.dataCompressed[dataIdxIn];
117       byteBuffer = (uint32_t)((byteBuffer << 8) + thisByte);
118       bitPointer += 8;
119       while (bitPointer >= dataIn.iqWidth)
120       {
121         /// byteBuffer currently has enough data in it to extract a sample
122         /// Shift left first to set sign bit at MSB, then shift right to
123         /// sign extend down to iqWidth. Finally recast to int16.
124         int32_t thisSample32 = (int32_t)((byteBuffer << (32 - bitPointer)) & iqMask);
125         int16_t thisSample = (int16_t)(thisSample32 >> signExtShift);
126         bitPointer -= dataIn.iqWidth;
127         dataOut->dataExpanded[dataIdxOut++] = thisSample;
128       }
129     }
130   }
131   dataOut->iqWidth = dataIn.iqWidth;
132   dataOut->numBlocks = dataIn.numBlocks;
133   dataOut->numDataElements = dataIn.numDataElements;
134 }