Verified HARQ-ACK in PUSCH

This commit is contained in:
Xavier Arteaga 2021-03-04 12:12:16 +01:00 committed by Xavier Arteaga
parent 9dffad87f2
commit dc2542901a
13 changed files with 270 additions and 142 deletions

View File

@ -20,6 +20,12 @@
#define SRSLTE_DMRS_SCH_MAX_SYMBOLS 4
/**
* @brief Helper macro for counting the number of subcarriers taken by DMRS in a PRB.
*/
#define SRSLTE_DMRS_SCH_SC(CDM_GROUPS, DMRS_TYPE) \
(SRSLTE_MIN(SRSLTE_NRE, (CDM_GROUPS) * ((DMRS_TYPE) == srslte_dmrs_sch_type_1 ? 6 : 4)))
/**
* @brief PDSCH DMRS estimator object
*

View File

@ -50,6 +50,7 @@ typedef struct SRSLTE_API {
srslte_evm_buffer_t* evm_buffer;
bool meas_time_en;
uint32_t meas_time_us;
srslte_uci_cfg_nr_t uci_cfg; ///< Internal UCI bits configuration
uint8_t* g_ulsch; ///< Temporal Encoded UL-SCH data
uint8_t* g_ack; ///< Temporal Encoded HARQ-ACK bits
uint8_t* g_csi1; ///< Temporal Encoded CSI part 1 bits
@ -61,6 +62,7 @@ typedef struct SRSLTE_API {
uint32_t G_ack; ///< Number of encoded HARQ-ACK bits
uint32_t G_csi1; ///< Number of encoded CSI part 1 bits
uint32_t G_csi2; ///< Number of encoded CSI part 2 bits
uint32_t G_ulsch; ///< Number of encoded shared channel
} srslte_pusch_nr_t;
/**

View File

@ -53,14 +53,13 @@ typedef struct {
typedef struct {
uint32_t l0; ///< First OFDM symbol that does not carry DMRS of the PUSCH, after the first DMRS symbol(s)
uint32_t l1; ///< OFDM symbol index of the first OFDM symbol that does not carry DMRS
uint32_t M_pusch_sc[SRSLTE_NSYMB_PER_SLOT_NR]; ///< Number of potential RE for PUSCH transmission
uint32_t M_pusch_sc_acc[SRSLTE_NSYMB_PER_SLOT_NR]; ///< Number of potential RE for PUSCH before the symbol
uint32_t M_uci_sc[SRSLTE_NSYMB_PER_SLOT_NR]; ///< Number of potential RE for UCI transmission
uint32_t K_sum; ///< Sum of UL-SCH code block sizes, set to zero if no UL-SCH
srslte_mod_t modulation; ///< Modulation for the PUSCH
uint32_t nof_layers; ///< Number of layers for PUSCH
float R; ///< Code rate of the PUSCH
float alpha; ///< Higher layer parameter scaling
uint32_t M_pusch_sc[SRSLTE_NSYMB_PER_SLOT_NR]; ///< Number of potential RE for PUSCH transmission
uint32_t M_uci_sc[SRSLTE_NSYMB_PER_SLOT_NR]; ///< Number of potential RE for UCI transmission
uint32_t K_sum; ///< Sum of UL-SCH code block sizes, set to zero if no UL-SCH
srslte_mod_t modulation; ///< Modulation for the PUSCH
uint32_t nof_layers; ///< Number of layers for PUSCH
float R; ///< Code rate of the PUSCH
float alpha; ///< Higher layer parameter scaling
float beta_harq_ack_offset;
float beta_csi_part1_offset;
uint32_t nof_re;

View File

@ -155,6 +155,19 @@ SRSLTE_API int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q,
const srslte_uci_value_nr_t* value,
uint8_t* o_ack);
/**
* @brief Decodes HARQ-ACK bits for PUSCH transmission
* @param[in,out] q NR-UCI object
* @param[in] cfg UCI configuration
* @param[in] llr Provides softbits LLR
* @param[out] value UCI value
* @return SRSLTE_SUCCESS if the decoding process was successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_uci_nr_decode_pusch_ack(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* cfg,
int8_t* llr,
srslte_uci_value_nr_t* value);
/**
* @brief Calculates the total number of UCI bits
* @param uci_cfg UCI configuration

View File

@ -40,6 +40,9 @@ extern "C" {
#define SRSLTE_MAX(a, b) ((a) > (b) ? (a) : (b))
#define SRSLTE_MIN(a, b) ((a) < (b) ? (a) : (b))
#define SRSLTE_CEIL(NUM, DEN) (((NUM) + ((DEN)-1)) / (DEN))
#define SRSLTE_FLOOR(NUM, DEN) ((NUM) / (DEN))
#define SRSLTE_ROUND(NUM, DEN) ((uint32_t)round((double)(NUM) / (double)(DEN)))
// Cumulative moving average
#define SRSLTE_VEC_CMA(data, average, n) ((average) + ((data) - (average)) / ((n) + 1))

View File

@ -430,8 +430,7 @@ int srslte_dmrs_sch_get_N_prb(const srslte_dmrs_sch_cfg_t* dmrs_cfg, const srslt
}
// Get number of frequency domain resource elements used for DMRS
int nof_sc = SRSLTE_MIN(SRSLTE_NRE,
grant->nof_dmrs_cdm_groups_without_data * (dmrs_cfg->type == srslte_dmrs_sch_type_1 ? 6 : 4));
int nof_sc = SRSLTE_DMRS_SCH_SC(grant->nof_dmrs_cdm_groups_without_data, dmrs_cfg->type);
// Get number of symbols used for DMRS
uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};

View File

@ -14,6 +14,7 @@
#include "srslte/phy/fec/ldpc/base_graph.h"
#include "srslte/phy/fec/turbo/turbodecoder_gen.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
#include <strings.h>
/**
@ -31,8 +32,6 @@ 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))
/**
* @brief Calculates the number of code blocks and the total size
* @param[in] B Transport block size including TB CRC
@ -46,7 +45,7 @@ static void cbsegm_cb_size(uint32_t B, uint32_t Z, uint32_t* C, uint32_t* B_prim
*C = 1;
*B_prime = B;
} else {
*C = CEIL(B, (Z - 24U));
*C = SRSLTE_CEIL(B, (Z - 24U));
*B_prime = B + 24U * (*C);
}
}
@ -151,12 +150,12 @@ bool srslte_cbsegm_cbsize_isvalid(uint32_t size)
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 (CEIL(Kp, K_b) > MAX_LIFTSIZE) {
if (SRSLTE_CEIL(Kp, K_b) > MAX_LIFTSIZE) {
return SRSLTE_ERROR;
}
// Iterate from the minimum required lift size to the maximum value
for (uint16_t Z = CEIL(Kp, K_b); Z <= MAX_LIFTSIZE; Z++) {
for (uint16_t Z = SRSLTE_CEIL(Kp, K_b); Z <= MAX_LIFTSIZE; Z++) {
// Get index for a selected lifting size
uint8_t i = get_ls_index(Z);

View File

@ -206,6 +206,7 @@ void srslte_pusch_nr_free(srslte_pusch_nr_t* q)
}
srslte_sch_nr_free(&q->sch);
srslte_uci_nr_free(&q->uci);
for (uint32_t i = 0; i < SRSLTE_MAX_LAYERS_NR; i++) {
if (q->x[i]) {
@ -466,14 +467,13 @@ pusch_nr_cinit(const srslte_carrier_nr_t* carrier, const srslte_sch_cfg_nr_t* cf
return cinit;
}
static inline int
pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg, srslte_uci_cfg_nr_t* uci_cfg)
static inline int pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg)
{
// Initially, copy all fields
*uci_cfg = cfg->uci;
q->uci_cfg = cfg->uci;
// Reset UCI PUSCH configuration
SRSLTE_MEM_ZERO(&uci_cfg->pusch, srslte_uci_nr_pusch_cfg_t, 1);
SRSLTE_MEM_ZERO(&q->uci_cfg.pusch, srslte_uci_nr_pusch_cfg_t, 1);
// Get DMRS symbol indexes
uint32_t nof_dmrs_l = 0;
@ -490,7 +490,7 @@ pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg, srsl
// Check if it is not carrying DMRS...
if (l != dmrs_l[dmrs_l_idx]) {
// Set value and stop iterating
uci_cfg->pusch.l0 = l;
q->uci_cfg.pusch.l0 = l;
break;
}
@ -505,7 +505,7 @@ pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg, srsl
for (uint32_t l = cfg->grant.S, dmrs_l_idx = 0; l < cfg->grant.S + cfg->grant.L; l++) {
// Check if it is not carrying DMRS...
if (l != dmrs_l[dmrs_l_idx]) {
uci_cfg->pusch.l1 = l;
q->uci_cfg.pusch.l1 = l;
break;
}
@ -516,33 +516,24 @@ pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg, srsl
}
// Number of DMRS per PRB
int n_prb_dmrs = srslte_dmrs_sch_get_N_prb(&cfg->dmrs, &cfg->grant);
if (n_prb_dmrs < SRSLTE_SUCCESS) {
ERROR("Error calculating number of DMRS per PRB");
return SRSLTE_ERROR;
}
// Accumulative Resource Element shall start in zero
uci_cfg->pusch.M_pusch_sc_acc[0] = 0;
uint32_t n_sc_dmrs = SRSLTE_DMRS_SCH_SC(cfg->grant.nof_dmrs_cdm_groups_without_data, cfg->dmrs.type);
// Set UCI RE number of candidates per OFDM symbol according to TS 38.312 6.3.2.4.2.1
for (uint32_t l = 0, dmrs_l_idx = 0; l < SRSLTE_NSYMB_PER_SLOT_NR; l++) {
// Skip if OFDM symbol is outside of the PUSCH transmission
if (l < cfg->grant.S || l >= (cfg->grant.S + cfg->grant.L) || l == dmrs_l[dmrs_l_idx]) {
uci_cfg->pusch.M_pusch_sc[l] = 0;
uci_cfg->pusch.M_pusch_sc_acc[l + 1] = uci_cfg->pusch.M_pusch_sc_acc[l] + uci_cfg->pusch.M_pusch_sc[l];
uci_cfg->pusch.M_uci_sc[l] = 0;
if (l < cfg->grant.S || l >= (cfg->grant.S + cfg->grant.L)) {
q->uci_cfg.pusch.M_pusch_sc[l] = 0;
q->uci_cfg.pusch.M_uci_sc[l] = 0;
continue;
}
// OFDM symbol carries DMRS
if (l == dmrs_l[dmrs_l_idx]) {
// Calculate PUSCH RE candidates
uci_cfg->pusch.M_pusch_sc[l] = cfg->grant.nof_prb * (SRSLTE_NRE - n_prb_dmrs);
uci_cfg->pusch.M_pusch_sc_acc[l + 1] = uci_cfg->pusch.M_pusch_sc_acc[l] + uci_cfg->pusch.M_pusch_sc[l];
q->uci_cfg.pusch.M_pusch_sc[l] = cfg->grant.nof_prb * (SRSLTE_NRE - n_sc_dmrs);
// The Number of RE candidates for UCI are 0
uci_cfg->pusch.M_uci_sc[l] = 0;
q->uci_cfg.pusch.M_uci_sc[l] = 0;
// Advance DMRS symbol index
dmrs_l_idx++;
@ -555,10 +546,10 @@ pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg, srsl
uint32_t M_ptrs_sc = 0; // Not implemented yet
// Number of RE given by the grant
uci_cfg->pusch.M_pusch_sc[l] = cfg->grant.nof_prb * SRSLTE_NRE;
q->uci_cfg.pusch.M_pusch_sc[l] = cfg->grant.nof_prb * SRSLTE_NRE;
// Calculate the number of UCI candidates
uci_cfg->pusch.M_uci_sc[l] = uci_cfg->pusch.M_pusch_sc[l] - M_ptrs_sc;
q->uci_cfg.pusch.M_uci_sc[l] = q->uci_cfg.pusch.M_pusch_sc[l] - M_ptrs_sc;
}
// Generate SCH Transport block information
@ -571,23 +562,21 @@ pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg, srsl
// Calculate the sum of codeblock sizes
for (uint32_t i = 0; i < sch_tb_info.C; i++) {
// Accumulate codeblock size if mask is enabled
uci_cfg->pusch.K_sum += (sch_tb_info.mask[i]) ? sch_tb_info.Kr : 0;
q->uci_cfg.pusch.K_sum += (sch_tb_info.mask[i]) ? sch_tb_info.Kr : 0;
}
// Set other PUSCH parameters
uci_cfg->pusch.modulation = cfg->grant.tb[0].mod;
uci_cfg->pusch.nof_layers = cfg->grant.nof_layers;
uci_cfg->pusch.R = (float)cfg->grant.tb[0].R;
uci_cfg->pusch.alpha = cfg->scaling;
uci_cfg->pusch.beta_harq_ack_offset = cfg->beta_harq_ack_offset;
uci_cfg->pusch.beta_csi_part1_offset = cfg->beta_csi_part1_offset;
uci_cfg->pusch.nof_re = cfg->grant.tb[0].nof_re;
q->uci_cfg.pusch.modulation = cfg->grant.tb[0].mod;
q->uci_cfg.pusch.nof_layers = cfg->grant.nof_layers;
q->uci_cfg.pusch.R = (float)cfg->grant.tb[0].R;
q->uci_cfg.pusch.alpha = cfg->scaling;
q->uci_cfg.pusch.beta_harq_ack_offset = cfg->beta_harq_ack_offset;
q->uci_cfg.pusch.beta_csi_part1_offset = cfg->beta_csi_part1_offset;
q->uci_cfg.pusch.nof_re = cfg->grant.tb[0].nof_re;
return SRSLTE_SUCCESS;
}
#define CEIL(NUM, DEN) (((NUM) + ((DEN)-1)) / (DEN))
// Implements TS 38.212 6.2.7 Data and control multiplexing (for NR-PUSCH)
static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t* cfg)
{
@ -646,21 +635,21 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t*
// Compute HARQ-ACK bits multiplexing
uint32_t ack_d = 0;
uint32_t ack_m_re_count = 0;
if (l >= l1 && m_ack_count < G_ack_rvd) {
if (cfg->o_ack <= 2) {
if (l >= l1) {
if (cfg->o_ack <= 2 && m_ack_count < G_ack_rvd) {
ack_d = 1;
ack_m_re_count = M_ulsch_sc;
if (G_ack_rvd - m_ack_count < M_uci_sc * Nl * Qm) {
ack_d = (M_uci_sc * Nl * Qm) / (G_ack_rvd - m_ack_count);
ack_m_re_count = CEIL(G_ack_rvd - m_ack_count, Nl * Qm);
ack_m_re_count = SRSLTE_CEIL(G_ack_rvd - m_ack_count, Nl * Qm);
}
M_uci_rvd = ack_m_re_count;
} else {
} else if (m_ack_count < G_ack) {
ack_d = 1;
ack_m_re_count = M_ulsch_sc;
if (G_ack - m_ack_count < M_uci_sc * Nl * Qm) {
ack_d = (M_uci_sc * Nl * Qm) / (G_ack_rvd - m_ack_count);
ack_m_re_count = M_ulsch_sc;
ack_d = (M_uci_sc * Nl * Qm) / (G_ack - m_ack_count);
ack_m_re_count = SRSLTE_CEIL(G_ack - m_ack_count, Nl * Qm);
}
M_uci_sc -= ack_m_re_count;
}
@ -674,7 +663,7 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t*
csi1_m_re_count = M_uci_sc - M_uci_rvd;
if (G_csi1 - m_csi1_count < (M_uci_sc - M_uci_rvd) * Nl * Qm) {
csi1_d = ((M_uci_sc - M_uci_rvd) * Nl * Qm) / (G_csi1 - m_csi1_count);
csi1_m_re_count = CEIL(G_csi1 - m_csi1_count, Nl * Qm);
csi1_m_re_count = SRSLTE_CEIL(G_csi1 - m_csi1_count, Nl * Qm);
}
M_uci_sc -= csi1_m_re_count;
}
@ -687,7 +676,7 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t*
csi2_m_re_count = M_uci_sc - M_uci_rvd;
if (G_csi2 - m_csi2_count < (M_uci_sc - M_uci_rvd) * Nl * Qm) {
csi2_d = ((M_uci_sc - M_uci_rvd) * Nl * Qm) / (G_csi2 - m_csi2_count);
csi2_m_re_count = CEIL(G_csi2 - m_csi2_count, Nl * Qm);
csi2_m_re_count = SRSLTE_CEIL(G_csi2 - m_csi2_count, Nl * Qm);
}
M_uci_sc -= csi2_m_re_count;
}
@ -695,7 +684,7 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t*
// Leave the rest for UL-SCH
uint32_t ulsch_m_re_count = M_uci_sc;
for (uint32_t i = 0, csi1_i = 0, csi2_i = 0; i < cfg->pusch.M_pusch_sc[l] * Qm * Nl; i++) {
for (uint32_t i = 0, csi1_i = 0, csi2_i = 0; i < cfg->pusch.M_pusch_sc[l]; i++) {
if (ack_m_re_count != 0 && i % ack_d == 0 && m_ack_count < G_ack) {
for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_ack[m_ack_count++] = m_all_count++;
@ -724,7 +713,7 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t*
}
// Set reserved bits
if (i % ack_d == 0 && m_ack_count < G_ack_rvd) {
if (ack_m_re_count != 0 && i % ack_d == 0 && m_ack_count < G_ack_rvd) {
for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_ack[m_ack_count++] = m_all_count++;
}
@ -732,7 +721,7 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t*
}
}
// Checks that all RE are allocated as planned
// Assert that all RE have been allocated
if (ack_m_re_count != 0) {
ERROR("ack_m_re_count=%d", ack_m_re_count);
}
@ -747,6 +736,10 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t*
}
}
// Update UL-SCH number of encoded bits
q->G_ulsch = m_ulsch_count;
// Assert Number of bits
if (G_ack_rvd != 0 && G_ack_rvd != m_ack_count) {
ERROR("Not matched %d!=%d", G_ack_rvd, m_ack_count);
}
@ -760,6 +753,26 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t*
ERROR("Not matched %d!=%d", G_csi2, m_csi2_count);
}
// Print debug information if configured for ity
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
if (m_ulsch_count != 0) {
DEBUG("UL-SCH bit positions:");
srslte_vec_fprint_i(stdout, (int*)pos_ulsch, m_ulsch_count);
}
if (m_ack_count != 0) {
DEBUG("HARQ-ACK bit positions [%d]:", m_ack_count);
srslte_vec_fprint_i(stdout, (int*)pos_ack, m_ack_count);
}
if (m_csi1_count != 0) {
DEBUG("CSI part 1 bit positions [%d]:", m_csi1_count);
srslte_vec_fprint_i(stdout, (int*)pos_csi1, m_csi1_count);
}
if (m_csi2_count != 0) {
DEBUG("CSI part 2 bit positions [%d]:", m_csi2_count);
srslte_vec_fprint_i(stdout, (int*)pos_csi2, m_csi2_count);
}
}
return SRSLTE_SUCCESS;
}
@ -787,25 +800,32 @@ static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
return SRSLTE_ERROR_OUT_OF_BOUNDS;
}
// Encode HARQ-ACK bits
int E_uci_ack = srslte_uci_nr_encode_pusch_ack(&q->uci, &q->uci_cfg, uci, q->g_ack);
if (E_uci_ack < SRSLTE_SUCCESS) {
ERROR("Error encoding HARQ-ACK bits");
return SRSLTE_ERROR;
}
q->G_ack = E_uci_ack;
q->G_csi1 = 0;
q->G_csi2 = 0;
// Generate PUSCH UCI/UL-SCH multiplexing
if (pusch_nr_gen_mux_uci(q, &q->uci_cfg) < SRSLTE_SUCCESS) {
ERROR("Error generating PUSCH mux tables");
return SRSLTE_ERROR;
}
// Encode SCH
if (srslte_ulsch_nr_encode(&q->sch, &cfg->sch_cfg, tb, data, q->g_ulsch) < SRSLTE_SUCCESS) {
ERROR("Error in SCH encoding");
return SRSLTE_ERROR;
}
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("b=");
srslte_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits);
}
// Multiplex UL-SCH
for (uint32_t i = 0; i < tb->nof_bits; i++) {
for (uint32_t i = 0; i < q->G_ulsch; i++) {
q->b[tb->cw_idx][q->pos_ulsch[i]] = q->g_ulsch[i];
}
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("UL-SCH bit positions:");
srslte_vec_fprint_i(stdout, (int*)q->pos_ulsch, tb->nof_bits);
}
// Multiplex CSI part 1
for (uint32_t i = 0; i < q->G_csi1; i++) {
@ -822,6 +842,11 @@ static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
q->b[tb->cw_idx][q->pos_ack[i]] = q->g_ack[i];
}
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("b=");
srslte_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits);
}
// 7.3.1.1 Scrambling
uint32_t cinit = pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx);
srslte_sequence_apply_bit(q->b[tb->cw_idx], q->b[tb->cw_idx], tb->nof_bits, cinit);
@ -860,26 +885,11 @@ int srslte_pusch_nr_encode(srslte_pusch_nr_t* q,
}
// Fill UCI configuration for PUSCH configuration
srslte_uci_cfg_nr_t uci_cfg = {};
if (pusch_nr_fill_uci_cfg(q, cfg, &uci_cfg) < SRSLTE_SUCCESS) {
if (pusch_nr_fill_uci_cfg(q, cfg) < SRSLTE_SUCCESS) {
ERROR("Error filling UCI configuration for PUSCH");
return SRSLTE_ERROR;
}
// Encode HARQ-ACK bits
int E_uci_ack = srslte_uci_nr_encode_pusch_ack(&q->uci, &uci_cfg, &data[0].uci, q->g_ack);
if (E_uci_ack < SRSLTE_SUCCESS) {
ERROR("Error encoding HARQ-ACK bits");
return SRSLTE_ERROR;
}
q->G_ack = E_uci_ack;
// Generate PUSCH UCI/UL-SCH multiplexing
if (pusch_nr_gen_mux_uci(q, &uci_cfg) < SRSLTE_SUCCESS) {
ERROR("Error generating PUSCH mux tables");
return SRSLTE_ERROR;
}
// 7.3.1.1 and 7.3.1.2
uint32_t nof_cw = 0;
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
@ -954,6 +964,22 @@ static inline int pusch_nr_decode_codeword(srslte_pusch_nr_t* q,
srslte_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re);
}
// Calculate UCI bits
int n = srslte_uci_nr_pusch_ack_nof_bits(&q->uci_cfg.pusch, q->uci_cfg.o_ack);
if (n < SRSLTE_SUCCESS) {
ERROR("Calculating G_ack");
return SRSLTE_ERROR;
}
q->G_ack = (uint32_t)n;
q->G_csi1 = 0;
q->G_csi2 = 0;
// Generate PUSCH UCI/UL-SCH multiplexing
if (pusch_nr_gen_mux_uci(q, &q->uci_cfg) < SRSLTE_SUCCESS) {
ERROR("Error generating PUSCH mux tables");
return SRSLTE_ERROR;
}
// Demodulation
int8_t* llr = (int8_t*)q->b[tb->cw_idx];
if (srslte_demod_soft_demodulate_b(tb->mod, q->d[tb->cw_idx], llr, tb->nof_re)) {
@ -965,28 +991,55 @@ static inline int pusch_nr_decode_codeword(srslte_pusch_nr_t* q,
res->evm = srslte_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits);
}
// Demultiplex UL-SCH, change sign
int8_t* g_ulsch_llr = (int8_t*)q->g_ulsch;
for (uint32_t i = 0; i < tb->nof_bits; i++) {
g_ulsch_llr[i] = -llr[q->pos_ulsch[i]];
}
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("UL-SCH bit positions:");
srslte_vec_fprint_i(stdout, (int*)q->pos_ulsch, tb->nof_bits);
}
// Descrambling
srslte_sequence_apply_c(g_ulsch_llr, g_ulsch_llr, tb->nof_bits, pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx));
srslte_sequence_apply_c(llr, llr, tb->nof_bits, pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx));
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) {
DEBUG("b=");
srslte_vec_fprint_bs(stdout, g_ulsch_llr, tb->nof_bits);
srslte_vec_fprint_bs(stdout, llr, tb->nof_bits);
}
// Decode SCH
if (srslte_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, g_ulsch_llr, res->payload, &res->crc) < SRSLTE_SUCCESS) {
ERROR("Error in SCH decoding");
return SRSLTE_ERROR;
// Demultiplex UL-SCH, change sign
int8_t* g_ulsch = (int8_t*)q->g_ulsch;
for (uint32_t i = 0; i < q->G_ulsch; i++) {
g_ulsch[i] = -llr[q->pos_ulsch[i]];
}
for (uint32_t i = q->G_ulsch; i < tb->nof_bits; i++) {
g_ulsch[i] = 0;
}
// Demultiplex HARQ-ACK
int8_t* g_ack = (int8_t*)q->g_ack;
for (uint32_t i = 0; i < q->G_ack; i++) {
g_ack[i] = llr[q->pos_ack[i]];
}
// Demultiplex CSI part 1
int8_t* g_csi1 = (int8_t*)q->g_csi1;
for (uint32_t i = 0; i < q->G_csi1; i++) {
g_csi1[i] = llr[q->pos_csi1[i]];
}
// Demultiplex CSI part 2
int8_t* g_csi2 = (int8_t*)q->g_csi2;
for (uint32_t i = 0; i < q->G_csi2; i++) {
g_csi2[i] = llr[q->pos_csi2[i]];
}
// Decode Ul-SCH
if (q->G_ulsch != 0) {
if (srslte_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, g_ulsch, res->payload, &res->crc) < SRSLTE_SUCCESS) {
ERROR("Error in SCH decoding");
return SRSLTE_ERROR;
}
}
// Decode HARQ-ACK
if (q->G_ack) {
if (srslte_uci_nr_decode_pusch_ack(&q->uci, &q->uci_cfg, g_ack, &res->uci)) {
ERROR("Error in UCI decoding");
return SRSLTE_ERROR;
}
}
return SRSLTE_SUCCESS;
@ -1016,18 +1069,11 @@ int srslte_pusch_nr_decode(srslte_pusch_nr_t* q,
}
// Fill UCI configuration for PUSCH configuration
srslte_uci_cfg_nr_t uci_cfg = {};
if (pusch_nr_fill_uci_cfg(q, cfg, &uci_cfg) < SRSLTE_SUCCESS) {
if (pusch_nr_fill_uci_cfg(q, cfg) < SRSLTE_SUCCESS) {
ERROR("Error filling UCI configuration for PUSCH");
return SRSLTE_ERROR;
}
// Generate PUSCH UCI/UL-SCH multiplexing
if (pusch_nr_gen_mux_uci(q, &uci_cfg) < SRSLTE_SUCCESS) {
ERROR("Error generating PUSCH mux tables");
return SRSLTE_ERROR;
}
uint32_t nof_cw = 0;
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
nof_cw += grant->tb[tb].enabled ? 1 : 0;

View File

@ -310,16 +310,13 @@ int srslte_ra_dl_nr_slot_nof_re(const srslte_sch_cfg_nr_t* pdsch_cfg, const srsl
return SRSLTE_MIN(SRSLTE_MAX_NRE_NR, n_re_prime) * n_prb;
}
#define CEIL(NUM, DEN) (((NUM) + ((DEN)-1)) / (DEN))
#define FLOOR(NUM, DEN) ((NUM) / (DEN))
#define ROUND(NUM, DEN) ((uint32_t)round((NUM) / (DEN)))
#define POW2(N) (1U << (N))
static uint32_t ra_nr_tbs_from_n_info3(uint32_t n_info)
{
// quantized intermediate number of information bits
uint32_t n = (uint32_t)SRSLTE_MAX(3.0, floor(log2(n_info)) - 6.0);
uint32_t n_info_prime = SRSLTE_MAX(ra_nr_tbs_table[0], POW2(n) * FLOOR(n_info, POW2(n)));
uint32_t n_info_prime = SRSLTE_MAX(ra_nr_tbs_table[0], POW2(n) * SRSLTE_FLOOR(n_info, POW2(n)));
// use Table 5.1.3.2-1 find the closest TBS that is not less than n_info_prime
for (uint32_t i = 0; i < RA_NR_TBS_SIZE_TABLE; i++) {
@ -335,19 +332,19 @@ static uint32_t ra_nr_tbs_from_n_info4(uint32_t n_info, double R)
{
// quantized intermediate number of information bits
uint32_t n = (uint32_t)(floor(log2(n_info - 24.0)) - 5.0);
uint32_t n_info_prime = SRSLTE_MAX(3840, POW2(n) * ROUND(n_info - 24.0, POW2(n)));
uint32_t n_info_prime = SRSLTE_MAX(3840, POW2(n) * SRSLTE_ROUND(n_info - 24.0, POW2(n)));
if (R <= 0.25) {
uint32_t C = CEIL(n_info_prime + 24U, 3816U);
return 8U * C * CEIL(n_info_prime + 24U, 8U * C) - 24U;
uint32_t C = SRSLTE_CEIL(n_info_prime + 24U, 3816U);
return 8U * C * SRSLTE_CEIL(n_info_prime + 24U, 8U * C) - 24U;
}
if (n_info_prime > 8424) {
uint32_t C = CEIL(n_info_prime + 24U, 8424U);
return 8U * C * CEIL(n_info_prime + 24U, 8U * C) - 24U;
uint32_t C = SRSLTE_CEIL(n_info_prime + 24U, 8424U);
return 8U * C * SRSLTE_CEIL(n_info_prime + 24U, 8U * C) - 24U;
}
return 8U * CEIL(n_info_prime + 24U, 8U) - 24U;
return 8U * SRSLTE_CEIL(n_info_prime + 24U, 8U) - 24U;
}
/**

View File

@ -131,7 +131,6 @@ int srslte_sch_nr_fill_tb_info(const srslte_carrier_nr_t* carrier,
return SRSLTE_SUCCESS;
}
#define CEIL(NUM, DEN) (((NUM) + ((DEN)-1)) / (DEN))
#define MOD(NUM, DEN) ((NUM) % (DEN))
static inline uint32_t sch_nr_get_E(const srslte_sch_nr_tb_info_t* cfg, uint32_t j)
@ -144,7 +143,7 @@ static inline uint32_t sch_nr_get_E(const srslte_sch_nr_tb_info_t* cfg, uint32_t
if (j <= (cfg->Cp - MOD(cfg->G / (cfg->Nl * cfg->Qm), cfg->Cp) - 1)) {
return cfg->Nl * cfg->Qm * (cfg->G / (cfg->Nl * cfg->Qm * cfg->Cp));
}
return cfg->Nl * cfg->Qm * CEIL(cfg->G, cfg->Nl * cfg->Qm * cfg->Cp);
return cfg->Nl * cfg->Qm * SRSLTE_CEIL(cfg->G, cfg->Nl * cfg->Qm * cfg->Cp);
}
static inline int sch_nr_init_common(srslte_sch_nr_t* q)

View File

@ -631,6 +631,8 @@ add_nr_test(pdsch_nr_test pdsch_nr_test -p 6 -m 20)
add_executable(pusch_nr_test pusch_nr_test.c)
target_link_libraries(pusch_nr_test srslte_phy)
add_nr_test(pusch_nr_test pusch_nr_test -p 6 -m 20)
add_nr_test(pusch_nr_ack_4_test pusch_nr_test -p 50 -m 20 -A 4)
add_nr_test(pusch_nr_ack_20_test pusch_nr_test -p 50 -m 20 -A 20)
add_executable(pdcch_nr_test pdcch_nr_test.c)
target_link_libraries(pdcch_nr_test srslte_phy)

View File

@ -187,9 +187,9 @@ int main(int argc, char** argv)
mcs_end = SRSLTE_MIN(mcs + 1, mcs_end);
}
pusch_cfg.scaling = 0.650f;
pusch_cfg.beta_harq_ack_offset = 5.000f;
pusch_cfg.beta_csi_part1_offset = 5.000f;
pusch_cfg.scaling = 0.5f;
pusch_cfg.beta_harq_ack_offset = 1.500f;
pusch_cfg.beta_csi_part1_offset = 1.500f;
if (srslte_chest_dl_res_init(&chest, carrier.nof_prb) < SRSLTE_SUCCESS) {
ERROR("Initiating chest");
@ -201,6 +201,7 @@ int main(int argc, char** argv)
for (uint32_t n = 0; n < SRSLTE_MAX_PRB_NR; n++) {
pusch_cfg.grant.prb_idx[n] = (n < n_prb);
}
pusch_cfg.grant.nof_prb = n_prb;
pusch_cfg.grant.dci_format = srslte_dci_format_nr_0_0;
if (srslte_ra_nr_fill_tb(&pusch_cfg, &pusch_cfg.grant, mcs, &pusch_cfg.grant.tb[0]) < SRSLTE_SUCCESS) {
@ -288,11 +289,13 @@ int main(int argc, char** argv)
goto clean_exit;
}
// Validate UL-SCH CRC check
if (!data_rx[0].crc) {
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pusch_cfg.grant.tb[0].tbs);
goto clean_exit;
}
// Validate UL-SCH payload
if (memcmp(data_tx[0].payload, data_rx[0].payload, pusch_cfg.grant.tb[0].tbs / 8) != 0) {
ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pusch_cfg.grant.tb[0].tbs);
printf("Tx data: ");
@ -302,6 +305,26 @@ int main(int argc, char** argv)
goto clean_exit;
}
// Validate UCI is decoded successfully
if (nof_ack_bits > 0 || nof_csi_bits > 0) {
if (!data_rx[0].uci.valid) {
ERROR("UCI data was not decoded ok");
goto clean_exit;
}
}
// Validate HARQ-ACK is decoded successfully
if (nof_ack_bits > 0) {
if (memcmp(data_tx[0].uci.ack, data_rx[0].uci.ack, nof_ack_bits) != 0) {
ERROR("UCI HARQ-ACK bits are unmatched");
printf("Tx data: ");
srslte_vec_fprint_byte(stdout, data_tx[0].uci.ack, nof_ack_bits);
printf("Rx data: ");
srslte_vec_fprint_byte(stdout, data_rx[0].uci.ack, nof_ack_bits);
goto clean_exit;
}
}
printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pusch_cfg.grant.tb[0].tbs, data_rx[0].evm);
}
}

View File

@ -467,8 +467,6 @@ static int uci_nr_decode_3_11_bit(srslte_uci_nr_t* q,
return SRSLTE_SUCCESS;
}
#define CEIL(NUM, DEN) (((NUM) + ((DEN)-1)) / (DEN))
static int
uci_nr_encode_11_1706_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint32_t A, uint8_t* o, uint32_t E_uci)
{
@ -487,7 +485,7 @@ uci_nr_encode_11_1706_bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, ui
if (I_seg == 1) {
C = 2;
}
uint32_t A_prime = CEIL(A, C) * C;
uint32_t A_prime = SRSLTE_CEIL(A, C) * C;
// Get polar code
uint32_t K_r = A_prime / C + L;
@ -570,7 +568,7 @@ static int uci_nr_decode_11_1706_bit(srslte_uci_nr_t* q,
if (I_seg == 1) {
C = 2;
}
uint32_t A_prime = CEIL(A, C) * C;
uint32_t A_prime = SRSLTE_CEIL(A, C) * C;
// Get polar code
uint32_t K_r = A_prime / C + L;
@ -664,13 +662,10 @@ static int uci_nr_encode(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* uci_cfg,
return SRSLTE_ERROR;
}
static int uci_nr_decode(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* uci_cfg,
int8_t* llr,
uint32_t E_uci,
srslte_uci_value_nr_t* uci_value)
static int
uci_nr_decode(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* uci_cfg, int8_t* llr, uint32_t E_uci, bool* valid)
{
if (q == NULL || uci_cfg == NULL || uci_value == NULL || llr == NULL) {
if (q == NULL || uci_cfg == NULL || valid == NULL || llr == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
@ -687,22 +682,17 @@ static int uci_nr_decode(srslte_uci_nr_t* q,
} else if (A == 2) {
ERROR("Not implemented");
} else if (A <= 11) {
if (uci_nr_decode_3_11_bit(q, uci_cfg, A, llr, E_uci, &uci_value->valid) < SRSLTE_SUCCESS) {
if (uci_nr_decode_3_11_bit(q, uci_cfg, A, llr, E_uci, valid) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
} else if (A < SRSLTE_UCI_NR_MAX_NOF_BITS) {
if (uci_nr_decode_11_1706_bit(q, uci_cfg, A, llr, E_uci, &uci_value->valid) < SRSLTE_SUCCESS) {
if (uci_nr_decode_11_1706_bit(q, uci_cfg, A, llr, E_uci, valid) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
} else {
ERROR("Invalid number of bits (A=%d)", A);
}
// Unpack bits
if (uci_nr_unpack_pucch(uci_cfg, q->bit_sequence, uci_value) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
@ -788,10 +778,22 @@ int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
int E_uci = uci_nr_pucch_E_uci(pucch_resource_cfg, uci_cfg, E_tot);
if (E_uci < SRSLTE_SUCCESS) {
ERROR("Error calculating number of encoded PUCCH UCI bits");
return SRSLTE_ERROR;
}
return uci_nr_decode(q, uci_cfg, llr, E_uci, value);
if (uci_nr_decode(q, uci_cfg, llr, E_uci, &value->valid) < SRSLTE_SUCCESS) {
ERROR("Error decoding UCI bits");
return SRSLTE_ERROR;
}
// Unpack bits
if (uci_nr_unpack_pucch(uci_cfg, q->bit_sequence, value) < SRSLTE_SUCCESS) {
ERROR("Error unpacking PUCCH UCI bits");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
uint32_t srslte_uci_nr_total_bits(const srslte_uci_cfg_nr_t* uci_cfg)
@ -904,4 +906,42 @@ int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q,
}
return uci_nr_encode(q, cfg, A, o, E_uci);
}
int srslte_uci_nr_decode_pusch_ack(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* cfg,
int8_t* llr,
srslte_uci_value_nr_t* value)
{
int A = cfg->o_ack;
// Check inputs
if (q == NULL || cfg == NULL || llr == NULL || value == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
// 6.3.2.1 UCI bit sequence generation
// 6.3.2.1.1 HARQ-ACK
bool has_csi_part2 = srslte_csi_has_part2(cfg->csi, cfg->nof_csi);
if (cfg->pusch.K_sum == 0 && cfg->nof_csi > 1 && !has_csi_part2 && cfg->o_ack < 2) {
A = 2;
}
// Compute total of encoded bits according to 6.3.2.4 Rate matching
int E_uci = srslte_uci_nr_pusch_ack_nof_bits(&cfg->pusch, A);
if (E_uci < SRSLTE_SUCCESS) {
ERROR("Error calculating number of encoded bits");
return SRSLTE_ERROR;
}
// Decode
if (uci_nr_decode(q, cfg, llr, E_uci, &value->valid) < SRSLTE_SUCCESS) {
ERROR("Error decoding UCI");
return SRSLTE_ERROR;
}
// Unpack
srslte_vec_u8_copy(value->ack, q->bit_sequence, A);
return SRSLTE_SUCCESS;
}