From e8f94c40b8268a0e07195ed78edf70036eeacd8c Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 4 Nov 2020 17:34:05 +0100 Subject: [PATCH] Added LDPC codeblock segmentation --- lib/include/srslte/phy/fec/cbsegm.h | 102 +++++++++++ lib/include/srslte/phy/fec/ldpc/base_graph.h | 3 + lib/include/srslte/phy/fec/turbo/cbsegm.h | 52 ------ .../srslte/phy/fec/turbo/turbodecoder.h | 2 +- .../srslte/phy/fec/turbo/turbodecoder_gen.h | 2 +- lib/include/srslte/phy/phch/pdsch_cfg.h | 2 +- lib/include/srslte/srslte.h | 2 +- lib/src/phy/fec/CMakeLists.txt | 1 + lib/src/phy/fec/{turbo => }/cbsegm.c | 173 ++++++++++++++---- lib/src/phy/fec/turbo/CMakeLists.txt | 1 - lib/src/phy/fec/turbo/rm_turbo.c | 2 +- lib/src/phy/fec/turbo/tc_interl_lte.c | 2 +- lib/src/phy/fec/turbo/turbocoder.c | 2 +- lib/src/phy/phch/uci.c | 2 +- 14 files changed, 254 insertions(+), 94 deletions(-) create mode 100644 lib/include/srslte/phy/fec/cbsegm.h delete mode 100644 lib/include/srslte/phy/fec/turbo/cbsegm.h rename lib/src/phy/fec/{turbo => }/cbsegm.c (55%) diff --git a/lib/include/srslte/phy/fec/cbsegm.h b/lib/include/srslte/phy/fec/cbsegm.h new file mode 100644 index 000000000..72602b7b8 --- /dev/null +++ b/lib/include/srslte/phy/fec/cbsegm.h @@ -0,0 +1,102 @@ +/* + * Copyright 2013-2020 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#ifndef SRSLTE_CBSEGM_H +#define SRSLTE_CBSEGM_H + +#include +#include + +#include "srslte/config.h" + +#define SRSLTE_NOF_TC_CB_SIZES 188 + +typedef struct SRSLTE_API { + uint32_t F; /*!< \brief %Total number of the transport block bit */ + uint32_t C; /*!< \brief %Total number of code blocks */ + uint32_t K1; /*!< \brief %Code block size 1 */ + uint32_t K2; /*!< \brief %Code block size 2 */ + uint32_t K1_idx; /*!< \brief %Code block size index 1 */ + uint32_t K2_idx; /*!< \brief %Code block size index 2 */ + uint32_t C1; /*!< \brief %Number of code blocks of size 1 */ + uint32_t C2; /*!< \brief %Number of code blocks of size 2 */ + uint32_t tbs; /*!< \brief %Actual transport block size */ +} srslte_cbsegm_t; + +/** + * @brief Calculate code block Segmentation for LTE + * + * @remark Defined as in TS 36.212 V8.8.0 section 5.1.2 Code block segmentation and code block CRC attachment + * + * @param[out] s Output of code block segmentation calculation + * @param[in] tbs Input Transport Block Size in bits. CRC's will be added to this + * @return It returns SRSLTE_SUCCESS if the provided arguments are valid, otherwise it returns SRSLTE_ERROR code + */ +SRSLTE_API int srslte_cbsegm(srslte_cbsegm_t* s, uint32_t tbs); + +/** + * @brief provides interleaver size Table 5.1.3-3 (36.212) index + * + * @remark Defined as in TS 36.212 V8.8.0 Table 5.1.3-3 Turbo code internal interleaver parameters + * + * @return It returns Turbo coder interleaver size if the provided arguments are valid, otherwise it returns + * SRSLTE_ERROR code + */ +SRSLTE_API int srslte_cbsegm_cbsize(uint32_t index); + +/** + * @brief Check is code block size is valid for LTE Turbo Code + * + * @param[in] size Size of code block in bits + * @return true if Code Block size is allowed + */ +SRSLTE_API bool srslte_cbsegm_cbsize_isvalid(uint32_t size); + +/** + * @brief Finds index of minimum K>=long_cb in Table 5.1.3-3 of 36.212 + * + * @return I_TBS or error code + */ +SRSLTE_API int srslte_cbsegm_cbindex(uint32_t long_cb); + +/** + * @brief Calculate code block Segmentation for NR LDPC base graph 1 + * + * @remark Defined as in Section 5.2.2 of 38.212 V15.9.0 + * + * @param[out] s Output of code block segmentation calculation + * @param[in] tbs Input Transport Block Size in bits. CRC's will be added to this + * @return It returns SRSLTE_SUCCESS if the provided arguments are valid, otherwise it returns SRSLTE_ERROR code + */ +SRSLTE_API int srslte_cbsegm_ldpc_bg1(srslte_cbsegm_t* s, uint32_t tbs); + +/** + * @brief Calculate code block Segmentation for NR LDPC base graph 2 + * + * @remark Defined as in Section 5.2.2 of 38.212 V15.9.0 + * + * @param[out] s Output of code block segmentation calculation + * @param[in] tbs Input Transport Block Size in bits. CRC's will be added to this + * @return It returns SRSLTE_SUCCESS if the provided arguments are valid, otherwise it returns SRSLTE_ERROR code + */ +SRSLTE_API int srslte_cbsegm_nr_bg2(srslte_cbsegm_t* s, uint32_t tbs); + +#endif // SRSLTE_CBSEGM_H diff --git a/lib/include/srslte/phy/fec/ldpc/base_graph.h b/lib/include/srslte/phy/fec/ldpc/base_graph.h index a4b78a204..c7c2ab345 100644 --- a/lib/include/srslte/phy/fec/ldpc/base_graph.h +++ b/lib/include/srslte/phy/fec/ldpc/base_graph.h @@ -41,6 +41,9 @@ #include +#define SRSLTE_LDPC_BG1_MAX_LEN_CB 8448 /*!< \brief Maximum code block size for LDPC BG1 */ +#define SRSLTE_LDPC_BG2_MAX_LEN_CB 3840 /*!< \brief Maximum code block size for LDPC BG2 */ + #define BG1Nfull 68 /*!< \brief Number of variable nodes in BG1. */ #define BG1N 66 /*!< \brief Number of variable nodes in BG1 after puncturing. */ #define BG1M 46 /*!< \brief Number of check nodes in BG1. */ diff --git a/lib/include/srslte/phy/fec/turbo/cbsegm.h b/lib/include/srslte/phy/fec/turbo/cbsegm.h deleted file mode 100644 index 21157f414..000000000 --- a/lib/include/srslte/phy/fec/turbo/cbsegm.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2013-2020 Software Radio Systems Limited - * - * This file is part of srsLTE. - * - * srsLTE is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsLTE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#include -#include - -#include "srslte/config.h" - -#ifndef SRSLTE_CBSEGM_H -#define SRSLTE_CBSEGM_H - -#define SRSLTE_NOF_TC_CB_SIZES 188 - -typedef struct SRSLTE_API { - uint32_t F; - uint32_t C; - uint32_t K1; - uint32_t K2; - uint32_t K1_idx; - uint32_t K2_idx; - uint32_t C1; - uint32_t C2; - uint32_t tbs; -} srslte_cbsegm_t; - -SRSLTE_API int srslte_cbsegm(srslte_cbsegm_t* s, uint32_t tbs); - -SRSLTE_API int srslte_cbsegm_cbsize(uint32_t index); - -SRSLTE_API bool srslte_cbsegm_cbsize_isvalid(uint32_t size); - -SRSLTE_API int srslte_cbsegm_cbindex(uint32_t long_cb); - -#endif // SRSLTE_CBSEGM_H diff --git a/lib/include/srslte/phy/fec/turbo/turbodecoder.h b/lib/include/srslte/phy/fec/turbo/turbodecoder.h index 213853868..d1f6f3d1f 100644 --- a/lib/include/srslte/phy/fec/turbo/turbodecoder.h +++ b/lib/include/srslte/phy/fec/turbo/turbodecoder.h @@ -35,7 +35,7 @@ #define SRSLTE_TURBODECODER_H #include "srslte/config.h" -#include "srslte/phy/fec/turbo/cbsegm.h" +#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/turbo/tc_interl.h" #define SRSLTE_TCOD_RATE 3 diff --git a/lib/include/srslte/phy/fec/turbo/turbodecoder_gen.h b/lib/include/srslte/phy/fec/turbo/turbodecoder_gen.h index d5fcfecde..0da818a75 100644 --- a/lib/include/srslte/phy/fec/turbo/turbodecoder_gen.h +++ b/lib/include/srslte/phy/fec/turbo/turbodecoder_gen.h @@ -35,7 +35,7 @@ #define SRSLTE_TURBODECODER_GEN_H #include "srslte/config.h" -#include "srslte/phy/fec/turbo/cbsegm.h" +#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/turbo/tc_interl.h" #define SRSLTE_TCOD_RATE 3 #define SRSLTE_TCOD_TOTALTAIL 12 diff --git a/lib/include/srslte/phy/phch/pdsch_cfg.h b/lib/include/srslte/phy/phch/pdsch_cfg.h index 6fdb4b423..08fb5d2b0 100644 --- a/lib/include/srslte/phy/phch/pdsch_cfg.h +++ b/lib/include/srslte/phy/phch/pdsch_cfg.h @@ -30,8 +30,8 @@ #ifndef SRSLTE_PDSCH_CFG_H #define SRSLTE_PDSCH_CFG_H +#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/softbuffer.h" -#include "srslte/phy/fec/turbo/cbsegm.h" #include "srslte/phy/phch/ra.h" typedef struct SRSLTE_API { diff --git a/lib/include/srslte/srslte.h b/lib/include/srslte/srslte.h index aef12345b..9024cf6f6 100644 --- a/lib/include/srslte/srslte.h +++ b/lib/include/srslte/srslte.h @@ -61,11 +61,11 @@ extern "C" { #include "srslte/phy/dft/dft.h" #include "srslte/phy/dft/dft_precoding.h" #include "srslte/phy/dft/ofdm.h" +#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/convolutional/convcoder.h" #include "srslte/phy/fec/convolutional/rm_conv.h" #include "srslte/phy/fec/convolutional/viterbi.h" #include "srslte/phy/fec/crc.h" -#include "srslte/phy/fec/turbo/cbsegm.h" #include "srslte/phy/fec/turbo/rm_turbo.h" #include "srslte/phy/fec/turbo/tc_interl.h" #include "srslte/phy/fec/turbo/turbocoder.h" diff --git a/lib/src/phy/fec/CMakeLists.txt b/lib/src/phy/fec/CMakeLists.txt index 7a86a2b4d..547fdaba6 100644 --- a/lib/src/phy/fec/CMakeLists.txt +++ b/lib/src/phy/fec/CMakeLists.txt @@ -19,6 +19,7 @@ # set(FEC_SOURCES + cbsegm.c crc.c softbuffer.c) diff --git a/lib/src/phy/fec/turbo/cbsegm.c b/lib/src/phy/fec/cbsegm.c similarity index 55% rename from lib/src/phy/fec/turbo/cbsegm.c rename to lib/src/phy/fec/cbsegm.c index 978c1c38d..2797f56dd 100644 --- a/lib/src/phy/fec/turbo/cbsegm.c +++ b/lib/src/phy/fec/cbsegm.c @@ -19,13 +19,15 @@ * */ -#include -#include - -#include "srslte/phy/fec/turbo/cbsegm.h" +#include "srslte/phy/fec/cbsegm.h" +#include "srslte/phy/fec/ldpc/base_graph.h" #include "srslte/phy/fec/turbo/turbodecoder_gen.h" #include "srslte/phy/utils/debug.h" +#include +/** + * TS 36.212 V8.8.0 Table 5.1.3-3: Turbo code internal interleaver parameters + */ const uint32_t tc_cb_sizes[SRSLTE_NOF_TC_CB_SIZES] = { 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, 240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, @@ -38,13 +40,26 @@ const uint32_t tc_cb_sizes[SRSLTE_NOF_TC_CB_SIZES] = { 3904, 3968, 4032, 4096, 4160, 4224, 4288, 4352, 4416, 4480, 4544, 4608, 4672, 4736, 4800, 4864, 4928, 4992, 5056, 5120, 5184, 5248, 5312, 5376, 5440, 5504, 5568, 5632, 5696, 5760, 5824, 5888, 5952, 6016, 6080, 6144}; +#define CEIL(NUM, DEN) (((NUM) + ((DEN)-1)) / (DEN)) + /** - * Calculate Codeblock Segmentation parameters as in Section 5.1.2 of 36.212 - * - * @param[out] s Output of code block segmentation calculation - * @param[in] tbs Input Transport Block Size in bits. CRC's will be added to this - * @return Error code + * @brief Calculates the number of code blocks and the total size + * @param[in] B Transport block size including TB CRC + * @param[in] Z Maximum transport block size + * @param[out] C Number of code blocks + * @param[out] B_prime Code block size */ +static void cbsegm_cb_size(uint32_t B, uint32_t Z, uint32_t* C, uint32_t* B_prime) +{ + if (B <= Z) { + *C = 1; + *B_prime = B; + } else { + *C = CEIL(B, (Z - 24U)); + *B_prime = B + 24U * (*C); + } +} + int srslte_cbsegm(srslte_cbsegm_t* s, uint32_t tbs) { uint32_t Bp, B, idx1; @@ -57,14 +72,9 @@ int srslte_cbsegm(srslte_cbsegm_t* s, uint32_t tbs) B = tbs + 24; s->tbs = tbs; - /* Calculate CB sizes */ - if (B <= SRSLTE_TCOD_MAX_LEN_CB) { - s->C = 1; - Bp = B; - } else { - s->C = (uint32_t)ceilf((float)B / (SRSLTE_TCOD_MAX_LEN_CB - 24)); - Bp = B + 24 * s->C; - } + // Calculate CB sizes + cbsegm_cb_size(B, SRSLTE_TCOD_MAX_LEN_CB, &s->C, &Bp); + ret = srslte_cbsegm_cbindex((Bp - 1) / s->C + 1); if (ret != SRSLTE_ERROR) { idx1 = (uint32_t)ret; @@ -105,11 +115,6 @@ int srslte_cbsegm(srslte_cbsegm_t* s, uint32_t tbs) return ret; } -/* - * Finds index of minimum K>=long_cb in Table 5.1.3-3 of 36.212 - * - * @return I_TBS or error code - */ int srslte_cbsegm_cbindex(uint32_t long_cb) { int j = 0; @@ -124,11 +129,6 @@ int srslte_cbsegm_cbindex(uint32_t long_cb) } } -/* - * Returns Turbo coder interleaver size for Table 5.1.3-3 (36.212) index - * - * @return Code block size in bits or error code - */ int srslte_cbsegm_cbsize(uint32_t index) { if (index < SRSLTE_NOF_TC_CB_SIZES) { @@ -138,12 +138,6 @@ int srslte_cbsegm_cbsize(uint32_t index) } } -/** - * Check is code block size is valid for LTE Turbo Code - * - * @param[in] size Size of code block in bits - * @return true if Code Block size is allowed - */ bool srslte_cbsegm_cbsize_isvalid(uint32_t size) { for (int i = 0; i < SRSLTE_NOF_TC_CB_SIZES; i++) { @@ -153,3 +147,116 @@ bool srslte_cbsegm_cbsize_isvalid(uint32_t size) } return false; } + +/** + * @brief Selects a lifting size Z_c that satisfies K_b ยท Z_c >= Kp + * @param[in] Kp actual code block size + * @param[in] K_b Some constant + * @param[out] Z_c Lifting size + * @param[out] i_ls Lifting size group index + */ +static int cbsegm_ldpc_select_ls(uint32_t Kp, uint32_t K_b, uint32_t* Z_c, uint8_t* i_ls) +{ + // Early return if the minimum required lift size is too high + if (Kp / K_b > MAX_LIFTSIZE) { + return SRSLTE_ERROR; + } + + // Iterate from the minimum required lift size to the maximum value + for (uint16_t Z = Kp / K_b; Z < MAX_LIFTSIZE; Z++) { + // Get index for a selected lifting size + uint8_t i = get_ls_index(Z); + + // If the lifting index is valid, save outputs and return + if (i != VOID_LIFTSIZE) { + + if (i_ls) { + *i_ls = i; + } + + if (Z_c) { + *Z_c = Z; + } + + return SRSLTE_SUCCESS; + } + + // Otherwise continue... + } + + return SRSLTE_ERROR; +} + +static int srslte_cbsegm_ldpc(srslte_cbsegm_t* s, srslte_basegraph_t bg, uint32_t tbs) +{ + // Check input pointer + if (s == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + // Early return if no TBS is provided + if (tbs == 0) { + bzero(s, sizeof(srslte_cbsegm_t)); + return SRSLTE_SUCCESS; + } + + // Select maximum code block size + uint32_t K_cb = (bg == BG1) ? SRSLTE_LDPC_BG1_MAX_LEN_CB : SRSLTE_LDPC_BG2_MAX_LEN_CB; + + // Calculate CB sizes + uint32_t B = tbs + 24; + uint32_t C = 0; + uint32_t Bp = 0; + cbsegm_cb_size(B, K_cb, &C, &Bp); + + // Calculate the code block size + uint32_t Kp = Bp / C; + uint32_t K_b = 22; + if (bg == BG2) { + if (B > 640) { + K_b = 10; + } else if (B > 560) { + K_b = 9; + } else if (B > 192) { + K_b = 8; + } else { + K_b = 6; + } + } + + // Select lifting size + uint8_t i_ls = 0; + uint32_t Z_c = 0; + int ret = cbsegm_ldpc_select_ls(Kp, K_b, &Z_c, &i_ls); + if (ret < SRSLTE_SUCCESS) { + return SRSLTE_ERROR; + } + uint32_t K = Z_c * ((bg == BG1) ? 22U : 10U); + + // Save segmentation + s->tbs = tbs; + s->C = C; + s->F = K * C; + s->C1 = C; + s->K1 = K; + s->K1_idx = i_ls; + + // Only one CB size is used + s->C2 = 0; + s->K2 = 0; + s->K2_idx = 0; + + INFO("LDPC CB Segmentation: TBS: %d, C=%d, K=%d, F=%d, Bp=%d\n", tbs, s->C, s->K1, s->F, Bp); + + return SRSLTE_SUCCESS; +} + +int srslte_cbsegm_ldpc_bg1(srslte_cbsegm_t* s, uint32_t tbs) +{ + return srslte_cbsegm_ldpc(s, BG1, tbs); +} + +int srslte_cbsegm_ldpc_bg2(srslte_cbsegm_t* s, uint32_t tbs) +{ + return srslte_cbsegm_ldpc(s, BG2, tbs); +} \ No newline at end of file diff --git a/lib/src/phy/fec/turbo/CMakeLists.txt b/lib/src/phy/fec/turbo/CMakeLists.txt index 134dbffdc..d7a50e61f 100644 --- a/lib/src/phy/fec/turbo/CMakeLists.txt +++ b/lib/src/phy/fec/turbo/CMakeLists.txt @@ -19,7 +19,6 @@ # set(FEC_SOURCES ${FEC_SOURCES} - turbo/cbsegm.c turbo/rm_conv.c turbo/rm_turbo.c turbo/tc_interl_lte.c diff --git a/lib/src/phy/fec/turbo/rm_turbo.c b/lib/src/phy/fec/turbo/rm_turbo.c index 848288c68..6bb25a1db 100644 --- a/lib/src/phy/fec/turbo/rm_turbo.c +++ b/lib/src/phy/fec/turbo/rm_turbo.c @@ -26,7 +26,7 @@ #include #include -#include "srslte/phy/fec/turbo/cbsegm.h" +#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/turbo/rm_turbo.h" #include "srslte/phy/utils/bit.h" #include "srslte/phy/utils/debug.h" diff --git a/lib/src/phy/fec/turbo/tc_interl_lte.c b/lib/src/phy/fec/turbo/tc_interl_lte.c index a4975953e..1410430da 100644 --- a/lib/src/phy/fec/turbo/tc_interl_lte.c +++ b/lib/src/phy/fec/turbo/tc_interl_lte.c @@ -24,7 +24,7 @@ #include #include "srslte/phy/common/phy_common.h" -#include "srslte/phy/fec/turbo/cbsegm.h" +#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/turbo/tc_interl.h" #include "srslte/phy/fec/turbo/turbocoder.h" #include "srslte/phy/utils/debug.h" diff --git a/lib/src/phy/fec/turbo/turbocoder.c b/lib/src/phy/fec/turbo/turbocoder.c index 05384f3d7..a5151f398 100644 --- a/lib/src/phy/fec/turbo/turbocoder.c +++ b/lib/src/phy/fec/turbo/turbocoder.c @@ -24,7 +24,7 @@ #include #include -#include "srslte/phy/fec/turbo/cbsegm.h" +#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/turbo/turbocoder.h" #include "srslte/phy/utils/bit.h" #include "srslte/phy/utils/debug.h" diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 8ad19cd33..5263bcfbb 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -29,10 +29,10 @@ #include #include "srslte/phy/common/phy_common.h" +#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/convolutional/convcoder.h" #include "srslte/phy/fec/convolutional/rm_conv.h" #include "srslte/phy/fec/crc.h" -#include "srslte/phy/fec/turbo/cbsegm.h" #include "srslte/phy/phch/uci.h" #include "srslte/phy/utils/bit.h" #include "srslte/phy/utils/debug.h"