Merge remote-tracking branch 'origin/tx-proc-optim' into bler_txoptim

This commit is contained in:
Raymond Knopp
2021-11-01 21:19:23 +01:00
22 changed files with 1752 additions and 473 deletions
+4 -4
View File
@@ -314,9 +314,9 @@ add_definitions("-DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAV
set(commonOpts "-pipe -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic")
set(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=gnu99 -funroll-loops")
"${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=gnu99 -funroll-loops -march=native")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=c++11")
"${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=c++11 -march=native")
# cuda compiler bug (limitation) on complex macro definition
if (CUDA_FOUND)
@@ -332,11 +332,11 @@ endif ()
add_definitions("-DASN_DISABLE_OER_SUPPORT")
#########################
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb3 -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb2 -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}")
#########################
# set a flag for changes in the source code
# these changes are related to hardcoded path to include .h files
set(debugOpt "-ggdb3 -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks")
set(debugOpt "-ggdb2 -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks")
set(CMAKE_C_FLAGS_DEBUG "${debugOpt} -O0")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${debugOpt} -O2")
set(CMAKE_C_FLAGS_RELEASE "-O3")
+5 -5
View File
@@ -387,15 +387,15 @@ void init_gNB_Tpool(int inst) {
LOG_I(PHY,"Number of threads requested in config file: %d, Number of threads available on this machine: %d\n",gNB->pusch_proc_threads,numCPU);
int threadCnt = min(numCPU, gNB->pusch_proc_threads);
if (threadCnt < 2) LOG_E(PHY,"Number of threads for gNB should be more than 1. Allocated only %d\n",threadCnt);
char ul_pool[80];
sprintf(ul_pool,"-1");
char pool[80];
sprintf(pool,"-1");
int s_offset = 0;
for (int icpu=1; icpu<threadCnt; icpu++) {
sprintf(ul_pool+2+s_offset,",-1");
sprintf(pool+2+s_offset,",-1");
s_offset += 3;
}
if (getenv("noThreads")) strcpy(ul_pool, "n");
initTpool(ul_pool, gNB->threadPool, false);
if (getenv("noThreads")) strcpy(pool, "n");
initTpool(pool, gNB->threadPool, false);
// ULSCH decoder result FIFO
gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
initNotifiedFIFO(gNB->respDecode);
+541
View File
@@ -0,0 +1,541 @@
/*******************************************************************************
Copyright (c) 2009-2018, Intel Corporation
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/**
* Header file for module with CRC computation methods
*
* PCLMULQDQ implementation is based on work by:
* Erdinc Ozturk
* Vinodh Gopal
* James Guilford
*
* "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction"
* URL: http://download.intel.com/design/intarch/papers/323102.pdf
*/
#ifndef __CRC_H__
#define __CRC_H__
#include <x86intrin.h>
#include "crcext.h"
#include "types.h"
/**
* PCLMULQDQ CRC computation context structure
*/
struct crc_pclmulqdq_ctx {
/**
* K1 = reminder X^128 / P(X) : 0-63
* K2 = reminder X^192 / P(X) : 64-127
*/
uint64_t k1;
uint64_t k2;
/**
* K3 = reminder X^64 / P(X) : 0-63
* q = quotient X^64 / P(X) : 64-127
*/
uint64_t k3;
uint64_t q;
/**
* p = polynomial / P(X) : 0-63
* res = reserved : 64-127
*/
uint64_t p;
uint64_t res;
};
/**
* Functions and prototypes
*/
/**
* @brief Initializes look-up-table (LUT) for given 8 bit polynomial
*
* @param poly CRC polynomial
* @param lut pointer to look-up-table to be initialized
*/
void crc8_init_lut(const uint8_t poly, uint8_t *lut);
/**
* @brief Calculates 8 bit CRC using LUT method.
*
* @param crc CRC initial value
* @param data pointer to data block to calculate CRC for
* @param data_len size of data block
* @param lut 256x8bits look-up-table pointer
*
* @return New CRC value
*/
__forceinline
uint8_t crc8_calc_lut(const uint8_t *data,
uint32_t data_len,
uint8_t crc,
const uint8_t *lut)
{
if (unlikely(data == NULL || lut == NULL))
return crc;
while (data_len--)
crc = lut[*data++ ^ crc];
return crc;
}
/**
* @brief Initializes look-up-table (LUT) for given 16 bit polynomial
*
* @param poly CRC polynomial
* @param lut pointer to 256x16bits look-up-table to be initialized
*/
void crc16_init_lut(const uint16_t poly, uint16_t *lut);
/**
* @brief Calculates 16 bit CRC using LUT method.
*
* @param crc CRC initial value
* @param data pointer to data block to calculate CRC for
* @param data_len size of data block
* @param lut 256x16bits look-up-table pointer
*
* @return New CRC value
*/
__forceinline
uint16_t crc16_calc_lut(const uint8_t *data,
uint32_t data_len,
uint16_t crc,
const uint16_t *lut)
{
if (unlikely(data == NULL || lut == NULL))
return crc;
while (data_len--)
crc = lut[(crc >> 8) ^ *data++] ^ (crc << 8);
return crc;
}
/**
* @brief Initializes look-up-table (LUT) for given 32 bit polynomial
*
* @param poly CRC polynomial
* @param lut pointer to 256x32bits look-up-table to be initialized
*/
void crc32_init_lut(const uint32_t poly, uint32_t *lut);
/**
* @brief Calculates 32 bit CRC using LUT method.
*
* @param crc CRC initial value
* @param data pointer to data block to calculate CRC for
* @param data_len size of data block
* @param lut 256x32bits look-up-table pointer
*
* @return New CRC value
*/
__forceinline
uint32_t crc32_calc_lut(const uint8_t *data,
uint32_t data_len,
uint32_t crc,
const uint32_t *lut)
{
if (unlikely(data == NULL || lut == NULL))
return crc;
while (data_len--)
crc = lut[(crc >> 24) ^ *data++] ^ (crc << 8);
return crc;
}
/**
* @brief Initializes look up tables for slice-By-2 method.
*
* @param poly CRC polynomial
* @param slice1 slice-by-2 look-up-table 1
* @param slice2 slice-by-2 look-up-table 2
*
* @return New CRC value
*/
void crc16_init_slice2(const uint16_t poly,
uint16_t *slice1,
uint16_t *slice2);
/**
* @brief Calculates 16 bit CRC using Slice-By-2 method.
*
* @param crc CRC initial value
* @param data pointer to data block to calculate CRC for
* @param data_len size of data block
* @param slice1 256x16bits slice look-up-table 1
* @param slice2 256x16bits slice look-up-table 2
*
* @return New CRC value
*/
__forceinline
uint16_t crc16_calc_slice2(const uint8_t *data,
uint32_t data_len,
uint16_t crc,
const uint16_t *slice1,
const uint16_t *slice2)
{
uint_fast32_t i;
if (unlikely(data == NULL))
return crc;
if (unlikely(slice1 == NULL || slice2 == NULL))
return crc;
crc = bswap2(crc);
for (i = (data_len & (~1)), data += (data_len & (~1)); i != 0;
i -= sizeof(uint16_t)) {
crc ^= (*((const uint16_t *)(data - i)));
crc = slice2[(uint8_t)crc] ^ slice1[(uint8_t)(crc >> 8)];
}
crc = bswap2(crc);
if (data_len & 1)
crc = (crc << 8) ^ bswap2(slice1[(crc >> 8) ^ *data]);
return crc;
}
/**
* @brief Initializes look up tables for slice-By-4 method.
*
* @param poly CRC polynomial
* @param slice1 256x32bits slice look-up-table 1
* @param slice2 256x32bits slice look-up-table 2
* @param slice3 256x32bits slice look-up-table 3
* @param slice4 256x32bits slice look-up-table 4
*
* @return New CRC value
*/
void crc32_init_slice4(const uint32_t poly,
uint32_t *slice1, uint32_t *slice2,
uint32_t *slice3, uint32_t *slice4);
/**
* @brief Calculates 32 bit CRC using Slice-By-4 method.
*
* @param data pointer to data block to calculate CRC for
* @param data_len size of data block
* @param crc CRC initial value
* @param slice1 256x32bits slice look-up-table 1
* @param slice2 256x32bits slice look-up-table 2
* @param slice3 256x32bits slice look-up-table 3
* @param slice4 256x32bits slice look-up-table 4
*
* @return New CRC value
*/
__forceinline
uint32_t crc32_calc_slice4(const uint8_t *data,
uint32_t data_len, uint32_t crc,
const uint32_t *slice1, const uint32_t *slice2,
const uint32_t *slice3, const uint32_t *slice4)
{
uint_fast32_t i;
if (unlikely(data == NULL))
return crc;
if (unlikely(slice1 == NULL || slice2 == NULL ||
slice3 == NULL || slice4 == NULL))
return crc;
crc = bswap4(crc);
for (i = data_len & (~3), data += (data_len & (~3)); i != 0;
i -= sizeof(uint32_t)) {
crc ^= (*((const uint32_t *)(data - i)));
crc = slice4[(uint8_t)(crc)] ^
slice3[(uint8_t)(crc >> 8)] ^
slice2[(uint8_t)(crc >> 16)] ^
slice1[(uint8_t)(crc >> 24)];
}
crc = bswap4(crc);
for (i = data_len & 3, data += (data_len & 3); i != 0; i--)
crc = (crc << 8) ^
bswap4(slice1[(crc >> 24) ^ *(data - i)]);
return crc;
}
/**
* @brief Performs one folding round
*
* Logically function operates as follows:
* DATA = READ_NEXT_16BYTES();
* F1 = LSB8(FOLD)
* F2 = MSB8(FOLD)
* T1 = CLMUL( F1, K1 )
* T2 = CLMUL( F2, K2 )
* FOLD = XOR( T1, T2, DATA )
*
* @param data_block 16 byte data block
* @param k1_k2 k1 and k2 constanst enclosed in XMM register
* @param fold running 16 byte folded data
*
* @return New 16 byte folded data
*/
__forceinline
__m128i crc32_folding_round(const __m128i data_block,
const __m128i k1_k2,
const __m128i fold)
{
__m128i tmp = _mm_clmulepi64_si128(fold, k1_k2, 0x11);
return _mm_xor_si128(_mm_clmulepi64_si128(fold, k1_k2, 0x00),
_mm_xor_si128(data_block, tmp));
}
/**
* @brief Performs Barret's reduction from 128 bits to 64 bits
*
* @param data128 128 bits data to be reduced
* @param k3_q k3 and Q constants enclosed in XMM register
*
* @return data reduced to 64 bits
*/
__forceinline
__m128i crc32_reduce_128_to_64(__m128i data128, const __m128i k3_q)
{
__m128i tmp;
tmp = _mm_xor_si128(_mm_clmulepi64_si128(data128, k3_q, 0x01 /* k3 */),
data128);
data128 = _mm_xor_si128(_mm_clmulepi64_si128(tmp, k3_q, 0x01 /* k3 */),
data128);
return _mm_srli_si128(_mm_slli_si128(data128, 8), 8);
}
/**
* @brief Performs Barret's reduction from 64 bits to 32 bits
*
* @param data64 64 bits data to be reduced
* @param k3_q k3 and Q constants enclosed in XMM register
* @param p_res P constant enclosed in XMM register
*
* @return data reduced to 32 bits
*/
__forceinline
uint32_t
crc32_reduce_64_to_32(__m128i fold, const __m128i k3_q, const __m128i p_res)
{
__m128i temp;
temp = _mm_clmulepi64_si128(_mm_srli_si128(fold, 4),
k3_q, 0x10 /* Q */);
temp = _mm_srli_si128(_mm_xor_si128(temp, fold), 4);
temp = _mm_clmulepi64_si128(temp, p_res, 0 /* P */);
return _mm_extract_epi32(_mm_xor_si128(temp, fold), 0);
}
/**
* @brief Calculates 32 bit CRC for given \a data block by applying folding and
* reduction methods.
*
* Algorithm operates on 32 bit CRCs so polynomials and initial values may
* need to be promoted to 32 bits where required.
*
* @param crc initial CRC value (32 bit value)
* @param data pointer to data block
* @param data_len length of \a data block in bytes
* @param params pointer to PCLMULQDQ CRC calculation context
*
* @return CRC for given \a data block (32 bits wide).
*/
__forceinline
uint32_t
crc32_calc_pclmulqdq(const uint8_t *data,
uint32_t data_len, uint32_t crc,
const struct crc_pclmulqdq_ctx *params)
{
__m128i temp, fold, k, swap;
uint32_t n;
if (unlikely(data == NULL || data_len == 0 || params == NULL))
return crc;
#ifdef __KERNEL__
/**
* Preserve FPU context
*/
kernel_fpu_begin();
#endif
/**
* Add 4 bytes to data block size
* This is to secure the following:
* CRC32 = M(X)^32 mod P(X)
* M(X) - message to compute CRC on
* P(X) - CRC polynomial
*/
data_len += 4;
/**
* Load first 16 data bytes in \a fold and
* set \a swap BE<->LE 16 byte conversion variable
*/
fold = _mm_loadu_si128((__m128i *)data);
swap = crc_xmm_be_le_swap128;
/**
* -------------------------------------------------
* Folding all data into single 16 byte data block
* Assumes: \a fold holds first 16 bytes of data
*/
if (unlikely(data_len <= 16)) {
/**
* Data block fits into 16 byte block
* - adjust data block
* - 4 least significant bytes need to be zero
*/
fold = _mm_shuffle_epi8(fold, swap);
fold = _mm_slli_si128(xmm_shift_right(fold, 20 - data_len), 4);
/**
* Apply CRC init value
*/
temp = _mm_insert_epi32(_mm_setzero_si128(), bswap4(crc), 0);
temp = xmm_shift_left(temp, data_len - 4);
fold = _mm_xor_si128(fold, temp);
} else {
/**
* There are 2x16 data blocks or more
*/
__m128i next_data;
/**
* n = number of bytes required to align \a data_len
* to multiple of 16
*/
n = ((~data_len) + 1) & 15;
/**
* Apply CRC initial value and
* get \a fold to BE format
*/
fold = _mm_xor_si128(fold,
_mm_insert_epi32(_mm_setzero_si128(),
crc, 0));
fold = _mm_shuffle_epi8(fold, swap);
/**
* Load next 16 bytes of data and
* adjust \a fold & \a next_data as follows:
*
* CONCAT(fold,next_data) >> (n*8)
*/
next_data = _mm_loadu_si128((__m128i *)&data[16]);
next_data = _mm_shuffle_epi8(next_data, swap);
next_data = _mm_or_si128(xmm_shift_right(next_data, n),
xmm_shift_left(fold, 16 - n));
fold = xmm_shift_right(fold, n);
if (unlikely(data_len <= 32))
/**
* In such unlikely case clear 4 least significant bytes
*/
next_data =
_mm_slli_si128(_mm_srli_si128(next_data, 4), 4);
/**
* Do the initial folding round on 2 first 16 byte chunks
*/
k = _mm_load_si128((__m128i *)(&params->k1));
fold = crc32_folding_round(next_data, k, fold);
if (likely(data_len > 32)) {
/**
* \a data_block needs to be at least 48 bytes long
* in order to get here
*/
__m128i new_data;
/**
* Main folding loop
* - n is adjusted to point to next 16 data block
* to read
* (16+16) = 2x16; represents 2 first data blocks
* processed above
* (- n) is the number of zero bytes padded to
* the message in order to align it to 16 bytes
* - the last 16 bytes is processed separately
*/
for (n = 16 + 16 - n; n < (data_len - 16); n += 16) {
new_data = _mm_loadu_si128((__m128i *)&data[n]);
new_data = _mm_shuffle_epi8(new_data, swap);
fold = crc32_folding_round(new_data, k, fold);
}
/**
* The last folding round works always on 12 bytes
* (12 bytes of data and 4 zero bytes)
* Read from offset -4 is to avoid one
* shift right operation.
*/
new_data = _mm_loadu_si128((__m128i *)&data[n - 4]);
new_data = _mm_shuffle_epi8(new_data, swap);
new_data = _mm_slli_si128(new_data, 4);
fold = crc32_folding_round(new_data, k, fold);
} /* if (data_len > 32) */
}
/**
* -------------------------------------------------
* Reduction 128 -> 32
* Assumes: \a fold holds 128bit folded data
*/
/**
* REDUCTION 128 -> 64
*/
k = _mm_load_si128((__m128i *)(&params->k3));
fold = crc32_reduce_128_to_64(fold, k);
/**
* REDUCTION 64 -> 32
*/
n = crc32_reduce_64_to_32(fold, k,
_mm_load_si128((__m128i *)(&params->p)));
#ifdef __KERNEL__
/**
* - restore FPU context
*/
kernel_fpu_end();
#endif
return n;
}
#endif /* __CRC_H__ */
+57 -7
View File
@@ -30,10 +30,14 @@
Modified in June, 2001, to include the length non multiple of 8
*/
#define USE_INTEL_CRC 1
#include "coding_defs.h"
#include "assertions.h"
#ifdef USE_INTEL_CRC
#include "crc_intel.h"
#include "crc.h"
#endif
/*ref 36-212 v8.6.0 , pp 8-9 */
/* the highest degree is set by default */
@@ -94,6 +98,28 @@ static unsigned short crc11Table[256];
static unsigned char crc8Table[256];
static unsigned char crc6Table[256];
#ifdef USE_INTEL_CRC
static DECLARE_ALIGNED(struct crc_pclmulqdq_ctx lte_crc24a_pclmulqdq, 16) = {
0x64e4d700, /**< k1 */
0x2c8c9d00, /**< k2 */
0xd9fe8c00, /**< k3 */
0xf845fe24, /**< q */
0x864cfb00, /**< p */
0ULL /**< res */
};
__m128i crc_xmm_be_le_swap128;
DECLARE_ALIGNED(const uint8_t crc_xmm_shift_tab[48], 16) = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
#endif
void crcTableInit (void)
{
unsigned char c = 0;
@@ -108,14 +134,20 @@ void crcTableInit (void)
crc8Table[c] = (unsigned char) (crcbit (&c, 1, poly8) >> 24);
crc6Table[c] = (unsigned char) (crcbit (&c, 1, poly6) >> 24);
} while (++c);
#ifdef USE_INTEL_CRC
crc_xmm_be_le_swap128 = _mm_setr_epi32(0x0c0d0e0f, 0x08090a0b,
0x04050607, 0x00010203);
#endif
}
/*********************************************************
Byte by byte implementations,
Byte by byte LUT implementations,
assuming initial byte is 0 padded (in MSB) if necessary
can use SIMD optimized Intel CRC for LTE/NR 24a/24b variants
*********************************************************/
unsigned int crc24a (unsigned char * inptr,
int bitlen)
{
@@ -124,7 +156,7 @@ unsigned int crc24a (unsigned char * inptr,
unsigned int crc = 0;
octetlen = bitlen / 8; /* Change in octets */
resbit = (bitlen % 8);
#ifndef USE_INTEL_CRC
while (octetlen-- > 0) {
// printf("crc24a: in %x => crc %x\n",crc,*inptr);
crc = (crc << 8) ^ crc24aTable[(*inptr++) ^ (crc >> 24)];
@@ -132,18 +164,32 @@ unsigned int crc24a (unsigned char * inptr,
if (resbit > 0)
crc = (crc << resbit) ^ crc24aTable[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))];
return crc;
#else
return crc32_calc_pclmulqdq(inptr, octetlen, 0,
&lte_crc24a_pclmulqdq) >> 8;
#endif
}
#ifdef USE_INTEL_CRC
static DECLARE_ALIGNED(struct crc_pclmulqdq_ctx lte_crc24b_pclmulqdq, 16) = {
0x80140500, /**< k1 */
0x42000100, /**< k2 */
0x90042100, /**< k3 */
0xffff83ff, /**< q */
0x80006300, /**< p */
0ULL /**< res */
};
#endif
unsigned int crc24b (unsigned char * inptr,
int bitlen)
int bitlen)
{
int octetlen, resbit;
unsigned int crc = 0;
octetlen = bitlen / 8; /* Change in octets */
resbit = (bitlen % 8);
#ifndef USE_INTEL_CRC
while (octetlen-- > 0) {
// printf("crc24b: in %x => crc %x (%x)\n",crc,*inptr,crc24bTable[(*inptr) ^ (crc >> 24)]);
crc = (crc << 8) ^ crc24bTable[(*inptr++) ^ (crc >> 24)];
@@ -153,6 +199,10 @@ unsigned int crc24b (unsigned char * inptr,
crc = (crc << resbit) ^ crc24bTable[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))];
return crc;
#else
return crc32_calc_pclmulqdq(inptr, octetlen, 0,
&lte_crc24b_pclmulqdq) >> 8;
#endif
}
unsigned int crc24c (unsigned char * inptr,
+541
View File
@@ -0,0 +1,541 @@
/*******************************************************************************
Copyright (c) 2009-2018, Intel Corporation
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/**
* Header file for module with CRC computation methods
*
* PCLMULQDQ implementation is based on work by:
* Erdinc Ozturk
* Vinodh Gopal
* James Guilford
*
* "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction"
* URL: http://download.intel.com/design/intarch/papers/323102.pdf
*/
#ifndef __CRC_H__
#define __CRC_H__
#include <x86intrin.h>
#include "crcext.h"
#include "types.h"
/**
* PCLMULQDQ CRC computation context structure
*/
struct crc_pclmulqdq_ctx {
/**
* K1 = reminder X^128 / P(X) : 0-63
* K2 = reminder X^192 / P(X) : 64-127
*/
uint64_t k1;
uint64_t k2;
/**
* K3 = reminder X^64 / P(X) : 0-63
* q = quotient X^64 / P(X) : 64-127
*/
uint64_t k3;
uint64_t q;
/**
* p = polynomial / P(X) : 0-63
* res = reserved : 64-127
*/
uint64_t p;
uint64_t res;
};
/**
* Functions and prototypes
*/
/**
* @brief Initializes look-up-table (LUT) for given 8 bit polynomial
*
* @param poly CRC polynomial
* @param lut pointer to look-up-table to be initialized
*/
void crc8_init_lut(const uint8_t poly, uint8_t *lut);
/**
* @brief Calculates 8 bit CRC using LUT method.
*
* @param crc CRC initial value
* @param data pointer to data block to calculate CRC for
* @param data_len size of data block
* @param lut 256x8bits look-up-table pointer
*
* @return New CRC value
*/
__forceinline
uint8_t crc8_calc_lut(const uint8_t *data,
uint32_t data_len,
uint8_t crc,
const uint8_t *lut)
{
if (unlikely(data == NULL || lut == NULL))
return crc;
while (data_len--)
crc = lut[*data++ ^ crc];
return crc;
}
/**
* @brief Initializes look-up-table (LUT) for given 16 bit polynomial
*
* @param poly CRC polynomial
* @param lut pointer to 256x16bits look-up-table to be initialized
*/
void crc16_init_lut(const uint16_t poly, uint16_t *lut);
/**
* @brief Calculates 16 bit CRC using LUT method.
*
* @param crc CRC initial value
* @param data pointer to data block to calculate CRC for
* @param data_len size of data block
* @param lut 256x16bits look-up-table pointer
*
* @return New CRC value
*/
__forceinline
uint16_t crc16_calc_lut(const uint8_t *data,
uint32_t data_len,
uint16_t crc,
const uint16_t *lut)
{
if (unlikely(data == NULL || lut == NULL))
return crc;
while (data_len--)
crc = lut[(crc >> 8) ^ *data++] ^ (crc << 8);
return crc;
}
/**
* @brief Initializes look-up-table (LUT) for given 32 bit polynomial
*
* @param poly CRC polynomial
* @param lut pointer to 256x32bits look-up-table to be initialized
*/
void crc32_init_lut(const uint32_t poly, uint32_t *lut);
/**
* @brief Calculates 32 bit CRC using LUT method.
*
* @param crc CRC initial value
* @param data pointer to data block to calculate CRC for
* @param data_len size of data block
* @param lut 256x32bits look-up-table pointer
*
* @return New CRC value
*/
__forceinline
uint32_t crc32_calc_lut(const uint8_t *data,
uint32_t data_len,
uint32_t crc,
const uint32_t *lut)
{
if (unlikely(data == NULL || lut == NULL))
return crc;
while (data_len--)
crc = lut[(crc >> 24) ^ *data++] ^ (crc << 8);
return crc;
}
/**
* @brief Initializes look up tables for slice-By-2 method.
*
* @param poly CRC polynomial
* @param slice1 slice-by-2 look-up-table 1
* @param slice2 slice-by-2 look-up-table 2
*
* @return New CRC value
*/
void crc16_init_slice2(const uint16_t poly,
uint16_t *slice1,
uint16_t *slice2);
/**
* @brief Calculates 16 bit CRC using Slice-By-2 method.
*
* @param crc CRC initial value
* @param data pointer to data block to calculate CRC for
* @param data_len size of data block
* @param slice1 256x16bits slice look-up-table 1
* @param slice2 256x16bits slice look-up-table 2
*
* @return New CRC value
*/
__forceinline
uint16_t crc16_calc_slice2(const uint8_t *data,
uint32_t data_len,
uint16_t crc,
const uint16_t *slice1,
const uint16_t *slice2)
{
uint_fast32_t i;
if (unlikely(data == NULL))
return crc;
if (unlikely(slice1 == NULL || slice2 == NULL))
return crc;
crc = bswap2(crc);
for (i = (data_len & (~1)), data += (data_len & (~1)); i != 0;
i -= sizeof(uint16_t)) {
crc ^= (*((const uint16_t *)(data - i)));
crc = slice2[(uint8_t)crc] ^ slice1[(uint8_t)(crc >> 8)];
}
crc = bswap2(crc);
if (data_len & 1)
crc = (crc << 8) ^ bswap2(slice1[(crc >> 8) ^ *data]);
return crc;
}
/**
* @brief Initializes look up tables for slice-By-4 method.
*
* @param poly CRC polynomial
* @param slice1 256x32bits slice look-up-table 1
* @param slice2 256x32bits slice look-up-table 2
* @param slice3 256x32bits slice look-up-table 3
* @param slice4 256x32bits slice look-up-table 4
*
* @return New CRC value
*/
void crc32_init_slice4(const uint32_t poly,
uint32_t *slice1, uint32_t *slice2,
uint32_t *slice3, uint32_t *slice4);
/**
* @brief Calculates 32 bit CRC using Slice-By-4 method.
*
* @param data pointer to data block to calculate CRC for
* @param data_len size of data block
* @param crc CRC initial value
* @param slice1 256x32bits slice look-up-table 1
* @param slice2 256x32bits slice look-up-table 2
* @param slice3 256x32bits slice look-up-table 3
* @param slice4 256x32bits slice look-up-table 4
*
* @return New CRC value
*/
__forceinline
uint32_t crc32_calc_slice4(const uint8_t *data,
uint32_t data_len, uint32_t crc,
const uint32_t *slice1, const uint32_t *slice2,
const uint32_t *slice3, const uint32_t *slice4)
{
uint_fast32_t i;
if (unlikely(data == NULL))
return crc;
if (unlikely(slice1 == NULL || slice2 == NULL ||
slice3 == NULL || slice4 == NULL))
return crc;
crc = bswap4(crc);
for (i = data_len & (~3), data += (data_len & (~3)); i != 0;
i -= sizeof(uint32_t)) {
crc ^= (*((const uint32_t *)(data - i)));
crc = slice4[(uint8_t)(crc)] ^
slice3[(uint8_t)(crc >> 8)] ^
slice2[(uint8_t)(crc >> 16)] ^
slice1[(uint8_t)(crc >> 24)];
}
crc = bswap4(crc);
for (i = data_len & 3, data += (data_len & 3); i != 0; i--)
crc = (crc << 8) ^
bswap4(slice1[(crc >> 24) ^ *(data - i)]);
return crc;
}
/**
* @brief Performs one folding round
*
* Logically function operates as follows:
* DATA = READ_NEXT_16BYTES();
* F1 = LSB8(FOLD)
* F2 = MSB8(FOLD)
* T1 = CLMUL( F1, K1 )
* T2 = CLMUL( F2, K2 )
* FOLD = XOR( T1, T2, DATA )
*
* @param data_block 16 byte data block
* @param k1_k2 k1 and k2 constanst enclosed in XMM register
* @param fold running 16 byte folded data
*
* @return New 16 byte folded data
*/
__forceinline
__m128i crc32_folding_round(const __m128i data_block,
const __m128i k1_k2,
const __m128i fold)
{
__m128i tmp = _mm_clmulepi64_si128(fold, k1_k2, 0x11);
return _mm_xor_si128(_mm_clmulepi64_si128(fold, k1_k2, 0x00),
_mm_xor_si128(data_block, tmp));
}
/**
* @brief Performs Barret's reduction from 128 bits to 64 bits
*
* @param data128 128 bits data to be reduced
* @param k3_q k3 and Q constants enclosed in XMM register
*
* @return data reduced to 64 bits
*/
__forceinline
__m128i crc32_reduce_128_to_64(__m128i data128, const __m128i k3_q)
{
__m128i tmp;
tmp = _mm_xor_si128(_mm_clmulepi64_si128(data128, k3_q, 0x01 /* k3 */),
data128);
data128 = _mm_xor_si128(_mm_clmulepi64_si128(tmp, k3_q, 0x01 /* k3 */),
data128);
return _mm_srli_si128(_mm_slli_si128(data128, 8), 8);
}
/**
* @brief Performs Barret's reduction from 64 bits to 32 bits
*
* @param data64 64 bits data to be reduced
* @param k3_q k3 and Q constants enclosed in XMM register
* @param p_res P constant enclosed in XMM register
*
* @return data reduced to 32 bits
*/
__forceinline
uint32_t
crc32_reduce_64_to_32(__m128i fold, const __m128i k3_q, const __m128i p_res)
{
__m128i temp;
temp = _mm_clmulepi64_si128(_mm_srli_si128(fold, 4),
k3_q, 0x10 /* Q */);
temp = _mm_srli_si128(_mm_xor_si128(temp, fold), 4);
temp = _mm_clmulepi64_si128(temp, p_res, 0 /* P */);
return _mm_extract_epi32(_mm_xor_si128(temp, fold), 0);
}
/**
* @brief Calculates 32 bit CRC for given \a data block by applying folding and
* reduction methods.
*
* Algorithm operates on 32 bit CRCs so polynomials and initial values may
* need to be promoted to 32 bits where required.
*
* @param crc initial CRC value (32 bit value)
* @param data pointer to data block
* @param data_len length of \a data block in bytes
* @param params pointer to PCLMULQDQ CRC calculation context
*
* @return CRC for given \a data block (32 bits wide).
*/
__forceinline
uint32_t
crc32_calc_pclmulqdq(const uint8_t *data,
uint32_t data_len, uint32_t crc,
const struct crc_pclmulqdq_ctx *params)
{
__m128i temp, fold, k, swap;
uint32_t n;
if (unlikely(data == NULL || data_len == 0 || params == NULL))
return crc;
#ifdef __KERNEL__
/**
* Preserve FPU context
*/
kernel_fpu_begin();
#endif
/**
* Add 4 bytes to data block size
* This is to secure the following:
* CRC32 = M(X)^32 mod P(X)
* M(X) - message to compute CRC on
* P(X) - CRC polynomial
*/
data_len += 4;
/**
* Load first 16 data bytes in \a fold and
* set \a swap BE<->LE 16 byte conversion variable
*/
fold = _mm_loadu_si128((__m128i *)data);
swap = crc_xmm_be_le_swap128;
/**
* -------------------------------------------------
* Folding all data into single 16 byte data block
* Assumes: \a fold holds first 16 bytes of data
*/
if (unlikely(data_len <= 16)) {
/**
* Data block fits into 16 byte block
* - adjust data block
* - 4 least significant bytes need to be zero
*/
fold = _mm_shuffle_epi8(fold, swap);
fold = _mm_slli_si128(xmm_shift_right(fold, 20 - data_len), 4);
/**
* Apply CRC init value
*/
temp = _mm_insert_epi32(_mm_setzero_si128(), bswap4(crc), 0);
temp = xmm_shift_left(temp, data_len - 4);
fold = _mm_xor_si128(fold, temp);
} else {
/**
* There are 2x16 data blocks or more
*/
__m128i next_data;
/**
* n = number of bytes required to align \a data_len
* to multiple of 16
*/
n = ((~data_len) + 1) & 15;
/**
* Apply CRC initial value and
* get \a fold to BE format
*/
fold = _mm_xor_si128(fold,
_mm_insert_epi32(_mm_setzero_si128(),
crc, 0));
fold = _mm_shuffle_epi8(fold, swap);
/**
* Load next 16 bytes of data and
* adjust \a fold & \a next_data as follows:
*
* CONCAT(fold,next_data) >> (n*8)
*/
next_data = _mm_loadu_si128((__m128i *)&data[16]);
next_data = _mm_shuffle_epi8(next_data, swap);
next_data = _mm_or_si128(xmm_shift_right(next_data, n),
xmm_shift_left(fold, 16 - n));
fold = xmm_shift_right(fold, n);
if (unlikely(data_len <= 32))
/**
* In such unlikely case clear 4 least significant bytes
*/
next_data =
_mm_slli_si128(_mm_srli_si128(next_data, 4), 4);
/**
* Do the initial folding round on 2 first 16 byte chunks
*/
k = _mm_load_si128((__m128i *)(&params->k1));
fold = crc32_folding_round(next_data, k, fold);
if (likely(data_len > 32)) {
/**
* \a data_block needs to be at least 48 bytes long
* in order to get here
*/
__m128i new_data;
/**
* Main folding loop
* - n is adjusted to point to next 16 data block
* to read
* (16+16) = 2x16; represents 2 first data blocks
* processed above
* (- n) is the number of zero bytes padded to
* the message in order to align it to 16 bytes
* - the last 16 bytes is processed separately
*/
for (n = 16 + 16 - n; n < (data_len - 16); n += 16) {
new_data = _mm_loadu_si128((__m128i *)&data[n]);
new_data = _mm_shuffle_epi8(new_data, swap);
fold = crc32_folding_round(new_data, k, fold);
}
/**
* The last folding round works always on 12 bytes
* (12 bytes of data and 4 zero bytes)
* Read from offset -4 is to avoid one
* shift right operation.
*/
new_data = _mm_loadu_si128((__m128i *)&data[n - 4]);
new_data = _mm_shuffle_epi8(new_data, swap);
new_data = _mm_slli_si128(new_data, 4);
fold = crc32_folding_round(new_data, k, fold);
} /* if (data_len > 32) */
}
/**
* -------------------------------------------------
* Reduction 128 -> 32
* Assumes: \a fold holds 128bit folded data
*/
/**
* REDUCTION 128 -> 64
*/
k = _mm_load_si128((__m128i *)(&params->k3));
fold = crc32_reduce_128_to_64(fold, k);
/**
* REDUCTION 64 -> 32
*/
n = crc32_reduce_64_to_32(fold, k,
_mm_load_si128((__m128i *)(&params->p)));
#ifdef __KERNEL__
/**
* - restore FPU context
*/
kernel_fpu_end();
#endif
return n;
}
#endif /* __CRC_H__ */
+89
View File
@@ -0,0 +1,89 @@
/*******************************************************************************
Copyright (c) 2009-2018, Intel Corporation
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/**
* Header file with CRC external definitions
*
*/
#ifndef __CRCEXT_H__
#define __CRCEXT_H__
#include <x86intrin.h>
#include "types.h"
/**
* Flag indicating availability of PCLMULQDQ instruction
* Only valid after running CRCInit() function.
*/
extern int pclmulqdq_available;
/**
* Flag indicating availability of PCLMULQDQ instruction
* Only valid after running CRCInit() function.
*/
extern __m128i crc_xmm_be_le_swap128;
extern const uint8_t crc_xmm_shift_tab[48];
/**
* @brief Shifts right 128 bit register by specified number of bytes
*
* @param reg 128 bit value
* @param num number of bytes to shift right \a reg by (0-16)
*
* @return \a reg >> (\a num * 8)
*/
__forceinline
__m128i xmm_shift_right(__m128i reg, const unsigned int num)
{
const __m128i *p = (const __m128i *)(crc_xmm_shift_tab + 16 + num);
return _mm_shuffle_epi8(reg, _mm_loadu_si128(p));
}
/**
* @brief Shifts left 128 bit register by specified number of bytes
*
* @param reg 128 bit value
* @param num number of bytes to shift left \a reg by (0-16)
*
* @return \a reg << (\a num * 8)
*/
__forceinline
__m128i xmm_shift_left(__m128i reg, const unsigned int num)
{
const __m128i *p = (const __m128i *)(crc_xmm_shift_tab + 16 - num);
return _mm_shuffle_epi8(reg, _mm_loadu_si128(p));
}
/**
* @brief Initializes CRC module.
* @note It is mandatory to run it before using any of CRC API's.
*/
extern void CRCInit(void);
#endif /* __CRCEXT_H__ */
+17 -2
View File
@@ -22,6 +22,7 @@
// encoder interface
#ifndef __NRLDPC_DEFS__H__
#define __NRLDPC_DEFS__H__
#include <openair1/PHY/defs_nr_common.h>
#include "openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
/**
\brief LDPC encoder
@@ -36,13 +37,27 @@
\param 9-12 time_stats_t *tinput,*tprep, *tparity,*toutput
*/
typedef struct {
int n_segments; // optim8seg
unsigned int n_segments; // optim8seg
unsigned int macro_num; // optim8segmulti
unsigned char gen_code; //orig
time_stats_t *tinput;
time_stats_t *tprep;
time_stats_t *tparity;
time_stats_t *toutput;
int Kr;
uint32_t Kb;
uint32_t *Zc;
void *harq;
/// Encoder BG
uint8_t BG;
/// Interleaver outputs
unsigned char *output;
/// Number of bits in "small" code segments
uint32_t K;
/// Number of "Filler" bits
uint32_t F;
/// LDPC-code outputs
uint8_t *d[MAX_NUM_NR_DLSCH_SEGMENTS];
}encoder_implemparams_t;
#define INIT0_LDPCIMPLEMPARAMS {0,0,0,NULL,NULL,NULL,NULL}
typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,short, short, encoder_implemparams_t*);
@@ -56,4 +71,4 @@ typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,sho
\param p_profiler LDPC profiler statistics
*/
typedef int32_t(*nrLDPC_decoderfunc_t)(t_nrLDPC_dec_params* , int8_t*, int8_t* , t_nrLDPC_procBuf* , t_nrLDPC_time_stats* );
#endif
#endif
@@ -73,9 +73,18 @@
static inline void encode_parity_check_part_optim(uint8_t *c,uint8_t *d, short BG,short Zc,short Kb)
static void encode_parity_check_part_optim(uint8_t *cc,uint8_t *d, short BG,short Zc,short Kb, int simd_size, int ncols)
{
unsigned char c[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c
for (int i1=0; i1 < ncols; i1++) {
memcpy(&c[2*i1*Zc], &cc[i1*Zc], Zc*sizeof(unsigned char));
memcpy(&c[(2*i1+1)*Zc], &cc[i1*Zc], Zc*sizeof(unsigned char));
}
for (int i1=1;i1<simd_size;i1++) {
memcpy(&c[(2*ncols*Zc*i1)], &c[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
}
if (BG==1)
{
switch (Zc)
@@ -86,8 +86,6 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size
unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size
unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c
// calculate number of punctured bits
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc;
removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length*rate);
@@ -108,24 +106,10 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) {
// extend matrix
if(impp->tprep != NULL) start_meas(impp->tprep);
for (i1=0; i1 < ncols; i1++)
{
memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
}
for (i1=1;i1<simd_size;i1++) {
memcpy(&c_extension[(2*ncols*Zc*i1)], &c_extension[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
// memset(&c_extension[(2*ncols*Zc*i1)],0,i1);
/*
printf("shift %d: ",i1);
for (int j=0;j<64;j++) printf("%d ",c_extension[(2*ncols*Zc*i1)+j]);
printf("\n");
*/
}
if(impp->tprep != NULL) stop_meas(impp->tprep);
//parity check part
if(impp->tparity != NULL) start_meas(impp->tparity);
encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb);
encode_parity_check_part_optim(c, d, BG, Zc, Kb,simd_size, ncols);
if(impp->tparity != NULL) stop_meas(impp->tparity);
}
else {
@@ -102,7 +102,6 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size
unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size
unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c
// calculate number of punctured bits
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc;
@@ -151,24 +150,10 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) {
// extend matrix
if(impp->tprep != NULL) start_meas(impp->tprep);
for (i1=0; i1 < ncols; i1++)
{
memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
}
for (i1=1;i1<simd_size;i1++) {
memcpy(&c_extension[(2*ncols*Zc*i1)], &c_extension[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
// memset(&c_extension[(2*ncols*Zc*i1)],0,i1);
/*
printf("shift %d: ",i1);
for (int j=0;j<64;j++) printf("%d ",c_extension[(2*ncols*Zc*i1)+j]);
printf("\n");
*/
}
if(impp->tprep != NULL) stop_meas(impp->tprep);
//parity check part
if(impp->tparity != NULL) start_meas(impp->tparity);
encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb);
encode_parity_check_part_optim(c, d, BG, Zc, Kb, simd_size, ncols);
if(impp->tparity != NULL) stop_meas(impp->tparity);
}
else {
@@ -38,18 +38,19 @@
#include "common/utils/LOG/log.h"
#include "PHY/TOOLS/time_meas.h"
#include "openair1/PHY/CODING/nrLDPC_defs.h"
//#define DEBUG_LDPC
#define DEBUG_LDPC
#include "ldpc_encode_parity_check.c"
#include "ldpc_generate_coefficient.c"
int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp)
int nrLDPC_encod(unsigned char **input,unsigned char **output,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp)
{
//set_log(PHY, 4);
short nrows=0,ncols=0;
int i,i1,j,rate=3;
int nrows=0,ncols=0;
int rate=3;
int no_punctured_columns,removed_bit;
//Table of possible lifting sizes
char temp;
@@ -95,8 +96,8 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
}
#ifdef DEBUG_LDPC
LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d, segments %d\n",BG,Zc,Kb,block_length,n_segments);
LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU (seg 0) %x %x %x %x\n",test_input[0][0],test_input[0][1],test_input[0][2],test_input[0][3]);
LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d, segments %d\n",BG,Zc,Kb,block_length,impp->n_segments);
LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU (seg 0) %x %x %x %x\n",input[0][0],input[0][1],input[0][2],input[0][3]);
#endif
AssertFatal(Zc>0,"no valid Zc found for block length %d\n",block_length);
@@ -104,10 +105,8 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
if ((Zc&31) > 0) simd_size = 16;
else simd_size = 32;
unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size
unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size
unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c
unsigned char cc[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size
unsigned char dd[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size
// calculate number of punctured bits
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc;
@@ -115,8 +114,8 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
//printf("%d\n",no_punctured_columns);
//printf("%d\n",removed_bit);
// unpack input
memset(c,0,sizeof(unsigned char) * ncols * Zc);
memset(d,0,sizeof(unsigned char) * nrows * Zc);
memset(cc,0,sizeof(unsigned char) * ncols * Zc);
memset(dd,0,sizeof(unsigned char) * nrows * Zc);
if(impp->tinput != NULL) start_meas(impp->tinput);
#if 0
@@ -124,29 +123,29 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
//for (j=0; j<n_segments; j++) {
for (j=macro_segment; j < macro_segment_end; j++) {
temp = (test_input[j][i/8]&(1<<(i&7)))>>(i&7);
temp = (input[j][i/8]&(1<<(i&7)))>>(i&7);
//printf("c(%d,%d)=%d\n",j,i,temp);
c[i] |= (temp << (j-macro_segment));
}
}
#else
#ifdef __AVX2__
for (i=0; i<block_length>>5; i++) {
c256 = _mm256_and_si256(_mm256_cmpeq_epi8(_mm256_andnot_si256(_mm256_shuffle_epi8(_mm256_set1_epi32(((uint32_t*)test_input[macro_segment])[i]), shufmask),andmask),zero256),masks[0]);
for (int i=0; i<block_length>>5; i++) {
c256 = _mm256_and_si256(_mm256_cmpeq_epi8(_mm256_andnot_si256(_mm256_shuffle_epi8(_mm256_set1_epi32(((uint32_t*)input[macro_segment])[i]), shufmask),andmask),zero256),masks[0]);
//for (j=1; j<n_segments; j++) {
for (j=macro_segment+1; j < macro_segment_end; j++) {
c256 = _mm256_or_si256(_mm256_and_si256(_mm256_cmpeq_epi8(_mm256_andnot_si256(_mm256_shuffle_epi8(_mm256_set1_epi32(((uint32_t*)test_input[j])[i]), shufmask),andmask),zero256),masks[j-macro_segment]),c256);
for (int j=macro_segment+1; j < macro_segment_end; j++) {
c256 = _mm256_or_si256(_mm256_and_si256(_mm256_cmpeq_epi8(_mm256_andnot_si256(_mm256_shuffle_epi8(_mm256_set1_epi32(((uint32_t*)input[j])[i]), shufmask),andmask),zero256),masks[j-macro_segment]),c256);
}
((__m256i *)c)[i] = c256;
((__m256i *)cc)[i] = c256;
}
for (i=(block_length>>5)<<5;i<block_length;i++) {
for (int i=(block_length>>5)<<5;i<block_length;i++) {
//for (j=0; j<n_segments; j++) {
for (j=macro_segment; j < macro_segment_end; j++) {
for (int j=macro_segment; j < macro_segment_end; j++) {
temp = (test_input[j][i/8]&(128>>(i&7)))>>(7-(i&7));
temp = (input[j][i/8]&(128>>(i&7)))>>(7-(i&7));
//printf("c(%d,%d)=%d\n",j,i,temp);
c[i] |= (temp << (j-macro_segment));
cc[i] |= (temp << (j-macro_segment));
}
}
#else
@@ -159,28 +158,14 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) {
// extend matrix
if(impp->tprep != NULL) start_meas(impp->tprep);
for (i1=0; i1 < ncols; i1++)
{
memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
}
for (i1=1;i1<simd_size;i1++) {
memcpy(&c_extension[(2*ncols*Zc*i1)], &c_extension[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
// memset(&c_extension[(2*ncols*Zc*i1)],0,i1);
/*
printf("shift %d: ",i1);
for (int j=0;j<64;j++) printf("%d ",c_extension[(2*ncols*Zc*i1)+j]);
printf("\n");
*/
}
if(impp->tprep != NULL) stop_meas(impp->tprep);
//parity check part
if(impp->tparity != NULL) start_meas(impp->tparity);
encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb);
encode_parity_check_part_optim(cc, dd, BG, Zc, Kb, simd_size, ncols);
if(impp->tparity != NULL) stop_meas(impp->tparity);
}
else {
if (encode_parity_check_part_orig(c, d, BG, Zc, Kb, block_length)!=0) {
if (encode_parity_check_part_orig(cc, dd, BG, Zc, Kb, block_length)!=0) {
printf("Problem with encoder\n");
return(-1);
}
@@ -188,8 +173,8 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
if(impp->toutput != NULL) start_meas(impp->toutput);
// information part and puncture columns
/*
memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char));
memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char));
memcpy(&output[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char));
memcpy(&output[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char));
*/
#ifdef __AVX2__
if ((((2*Zc)&31) == 0) && (((block_length-(2*Zc))&31) == 0)) {
@@ -197,34 +182,34 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
//AssertFatal(((block_length-(2*Zc))&31) == 0,"block_length-(2*Zc) needs to be a multiple of 32 for now\n");
uint32_t l1 = (block_length-(2*Zc))>>5;
uint32_t l2 = ((nrows-no_punctured_columns) * Zc-removed_bit)>>5;
__m256i *c256p = (__m256i *)&c[2*Zc];
__m256i *d256p = (__m256i *)&d[0];
__m256i *c256p = (__m256i *)&cc[2*Zc];
__m256i *d256p = (__m256i *)&dd[0];
// if (((block_length-(2*Zc))&31)>0) l1++;
for (i=0;i<l1;i++)
//for (j=0;j<n_segments;j++) ((__m256i *)channel_input[j])[i] = _mm256_and_si256(_mm256_srai_epi16(c256p[i],j),masks[0]);
for (j=macro_segment; j < macro_segment_end; j++) ((__m256i *)channel_input[j])[i] = _mm256_and_si256(_mm256_srai_epi16(c256p[i],j-macro_segment),masks[0]);
for (int i=0;i<l1;i++)
//for (j=0;j<n_segments;j++) ((__m256i *)output[j])[i] = _mm256_and_si256(_mm256_srai_epi16(c256p[i],j),masks[0]);
for (int j=macro_segment; j < macro_segment_end; j++) ((__m256i *)output[j])[i] = _mm256_and_si256(_mm256_srai_epi16(c256p[i],j-macro_segment),masks[0]);
// if ((((nrows-no_punctured_columns) * Zc-removed_bit)&31)>0) l2++;
for (i1=0;i1<l2;i1++,i++)
//for (j=0;j<n_segments;j++) ((__m256i *)channel_input[j])[i] = _mm256_and_si256(_mm256_srai_epi16(d256p[i1],j),masks[0]);
for (j=macro_segment; j < macro_segment_end; j++) ((__m256i *)channel_input[j])[i] = _mm256_and_si256(_mm256_srai_epi16(d256p[i1],j-macro_segment),masks[0]);
for (int i1=0, i=l1;i1<l2;i1++,i++)
//for (j=0;j<n_segments;j++) ((__m256i *)output[j])[i] = _mm256_and_si256(_mm256_srai_epi16(d256p[i1],j),masks[0]);
for (int j=macro_segment; j < macro_segment_end; j++) ((__m256i *)output[j])[i] = _mm256_and_si256(_mm256_srai_epi16(d256p[i1],j-macro_segment),masks[0]);
}
else {
#ifdef DEBUG_LDPC
LOG_W(PHY,"using non-optimized version\n");
#endif
// do non-SIMD version
for (i=0;i<(block_length-2*Zc);i++)
for (int i=0;i<(block_length-2*Zc);i++)
//for (j=0; j<n_segments; j++)
for (j=macro_segment; j < macro_segment_end; j++)
channel_input[j][i] = (c[2*Zc+i]>>(j-macro_segment))&1;
for (i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++)
for (int j=macro_segment; j < macro_segment_end; j++)
output[j][i] = (cc[2*Zc+i]>>(j-macro_segment))&1;
for (int i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++)
//for (j=0; j<n_segments; j++)
for (j=macro_segment; j < macro_segment_end; j++)
channel_input[j][block_length-2*Zc+i] = (d[i]>>(j-macro_segment))&1;
for (int j=macro_segment; j < macro_segment_end; j++)
output[j][block_length-2*Zc+i] = (dd[i]>>(j-macro_segment))&1;
}
#else
+98
View File
@@ -0,0 +1,98 @@
/*******************************************************************************
Copyright (c) 2009-2018, Intel Corporation
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/* Common data types, macros and functions used across the CRC library */
#ifndef CRC_TYPES_H_
#define CRC_TYPES_H_
#ifdef __KERNEL__
#include <asm/i387.h>
#include <linux/types.h>
typedef uint32_t uint_fast32_t;
typedef uint16_t uint_fast16_t;
typedef uint8_t uint_fast8_t;
#else
#include <stdint.h>
#include <stddef.h>
#endif
/* Declare variable at address aligned to a boundary */
#define DECLARE_ALIGNED(_declaration, _boundary) \
_declaration __attribute__((aligned(_boundary)))
/* Macro to make function to be always inlined */
#ifndef DEBUG
#define __forceinline \
static inline __attribute__((always_inline))
#else
#define __forceinline \
static
#endif
/* Likely & unliekly hints for the compiler */
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
/* Macro to get dimension of an array */
#ifndef DIM
#define DIM(x) (sizeof(x)/sizeof(x[0]))
#endif
/**
* Common functions
*/
/**
* @brief Swaps bytes in 16 bit word
*
* @param val 16 bit data value
*
* @return byte swapped value
*/
__forceinline uint16_t bswap2(const uint16_t val)
{
return (uint16_t) ((val >> 8) | (val << 8));
}
/**
* @brief Swaps bytes in 32 bit word
* ABCD -> DCBA
*
* @param val 32 bit data value
*
* @return byte swapped value
*/
__forceinline uint32_t bswap4(const uint32_t val)
{
return ((val >> 24) | /**< A*/
((val & 0xff0000) >> 8) | /**< B*/
((val & 0xff00) << 8) | /**< C*/
(val << 24)); /**< D*/
}
#endif /* CRC_TYPES_H_ */
+133 -65
View File
@@ -180,9 +180,12 @@ uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
/// CRC, coding, interleaving and rate matching
AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n");
unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS] __attribute__((aligned(32)));
bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
start_meas(dlsch_encoding_stats);
nr_dlsch_encoding(gNB,
harq->pdu, frame, slot, dlsch, frame_parms,tinput,tprep,tparity,toutput,
harq->pdu, frame, slot, dlsch, frame_parms, output,
tinput,tprep,tparity,toutput,
dlsch_rate_matching_stats,
dlsch_interleaving_stats,
dlsch_segmentation_stats);
@@ -197,7 +200,7 @@ uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
printf("\nEncoded payload:\n");
for (int i=0; i<encoded_length>>3; i++) {
for (int j=0; j<8; j++)
printf("%d", harq->f[(i<<3)+j]);
printf("%d", output[(i<<3)+j]);
printf("\t");
}
printf("\n");
@@ -210,7 +213,7 @@ uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
for (int q=0; q<rel15->NrOfCodewords; q++)
memset((void*)scrambled_output[q], 0, (encoded_length>>5)*sizeof(uint32_t));
for (int q=0; q<rel15->NrOfCodewords; q++)
nr_pdsch_codeword_scrambling_optim(harq->f,
nr_pdsch_codeword_scrambling_optim(output,
encoded_length,
q,
rel15->dataScramblingId,
@@ -247,7 +250,7 @@ uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
}
#endif
start_meas(&gNB->dlsch_layer_mapping_stats);
/// Layer mapping
nr_layer_mapping(mod_symbs,
rel15->nrOfLayers,
@@ -265,6 +268,7 @@ uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
}
#endif
stop_meas(&gNB->dlsch_layer_mapping_stats);
/// Resource mapping
// Non interleaved VRB to PRB mapping
@@ -278,7 +282,7 @@ uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n",
start_sc, rel15->StartSymbolIndex, rel15->rbSize, nb_re,rel15->nrOfLayers);
#endif
start_meas(&gNB->dlsch_resource_mapping_stats);
for (int ap=0; ap<rel15->nrOfLayers; ap++) {
// DMRS params for this ap
@@ -320,20 +324,13 @@ uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
dmrs_idx = (rel15->rbStart+rel15->BWPStart)*4;
}
}
}
// Update l_prime in the case of double DMRS config
if ((dmrs_symbol_map & (1 << l))){ //DMRS time occasion
if (l==(l_overline+1)) //take into account the double DMRS symbols
l_prime = 1;
else if (l>(l_overline+1)) {//new DMRS pair
l_overline = l;
l_prime = 0;
}
}
/// DMRS QPSK modulation
if (rel15->dlDmrsSymbPos & (1 << l)) {
/// DMRS QPSK modulation
nr_modulation(pdsch_dmrs[l][0], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
#ifdef DEBUG_DLSCH
@@ -358,69 +355,137 @@ uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
}
}
uint16_t k = start_sc;
// Loop Over SCs:
for (int i=0; i<rel15->rbSize*NR_NB_SC_PER_RB; i++) {
/* check if cuurent RE is PTRS RE*/
is_ptrs_re=0;
/* check for PTRS symbol and set flag for PTRS RE */
if(ptrs_symbol){
is_ptrs_re = is_ptrs_subcarrier(k,
rel15->rnti,
ap,
rel15->dmrsConfigType,
rel15->PTRSFreqDensity,
rel15->rbSize,
rel15->PTRSReOffset,
start_sc,
frame_parms->ofdm_symbol_size);
}
if (ptrs_symbol || dmrs_symbol_map & (1 << l)) {
/* Map DMRS Symbol */
if ( ( dmrs_symbol_map & (1 << l) ) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) {
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15;
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
// Loop Over SCs:
for (int i=0; i<rel15->rbSize*NR_NB_SC_PER_RB; i++) {
/* check if cuurent RE is PTRS RE*/
is_ptrs_re = 0;
if (ptrs_symbol)
is_ptrs_re = is_ptrs_subcarrier(k,
rel15->rnti,
ap,
rel15->dmrsConfigType,
rel15->PTRSFreqDensity,
rel15->rbSize,
rel15->PTRSReOffset,
start_sc,
frame_parms->ofdm_symbol_size);
/* Map DMRS Symbol */
if ( (dmrs_symbol_map & (1 << l)) &&
(k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) {
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15;
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
#ifdef DEBUG_DLSCH_MAPPING
printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n",
dmrs_idx, l, k, k_prime, n, txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n",
dmrs_idx, l, k, k_prime, n, txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
#endif
dmrs_idx++;
k_prime++;
k_prime&=1;
n+=(k_prime)?0:1;
}
/* Map PTRS Symbol */
else if(is_ptrs_re){
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (beta_ptrs*amp*mod_ptrs[ptrs_idx<<1]) >> 15;
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (beta_ptrs*amp*mod_ptrs[(ptrs_idx<<1) + 1])>> 15;
dmrs_idx++;
k_prime++;
k_prime&=1;
n+=(k_prime)?0:1;
}
else if(is_ptrs_re){
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (beta_ptrs*amp*mod_ptrs[ptrs_idx<<1]) >> 15;
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (beta_ptrs*amp*mod_ptrs[(ptrs_idx<<1) + 1])>> 15;
#ifdef DEBUG_DLSCH_MAPPING
printf("ptrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n",
ptrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
printf("ptrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n",
ptrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
#endif
ptrs_idx++;
}
ptrs_idx++;
}
/* Map DATA Symbol */
else if( (!(dmrs_symbol_map & (1 << l))) || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,frame_parms->ofdm_symbol_size,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) {
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15;
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15;
else if( allowed_xlsch_re_in_dmrs_symbol(k,start_sc,frame_parms->ofdm_symbol_size,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) {
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15;
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15;
#ifdef DEBUG_DLSCH_MAPPING
printf("m %d\t l %d \t k %d \t txdataF: %d %d\n",
m, l, k, txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
printf("m %d\t l %d \t k %d \t txdataF: %d %d\n",
m, l, k, txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
#endif
m++;
m++;
}
/* mute RE */
else {
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = 0;
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = 0;
}
if (++k >= frame_parms->ofdm_symbol_size)
k -= frame_parms->ofdm_symbol_size;
} //RE loop
}
else { // no PTRS or DMRS in this symbol
// Loop Over SCs:
int upper_limit=rel15->rbSize*NR_NB_SC_PER_RB;
int remaining_re = 0;
if (start_sc + upper_limit > frame_parms->ofdm_symbol_size) {
remaining_re = upper_limit + start_sc - frame_parms->ofdm_symbol_size;
upper_limit = frame_parms->ofdm_symbol_size - start_sc;
}
if (frame_parms->N_RB_DL&1==0) {
__m128i *txF=(__m128i*)&txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size+start_sc+txdataF_offset)<<1)];
__m128i *txl = (__m128i*)&tx_layers[ap][m<<1];
__m128i amp128=_mm_set1_epi16(amp);
for (int i=0; i<(upper_limit>>2); i++) {
txF[i] = _mm_mulhrs_epi16(amp128,txl[i]);
} //RE loop, first part
m+=upper_limit;
if (remaining_re > 0) {
txF = (__m128i*)&txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size+txdataF_offset)<<1)];
txl = (__m128i*)&tx_layers[ap][m<<1];
for (int i=0; i<(remaining_re>>2); i++) {
txF[i] = _mm_mulhrs_epi16(amp128,txl[i]);
}
}
}
/* mute RE */
else {
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = 0;
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = 0;
}
if (++k >= frame_parms->ofdm_symbol_size)
k -= frame_parms->ofdm_symbol_size;
} //RE loop
__m64 *txF=(__m64*)&txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size+start_sc+txdataF_offset)<<1)];
__m64 *txl = (__m64*)&tx_layers[ap][m<<1];
__m64 amp64=_mm_set1_pi16(amp);
for (int i=0; i<(upper_limit>>1); i++) {
txF[i] = _mm_mulhrs_pi16(amp64,txl[i]);
#ifdef DEBUG_DLSCH_MAPPING
if ((i&1) > 0)
printf("m %d\t l %d \t k %d \t txdataF: %d %d\n",
m, l, start_sc+(i>>1), txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + start_sc+(i>>1))<<1) + (2*txdataF_offset)],
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + start_sc+(i>>1))<<1) + 1 + (2*txdataF_offset)]);
#endif
/* handle this, mute RE */
/*else {
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = 0;
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = 0;
}*/
} //RE loop, first part
m+=upper_limit;
if (remaining_re > 0) {
txF = (__m64*)&txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size+txdataF_offset)<<1)];
txl = (__m64*)&tx_layers[ap][m<<1];
for (int i=0; i<(remaining_re>>1); i++) {
txF[i] = _mm_mulhrs_pi16(amp64,txl[i]);
#ifdef DEBUG_DLSCH_MAPPING
if ((i&1) > 0)
printf("m %d\t l %d \t k %d \t txdataF: %d %d\n",
m, l, i>>1, txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + (i>>1))<<1) + (2*txdataF_offset)],
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + (i>>1))<<1) + 1 + (2*txdataF_offset)]);
#endif
/* handle this, mute RE */
/*else {
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = 0;
txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = 0;
}*/
} //RE loop, second part
} //
m+=remaining_re;
} // N_RB_DL even
} // no DMRS/PTRS in symbol
} // symbol loop
}// layer loop
stop_meas(&gNB->dlsch_resource_mapping_stats);
///Layer Precoding and Antenna port mapping
// tx_layers 1-8 are mapped on antenna ports 1000-1007
@@ -429,7 +494,9 @@ uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
// pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1
// The Precoding matrix:
// The Codebook Type I and Type II are not supported yet.
// We adopt the precoding matrices of PUSCH for 4 layers.
// We`adopt the precoding matrices of PUSCH for 4 layers.
start_meas(&gNB->dlsch_precoding_stats);
for (int ap=0; ap<frame_parms->nb_antennas_tx; ap++) {
for (int l=rel15->StartSymbolIndex; l<rel15->StartSymbolIndex+rel15->NrOfSymbols; l++) {
@@ -504,6 +571,7 @@ uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
} // symbol loop
}// port loop
stop_meas(&gNB->dlsch_precoding_stats);
dlsch->slot_tx[slot]=0;
// TODO: handle precoding
+1
View File
@@ -85,6 +85,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
uint8_t slot,
NR_gNB_DLSCH_t *dlsch,
NR_DL_FRAME_PARMS* frame_parms,
unsigned char * output,
time_stats_t *tinput,
time_stats_t *tprep,
time_stats_t *tparity,
+165 -222
View File
@@ -50,70 +50,47 @@
//#define DEBUG_DLSCH_FREE 1
void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB)
{
void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB) {
int r;
NR_gNB_DLSCH_t *dlsch = *dlschptr;
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated
if (dlsch) {
if (dlsch) {
if (N_RB != 273) {
a_segments = a_segments*N_RB;
a_segments = a_segments/273 +1;
}
#ifdef DEBUG_DLSCH_FREE
LOG_D(PHY,"Freeing dlsch %p\n",dlsch);
#endif
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
if (harq->b) {
free16(harq->b, a_segments * 1056);
harq->b = NULL;
#ifdef DEBUG_DLSCH_FREE
LOG_D(PHY, "Freeing harq->b (%p)\n", harq->b);
#endif
if (harq->e) {
free16(harq->e, 14 * N_RB * 12 * 8);
harq->e = NULL;
}
#ifdef DEBUG_DLSCH_FREE
printf("Freeing dlsch process %d e (%p)\n", i, harq->e);
LOG_D(PHY, "Freeing dlsch process %d c (%p)\n", i, harq->c);
#endif
}
if (harq->f) {
free16(harq->f, 14 * N_RB * 12 * 8);
harq->f = NULL;
for (r = 0; r < a_segments; r++) {
#ifdef DEBUG_DLSCH_FREE
printf("Freeing dlsch process %d f (%p)\n", i, harq->f);
LOG_D(PHY, "Freeing dlsch process %d c[%d] (%p)\n", i, r, harq->c[r]);
#endif
}
#ifdef DEBUG_DLSCH_FREE
LOG_D(PHY, "Freeing dlsch process %d c (%p)\n", i, harq->c);
#endif
for (r = 0; r < a_segments; r++) {
#ifdef DEBUG_DLSCH_FREE
LOG_D(PHY, "Freeing dlsch process %d c[%d] (%p)\n", i, r, harq->c[r]);
#endif
if (harq->c[r]) {
free16(harq->c[r], 1056);
harq->c[r] = NULL;
}
if (harq->d[r]) {
free16(harq->d[r], 3 * 8448);
harq->d[r] = NULL;
}
if (harq->c[r]) {
free16(harq->c[r], 1056);
harq->c[r] = NULL;
}
}
free16(dlsch, sizeof(NR_gNB_DLSCH_t));
*dlschptr = NULL;
}
free16(dlsch, sizeof(NR_gNB_DLSCH_t));
*dlschptr = NULL;
}
NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
@@ -121,8 +98,7 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
unsigned char Mdlharq,
uint32_t Nsoft,
uint8_t abstraction_flag,
uint16_t N_RB)
{
uint16_t N_RB) {
unsigned char i,r,aa,layer;
int re;
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated
@@ -133,10 +109,8 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
}
uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment
NR_gNB_DLSCH_t *dlsch = malloc16(sizeof(NR_gNB_DLSCH_t));
AssertFatal(dlsch, "cannot allocate dlsch\n");
bzero(dlsch,sizeof(NR_gNB_DLSCH_t));
dlsch->Kmimo = Kmimo;
dlsch->Mdlharq = Mdlharq;
@@ -144,11 +118,12 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
dlsch->Nsoft = Nsoft;
for (layer=0; layer<NR_MAX_NB_LAYERS; layer++) {
dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(64*sizeof(int32_t*));
dlsch->ue_spec_bf_weights[layer] = (int32_t **)malloc16(64*sizeof(int32_t *));
for (aa=0; aa<64; aa++) {
dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
for (re=0;re<OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) {
for (re=0; re<OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) {
dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
}
}
@@ -160,7 +135,8 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
for (int q=0; q<NR_MAX_NB_CODEWORDS; q++)
dlsch->mod_symbs[q] = (int32_t *)malloc16(NR_MAX_PDSCH_ENCODED_LENGTH*sizeof(int32_t));
dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(64*sizeof(int32_t*));
dlsch->calib_dl_ch_estimates = (int32_t **)malloc16(64*sizeof(int32_t *));
for (aa=0; aa<64; aa++) {
dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
}
@@ -172,7 +148,6 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
bzero(harq, sizeof(NR_DL_gNB_HARQ_t));
harq->b = malloc16(dlsch_bytes);
AssertFatal(harq->b, "cannot allocate memory for harq->b\n");
harq->pdu = malloc16(dlsch_bytes);
@@ -188,71 +163,33 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
// In section 5.3.2 in 38.212, the for loop is up to N + 2*Zc (maximum size of N is 66*Zc, therefore 68*Zc)
harq->c[r] = malloc16(8448);
AssertFatal(harq->c[r], "cannot allocate harq->c[%d]\n", r);
harq->d[r] = malloc16(68 * 384);
AssertFatal(harq->d[r], "cannot allocate harq->d[%d]\n", r); // max size for coded output
bzero(harq->c[r], 8448);
bzero(harq->d[r], (3 * 8448));
}
harq->e = malloc16(N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
AssertFatal(harq->e, "cannot allocate harq->e\n");
bzero(harq->e, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
harq->f = malloc16(N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
AssertFatal(harq->f, "cannot allocate harq->f\n");
bzero(harq->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
return(dlsch);
}
void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch)
{
unsigned char Mdlharq;
unsigned char i,j,r;
void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch) {
AssertFatal(dlsch!=NULL,"dlsch is null\n");
Mdlharq = dlsch->Mdlharq;
unsigned char Mdlharq = dlsch->Mdlharq;
dlsch->rnti = 0;
dlsch->active = 0;
NR_DL_gNB_HARQ_t *harq=&dlsch->harq_process;
for (i=0; i<10; i++) {
for (int i=0; i<10; i++) {
dlsch->harq_ids[0][i] = Mdlharq;
dlsch->harq_ids[1][i] = Mdlharq;
}
for (i=0; i<Mdlharq; i++) {
for (j=0; j<96; j++)
for (r=0; r<MAX_NUM_NR_DLSCH_SEGMENTS; r++)
if (harq->d[r])
harq->d[r][j] = NR_NULL;
}
}
int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
unsigned char *a,
int frame,
uint8_t slot,
NR_gNB_DLSCH_t *dlsch,
NR_DL_FRAME_PARMS* frame_parms,
time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput,
time_stats_t *dlsch_rate_matching_stats,time_stats_t *dlsch_interleaving_stats,
time_stats_t *dlsch_segmentation_stats)
{
unsigned int G;
unsigned int crc=1;
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
void ldpc8blocks( void *p) {
encoder_implemparams_t *impp=(encoder_implemparams_t *) p;
NR_DL_gNB_HARQ_t *harq = (NR_DL_gNB_HARQ_t *)impp->harq;
uint16_t Kr= impp->K;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
uint8_t mod_order = rel15->qamModOrder[0];
uint16_t nb_rb = rel15->rbSize;
uint8_t nb_symb_sch = rel15->NrOfSymbols;
uint32_t A, Kb, F=0;
uint32_t *Zc = &dlsch->harq_process.Z;
uint8_t mod_order = rel15->qamModOrder[0];
uint16_t Kr=0,r;
uint32_t r_offset=0;
uint32_t E;
uint8_t Ilbrm = 1;
uint32_t Tbslbrm = 950984; //max tbs
uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
uint32_t A = rel15->TBSize[0]<<3;
uint8_t nb_re_dmrs;
if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1)
@@ -260,24 +197,115 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
else
nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData;
uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
uint16_t R=rel15->targetCodeRate[0];
unsigned int G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers);
LOG_D(PHY,"dlsch coding A %d Kr %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n",
A,impp->K,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,(int)mod_order);
// nrLDPC_encoder output is in "d"
// let's make this interface happy!
uint8_t tmp[8][68 * 384]__attribute__((aligned(32)));
for (int rr=impp->macro_num*8, i=0; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++,i++ )
impp->d[rr]=tmp[i];
nrLDPC_encoder(harq->c,impp->d,*impp->Zc, impp->Kb,Kr,impp->BG,impp);
// Compute where to place in output buffer that is concatenation of all segments
uint32_t r_offset=0;
for (int i=0; i < impp->macro_num*8; i++ )
r_offset+=nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, i);
for (int rr=impp->macro_num*8; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++ ) {
if (impp->F>0) {
// writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212
memset(&impp->d[rr][Kr-impp->F-2*(*impp->Zc)], impp->F, NR_NULL);
}
#ifdef DEBUG_DLSCH_CODING
LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]);
#endif
uint32_t E = nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, rr);
//#ifdef DEBUG_DLSCH_CODING
LOG_D(NR_PHY,"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb %d)...\n",
rr,
impp->n_segments,
G,
E,
impp->F,
Kr-impp->F-2*(*impp->Zc),
mod_order,nb_rb);
// for tbslbrm calculation according to 5.4.2.1 of 38.212
uint8_t Nl = 4;
if (rel15->nrOfLayers < Nl)
Nl = rel15->nrOfLayers;
uint32_t Tbslbrm = nr_compute_tbslbrm(rel15->mcsTable[0],nb_rb,Nl);
uint8_t Ilbrm = 1;
uint8_t e[E];
bzero (e, E);
nr_rate_matching_ldpc(Ilbrm,
Tbslbrm,
impp->BG,
*impp->Zc,
impp->d[rr],
e,
impp->n_segments,
impp->F,
Kr-impp->F-2*(*impp->Zc),
rel15->rvIndex[0],
E);
#ifdef DEBUG_DLSCH_CODING
for (int i =0; i<16; i++)
printf("output ratematching e[%d]= %d r_offset %u\n", i,harq->e[i+r_offset], r_offset);
#endif
nr_interleaving_ldpc(E,
mod_order,
e,
impp->output+r_offset);
#ifdef DEBUG_DLSCH_CODING
for (int i =0; i<16; i++)
printf("output interleaving f[%d]= %d r_offset %u\n", i,impp->output[i+r_offset], r_offset);
if (r==impp->n_segments-1)
write_output("enc_output.m","enc",impp->output,G,1,4);
#endif
r_offset += E;
}
}
int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
unsigned char *a,
int frame,
uint8_t slot,
NR_gNB_DLSCH_t *dlsch,
NR_DL_FRAME_PARMS *frame_parms,
unsigned char * output,
time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput,
time_stats_t *dlsch_rate_matching_stats,time_stats_t *dlsch_interleaving_stats,
time_stats_t *dlsch_segmentation_stats) {
encoder_implemparams_t impp;
impp.output=output;
unsigned int crc=1;
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
impp.Zc = &dlsch->harq_process.Z;
float Coderate = 0.0;
uint8_t Nl = 4;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN);
uint32_t A = rel15->TBSize[0]<<3;
A = rel15->TBSize[0]<<3;
if ( dlsch->rnti != SI_RNTI )
trace_NRpdu(DIRECTION_DOWNLINK, a, rel15->TBSize[0], 0, WS_C_RNTI, dlsch->rnti, frame, slot,0, 0);
trace_NRpdu(DIRECTION_DOWNLINK, a, rel15->TBSize[0], 0, WS_C_RNTI, dlsch->rnti, frame, slot,0, 0);
NR_gNB_SCH_STATS_t *stats=NULL;
int first_free=-1;
for (int i=0;i<NUMBER_OF_NR_SCH_STATS_MAX;i++) {
for (int i=0; i<NUMBER_OF_NR_SCH_STATS_MAX; i++) {
if (gNB->dlsch_stats[i].rnti == 0 && first_free == -1) {
first_free = i;
stats=&gNB->dlsch_stats[i];
}
if (gNB->dlsch_stats[i].rnti == dlsch->rnti) {
stats=&gNB->dlsch_stats[i];
break;
@@ -290,179 +318,94 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
stats->current_RI = rel15->nrOfLayers;
stats->current_Qm = rel15->qamModOrder[0];
}
G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers);
LOG_D(PHY,"dlsch coding A %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n",
A,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,(int)mod_order);
if (A > 3824) {
// Add 24-bit crc (polynomial A) to payload
crc = crc24a(a,A)>>8;
a[A>>3] = ((uint8_t*)&crc)[2];
a[1+(A>>3)] = ((uint8_t*)&crc)[1];
a[2+(A>>3)] = ((uint8_t*)&crc)[0];
a[A>>3] = ((uint8_t *)&crc)[2];
a[1+(A>>3)] = ((uint8_t *)&crc)[1];
a[2+(A>>3)] = ((uint8_t *)&crc)[0];
//printf("CRC %x (A %d)\n",crc,A);
//printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]);
harq->B = A+24;
// harq->b = a;
AssertFatal((A / 8) + 4 <= MAX_NR_DLSCH_PAYLOAD_BYTES,
"A %d is too big (A/8+4 = %d > %d)\n",
A,
(A / 8) + 4,
MAX_NR_DLSCH_PAYLOAD_BYTES);
memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes?
}
else {
} else {
// Add 16-bit crc (polynomial A) to payload
crc = crc16(a,A)>>16;
a[A>>3] = ((uint8_t*)&crc)[1];
a[1+(A>>3)] = ((uint8_t*)&crc)[0];
a[A>>3] = ((uint8_t *)&crc)[1];
a[1+(A>>3)] = ((uint8_t *)&crc)[0];
//printf("CRC %x (A %d)\n",crc,A);
//printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]);
harq->B = A+16;
// harq->b = a;
AssertFatal((A / 8) + 3 <= MAX_NR_DLSCH_PAYLOAD_BYTES,
"A %d is too big (A/8+3 = %d > %d)\n",
A,
(A / 8) + 3,
MAX_NR_DLSCH_PAYLOAD_BYTES);
memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc
}
if (R<1000)
Coderate = (float) R /(float) 1024;
if (rel15->targetCodeRate[0]<1000)
Coderate = (float)rel15->targetCodeRate[0] /(float) 1024;
else // to scale for mcs 20 and 26 in table 5.1.3.1-2 which are decimal and input 2* in nr_tbs_tools
Coderate = (float) R /(float) 2048;
Coderate = (float)rel15->targetCodeRate[0] /(float) 2048;
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25)
harq->BG = 2;
impp.BG = 2;
else
harq->BG = 1;
impp.BG = 1;
start_meas(dlsch_segmentation_stats);
Kb = nr_segmentation(harq->b, harq->c, harq->B, &harq->C, &harq->K, Zc, &harq->F, harq->BG);
impp.Kb = nr_segmentation(harq->b, harq->c, harq->B, &impp.n_segments, &impp.K, impp.Zc, &impp.F, impp.BG);
stop_meas(dlsch_segmentation_stats);
F = harq->F;
Kr = harq->K;
#ifdef DEBUG_DLSCH_CODING
uint16_t Kr_bytes;
Kr_bytes = Kr>>3;
#endif
//printf("segment Z %d k %d Kr %d BG %d C %d\n", *Zc,harq->K,Kr,BG,harq->C);
for (r=0; r<harq->C; r++) {
for (int r=0; r<impp.n_segments; r++) {
//d_tmp[r] = &harq->d[r][0];
//channel_input[r] = &harq->d[r][0];
#ifdef DEBUG_DLSCH_CODING
LOG_D(PHY,"Encoder: B %d F %d \n",harq->B, harq->F);
LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,harq->C);
LOG_D(PHY,"Encoder: B %d F %d \n",harq->B, impp->F);
LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,impp.n_segments);
LOG_D(PHY,"input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2],harq->c[r][3], harq->c[r][4]);
for (int cnt =0 ; cnt < 22*(*Zc)/8; cnt ++){
for (int cnt =0 ; cnt < 22*(*Zc)/8; cnt ++) {
LOG_D(PHY,"%d ", harq->c[r][cnt]);
}
LOG_D(PHY,"\n");
LOG_D(PHY,"\n");
#endif
//ldpc_encoder_orig((unsigned char*)harq->c[r],harq->d[r],*Zc,Kb,Kr,BG,0);
//ldpc_encoder_optim((unsigned char*)harq->c[r],(unsigned char*)&harq->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL);
}
encoder_implemparams_t impp;
impp.n_segments=harq->C;
impp.tprep = tprep;
impp.tinput = tinput;
impp.tparity = tparity;
impp.toutput = toutput;
for(int j=0;j<(harq->C/8+1);j++) {
impp.macro_num=j;
nrLDPC_encoder(harq->c,harq->d,*Zc,Kb,Kr,harq->BG,&impp);
impp.harq=harq;
notifiedFIFO_t nf;
initNotifiedFIFO(&nf);
int nbJobs=0;
for(int j=0; j<(impp.n_segments/8+((impp.n_segments&7)==0 ? 0 : 1)); j++) {
notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(impp), j, &nf, ldpc8blocks);
encoder_implemparams_t* perJobImpp=(encoder_implemparams_t*)NotifiedFifoData(req);
*perJobImpp=impp;
perJobImpp->macro_num=j;
pushTpool(gNB->threadPool,req);
nbJobs++;
}
#ifdef DEBUG_DLSCH_CODING
write_output("enc_input0.m","enc_in0",&harq->c[0][0],Kr_bytes,1,4);
write_output("enc_output0.m","enc0",&harq->d[0][0],(3*8*Kr_bytes)+12,1,4);
#endif
F = harq->F;
Kr = harq->K;
for (r=0; r<harq->C; r++) {
if (F>0) {
for (int k=(Kr-F-2*(*Zc)); k<Kr-2*(*Zc); k++) {
// writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212
harq->d[r][k] = NR_NULL;
//if (k<(Kr-F+8))
//printf("r %d filler bits [%d] = %d \n", r,k, harq->d[r][k]);
}
}
#ifdef DEBUG_DLSCH_CODING
LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]);
#endif
E = nr_get_E(G, harq->C, mod_order, rel15->nrOfLayers, r);
//#ifdef DEBUG_DLSCH_CODING
LOG_D(NR_PHY,"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb %d)...\n",
r,
harq->C,
G,
E,
F,
Kr-F-2*(*Zc),
mod_order,nb_rb);
// for tbslbrm calculation according to 5.4.2.1 of 38.212
if (rel15->nrOfLayers < Nl)
Nl = rel15->nrOfLayers;
Tbslbrm = nr_compute_tbslbrm(rel15->mcsTable[0],nb_rb,Nl);
start_meas(dlsch_rate_matching_stats);
nr_rate_matching_ldpc(Ilbrm,
Tbslbrm,
harq->BG,
*Zc,
harq->d[r],
harq->e+r_offset,
harq->C,
F,
Kr-F-2*(*Zc),
rel15->rvIndex[0],
E);
stop_meas(dlsch_rate_matching_stats);
#ifdef DEBUG_DLSCH_CODING
for (int i =0; i<16; i++)
printf("output ratematching e[%d]= %d r_offset %u\n", i,harq->e[i+r_offset], r_offset);
#endif
start_meas(dlsch_interleaving_stats);
nr_interleaving_ldpc(E,
mod_order,
harq->e+r_offset,
harq->f+r_offset);
stop_meas(dlsch_interleaving_stats);
#ifdef DEBUG_DLSCH_CODING
for (int i =0; i<16; i++)
printf("output interleaving f[%d]= %d r_offset %u\n", i,harq->f[i+r_offset], r_offset);
if (r==harq->C-1)
write_output("enc_output.m","enc",harq->f,G,1,4);
#endif
r_offset += E;
while(nbJobs) {
notifiedFIFO_elt_t *req=pullTpool(&nf, gNB->threadPool);
delNotifiedFIFO_elt(req);
nbJobs--;
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return 0;
}
+1 -1
View File
@@ -368,7 +368,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
xrtmag_next = temp;
}
av_corr/=nr_sequences/l;
//av_corr/=nr_sequences/l;
int xrtmag_dBtimes10 = 10*(int)dB_fixed64(xrtmag/(12*l));
int xrtmag_next_dBtimes10 = 10*(int)dB_fixed64(xrtmag_next/(12*l));
@@ -389,7 +389,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
printf("[AbsSFN %u.%d] Slot%d Symbol %d type %d: Pilot/Data extraction %5.2f \n",
frame,nr_slot_rx,slot,symbol,type,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#else
LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d type %d: Pilot/Data extraction %5.2f \n",
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d type %d: Pilot/Data extraction %5.2f \n",
frame,nr_slot_rx,slot,symbol,type,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#endif
@@ -411,7 +411,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
#if DISABLE_LOG_X
printf("[AbsSFN %u.%d] Slot%d Symbol %d: Channel Scale %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#else
LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Scale %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Scale %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#endif
start_meas(&ue->generic_stat_bis[proc->thread_id][slot]);
if (first_symbol_flag==1) {
@@ -472,7 +472,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
#if DISABLE_LOG_X
printf("[AbsSFN %u.%d] Slot%d Symbol %d first_symbol_flag %d: Channel Level %5.2f \n",frame,nr_slot_rx,slot,symbol,first_symbol_flag,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#else
LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d first_symbol_flag %d: Channel Level %5.2f \n",frame,nr_slot_rx,slot,symbol,first_symbol_flag,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d first_symbol_flag %d: Channel Level %5.2f \n",frame,nr_slot_rx,slot,symbol,first_symbol_flag,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#endif
start_meas(&ue->generic_stat_bis[proc->thread_id][slot]);
@@ -524,7 +524,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
#if DISABLE_LOG_X
printf("[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n", frame, nr_slot_rx, slot, symbol, pdsch_vars[gNB_id]->log2_maxh, proc->channel_level, ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#else
LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n", frame, nr_slot_rx, slot, symbol, pdsch_vars[gNB_id]->log2_maxh, proc->channel_level, ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n", frame, nr_slot_rx, slot, symbol, pdsch_vars[gNB_id]->log2_maxh, proc->channel_level, ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#endif
start_meas(&ue->generic_stat_bis[proc->thread_id][slot]);
@@ -583,7 +583,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
#if DISABLE_LOG_X
printf("[AbsSFN %u.%d] Slot%d Symbol %d: Channel Combine %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#else
LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Combine %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Combine %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#endif
start_meas(&ue->generic_stat_bis[proc->thread_id][slot]);
/* Store the valid DL RE's */
@@ -666,7 +666,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
#if DISABLE_LOG_X
printf("[AbsSFN %u.%d] Slot%d Symbol %d: LLR Computation %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#else
LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: LLR Computation %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: LLR Computation %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0));
#endif
// Please keep it: useful for debugging
+3 -14
View File
@@ -96,20 +96,6 @@ typedef struct {
uint32_t subframe;
/// MIMO mode for this DLSCH
MIMO_mode_t mimo_mode;
/// Concatenated sequences
uint8_t *e;
/// LDPC-code outputs
uint8_t *d[MAX_NUM_NR_DLSCH_SEGMENTS];
/// Interleaver outputs
uint8_t *f;
/// Number of code segments
uint32_t C;
/// Number of bits in "small" code segments
uint32_t K;
/// Number of "Filler" bits
uint32_t F;
/// Encoder BG
uint8_t BG;
/// LDPC lifting size
uint32_t Z;
} NR_DL_gNB_HARQ_t;
@@ -868,6 +854,9 @@ typedef struct PHY_VARS_gNB_s {
time_stats_t dlsch_encoding_stats;
time_stats_t dlsch_modulation_stats;
time_stats_t dlsch_scrambling_stats;
time_stats_t dlsch_resource_mapping_stats;
time_stats_t dlsch_layer_mapping_stats;
time_stats_t dlsch_precoding_stats;
time_stats_t tinput;
time_stats_t tprep;
time_stats_t tparity;
+2 -40
View File
@@ -843,11 +843,7 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
} else AssertFatal(1==0,"Not RA_PDSCH, SI_PDSCH or PDSCH\n");
stop_meas(&ue->dlsch_llr_stats_parallelization[proc->thread_id][slot]);
#if PHYSIM
printf("[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",frame_rx,nr_slot_rx,m,ue->dlsch_llr_stats_parallelization[proc->thread_id][slot].p_time/(cpuf*1000.0));
#else
LOG_D(PHY, "[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",frame_rx,nr_slot_rx,m,ue->dlsch_llr_stats_parallelization[proc->thread_id][slot].p_time/(cpuf*1000.0));
#endif
if(first_symbol_flag) {
proc->first_symbol_available = 1;
@@ -1041,17 +1037,10 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]);
#if PHYSIM
printf(" --> Unscrambling for CW0 %5.3f\n",
(ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
printf("AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n",
frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
#else
LOG_I(PHY, " --> Unscrambling for CW0 %5.3f\n",
LOG_D(PHY, " --> Unscrambling for CW0 %5.3f\n",
(ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
LOG_I(PHY, "AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n",
LOG_D(PHY, "AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n",
frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
#endif
if(is_cw1_active) {
// start ldpc decode for CW 1
@@ -1117,17 +1106,10 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]);
#if PHYSIM
printf(" --> Unscrambling for CW1 %5.3f\n",
(ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
printf("AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
#else
LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n",
(ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
#endif
LOG_D(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
@@ -1438,11 +1420,7 @@ void *UE_thread_slot1_dl_processing(void *arg) {
stop_meas(&ue->ue_front_end_per_slot_stat[proc->thread_id][1]);
#if PHYSIM
printf("[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,nr_slot_rx,ue->ue_front_end_per_slot_stat[proc->thread_id][1].p_time/(cpuf*1000.0));
#else
LOG_D(PHY, "[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,nr_slot_rx,ue->ue_front_end_per_slot_stat[proc->thread_id][1].p_time/(cpuf*1000.0));
#endif
//wait until pdcch is decoded
@@ -1532,11 +1510,7 @@ void *UE_thread_slot1_dl_processing(void *arg) {
//printf("Set available LLR slot1 to 1 AbsSubframe %d.%d \n",frame_rx,nr_slot_rx);
stop_meas(&ue->pdsch_procedures_per_slot_stat[proc->thread_id][1]);
#if PHYSIM
printf("[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,nr_slot_rx,ue->pdsch_procedures_per_slot_stat[proc->thread_id][1].p_time/(cpuf*1000.0));
#else
LOG_D(PHY, "[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,nr_slot_rx,ue->pdsch_procedures_per_slot_stat[proc->thread_id][1].p_time/(cpuf*1000.0));
#endif
if (pthread_mutex_lock(&proc->mutex_slot1_dl_processing) != 0) {
LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
@@ -1906,13 +1880,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
dlsch_parallel);
stop_meas(&ue->dlsch_procedures_stat[proc->thread_id]);
#if PHYSIM
printf("[SFN %d] Slot1: Pdsch Proc %5.2f\n",nr_slot_rx,ue->pdsch_procedures_stat[proc->thread_id].p_time/(cpuf*1000.0));
printf("[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",nr_slot_rx,ue->dlsch_procedures_stat[proc->thread_id].p_time/(cpuf*1000.0));
#else
LOG_D(PHY, "[SFN %d] Slot1: Pdsch Proc %5.2f\n",nr_slot_rx,ue->pdsch_procedures_stat[proc->thread_id].p_time/(cpuf*1000.0));
LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",nr_slot_rx,ue->dlsch_procedures_stat[proc->thread_id].p_time/(cpuf*1000.0));
#endif
@@ -1989,9 +1958,6 @@ if (nr_slot_rx==9) {
}
stop_meas(&ue->generic_stat);
#if PHYSIM
printf("after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0));
#endif
#ifdef EMOS
phy_procedures_emos_UE_RX(ue,slot,gNB_id);
@@ -2001,11 +1967,7 @@ phy_procedures_emos_UE_RX(ue,slot,gNB_id);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
stop_meas(&ue->phy_proc_rx[proc->thread_id]);
#if PHYSIM
printf("------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_slot_rx,ue->phy_proc_rx[proc->thread_id].p_time/(cpuf*1000.0));
#else
LOG_D(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_slot_rx,ue->phy_proc_rx[proc->thread_id].p_time/(cpuf*1000.0));
#endif
//#endif //pdsch
+7 -3
View File
@@ -503,8 +503,10 @@ int main(int argc, char **argv)
//printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32));
// generate signal
unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS] __attribute__((aligned(32)));
bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
if (input_fd == NULL) {
nr_dlsch_encoding(gNB, test_input, frame, slot, dlsch, frame_parms,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
nr_dlsch_encoding(gNB, test_input, frame, slot, dlsch, frame_parms,output,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
}
for (SNR = snr0; SNR < snr1; SNR += snr_step) {
@@ -521,11 +523,12 @@ int main(int argc, char **argv)
//if (i<16)
// printf("encoder output f[%d] = %d\n",i,dlsch->harq_processes[0]->f[i]);
/*
if (dlsch->harq_process.f[i] == 0)
modulated_input[i] = 1.0; ///sqrt(2); //QPSK
else
modulated_input[i] = -1.0; ///sqrt(2);
*/
//if (i<16) printf("modulated_input[%d] = %d\n",i,modulated_input[i]);
//SNR =10;
SNR_lin = pow(10, SNR / 10.0);
@@ -548,9 +551,10 @@ int main(int argc, char **argv)
channel_output_uncoded[i] = 1; //QPSK demod
else
channel_output_uncoded[i] = 0;
/*
if (channel_output_uncoded[i] != dlsch->harq_process.f[i])
errors_bit_uncoded = errors_bit_uncoded + 1;
*/
}
//if (errors_bit_uncoded>10)
+28 -13
View File
@@ -369,6 +369,7 @@ int main(int argc, char **argv)
uint8_t n_tx=1,n_rx=1;
uint8_t round;
uint8_t num_rounds = 4;
char gNBthreads[128]="n";
channel_desc_t *gNB2UE;
//uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0;
@@ -430,9 +431,7 @@ int main(int argc, char **argv)
FILE *scg_fd=NULL;
while ((c = getopt (argc, argv, "f:hA:pf:g:in:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:D:e:m:w:T:U:q")) != -1) {
while ((c = getopt (argc, argv, "f:hA:pf:g:in:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:d:e:m:w:T:U:qX:")) != -1) {
switch (c) {
case 'f':
scg_fd = fopen(optarg,"r");
@@ -635,7 +634,12 @@ int main(int argc, char **argv)
dmrs_arg[i] = atoi(argv[optind++]);
}
break;
case 'X':
strncpy(gNBthreads, optarg, sizeof(gNBthreads));
gNBthreads[sizeof(gNBthreads)-1]=0;
break;
default:
case 'h':
printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n",
@@ -671,7 +675,8 @@ int main(int argc, char **argv)
printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:2} DMRS ConfType{1:2}, e.g. -U 3 0 2 1 \n");
printf("-P Print DLSCH performances\n");
printf("-w Write txdata to binary file (one frame)\n");
printf("-D number of dlsch threads, 0: no dlsch parallelization\n");
printf("-d number of dlsch threads, 0: no dlsch parallelization\n");
printf("-X gNB thread pool configuration, n => no threads");
exit (-1);
break;
}
@@ -827,6 +832,14 @@ int main(int argc, char **argv)
fs = 61.44e6;
bw = 40e6;
}
else if (mu == 1 && N_RB_DL == 133) {
fs = 61.44e6;
bw = 50e6;
}
else if (mu == 1 && N_RB_DL == 162) {
fs = 61.44e6;
bw = 60e6;
}
else if (mu == 3 && N_RB_DL == 66) {
fs = 122.88e6;
bw = 100e6;
@@ -966,8 +979,7 @@ int main(int argc, char **argv)
snrRun = 0;
gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
char tp_param[] = "n";
initTpool(tp_param, gNB->threadPool, true);
initTpool(gNBthreads, gNB->threadPool, true);
gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
initNotifiedFIFO(gNB->resp_L1_tx);
// we create 2 threads for L1 tx processing
@@ -1221,8 +1233,8 @@ int main(int argc, char **argv)
UE->dlsch[UE_proc.thread_id][0][0]->max_ldpc_iterations+1)
n_errors++;
NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE_proc.thread_id];
int16_t *UE_llr = pdsch_vars[0]->llr[0];
//NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE_proc.thread_id];
//int16_t *UE_llr = pdsch_vars[0]->llr[0];
TBS = UE_harq_process->TBS;//rel15->TBSize[0];
uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
@@ -1237,6 +1249,7 @@ int main(int argc, char **argv)
printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2) );
}
/*
for (i = 0; i < available_bits; i++) {
if(((gNB_dlsch->harq_process.f[i] == 0) && (UE_llr[i] <= 0)) ||
@@ -1250,6 +1263,7 @@ int main(int argc, char **argv)
}
}
*/
for (i = 0; i < TBS; i++) {
estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7);
@@ -1293,11 +1307,9 @@ int main(int argc, char **argv)
printf("\n");
if (print_perf==1) {
printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n",
printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d)\n",
1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex,
msgDataTx->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
msgDataTx->dlsch[0][0]->harq_process.K,
msgDataTx->dlsch[0][0]->harq_process.K/((msgDataTx->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
msgDataTx->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3);
printDistribution(gNB->phy_proc_tx_0,table_tx,"PHY proc tx");
printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time");
printStatIndent3(&gNB->dlsch_segmentation_stats,"DLSCH segmentation time");
@@ -1309,6 +1321,9 @@ int main(int argc, char **argv)
printStatIndent3(&gNB->dlsch_interleaving_stats, "DLSCH Interleaving time");
printStatIndent2(&gNB->dlsch_modulation_stats,"DLSCH modulation time");
printStatIndent2(&gNB->dlsch_scrambling_stats, "DLSCH scrambling time");
printStatIndent2(&gNB->dlsch_layer_mapping_stats, "DLSCH Layer Mapping time");
printStatIndent2(&gNB->dlsch_resource_mapping_stats, "DLSCH Resource Mapping time");
printStatIndent2(&gNB->dlsch_precoding_stats,"DLSCH Layer Precoding time");
printf("\nUE RX function statistics (per %d us slot)\n",1000>>*scc->ssbSubcarrierSpacing);
+1 -1
View File
@@ -64,7 +64,7 @@ void *nrmac_stats_thread(void *arg) {
fseek(fd,0,SEEK_SET);
}
fclose(fd);
return (void *)0;
return NULL;
}
void clear_mac_stats(gNB_MAC_INST *gNB) {