X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=blobdiff_plain;f=fhi_lib%2Flib%2Fsrc%2Fxran_bfp_ref.cpp;fp=fhi_lib%2Flib%2Fsrc%2Fxran_bfp_ref.cpp;h=84a6962ff88d48e61d446192531d1f3d3f38c369;hp=0000000000000000000000000000000000000000;hb=70d9d920dd4e575f085f1f1a9050fefd1c10e127;hpb=331df2273a6667941167c9bcc141a517369bdf43 diff --git a/fhi_lib/lib/src/xran_bfp_ref.cpp b/fhi_lib/lib/src/xran_bfp_ref.cpp new file mode 100644 index 0000000..84a6962 --- /dev/null +++ b/fhi_lib/lib/src/xran_bfp_ref.cpp @@ -0,0 +1,134 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +/** + * @brief xRAN BFP compression/decompression [C-code version, no AVX512 optimization] + * + * @file xran_bfp_ref.cpp + * @ingroup group_source_xran + * @author Intel Corporation + **/ + +#include "xran_compression.hpp" +#include "xran_bfp_utils.hpp" +#include +#include +#include + +static int16_t saturateAbs(int16_t inVal) +{ + int16_t result; + if (inVal == std::numeric_limits::min()) + { + result = std::numeric_limits::max(); + } + else + { + result = (int16_t)std::abs(inVal); + } + return result; +} + + +/// Reference compression +void +BlockFloatCompander::BFPCompressRef(const ExpandedData& dataIn, CompressedData* dataOut) +{ + int dataOutIdx = 0; + int16_t iqMask = (int16_t)((1 << dataIn.iqWidth) - 1); + int byteShiftUnits = dataIn.iqWidth - 8; + + for (int rb = 0; rb < dataIn.numBlocks; ++rb) + { + /// Find max abs value for this RB + int16_t maxAbs = 0; + for (int re = 0; re < dataIn.numDataElements; ++re) + { + auto dataIdx = rb * dataIn.numDataElements + re; + auto dataAbs = saturateAbs(dataIn.dataExpanded[dataIdx]); + maxAbs = std::max(maxAbs, dataAbs); + } + + /// Find exponent and insert into byte stream + auto thisExp = (uint8_t)(std::max(0,(16 - dataIn.iqWidth + 1 - __lzcnt16(maxAbs)))); + dataOut->dataCompressed[dataOutIdx++] = thisExp; + + /// ARS data by exponent and pack bytes in Network order + /// This uses a sliding buffer where one or more bytes are + /// extracted after the insertion of each compressed sample + static constexpr int k_byteMask = 0xFF; + int byteShiftVal = -8; + int byteBuffer = { 0 }; + for (int re = 0; re < dataIn.numDataElements; ++re) + { + auto dataIdxIn = rb * dataIn.numDataElements + re; + auto thisRE = dataIn.dataExpanded[dataIdxIn] >> thisExp; + byteBuffer = (byteBuffer << dataIn.iqWidth) + (int)(thisRE & iqMask); + + byteShiftVal += (8 + byteShiftUnits); + while (byteShiftVal >= 0) + { + auto thisByte = (uint8_t)((byteBuffer >> byteShiftVal) & k_byteMask); + dataOut->dataCompressed[dataOutIdx++] = thisByte; + byteShiftVal -= 8; + } + } + } + dataOut->iqWidth = dataIn.iqWidth; + dataOut->numBlocks = dataIn.numBlocks; + dataOut->numDataElements = dataIn.numDataElements; +} + + +/// Reference expansion +void +BlockFloatCompander::BFPExpandRef(const CompressedData& dataIn, ExpandedData* dataOut) +{ + uint32_t iqMask = (uint32_t)(UINT_MAX - ((1 << (32 - dataIn.iqWidth)) - 1)); + uint32_t byteBuffer = { 0 }; + int numBytesPerRB = ((dataIn.numDataElements * dataIn.iqWidth) >> 3) + 1; + int bitPointer = 0; + int dataIdxOut = 0; + + for (int rb = 0; rb < dataIn.numBlocks; ++rb) + { + auto expIdx = rb * numBytesPerRB; + auto signExtShift = 32 - dataIn.iqWidth - dataIn.dataCompressed[expIdx]; + + for (int b = 0; b < numBytesPerRB - 1; ++b) + { + auto dataIdxIn = (expIdx + 1) + b; + auto thisByte = (uint16_t)dataIn.dataCompressed[dataIdxIn]; + byteBuffer = (uint32_t)((byteBuffer << 8) + thisByte); + bitPointer += 8; + while (bitPointer >= dataIn.iqWidth) + { + /// byteBuffer currently has enough data in it to extract a sample + /// Shift left first to set sign bit at MSB, then shift right to + /// sign extend down to iqWidth. Finally recast to int16. + int32_t thisSample32 = (int32_t)((byteBuffer << (32 - bitPointer)) & iqMask); + int16_t thisSample = (int16_t)(thisSample32 >> signExtShift); + bitPointer -= dataIn.iqWidth; + dataOut->dataExpanded[dataIdxOut++] = thisSample; + } + } + } + dataOut->iqWidth = dataIn.iqWidth; + dataOut->numBlocks = dataIn.numBlocks; + dataOut->numDataElements = dataIn.numDataElements; +}