1 /******************************************************************************
3 * Copyright (c) 2019 Intel.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 *******************************************************************************/
20 * @brief xRAN BFP compression/decompression [C-code version, no AVX512 optimization]
22 * @file xran_bfp_ref.cpp
23 * @ingroup group_source_xran
24 * @author Intel Corporation
27 #include "xran_compression.hpp"
28 #include "xran_bfp_utils.hpp"
33 static int16_t saturateAbs(int16_t inVal)
36 if (inVal == std::numeric_limits<int16_t>::min())
38 result = std::numeric_limits<int16_t>::max();
42 result = (int16_t)std::abs(inVal);
48 /// Reference compression
50 BlockFloatCompander::BFPCompressRef(const ExpandedData& dataIn, CompressedData* dataOut)
53 int16_t iqMask = (int16_t)((1 << dataIn.iqWidth) - 1);
54 int byteShiftUnits = dataIn.iqWidth - 8;
56 for (int rb = 0; rb < dataIn.numBlocks; ++rb)
58 /// Find max abs value for this RB
60 for (int re = 0; re < dataIn.numDataElements; ++re)
62 auto dataIdx = rb * dataIn.numDataElements + re;
63 auto dataAbs = saturateAbs(dataIn.dataExpanded[dataIdx]);
64 maxAbs = std::max(maxAbs, dataAbs);
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;
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)
79 auto dataIdxIn = rb * dataIn.numDataElements + re;
80 auto thisRE = dataIn.dataExpanded[dataIdxIn] >> thisExp;
81 byteBuffer = (byteBuffer << dataIn.iqWidth) + (int)(thisRE & iqMask);
83 byteShiftVal += (8 + byteShiftUnits);
84 while (byteShiftVal >= 0)
86 auto thisByte = (uint8_t)((byteBuffer >> byteShiftVal) & k_byteMask);
87 dataOut->dataCompressed[dataOutIdx++] = thisByte;
92 dataOut->iqWidth = dataIn.iqWidth;
93 dataOut->numBlocks = dataIn.numBlocks;
94 dataOut->numDataElements = dataIn.numDataElements;
98 /// Reference expansion
100 BlockFloatCompander::BFPExpandRef(const CompressedData& dataIn, ExpandedData* dataOut)
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;
108 for (int rb = 0; rb < dataIn.numBlocks; ++rb)
110 auto expIdx = rb * numBytesPerRB;
111 auto signExtShift = 32 - dataIn.iqWidth - dataIn.dataCompressed[expIdx];
113 for (int b = 0; b < numBytesPerRB - 1; ++b)
115 auto dataIdxIn = (expIdx + 1) + b;
116 auto thisByte = (uint16_t)dataIn.dataCompressed[dataIdxIn];
117 byteBuffer = (uint32_t)((byteBuffer << 8) + thisByte);
119 while (bitPointer >= dataIn.iqWidth)
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;
131 dataOut->iqWidth = dataIn.iqWidth;
132 dataOut->numBlocks = dataIn.numBlocks;
133 dataOut->numDataElements = dataIn.numDataElements;