Refactored PDSCH/PUSCH decoder for LDPC early stopping

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent 6c5e28bc19
commit e4e3456d76

@ -150,4 +150,24 @@ srsran_ldpc_decoder_decode_s(srsran_ldpc_decoder_t* q, const int16_t* llrs, uint
SRSRAN_API int SRSRAN_API int
srsran_ldpc_decoder_decode_c(srsran_ldpc_decoder_t* q, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length); srsran_ldpc_decoder_decode_c(srsran_ldpc_decoder_t* q, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length);
/*!
* Carries out the actual decoding with 8-bit integer-valued LLRs. It is
* recommended to use a 7-bit representation for the LLRs, given that all
* values exceeding \f$ 2^{7}-1 \f$ (in magnitude) will be considered as infinity.
* \param[in] q A pointer to the LDPC decoder (a srsran_ldpc_decoder_t structure
* instance) that carries out the decoding.
* \param[in] llrs The LLRs obtained from the channel samples that correspond to
* the codeword to be decoded.
* \param[out] message The message (uncoded bits) resulting from the decoding
* operation.
* \param[in] cdwd_rm_length The number of bits forming the codeword (after rate matching).
* \param[in,out] crc Code-block CRC object for early stop. Set for NULL to disable check
* \return -1 if an error occurred, the number of used iterations, and 0 if CRC is provided and did not match
*/
SRSRAN_API int srsran_ldpc_decoder_decode_crc_c(srsran_ldpc_decoder_t* q,
const int8_t* llrs,
uint8_t* message,
uint32_t cdwd_rm_length,
srsran_crc_t* crc);
#endif // SRSRAN_LDPCDECODER_H #endif // SRSRAN_LDPCDECODER_H

@ -64,13 +64,11 @@ typedef struct SRSRAN_API {
} srsran_pdsch_nr_t; } srsran_pdsch_nr_t;
/** /**
* * @brief Groups NR-PDSCH data for reception
*/ */
typedef struct { typedef struct {
uint8_t* payload; srsran_sch_tb_res_nr_t tb[SRSRAN_MAX_TB]; ///< SCH payload
bool crc; float evm[SRSRAN_MAX_CODEWORDS]; ///< EVM measurement if configured through arguments
float evm;
uint32_t fec_iters;
} srsran_pdsch_res_nr_t; } srsran_pdsch_res_nr_t;
SRSRAN_API int srsran_pdsch_nr_init_enb(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* args); SRSRAN_API int srsran_pdsch_nr_init_enb(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* args);
@ -92,7 +90,7 @@ SRSRAN_API int srsran_pdsch_nr_decode(srsran_pdsch_nr_t* q,
const srsran_sch_grant_nr_t* grant, const srsran_sch_grant_nr_t* grant,
srsran_chest_dl_res_t* channel, srsran_chest_dl_res_t* channel,
cf_t* sf_symbols[SRSRAN_MAX_PORTS], cf_t* sf_symbols[SRSRAN_MAX_PORTS],
srsran_pdsch_res_nr_t data[SRSRAN_MAX_TB]); srsran_pdsch_res_nr_t* res);
SRSRAN_API uint32_t srsran_pdsch_nr_rx_info(const srsran_pdsch_nr_t* q, SRSRAN_API uint32_t srsran_pdsch_nr_rx_info(const srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg, const srsran_sch_cfg_nr_t* cfg,

@ -70,18 +70,17 @@ typedef struct SRSRAN_API {
* @brief Groups NR-PUSCH data for transmission * @brief Groups NR-PUSCH data for transmission
*/ */
typedef struct { typedef struct {
uint8_t* payload; ///< SCH payload uint8_t* payload[SRSRAN_MAX_TB]; ///< SCH payload
srsran_uci_value_nr_t uci; ///< UCI payload srsran_uci_value_nr_t uci; ///< UCI payload
} srsran_pusch_data_nr_t; } srsran_pusch_data_nr_t;
/** /**
* @brief Groups NR-PUSCH data for reception * @brief Groups NR-PUSCH data for reception
*/ */
typedef struct { typedef struct {
uint8_t* payload; ///< SCH payload srsran_sch_tb_res_nr_t tb[SRSRAN_MAX_TB]; ///< SCH payload
srsran_uci_value_nr_t uci; ///< UCI payload srsran_uci_value_nr_t uci; ///< UCI payload
bool crc; ///< CRC match float evm[SRSRAN_MAX_CODEWORDS]; ///< EVM measurement if configured through arguments
float evm; ///< EVM measurement if configured through arguments
} srsran_pusch_res_nr_t; } srsran_pusch_res_nr_t;
SRSRAN_API int srsran_pusch_nr_init_gnb(srsran_pusch_nr_t* q, const srsran_pusch_nr_args_t* args); SRSRAN_API int srsran_pusch_nr_init_gnb(srsran_pusch_nr_t* q, const srsran_pusch_nr_args_t* args);

@ -32,6 +32,15 @@
#define SRSRAN_SCH_NR_MAX_NOF_CB_LDPC \ #define SRSRAN_SCH_NR_MAX_NOF_CB_LDPC \
((SRSRAN_SLOT_MAX_NOF_BITS_NR + (SRSRAN_LDPC_BG2_MAX_LEN_CB - 1)) / SRSRAN_LDPC_BG2_MAX_LEN_CB) ((SRSRAN_SLOT_MAX_NOF_BITS_NR + (SRSRAN_LDPC_BG2_MAX_LEN_CB - 1)) / SRSRAN_LDPC_BG2_MAX_LEN_CB)
/**
* @brief Groups NR-PUSCH data for reception
*/
typedef struct {
uint8_t* payload; ///< SCH payload
bool crc; ///< CRC match
float avg_iter; ///< Average iterations
} srsran_sch_tb_res_nr_t;
typedef struct SRSRAN_API { typedef struct SRSRAN_API {
srsran_carrier_nr_t carrier; srsran_carrier_nr_t carrier;
@ -153,8 +162,7 @@ SRSRAN_API int srsran_dlsch_nr_decode(srsran_sch_nr_t* q,
const srsran_sch_cfg_t* sch_cfg, const srsran_sch_cfg_t* sch_cfg,
const srsran_sch_tb_t* tb, const srsran_sch_tb_t* tb,
int8_t* e_bits, int8_t* e_bits,
uint8_t* data, srsran_sch_tb_res_nr_t* res);
bool* crc_ok);
SRSRAN_API int srsran_ulsch_nr_encode(srsran_sch_nr_t* q, SRSRAN_API int srsran_ulsch_nr_encode(srsran_sch_nr_t* q,
const srsran_sch_cfg_t* cfg, const srsran_sch_cfg_t* cfg,
@ -166,9 +174,9 @@ SRSRAN_API int srsran_ulsch_nr_decode(srsran_sch_nr_t* q,
const srsran_sch_cfg_t* sch_cfg, const srsran_sch_cfg_t* sch_cfg,
const srsran_sch_tb_t* tb, const srsran_sch_tb_t* tb,
int8_t* e_bits, int8_t* e_bits,
uint8_t* data, srsran_sch_tb_res_nr_t* res);
bool* crc_ok);
SRSRAN_API int srsran_sch_nr_tb_info(const srsran_sch_tb_t* tb, char* str, uint32_t str_len); SRSRAN_API int
srsran_sch_nr_tb_info(const srsran_sch_tb_t* tb, const srsran_sch_tb_res_nr_t* res, char* str, uint32_t str_len);
#endif // SRSRAN_SCH_NR_H #endif // SRSRAN_SCH_NR_H

@ -73,11 +73,24 @@
update_ldpc_check_to_var_##SUFFIX(q->ptr, i_layer, this_pcm, these_var_indices); \ update_ldpc_check_to_var_##SUFFIX(q->ptr, i_layer, this_pcm, these_var_indices); \
\ \
update_ldpc_soft_bits_##SUFFIX(q->ptr, i_layer, these_var_indices); \ update_ldpc_soft_bits_##SUFFIX(q->ptr, i_layer, these_var_indices); \
} \
\
if (crc != NULL) { \
extract_ldpc_message_##SUFFIX(q->ptr, message, q->liftK); \
\
if (srsran_crc_match(crc, message, q->liftK - crc->order)) { \
return i_iteration + 1; \
} \
} \ } \
} \ } \
\ \
extract_ldpc_message_##SUFFIX(q->ptr, message, q->liftK); \ /* If reached here, and CRC is being checked, it has failed */ \
if (crc != NULL) { \
return 0; \
} \
\ \
/* Without CRC, extract message and return the maximum number of iterations */ \
extract_ldpc_message_##SUFFIX(q->ptr, message, q->liftK); \
return q->max_nof_iter; \ return q->max_nof_iter; \
} }
#define LDPC_DECODER_TEMPLATE_FLOOD(LLR_TYPE, SUFFIX) \ #define LDPC_DECODER_TEMPLATE_FLOOD(LLR_TYPE, SUFFIX) \
@ -638,3 +651,12 @@ int srsran_ldpc_decoder_decode_c(srsran_ldpc_decoder_t* q,
{ {
return q->decode_c(q, llrs, message, cdwd_rm_length, NULL); return q->decode_c(q, llrs, message, cdwd_rm_length, NULL);
} }
int srsran_ldpc_decoder_decode_crc_c(srsran_ldpc_decoder_t* q,
const int8_t* llrs,
uint8_t* message,
uint32_t cdwd_rm_length,
srsran_crc_t* crc)
{
return q->decode_c(q, llrs, message, cdwd_rm_length, crc);
}

@ -462,7 +462,8 @@ static inline int pdsch_nr_decode_codeword(srsran_pdsch_nr_t* q,
// EVM // EVM
if (q->evm_buffer != NULL) { if (q->evm_buffer != NULL) {
res->evm = srsran_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits); res->evm[tb->cw_idx] =
srsran_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits);
} }
// Change LLR sign and set to zero the LLR that are not used // Change LLR sign and set to zero the LLR that are not used
@ -477,7 +478,7 @@ static inline int pdsch_nr_decode_codeword(srsran_pdsch_nr_t* q,
} }
// Decode SCH // Decode SCH
if (srsran_dlsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, res->payload, &res->crc) < SRSRAN_SUCCESS) { if (srsran_dlsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, &res->tb[tb->cw_idx]) < SRSRAN_SUCCESS) {
ERROR("Error in DL-SCH encoding"); ERROR("Error in DL-SCH encoding");
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
@ -566,10 +567,12 @@ int srsran_pdsch_nr_decode(srsran_pdsch_nr_t* q,
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
static uint32_t srsran_pdsch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg, static uint32_t pdsch_nr_grant_info(const srsran_pdsch_nr_t* q,
const srsran_sch_grant_nr_t* grant, const srsran_sch_cfg_nr_t* cfg,
char* str, const srsran_sch_grant_nr_t* grant,
uint32_t str_len) const srsran_pdsch_res_nr_t* res,
char* str,
uint32_t str_len)
{ {
uint32_t len = 0; uint32_t len = 0;
len = srsran_print_check(str, str_len, len, "rnti=0x%x ", grant->rnti); len = srsran_print_check(str, str_len, len, "rnti=0x%x ", grant->rnti);
@ -606,7 +609,15 @@ static uint32_t srsran_pdsch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg,
// Append TB info // Append TB info
for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) { for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) {
len += srsran_sch_nr_tb_info(&grant->tb[i], &str[len], str_len - len); len += srsran_sch_nr_tb_info(&grant->tb[i], &res->tb[i], &str[len], str_len - len);
if (res != NULL) {
if (grant->tb[i].enabled && !isnan(res->evm[i])) {
len = srsran_print_check(str, str_len, len, "evm=%.2f ", res->evm[i]);
if (i < SRSRAN_MAX_CODEWORDS - 1) {
}
}
}
} }
return len; return len;
@ -615,52 +626,21 @@ static uint32_t srsran_pdsch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg,
uint32_t srsran_pdsch_nr_rx_info(const srsran_pdsch_nr_t* q, uint32_t srsran_pdsch_nr_rx_info(const srsran_pdsch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg, const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant, const srsran_sch_grant_nr_t* grant,
const srsran_pdsch_res_nr_t res[SRSRAN_MAX_CODEWORDS], const srsran_pdsch_res_nr_t* res,
char* str, char* str,
uint32_t str_len) uint32_t str_len)
{ {
uint32_t len = 0; uint32_t len = 0;
len += srsran_pdsch_nr_grant_info(cfg, grant, &str[len], str_len - len); len += pdsch_nr_grant_info(q, cfg, grant, res, &str[len], str_len - len);
if (cfg->rvd_re.count != 0) { if (cfg->rvd_re.count != 0) {
len = srsran_print_check(str, str_len, len, ", Reserved={"); len = srsran_print_check(str, str_len, len, "Reserved: ");
len += srsran_re_pattern_list_info(&cfg->rvd_re, &str[len], str_len - len); len += srsran_re_pattern_list_info(&cfg->rvd_re, &str[len], str_len - len);
len = srsran_print_check(str, str_len, len, "}");
}
if (q->evm_buffer != NULL) {
len = srsran_print_check(str, str_len, len, ",evm={", 0);
for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) {
if (grant->tb[i].enabled && !isnan(res[i].evm)) {
len = srsran_print_check(str, str_len, len, "%.2f", res[i].evm);
if (i < SRSRAN_MAX_CODEWORDS - 1) {
if (grant->tb[i + 1].enabled) {
len = srsran_print_check(str, str_len, len, ",", 0);
}
}
}
}
len = srsran_print_check(str, str_len, len, "}", 0);
}
if (res != NULL) {
len = srsran_print_check(str, str_len, len, ",crc={", 0);
for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) {
if (grant->tb[i].enabled) {
len = srsran_print_check(str, str_len, len, "%s", res[i].crc ? "OK" : "KO");
if (i < SRSRAN_MAX_CODEWORDS - 1) {
if (grant->tb[i + 1].enabled) {
len = srsran_print_check(str, str_len, len, ",", 0);
}
}
}
}
len = srsran_print_check(str, str_len, len, "}", 0);
} }
if (q->meas_time_en) { if (q->meas_time_en) {
len = srsran_print_check(str, str_len, len, ", t=%d us", q->meas_time_us); len = srsran_print_check(str, str_len, len, " t=%d us", q->meas_time_us);
} }
return len; return len;

@ -961,7 +961,7 @@ int srsran_pusch_nr_encode(srsran_pusch_nr_t* q,
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) { for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
nof_cw += grant->tb[tb].enabled ? 1 : 0; nof_cw += grant->tb[tb].enabled ? 1 : 0;
if (pusch_nr_encode_codeword(q, cfg, &grant->tb[tb], data[tb].payload, &data[0].uci, grant->rnti) < if (pusch_nr_encode_codeword(q, cfg, &grant->tb[tb], data->payload[tb], &data[0].uci, grant->rnti) <
SRSRAN_SUCCESS) { SRSRAN_SUCCESS) {
ERROR("Error encoding TB %d", tb); ERROR("Error encoding TB %d", tb);
return SRSRAN_ERROR; return SRSRAN_ERROR;
@ -1064,7 +1064,8 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
// EVM // EVM
if (q->evm_buffer != NULL) { if (q->evm_buffer != NULL) {
res->evm = srsran_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits); res->evm[tb->cw_idx] =
srsran_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits);
} }
// Descrambling // Descrambling
@ -1133,7 +1134,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
// Decode Ul-SCH // Decode Ul-SCH
if (tb->nof_bits != 0) { if (tb->nof_bits != 0) {
if (srsran_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, res->payload, &res->crc) < SRSRAN_SUCCESS) { if (srsran_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, &res->tb[tb->cw_idx]) < SRSRAN_SUCCESS) {
ERROR("Error in SCH decoding"); ERROR("Error in SCH decoding");
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
@ -1231,6 +1232,7 @@ int srsran_pusch_nr_decode(srsran_pusch_nr_t* q,
static uint32_t srsran_pusch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg, static uint32_t srsran_pusch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant, const srsran_sch_grant_nr_t* grant,
const srsran_pusch_res_nr_t* res,
char* str, char* str,
uint32_t str_len) uint32_t str_len)
{ {
@ -1267,7 +1269,7 @@ static uint32_t srsran_pusch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg,
// Append TB info // Append TB info
for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) { for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) {
len += srsran_sch_nr_tb_info(&grant->tb[i], &str[len], str_len - len); len += srsran_sch_nr_tb_info(&grant->tb[i], &res->tb[i], &str[len], str_len - len);
} }
return len; return len;
@ -1276,7 +1278,7 @@ static uint32_t srsran_pusch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg,
uint32_t srsran_pusch_nr_rx_info(const srsran_pusch_nr_t* q, uint32_t srsran_pusch_nr_rx_info(const srsran_pusch_nr_t* q,
const srsran_sch_cfg_nr_t* cfg, const srsran_sch_cfg_nr_t* cfg,
const srsran_sch_grant_nr_t* grant, const srsran_sch_grant_nr_t* grant,
const srsran_pusch_res_nr_t res[SRSRAN_MAX_CODEWORDS], const srsran_pusch_res_nr_t* res,
char* str, char* str,
uint32_t str_len) uint32_t str_len)
{ {
@ -1286,12 +1288,12 @@ uint32_t srsran_pusch_nr_rx_info(const srsran_pusch_nr_t* q,
return 0; return 0;
} }
len += srsran_pusch_nr_grant_info(cfg, grant, &str[len], str_len - len); len += srsran_pusch_nr_grant_info(cfg, grant, res, &str[len], str_len - len);
if (q->evm_buffer != NULL) { if (q->evm_buffer != NULL) {
len = srsran_print_check(str, str_len, len, ",evm={", 0); len = srsran_print_check(str, str_len, len, ",evm={", 0);
for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) { for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) {
if (grant->tb[i].enabled && !isnan(res[i].evm)) { if (grant->tb[i].enabled && !isnan(res->evm[i])) {
len = srsran_print_check(str, str_len, len, "%.2f", res[i].evm); len = srsran_print_check(str, str_len, len, "%.2f", res[i].evm);
if (i < SRSRAN_MAX_CODEWORDS - 1) { if (i < SRSRAN_MAX_CODEWORDS - 1) {
if (grant->tb[i + 1].enabled) { if (grant->tb[i + 1].enabled) {
@ -1312,7 +1314,7 @@ uint32_t srsran_pusch_nr_rx_info(const srsran_pusch_nr_t* q,
len = srsran_print_check(str, str_len, len, ",crc={", 0); len = srsran_print_check(str, str_len, len, ",crc={", 0);
for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) { for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) {
if (grant->tb[i].enabled) { if (grant->tb[i].enabled) {
len = srsran_print_check(str, str_len, len, "%s", res[i].crc ? "OK" : "KO"); len = srsran_print_check(str, str_len, len, "%s", res->tb[i].crc ? "OK" : "KO");
if (i < SRSRAN_MAX_CODEWORDS - 1) { if (i < SRSRAN_MAX_CODEWORDS - 1) {
if (grant->tb[i + 1].enabled) { if (grant->tb[i + 1].enabled) {
len = srsran_print_check(str, str_len, len, ",", 0); len = srsran_print_check(str, str_len, len, ",", 0);
@ -1343,7 +1345,7 @@ uint32_t srsran_pusch_nr_tx_info(const srsran_pusch_nr_t* q,
return 0; return 0;
} }
len += srsran_pusch_nr_grant_info(cfg, grant, &str[len], str_len - len); len += srsran_pusch_nr_grant_info(cfg, grant, NULL, &str[len], str_len - len);
if (uci_value != NULL) { if (uci_value != NULL) {
srsran_uci_data_nr_t uci_data = {}; srsran_uci_data_nr_t uci_data = {};

@ -509,19 +509,19 @@ static inline int sch_nr_encode(srsran_sch_nr_t* q,
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
int sch_nr_decode(srsran_sch_nr_t* q, static int sch_nr_decode(srsran_sch_nr_t* q,
const srsran_sch_cfg_t* sch_cfg, const srsran_sch_cfg_t* sch_cfg,
const srsran_sch_tb_t* tb, const srsran_sch_tb_t* tb,
int8_t* e_bits, int8_t* e_bits,
uint8_t* data, srsran_sch_tb_res_nr_t* res)
bool* crc_ok)
{ {
// Pointer protection // Pointer protection
if (!q || !sch_cfg || !tb || !data || !e_bits || !crc_ok) { if (!q || !sch_cfg || !tb || !e_bits || !res) {
return SRSRAN_ERROR_INVALID_INPUTS; return SRSRAN_ERROR_INVALID_INPUTS;
} }
int8_t* input_ptr = e_bits; int8_t* input_ptr = e_bits;
uint32_t nof_iter_sum = 0;
srsran_sch_nr_tb_info_t cfg = {}; srsran_sch_nr_tb_info_t cfg = {};
if (srsran_sch_nr_fill_tb_info(&q->carrier, sch_cfg, tb, &cfg) < SRSRAN_SUCCESS) { if (srsran_sch_nr_fill_tb_info(&q->carrier, sch_cfg, tb, &cfg) < SRSRAN_SUCCESS) {
@ -599,27 +599,25 @@ int sch_nr_decode(srsran_sch_nr_t* q,
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
// Decode // Select CB or TB early stop CRC
srsran_ldpc_decoder_decode_c(decoder, rm_buffer, q->temp_cb, n_llr); srsran_crc_t* crc = (cfg.L_tb == 16) ? &q->crc_tb_16 : &q->crc_tb_24;
// Compute CB CRC
uint32_t cb_len = cfg.Kp - cfg.L_cb;
if (cfg.L_cb) { if (cfg.L_cb) {
uint8_t* ptr = q->temp_cb + cb_len; crc = &q->crc_cb;
uint32_t checksum1 = srsran_crc_checksum(&q->crc_cb, q->temp_cb, (int)cb_len);
uint32_t checksum2 = srsran_bit_pack(&ptr, cfg.L_cb);
tb->softbuffer.rx->cb_crc[r] = (checksum1 == checksum2);
SCH_INFO_RX("CB %d/%d: CRC={%06x, %06x} ... %s",
r,
cfg.C,
checksum1,
checksum2,
tb->softbuffer.rx->cb_crc[r] ? "OK" : "KO");
} else {
tb->softbuffer.rx->cb_crc[r] = true;
} }
// Decode
int n_iter = srsran_ldpc_decoder_decode_crc_c(decoder, rm_buffer, q->temp_cb, n_llr, crc);
if (n_iter < SRSRAN_SUCCESS) {
ERROR("Error decoding CB");
return SRSRAN_ERROR;
}
nof_iter_sum += ((n_iter == 0) ? decoder->max_nof_iter : (uint32_t)n_iter);
// Compute CB CRC only if LDPC decoder reached the end
uint32_t cb_len = cfg.Kp - cfg.L_cb;
tb->softbuffer.rx->cb_crc[r] = (n_iter != 0);
SCH_INFO_RX("CB %d/%d CRC=%s", r, cfg.C, tb->softbuffer.rx->cb_crc[r] ? "OK" : "KO");
// Pack and count CRC OK only if CRC is match // Pack and count CRC OK only if CRC is match
if (tb->softbuffer.rx->cb_crc[r]) { if (tb->softbuffer.rx->cb_crc[r]) {
srsran_bit_pack_vector(q->temp_cb, tb->softbuffer.rx->data[r], cb_len); srsran_bit_pack_vector(q->temp_cb, tb->softbuffer.rx->data[r], cb_len);
@ -629,51 +627,64 @@ int sch_nr_decode(srsran_sch_nr_t* q,
input_ptr += E; input_ptr += E;
} }
// All CB are decoded // Not all CB are decoded, skip TB union and CRC check
if (cb_ok == cfg.C) { if (cb_ok != cfg.C) {
uint32_t checksum2 = 0; return SRSRAN_SUCCESS;
uint8_t* output_ptr = data; }
for (uint32_t r = 0; r < cfg.C; r++) { uint32_t checksum2 = 0;
uint32_t cb_len = cfg.Kp - cfg.L_cb; uint8_t* output_ptr = res->payload;
// Subtract TB CRC from the last code block for (uint32_t r = 0; r < cfg.C; r++) {
if (r == cfg.C - 1) { uint32_t cb_len = cfg.Kp - cfg.L_cb;
cb_len -= cfg.L_tb;
}
srsran_vec_u8_copy(output_ptr, tb->softbuffer.rx->data[r], cb_len / 8); // Subtract TB CRC from the last code block
output_ptr += cb_len / 8; if (r == cfg.C - 1) {
cb_len -= cfg.L_tb;
}
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) { // Append CB
DEBUG("CB %d:", r); srsran_vec_u8_copy(output_ptr, tb->softbuffer.rx->data[r], cb_len / 8);
srsran_vec_fprint_byte(stdout, tb->softbuffer.rx->data[r], cb_len / 8); output_ptr += cb_len / 8;
}
if (r == cfg.C - 1) { // CB Debug trace
uint8_t tb_crc_unpacked[24] = {}; if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
uint8_t* tb_crc_unpacked_ptr = tb_crc_unpacked; DEBUG("CB %d/%d:", r, cfg.C);
srsran_bit_unpack_vector(&tb->softbuffer.rx->data[r][cb_len / 8], tb_crc_unpacked, cfg.L_tb); srsran_vec_fprint_byte(stdout, tb->softbuffer.rx->data[r], cb_len / 8);
checksum2 = srsran_bit_pack(&tb_crc_unpacked_ptr, cfg.L_tb);
}
} }
// Check if TB is all zeros // Compute TB CRC for last block
bool all_zeros = true; if (cfg.C > 1 && r == cfg.C - 1) {
for (uint32_t i = 0; i < tb->tbs / 8 && all_zeros; i++) { uint8_t tb_crc_unpacked[24] = {};
all_zeros = (data[i] == 0); uint8_t* tb_crc_unpacked_ptr = tb_crc_unpacked;
srsran_bit_unpack_vector(&tb->softbuffer.rx->data[r][cb_len / 8], tb_crc_unpacked, cfg.L_tb);
checksum2 = srsran_bit_pack(&tb_crc_unpacked_ptr, cfg.L_tb);
} }
}
// Calculate TB CRC from packed data // Check if TB is all zeros
uint32_t checksum1 = srsran_crc_checksum_byte(crc_tb, data, tb->tbs); bool all_zeros = true;
*crc_ok = (checksum1 == checksum2 && !all_zeros); for (uint32_t i = 0; i < tb->tbs / 8 && all_zeros; i++) {
all_zeros = (res->payload[i] == 0);
}
SCH_INFO_RX("TB: TBS=%d; CRC={%06x, %06x}", tb->tbs, checksum1, checksum2); // Calculate TB CRC from packed data
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) { if (cfg.C == 1) {
DEBUG("Decode: "); res->crc = !all_zeros;
srsran_vec_fprint_byte(stdout, data, tb->tbs / 8); SCH_INFO_RX("TB: TBS=%d; CRC=%s", tb->tbs, tb->softbuffer.rx->cb_crc[0] ? "OK" : "KO");
}
} else { } else {
*crc_ok = false; // More than one
uint32_t checksum1 = srsran_crc_checksum_byte(crc_tb, res->payload, tb->tbs);
res->crc = (checksum1 == checksum2 && !all_zeros);
SCH_INFO_RX("TB: TBS=%d; CRC={%06x, %06x}", tb->tbs, checksum1, checksum2);
}
// Set average number of iterations
res->avg_iter = (float)nof_iter_sum / (float)cfg.C;
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
DEBUG("Decode: ");
srsran_vec_fprint_byte(stdout, res->payload, tb->tbs / 8);
} }
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
@ -692,10 +703,9 @@ int srsran_dlsch_nr_decode(srsran_sch_nr_t* q,
const srsran_sch_cfg_t* sch_cfg, const srsran_sch_cfg_t* sch_cfg,
const srsran_sch_tb_t* tb, const srsran_sch_tb_t* tb,
int8_t* e_bits, int8_t* e_bits,
uint8_t* data, srsran_sch_tb_res_nr_t* res)
bool* crc_ok)
{ {
return sch_nr_decode(q, sch_cfg, tb, e_bits, data, crc_ok); return sch_nr_decode(q, sch_cfg, tb, e_bits, res);
} }
int srsran_ulsch_nr_encode(srsran_sch_nr_t* q, int srsran_ulsch_nr_encode(srsran_sch_nr_t* q,
@ -711,30 +721,33 @@ int srsran_ulsch_nr_decode(srsran_sch_nr_t* q,
const srsran_sch_cfg_t* sch_cfg, const srsran_sch_cfg_t* sch_cfg,
const srsran_sch_tb_t* tb, const srsran_sch_tb_t* tb,
int8_t* e_bits, int8_t* e_bits,
uint8_t* data, srsran_sch_tb_res_nr_t* res)
bool* crc_ok)
{ {
return sch_nr_decode(q, sch_cfg, tb, e_bits, data, crc_ok); return sch_nr_decode(q, sch_cfg, tb, e_bits, res);
} }
int srsran_sch_nr_tb_info(const srsran_sch_tb_t* tb, char* str, uint32_t str_len) int srsran_sch_nr_tb_info(const srsran_sch_tb_t* tb, const srsran_sch_tb_res_nr_t* res, char* str, uint32_t str_len)
{ {
int len = 0; int len = 0;
if (tb->enabled) { if (tb->enabled) {
len += srsran_print_check(str, len = srsran_print_check(str,
str_len, str_len,
len, len,
"CW0: mod=%s Nl=%d tbs=%d R=%.3f rv=%d Nre=%d Nbit=%d cw=%d", "CW%d: mod=%s Nl=%d tbs=%d R=%.3f rv=%d Nre=%d Nbit=%d ",
srsran_mod_string(tb->mod), tb->cw_idx,
tb->N_L, srsran_mod_string(tb->mod),
tb->tbs / 8, tb->N_L,
tb->R, tb->tbs / 8,
tb->rv, tb->R,
tb->nof_re, tb->rv,
tb->nof_bits, tb->nof_re,
tb->cw_idx); tb->nof_bits);
if (res != NULL) {
len = srsran_print_check(str, str_len, len, "CRC=%s iter=%.1f ", res->crc ? "OK" : "KO", res->avg_iter);
}
} }
return len; return len;
} }

@ -75,12 +75,12 @@ int parse_args(int argc, char** argv)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
int ret = SRSRAN_ERROR; int ret = SRSRAN_ERROR;
srsran_pdsch_nr_t pdsch_tx = {}; srsran_pdsch_nr_t pdsch_tx = {};
srsran_pdsch_nr_t pdsch_rx = {}; srsran_pdsch_nr_t pdsch_rx = {};
srsran_chest_dl_res_t chest = {}; srsran_chest_dl_res_t chest = {};
srsran_pdsch_res_nr_t pdsch_res[SRSRAN_MAX_TB] = {}; srsran_pdsch_res_nr_t pdsch_res = {};
srsran_random_t rand_gen = srsran_random_init(1234); srsran_random_t rand_gen = srsran_random_init(1234);
uint8_t* data_tx[SRSRAN_MAX_TB] = {}; uint8_t* data_tx[SRSRAN_MAX_TB] = {};
uint8_t* data_rx[SRSRAN_MAX_CODEWORDS] = {}; uint8_t* data_rx[SRSRAN_MAX_CODEWORDS] = {};
@ -133,7 +133,7 @@ int main(int argc, char** argv)
goto clean_exit; goto clean_exit;
} }
pdsch_res[i].payload = data_rx[i]; pdsch_res.tb[i].payload = data_rx[i];
} }
srsran_softbuffer_tx_t softbuffer_tx = {}; srsran_softbuffer_tx_t softbuffer_tx = {};
@ -224,14 +224,14 @@ int main(int argc, char** argv)
} }
chest.nof_re = pdsch_cfg.grant.tb->nof_re; chest.nof_re = pdsch_cfg.grant.tb->nof_re;
if (srsran_pdsch_nr_decode(&pdsch_rx, &pdsch_cfg, &pdsch_cfg.grant, &chest, sf_symbols, pdsch_res) < if (srsran_pdsch_nr_decode(&pdsch_rx, &pdsch_cfg, &pdsch_cfg.grant, &chest, sf_symbols, &pdsch_res) <
SRSRAN_SUCCESS) { SRSRAN_SUCCESS) {
ERROR("Error encoding"); ERROR("Error encoding");
goto clean_exit; goto clean_exit;
} }
if (pdsch_res->evm > 0.001f) { if (pdsch_res.evm[0] > 0.001f) {
ERROR("Error PDSCH EVM is too high %f", pdsch_res->evm); ERROR("Error PDSCH EVM is too high %f", pdsch_res.evm[0]);
goto clean_exit; goto clean_exit;
} }
@ -256,7 +256,7 @@ int main(int argc, char** argv)
goto clean_exit; goto clean_exit;
} }
if (!pdsch_res[0].crc) { if (!pdsch_res.tb[0].crc) {
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs); ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs);
goto clean_exit; goto clean_exit;
} }
@ -270,7 +270,7 @@ int main(int argc, char** argv)
goto clean_exit; goto clean_exit;
} }
INFO("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs, pdsch_res[0].evm); INFO("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs, pdsch_res.evm[0]);
} }
} }

@ -90,8 +90,8 @@ int main(int argc, char** argv)
srsran_chest_dl_res_t chest = {}; srsran_chest_dl_res_t chest = {};
srsran_random_t rand_gen = srsran_random_init(1234); srsran_random_t rand_gen = srsran_random_init(1234);
srsran_pusch_data_nr_t data_tx[SRSRAN_MAX_TB] = {}; srsran_pusch_data_nr_t data_tx = {};
srsran_pusch_res_nr_t data_rx[SRSRAN_MAX_CODEWORDS] = {}; srsran_pusch_res_nr_t data_rx = {};
cf_t* sf_symbols[SRSRAN_MAX_LAYERS_NR] = {}; cf_t* sf_symbols[SRSRAN_MAX_LAYERS_NR] = {};
// Set default PUSCH configuration // Set default PUSCH configuration
@ -134,9 +134,9 @@ int main(int argc, char** argv)
} }
for (uint32_t i = 0; i < pusch_tx.max_cw; i++) { for (uint32_t i = 0; i < pusch_tx.max_cw; i++) {
data_tx[i].payload = srsran_vec_u8_malloc(SRSRAN_SLOT_MAX_NOF_BITS_NR); data_tx.payload[i] = srsran_vec_u8_malloc(SRSRAN_SLOT_MAX_NOF_BITS_NR);
data_rx[i].payload = srsran_vec_u8_malloc(SRSRAN_SLOT_MAX_NOF_BITS_NR); data_rx.tb[i].payload = srsran_vec_u8_malloc(SRSRAN_SLOT_MAX_NOF_BITS_NR);
if (data_tx[i].payload == NULL || data_rx[i].payload == NULL) { if (data_tx.payload[i] == NULL || data_rx.tb[i].payload == NULL) {
ERROR("Error malloc"); ERROR("Error malloc");
goto clean_exit; goto clean_exit;
} }
@ -212,12 +212,12 @@ int main(int argc, char** argv)
// Generate SCH payload // Generate SCH payload
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) { for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
// Skip TB if no allocated // Skip TB if no allocated
if (data_tx[tb].payload == NULL) { if (data_tx.payload[tb] == NULL) {
continue; continue;
} }
for (uint32_t i = 0; i < pusch_cfg.grant.tb[tb].tbs; i++) { for (uint32_t i = 0; i < pusch_cfg.grant.tb[tb].tbs; i++) {
data_tx[tb].payload[i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, UINT8_MAX); data_tx.payload[tb][i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, UINT8_MAX);
} }
pusch_cfg.grant.tb[tb].softbuffer.tx = &softbuffer_tx; pusch_cfg.grant.tb[tb].softbuffer.tx = &softbuffer_tx;
} }
@ -226,7 +226,7 @@ int main(int argc, char** argv)
if (nof_ack_bits > 0) { if (nof_ack_bits > 0) {
pusch_cfg.uci.o_ack = nof_ack_bits; pusch_cfg.uci.o_ack = nof_ack_bits;
for (uint32_t i = 0; i < nof_ack_bits; i++) { for (uint32_t i = 0; i < nof_ack_bits; i++) {
data_tx->uci.ack[i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, 1); data_tx.uci.ack[i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, 1);
} }
} }
@ -237,15 +237,15 @@ int main(int argc, char** argv)
pusch_cfg.uci.csi[0].quantity = SRSRAN_CSI_REPORT_QUANTITY_NONE; pusch_cfg.uci.csi[0].quantity = SRSRAN_CSI_REPORT_QUANTITY_NONE;
pusch_cfg.uci.csi[0].K_csi_rs = nof_csi_bits; pusch_cfg.uci.csi[0].K_csi_rs = nof_csi_bits;
pusch_cfg.uci.nof_csi = 1; pusch_cfg.uci.nof_csi = 1;
data_tx->uci.csi[0].none = csi_report_tx; data_tx.uci.csi[0].none = csi_report_tx;
for (uint32_t i = 0; i < nof_csi_bits; i++) { for (uint32_t i = 0; i < nof_csi_bits; i++) {
csi_report_tx[i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, 1); csi_report_tx[i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, 1);
} }
data_rx->uci.csi[0].none = csi_report_rx; data_rx.uci.csi[0].none = csi_report_rx;
} }
if (srsran_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_cfg.grant, data_tx, sf_symbols) < SRSRAN_SUCCESS) { if (srsran_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_cfg.grant, &data_tx, sf_symbols) < SRSRAN_SUCCESS) {
ERROR("Error encoding"); ERROR("Error encoding");
goto clean_exit; goto clean_exit;
} }
@ -260,14 +260,14 @@ int main(int argc, char** argv)
} }
chest.nof_re = pusch_cfg.grant.tb->nof_re; chest.nof_re = pusch_cfg.grant.tb->nof_re;
if (srsran_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &chest, sf_symbols, data_rx) < if (srsran_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &chest, sf_symbols, &data_rx) <
SRSRAN_SUCCESS) { SRSRAN_SUCCESS) {
ERROR("Error encoding"); ERROR("Error encoding");
goto clean_exit; goto clean_exit;
} }
if (data_rx[0].evm > 0.001f) { if (data_rx.evm[0] > 0.001f) {
ERROR("Error PUSCH EVM is too high %f", data_rx[0].evm); ERROR("Error PUSCH EVM is too high %f", data_rx.evm[0]);
goto clean_exit; goto clean_exit;
} }
@ -293,24 +293,24 @@ int main(int argc, char** argv)
} }
// Validate UL-SCH CRC check // Validate UL-SCH CRC check
if (!data_rx[0].crc) { if (!data_rx.tb[0].crc) {
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pusch_cfg.grant.tb[0].tbs); ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pusch_cfg.grant.tb[0].tbs);
goto clean_exit; goto clean_exit;
} }
// Validate UL-SCH payload // Validate UL-SCH payload
if (memcmp(data_tx[0].payload, data_rx[0].payload, pusch_cfg.grant.tb[0].tbs / 8) != 0) { if (memcmp(data_tx.payload[0], data_rx.tb[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); 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: "); printf("Tx data: ");
srsran_vec_fprint_byte(stdout, data_tx[0].payload, pusch_cfg.grant.tb[0].tbs / 8); srsran_vec_fprint_byte(stdout, data_tx.payload[0], pusch_cfg.grant.tb[0].tbs / 8);
printf("Rx data: "); printf("Rx data: ");
srsran_vec_fprint_byte(stdout, data_tx[0].payload, pusch_cfg.grant.tb[0].tbs / 8); srsran_vec_fprint_byte(stdout, data_tx.payload[0], pusch_cfg.grant.tb[0].tbs / 8);
goto clean_exit; goto clean_exit;
} }
// Validate UCI is decoded successfully // Validate UCI is decoded successfully
if (nof_ack_bits > 0 || nof_csi_bits > 0) { if (nof_ack_bits > 0 || nof_csi_bits > 0) {
if (!data_rx[0].uci.valid) { if (!data_rx.uci.valid) {
ERROR("UCI data was not decoded ok"); ERROR("UCI data was not decoded ok");
goto clean_exit; goto clean_exit;
} }
@ -318,29 +318,29 @@ int main(int argc, char** argv)
// Validate HARQ-ACK is decoded successfully // Validate HARQ-ACK is decoded successfully
if (nof_ack_bits > 0) { if (nof_ack_bits > 0) {
if (memcmp(data_tx[0].uci.ack, data_rx[0].uci.ack, nof_ack_bits) != 0) { if (memcmp(data_tx.uci.ack, data_rx.uci.ack, nof_ack_bits) != 0) {
ERROR("UCI HARQ-ACK bits are unmatched"); ERROR("UCI HARQ-ACK bits are unmatched");
printf("Tx data: "); printf("Tx data: ");
srsran_vec_fprint_byte(stdout, data_tx[0].uci.ack, nof_ack_bits); srsran_vec_fprint_byte(stdout, data_tx.uci.ack, nof_ack_bits);
printf("Rx data: "); printf("Rx data: ");
srsran_vec_fprint_byte(stdout, data_rx[0].uci.ack, nof_ack_bits); srsran_vec_fprint_byte(stdout, data_rx.uci.ack, nof_ack_bits);
goto clean_exit; goto clean_exit;
} }
} }
// Validate CSI is decoded successfully // Validate CSI is decoded successfully
if (nof_csi_bits > 0) { if (nof_csi_bits > 0) {
if (memcmp(data_tx[0].uci.csi[0].none, data_rx[0].uci.csi[0].none, nof_csi_bits) != 0) { if (memcmp(data_tx.uci.csi[0].none, data_rx.uci.csi[0].none, nof_csi_bits) != 0) {
ERROR("UCI CSI bits are unmatched"); ERROR("UCI CSI bits are unmatched");
printf("Tx data: "); printf("Tx data: ");
srsran_vec_fprint_byte(stdout, data_tx[0].uci.csi[0].none, nof_csi_bits); srsran_vec_fprint_byte(stdout, data_tx.uci.csi[0].none, nof_csi_bits);
printf("Rx data: "); printf("Rx data: ");
srsran_vec_fprint_byte(stdout, data_rx[0].uci.csi[0].none, nof_csi_bits); srsran_vec_fprint_byte(stdout, data_rx.uci.csi[0].none, nof_csi_bits);
goto clean_exit; 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); printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pusch_cfg.grant.tb[0].tbs, data_rx.evm[0]);
} }
} }
@ -352,11 +352,11 @@ clean_exit:
srsran_pusch_nr_free(&pusch_tx); srsran_pusch_nr_free(&pusch_tx);
srsran_pusch_nr_free(&pusch_rx); srsran_pusch_nr_free(&pusch_rx);
for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) { for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) {
if (data_tx[i].payload) { if (data_tx.payload[i]) {
free(data_tx[i].payload); free(data_tx.payload[i]);
} }
if (data_rx[i].payload) { if (data_rx.tb[i].payload) {
free(data_rx[i].payload); free(data_rx.tb[i].payload);
} }
} }
for (uint32_t i = 0; i < SRSRAN_MAX_LAYERS_NR; i++) { for (uint32_t i = 0; i < SRSRAN_MAX_LAYERS_NR; i++) {

@ -206,14 +206,15 @@ int main(int argc, char** argv)
tb.softbuffer.rx = &softbuffer_rx; tb.softbuffer.rx = &softbuffer_rx;
srsran_softbuffer_rx_reset(tb.softbuffer.rx); srsran_softbuffer_rx_reset(tb.softbuffer.rx);
bool crc = false; srsran_sch_tb_res_nr_t res = {};
if (srsran_dlsch_nr_decode(&sch_nr_rx, &pdsch_cfg.sch_cfg, &tb, llr, data_rx, &crc) < SRSRAN_SUCCESS) { res.payload = data_rx;
if (srsran_dlsch_nr_decode(&sch_nr_rx, &pdsch_cfg.sch_cfg, &tb, llr, &res) < SRSRAN_SUCCESS) {
ERROR("Error encoding"); ERROR("Error encoding");
goto clean_exit; goto clean_exit;
} }
if (rv == 0) { if (rv == 0) {
if (!crc) { if (!res.crc) {
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, tb.tbs); ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, tb.tbs);
goto clean_exit; goto clean_exit;
} }

@ -585,7 +585,7 @@ int srsran_ue_dl_nr_pdsch_info(const srsran_ue_dl_nr_t* q,
len += srsran_pdsch_nr_rx_info(&q->pdsch, cfg, &cfg->grant, res, &str[len], str_len - len); len += srsran_pdsch_nr_rx_info(&q->pdsch, cfg, &cfg->grant, res, &str[len], str_len - len);
// Append channel estimator info // Append channel estimator info
len = srsran_print_check(str, str_len, len, ",SNR=%+.1f", q->chest.snr_db); len = srsran_print_check(str, str_len, len, "SNR=%+.1f", q->chest.snr_db);
return len; return len;
} }

@ -184,16 +184,16 @@ static int work_ue_dl(srsran_ue_dl_nr_t* ue_dl, srsran_slot_cfg_t* slot, srsran_
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
int ret = SRSRAN_ERROR; int ret = SRSRAN_ERROR;
srsran_enb_dl_nr_t enb_dl = {}; srsran_enb_dl_nr_t enb_dl = {};
srsran_ue_dl_nr_t ue_dl = {}; srsran_ue_dl_nr_t ue_dl = {};
srsran_pdsch_res_nr_t pdsch_res[SRSRAN_MAX_TB] = {}; srsran_pdsch_res_nr_t pdsch_res = {};
srsran_random_t rand_gen = srsran_random_init(1234); srsran_random_t rand_gen = srsran_random_init(1234);
srsran_slot_cfg_t slot = {}; srsran_slot_cfg_t slot = {};
struct timeval t[3] = {}; struct timeval t[3] = {};
uint64_t pdsch_encode_us = 0; uint64_t pdsch_encode_us = 0;
uint64_t pdsch_decode_us = 0; uint64_t pdsch_decode_us = 0;
uint64_t nof_bits = 0; uint64_t nof_bits = 0;
uint8_t* data_tx[SRSRAN_MAX_TB] = {}; uint8_t* data_tx[SRSRAN_MAX_TB] = {};
uint8_t* data_rx[SRSRAN_MAX_CODEWORDS] = {}; uint8_t* data_rx[SRSRAN_MAX_CODEWORDS] = {};
@ -296,7 +296,7 @@ int main(int argc, char** argv)
goto clean_exit; goto clean_exit;
} }
pdsch_res[i].payload = data_rx[i]; pdsch_res.tb[i].payload = data_rx[i];
} }
srsran_softbuffer_tx_t softbuffer_tx = {}; srsran_softbuffer_tx_t softbuffer_tx = {};
@ -418,7 +418,7 @@ int main(int argc, char** argv)
} }
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
if (work_ue_dl(&ue_dl, &slot, pdsch_res) < SRSRAN_SUCCESS) { if (work_ue_dl(&ue_dl, &slot, &pdsch_res) < SRSRAN_SUCCESS) {
ERROR("Error running UE DL"); ERROR("Error running UE DL");
goto clean_exit; goto clean_exit;
} }
@ -426,14 +426,14 @@ int main(int argc, char** argv)
get_time_interval(t); get_time_interval(t);
pdsch_decode_us += (size_t)(t[0].tv_sec * 1e6 + t[0].tv_usec); pdsch_decode_us += (size_t)(t[0].tv_sec * 1e6 + t[0].tv_usec);
if (pdsch_res->evm > 0.02f) { if (pdsch_res.evm[0] > 0.02f) {
ERROR("Error PDSCH EVM is too high %f", pdsch_res->evm); ERROR("Error PDSCH EVM is too high %f", pdsch_res.evm[0]);
goto clean_exit; goto clean_exit;
} }
// Check CRC only for RV=0 // Check CRC only for RV=0
if (rv_idx == 0) { if (rv_idx == 0) {
if (!pdsch_res[0].crc) { if (!pdsch_res.tb[0].crc) {
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs); ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs);
goto clean_exit; goto clean_exit;
} }
@ -448,7 +448,7 @@ int main(int argc, char** argv)
} }
} }
INFO("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs, pdsch_res[0].evm); INFO("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs, pdsch_res.evm[0]);
// Count the Tx/Rx'd number of bits // Count the Tx/Rx'd number of bits
nof_bits += pdsch_cfg.grant.tb[0].tbs; nof_bits += pdsch_cfg.grant.tb[0].tbs;

@ -253,12 +253,12 @@ bool cc_worker::work_dl()
srsran_softbuffer_rx_reset(&softbuffer_rx); srsran_softbuffer_rx_reset(&softbuffer_rx);
// Initialise PDSCH Result // Initialise PDSCH Result
std::array<srsran_pdsch_res_nr_t, SRSRAN_MAX_CODEWORDS> pdsch_res = {}; srsran_pdsch_res_nr_t pdsch_res = {};
pdsch_res[0].payload = data->msg; pdsch_res.tb[0].payload = data->msg;
pdsch_cfg.grant.tb[0].softbuffer.rx = &softbuffer_rx; pdsch_cfg.grant.tb[0].softbuffer.rx = &softbuffer_rx;
// Decode actual PDSCH transmission // Decode actual PDSCH transmission
if (srsran_ue_dl_nr_decode_pdsch(&ue_dl, &dl_slot_cfg, &pdsch_cfg, pdsch_res.data()) < SRSRAN_SUCCESS) { if (srsran_ue_dl_nr_decode_pdsch(&ue_dl, &dl_slot_cfg, &pdsch_cfg, &pdsch_res) < SRSRAN_SUCCESS) {
ERROR("Error decoding PDSCH"); ERROR("Error decoding PDSCH");
return false; return false;
} }
@ -266,17 +266,17 @@ bool cc_worker::work_dl()
// Logging // Logging
if (logger.info.enabled()) { if (logger.info.enabled()) {
std::array<char, 512> str; std::array<char, 512> str;
srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, pdsch_res.data(), str.data(), str.size()); srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, &pdsch_res, str.data(), str.size());
logger.info(pdsch_res[0].payload, pdsch_cfg.grant.tb[0].tbs / 8, "PDSCH: cc=%d, %s", cc_idx, str.data()); logger.info(pdsch_res.tb[0].payload, pdsch_cfg.grant.tb[0].tbs / 8, "PDSCH: cc=%d, %s", cc_idx, str.data());
} }
// Enqueue PDSCH ACK information only if the RNTI is type C // Enqueue PDSCH ACK information only if the RNTI is type C
if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_c) { if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_c) {
phy->set_pending_ack(dl_slot_cfg.idx, ack_resource, pdsch_res[0].crc); phy->set_pending_ack(dl_slot_cfg.idx, ack_resource, pdsch_res.tb[0].crc);
} }
// Notify MAC about PDSCH decoding result // Notify MAC about PDSCH decoding result
if (pdsch_res[0].crc) { if (pdsch_res.tb[0].crc) {
// Prepare grant // Prepare grant
mac_interface_phy_nr::mac_nr_grant_dl_t mac_nr_grant = {}; mac_interface_phy_nr::mac_nr_grant_dl_t mac_nr_grant = {};
mac_nr_grant.tb[0] = std::move(data); mac_nr_grant.tb[0] = std::move(data);
@ -294,8 +294,8 @@ bool cc_worker::work_dl()
// Generate DL metrics // Generate DL metrics
dl_metrics_t dl_m = {}; dl_metrics_t dl_m = {};
dl_m.mcs = pdsch_cfg.grant.tb[0].mcs; dl_m.mcs = pdsch_cfg.grant.tb[0].mcs;
dl_m.fec_iters = pdsch_res[0].fec_iters; dl_m.fec_iters = pdsch_res.tb[0].avg_iter;
dl_m.evm = pdsch_res[0].evm; dl_m.evm = pdsch_res.evm[0];
phy->set_dl_metrics(dl_m); phy->set_dl_metrics(dl_m);
// Generate Synch metrics // Generate Synch metrics
@ -386,7 +386,7 @@ bool cc_worker::work_ul()
// Setup data for encoding // Setup data for encoding
srsran_pusch_data_nr_t data = {}; srsran_pusch_data_nr_t data = {};
data.payload = ul_action.tb.payload->msg; data.payload[0] = ul_action.tb.payload->msg;
data.uci = uci_data.value; data.uci = uci_data.value;
// Encode PUSCH transmission // Encode PUSCH transmission

Loading…
Cancel
Save