Initial NR-UCI encoder

This commit is contained in:
Xavier Arteaga 2021-01-12 10:24:52 +01:00 committed by Xavier Arteaga
parent 9ccc36d4fa
commit d100919561
4 changed files with 653 additions and 0 deletions

View File

@ -0,0 +1,49 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_PUCCH_NR_H
#define SRSLTE_PUCCH_NR_H
#include "srslte/config.h"
#include <stdbool.h>
#include <stdint.h>
typedef enum SRSLTE_API {
SRSLTE_PUCCH_NR_FORMAT_0 = 0,
SRSLTE_PUCCH_NR_FORMAT_1,
SRSLTE_PUCCH_NR_FORMAT_2,
SRSLTE_PUCCH_NR_FORMAT_3,
SRSLTE_PUCCH_NR_FORMAT_4,
SRSLTE_PUCCH_NR_FORMAT_ERROR,
} srslte_pucch_nr_format_t;
/**
* @brief Generic PUCCH Resource configuration
*/
typedef struct SRSLTE_API {
// Common
srslte_pucch_nr_format_t format; ///< PUCCH format this configuration belongs
uint32_t nof_symbols; ///< Number of symbols
uint32_t start_symbol_idx; ///< Starting symbol index
double max_code_rate; ///< Maximum code rate (0.08, 0.15, 0.25, 0.35, 0.45, 0.60, 0.80)
bool enable_pi_bpsk; ///< Enables PI-BPSK
// Other parameters
uint32_t initial_cyclic_shift; ///< Used by formats 0, 1
uint32_t time_domain_occ; ///< Used by format 1
uint32_t nof_prb; ///< Used by formats 2, 3
uint32_t occ_lenth; ///< Spreading factor, used by format 4
uint32_t occ_index; ///< Used by format 4
} srslte_pucch_nr_cfg_t;
#endif // SRSLTE_PUCCH_NR_H

View File

@ -0,0 +1,40 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_UCI_CFG_NR_H
#define SRSLTE_UCI_CFG_NR_H
#include <stdbool.h>
#include <stdint.h>
#define SRSLTE_UCI_NR_MAX_ACK_BITS 10
#define SRSLTE_UCI_NR_MAX_SR_BITS 10
#define SRSLTE_UCI_NR_MAX_CSI1_BITS 10
#define SRSLTE_UCI_NR_MAX_CSI2_BITS 10
typedef struct SRSLTE_API {
uint32_t o_ack; ///< Number of HARQ-ACK bits
uint32_t o_sr; ///< Number of SR bits
uint32_t o_csi1; ///< Number of CSI1 report number of bits
uint32_t o_csi2; ///< Number of CSI2 report number of bits
srslte_mod_t modulation; ///< Modulation
} srslte_uci_cfg_nr_t;
typedef struct SRSLTE_API {
uint8_t ack[SRSLTE_UCI_NR_MAX_ACK_BITS];
uint8_t sr[SRSLTE_UCI_NR_MAX_SR_BITS];
uint8_t csi1[SRSLTE_UCI_NR_MAX_CSI1_BITS];
uint8_t csi2[SRSLTE_UCI_NR_MAX_CSI2_BITS];
bool valid;
} srslte_uci_value_nr_t;
#endif // SRSLTE_UCI_CFG_NR_H

View File

@ -0,0 +1,80 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_UCI_NR_H
#define SRSLTE_UCI_NR_H
#include "srslte/phy/fec/crc.h"
#include "srslte/phy/fec/polar/polar_code.h"
#include "srslte/phy/fec/polar/polar_encoder.h"
#include "srslte/phy/fec/polar/polar_rm.h"
#include "srslte/phy/phch/pucch_nr.h"
#include "uci_cfg.h"
#include "uci_cfg_nr.h"
#include <stdbool.h>
#include <stdint.h>
typedef struct {
bool disable_simd;
} srslte_uci_nr_args_t;
typedef struct {
} srslte_uci_nr_cfg_t;
typedef struct {
srslte_polar_rm_t rm;
srslte_polar_encoder_t encoder;
srslte_crc_t crc6;
srslte_crc_t crc11;
srslte_polar_code_t code;
uint8_t* bit_sequence; ///< UCI bit sequence
uint8_t* c; ///< UCI code-block prior encoding or after decoding
uint8_t* allocated; ///< Polar code intermediate
uint8_t* d; ///< Polar code encoded intermediate
} srslte_uci_nr_t;
/**
* @brief Initialises NR-UCI encoder/decoder object
* @param[in,out] q NR-UCI object
* @param[in] args Configuration arguments
* @return SRSLTE_SUCCESS if initialization is successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args);
/**
* @brief Deallocates NR-UCI encoder/decoder object
* @param[in,out] q NR-UCI object
*/
SRSLTE_API void srslte_uci_nr_free(srslte_uci_nr_t* q);
/**
* @brief Encodes UCI bits
*
* @attention Compatible only with PUCCH formats 2, 3 and 4
*
* @remark Defined in TS 38.212 section 6.3.1.1
*
* @param[in,out] q NR-UCI object
* @param[in] pucch_cfg Higher layers PUCCH configuration
* @param[in] uci_cfg UCI configuration
* @param[in] uci_value UCI values
* @param[out] o Output encoded bits
* @return Number of encoded bits if encoding is successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_uci_nr_encode_pucch(srslte_uci_nr_t* q,
const srslte_pucch_nr_cfg_t* pucch_cfg,
const srslte_uci_cfg_nr_t* uci_cfg,
const srslte_uci_value_nr_t* value,
uint8_t* o);
#endif // SRSLTE_UCI_NR_H

484
lib/src/phy/phch/uci_nr.c Normal file
View File

@ -0,0 +1,484 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/phy/phch/uci_nr.h"
#include "srslte/phy/fec/block/block.h"
#include "srslte/phy/fec/polar/polar_chanalloc.h"
#include "srslte/phy/phch/uci_cfg.h"
#include "srslte/phy/utils/vector.h"
// TS 38.212 section 5.2.1 Polar coding: The value of A is no larger than 1706.
#define UCI_NR_MAX_A 1906U
#define UCI_NR_MAX_L 11U
#define UCI_NR_POLAR_MAX 2048U
#define UCI_NR_POLAR_RM_IBIL 0
int srslte_uci_nr_init(srslte_uci_nr_t* q, const srslte_uci_nr_args_t* args)
{
if (q == NULL || args == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
srslte_polar_encoder_type_t polar_encoder_type = SRSLTE_POLAR_ENCODER_PIPELINED;
#ifdef LV_HAVE_AVX2
if (!args->disable_simd) {
polar_encoder_type = SRSLTE_POLAR_ENCODER_AVX2;
}
#endif // LV_HAVE_AVX2
if (srslte_polar_encoder_init(&q->encoder, polar_encoder_type, NMAX_LOG) < SRSLTE_SUCCESS) {
ERROR("Initialising polar encoder\n");
return SRSLTE_ERROR;
}
if (srslte_polar_rm_tx_init(&q->rm) < SRSLTE_SUCCESS) {
ERROR("Initialising polar RM\n");
return SRSLTE_ERROR;
}
if (srslte_crc_init(&q->crc6, SRSLTE_LTE_CRC6, 6) < SRSLTE_SUCCESS) {
ERROR("Initialising CRC\n");
return SRSLTE_ERROR;
}
if (srslte_crc_init(&q->crc11, SRSLTE_LTE_CRC11, 11) < SRSLTE_SUCCESS) {
ERROR("Initialising CRC\n");
return SRSLTE_ERROR;
}
// Allocate bit sequence with space for the CRC
q->bit_sequence = srslte_vec_u8_malloc(UCI_NR_MAX_A);
if (q->bit_sequence == NULL) {
ERROR("Error malloc\n");
return SRSLTE_ERROR;
}
// Allocate c with space for a and the CRC
q->c = srslte_vec_u8_malloc(UCI_NR_MAX_A + UCI_NR_MAX_L);
if (q->c == NULL) {
ERROR("Error malloc\n");
return SRSLTE_ERROR;
}
q->allocated = srslte_vec_u8_malloc(UCI_NR_POLAR_MAX);
if (q->allocated == NULL) {
ERROR("Error malloc\n");
return SRSLTE_ERROR;
}
q->d = srslte_vec_u8_malloc(UCI_NR_POLAR_MAX);
if (q->d == NULL) {
ERROR("Error malloc\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
void srslte_uci_nr_free(srslte_uci_nr_t* q)
{
if (q == NULL) {
return;
}
srslte_polar_encoder_free(&q->encoder);
if (q->bit_sequence != NULL) {
free(q->bit_sequence);
}
if (q->c != NULL) {
free(q->c);
}
if (q->allocated != NULL) {
free(q->allocated);
}
if (q->d != NULL) {
free(q->d);
}
SRSLTE_MEM_ZERO(q, srslte_uci_nr_t, 1);
}
static int
uci_nr_sequence_generation_ack_sr(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value_nr_t* value, uint8_t* sequence)
{
int A = 0;
// Append ACK bits
srslte_vec_u8_copy(&sequence[A], value->ack, cfg->o_ack);
A += cfg->o_ack;
// Append SR bits
srslte_vec_u8_copy(&sequence[A], value->sr, cfg->o_sr);
A += cfg->o_sr;
return A;
}
static int
uci_nr_sequence_generation(const srslte_uci_cfg_nr_t* cfg, const srslte_uci_value_nr_t* value, uint8_t* sequence)
{
// 6.3.1.1.1 HARQ-ACK/SR only UCI bit sequence generation
if (cfg->o_csi1 == 0 && cfg->o_csi2 == 0) {
return uci_nr_sequence_generation_ack_sr(cfg, value, sequence);
}
// 6.3.1.1.2 CSI only
if (cfg->o_ack == 0 && cfg->o_sr == 0) {
ERROR("CSI only are not implemented\n");
return SRSLTE_ERROR;
}
// 6.3.1.1.3 HARQ-ACK/SR and CSI
ERROR("HARQ-ACK/SR and CSI encoding are not implemented\n");
return SRSLTE_ERROR;
}
static int uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint8_t* o, uint32_t E)
{
uint32_t i = 0;
srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1;
switch (cfg->modulation) {
case SRSLTE_MOD_BPSK:
while (i < E) {
o[i++] = c0;
}
break;
case SRSLTE_MOD_QPSK:
while (i < E) {
o[i++] = c0;
o[i++] = UCI_BIT_REPETITION;
}
break;
case SRSLTE_MOD_16QAM:
while (i < E) {
o[i++] = c0;
o[i++] = UCI_BIT_REPETITION;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
}
break;
case SRSLTE_MOD_64QAM:
while (i < E) {
while (i < E) {
o[i++] = c0;
o[i++] = UCI_BIT_REPETITION;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
}
}
break;
case SRSLTE_MOD_256QAM:
while (i < E) {
o[i++] = c0;
o[i++] = UCI_BIT_REPETITION;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
}
break;
case SRSLTE_MOD_NITEMS:
default:
ERROR("Invalid modulation\n");
return SRSLTE_ERROR;
}
return E;
}
static int uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint8_t* o, uint32_t E)
{
uint32_t i = 0;
srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1;
srslte_uci_bit_type_t c1 = (q->bit_sequence[1] == 0) ? UCI_BIT_0 : UCI_BIT_1;
srslte_uci_bit_type_t c2 = ((q->bit_sequence[0] ^ q->bit_sequence[1]) == 0) ? UCI_BIT_0 : UCI_BIT_1;
switch (cfg->modulation) {
case SRSLTE_MOD_BPSK:
case SRSLTE_MOD_QPSK:
while (i < E) {
o[i++] = c0;
o[i++] = c1;
o[i++] = c2;
}
break;
case SRSLTE_MOD_16QAM:
while (i < E) {
o[i++] = c0;
o[i++] = c1;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = c2;
o[i++] = c0;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = c1;
o[i++] = c2;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
}
break;
case SRSLTE_MOD_64QAM:
while (i < E) {
o[i++] = c0;
o[i++] = c1;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = c2;
o[i++] = c0;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = c1;
o[i++] = c2;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
}
break;
case SRSLTE_MOD_256QAM:
while (i < E) {
o[i++] = c0;
o[i++] = c1;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = c2;
o[i++] = c0;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = c1;
o[i++] = c2;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
o[i++] = UCI_BIT_PLACEHOLDER;
}
break;
case SRSLTE_MOD_NITEMS:
default:
ERROR("Invalid modulation\n");
return SRSLTE_ERROR;
}
return E;
}
static int
uci_nr_encode_3_11_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint32_t A, uint8_t* o, uint32_t E)
{
uint8_t encoded[SRSLTE_FEC_BLOCK_SIZE] = {};
srslte_block_encode(q->bit_sequence, A, encoded, SRSLTE_FEC_BLOCK_SIZE);
for (uint32_t i = 0; i < E; i++) {
o[i] = (encoded[i % SRSLTE_FEC_BLOCK_SIZE] == 0) ? UCI_BIT_0 : UCI_BIT_1;
}
return E;
}
#define CEIL(NUM, DEN) (((NUM) + ((DEN)-1)) / (DEN))
static int
uci_nr_encode_11_1906_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint32_t A, uint8_t* o, uint32_t E_uci)
{
// If ( A ≥ 360 and E ≥ 1088 ) or if A ≥ 1013 , I seg = 1 ; otherwise I seg = 0
uint32_t I_seg = 0;
if ((A >= 360 && E_uci >= 1088) || A >= 1013) {
I_seg = 1;
}
// Select CRC
srslte_crc_t* crc = &q->crc6;
if (A >= 20) {
crc = &q->crc11;
}
// Segmentation
uint32_t C = 1;
if (I_seg == 1) {
C = 2;
}
uint32_t A_prime = CEIL(A, C) * C;
// Get polar code
uint32_t K_r = A_prime / C + crc->order;
uint32_t E_r = E_uci / C;
if (srslte_polar_code_get(&q->code, K_r, E_r, 9U) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
// Write codeword
for (uint32_t r = 0, s = 0; r < C; r++) {
uint32_t k = 0;
// Suffix A_prime - A zeros for the first CB only
if (r == 0) {
for (uint32_t i = 0; i < (A_prime - A); i++) {
q->c[k++] = 0;
}
}
// Load codeword bits
while (k < A_prime / C) {
q->c[k++] = q->bit_sequence[s++];
}
// Attach CRC
srslte_crc_attach(crc, q->c, A_prime / C);
// Allocate channel
srslte_polar_chanalloc_tx(q->c, q->allocated, q->code.N, q->code.K, q->code.nPC, q->code.K_set, q->code.PC_set);
// Encode bits
if (srslte_polar_encoder_encode(&q->encoder, q->allocated, q->d, q->code.n) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
// Rate matching
srslte_polar_rm_tx(&q->rm, q->d, &o[E_r * r], q->code.n, E_r, K_r, UCI_NR_POLAR_RM_IBIL);
}
return E_uci;
}
int uci_nr_encode(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* uci_cfg,
const srslte_uci_value_nr_t* uci_value,
uint8_t* o,
uint32_t E_uci)
{
if (q == NULL || uci_cfg == NULL || uci_value == NULL || o == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
// 6.3.1.1 UCI bit sequence generation
int A = uci_nr_sequence_generation(uci_cfg, uci_value, q->bit_sequence);
if (A < SRSLTE_SUCCESS) {
ERROR("Generating bit sequence");
return SRSLTE_ERROR;
}
// 5.3.3.1 Encoding of 1-bit information
if (A == 1) {
return uci_nr_encode_1bit(q, uci_cfg, o, E_uci);
}
// 5.3.3.2 Encoding of 2-bit information
if (A == 2) {
return uci_nr_encode_2bit(q, uci_cfg, o, E_uci);
}
// 5.3.3.3 Encoding of other small block lengths
if (A <= 11) {
return uci_nr_encode_3_11_bit(q, uci_cfg, A, o, E_uci);
}
if (A < UCI_NR_MAX_A) {
return uci_nr_encode_11_1906_bit(q, uci_cfg, A, o, E_uci);
}
return SRSLTE_ERROR;
}
// Implements TS 38.212 Table 6.3.1.4-1: Total rate matching output sequence length Etot
static int uci_nr_pucch_E_tot(const srslte_pucch_nr_cfg_t* pucch_cfg, const srslte_uci_cfg_nr_t* uci_cfg)
{
if (pucch_cfg == NULL || uci_cfg == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
switch (pucch_cfg->format) {
case SRSLTE_PUCCH_NR_FORMAT_2:
if (uci_cfg->modulation == SRSLTE_MOD_QPSK) {
return (int)(16 * pucch_cfg->nof_symbols * pucch_cfg->nof_prb);
}
break;
case SRSLTE_PUCCH_NR_FORMAT_3:
if (uci_cfg->modulation == SRSLTE_MOD_QPSK) {
return (int)(24 * pucch_cfg->nof_symbols * pucch_cfg->nof_prb);
}
if (uci_cfg->modulation == SRSLTE_MOD_BPSK) {
return (int)(12 * pucch_cfg->nof_symbols * pucch_cfg->nof_prb);
}
break;
case SRSLTE_PUCCH_NR_FORMAT_4:
if (pucch_cfg->occ_lenth != 1 && pucch_cfg->occ_lenth != 2) {
ERROR("Invalid spreading factor (%d)\n", pucch_cfg->occ_lenth);
return SRSLTE_ERROR;
}
if (uci_cfg->modulation == SRSLTE_MOD_QPSK) {
return (int)(24 * pucch_cfg->nof_symbols / pucch_cfg->occ_lenth);
}
if (uci_cfg->modulation == SRSLTE_MOD_BPSK) {
return (int)(12 * pucch_cfg->nof_symbols / pucch_cfg->occ_lenth);
}
break;
default:
return SRSLTE_ERROR;
}
return SRSLTE_ERROR;
}
// Implements TS 38.212 Table 6.3.1.4.1-1: Rate matching output sequence length E UCI
static int
uci_nr_pucch_E_uci(const srslte_pucch_nr_cfg_t* pucch_cfg, const srslte_uci_cfg_nr_t* uci_cfg, uint32_t E_tot)
{
if (uci_cfg->o_csi1 != 0 && uci_cfg->o_csi2) {
ERROR("Simultaneous CSI part 1 and CSI part 2 is not implemented\n");
return SRSLTE_ERROR;
}
return E_tot;
}
int srslte_uci_nr_encode_pucch(srslte_uci_nr_t* q,
const srslte_pucch_nr_cfg_t* pucch_cfg,
const srslte_uci_cfg_nr_t* uci_cfg,
const srslte_uci_value_nr_t* value,
uint8_t* o)
{
int E_tot = uci_nr_pucch_E_tot(pucch_cfg, uci_cfg);
if (E_tot < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
int E_uci = uci_nr_pucch_E_uci(pucch_cfg, uci_cfg, E_tot);
if (E_uci < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
return uci_nr_encode(q, uci_cfg, value, o, E_uci);
}