Multiple NR-PUSCH fixes

This commit is contained in:
Xavier Arteaga 2021-04-16 18:33:41 +02:00 committed by Andre Puschmann
parent 7e06e789d5
commit abfc1da921
12 changed files with 229 additions and 203 deletions

View File

@ -164,6 +164,11 @@ typedef struct {
uint32_t csi1_index2; ///< Use for more than 11 CSI bits. Set to 13 if absent.
uint32_t csi2_index1; ///< Use for up to 11 CSI bits. Set to 13 if absent.
uint32_t csi2_index2; ///< Use for more than 11 CSI bits. Set to 13 if absent.
/// Fix values for testing purposes
float fix_ack; ///< Set to a non-zero value for fixing a beta offset value
float fix_csi1;
float fix_csi2;
} srsran_beta_offsets_t;
/**
@ -238,13 +243,11 @@ typedef struct SRSRAN_API {
/// PUSCH only parameters
srsran_uci_cfg_nr_t uci; ///< Uplink Control Information configuration
bool enable_transform_precoder;
float beta_harq_ack_offset;
float beta_csi_part1_offset;
float beta_csi_part2_offset;
float scaling;
bool freq_hopping_enabled;
} srsran_sch_cfg_nr_t;
SRSRAN_API uint32_t srsran_phch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len);
SRSRAN_API uint32_t srsran_sch_cfg_nr_nof_re(const srsran_sch_cfg_nr_t* sch_cfg);
SRSRAN_API uint32_t srsran_sch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len);
#endif // SRSRAN_PHCH_CFG_NR_H

View File

@ -51,7 +51,6 @@ typedef struct SRSRAN_API {
bool meas_time_en;
uint32_t meas_time_us;
srsran_re_pattern_t dmrs_re_pattern;
srsran_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

View File

@ -128,12 +128,14 @@ SRSRAN_API int srsran_ra_ul_dci_to_grant_nr(const srsran_carrier_nr_t* carrie
*
* @remark Implement procedure described in TS 38.213 9.3 UCI reporting in physical uplink shared channel
*
* @param carrier Carrier information struct
* @param pusch_hl_cfg PUSCH configuration provided by higher layers
* @param uci_cfg Uplink Control Information configuration for this PUSCH transmission
* @param pusch_cfg PUSCH configuration after applying the procedure
* @return SRSRAN_SUCCESS if the procedure is successful, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_ra_ul_set_grant_uci_nr(const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg,
SRSRAN_API int srsran_ra_ul_set_grant_uci_nr(const srsran_carrier_nr_t* carrier,
const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg,
const srsran_uci_cfg_nr_t* uci_cfg,
srsran_sch_cfg_nr_t* pusch_cfg);

View File

@ -32,8 +32,8 @@ typedef struct SRSRAN_API {
int rv; ///< Redundancy version
int ndi; ///< New Data Indicator
int pid; ///< HARQ Process ID
uint32_t nof_re; ///< Number of available resource elements to send, known as N_RE
uint32_t nof_bits; ///< Number of available bits to send, known as G
uint32_t nof_re; ///< Number of available resource elements to transmit ULSCH (data) and UCI (control)
uint32_t nof_bits; ///< Number of available bits to send ULSCH
uint32_t cw_idx;
bool enabled;

View File

@ -62,6 +62,7 @@ typedef struct {
float alpha; ///< Higher layer parameter scaling
float beta_harq_ack_offset;
float beta_csi1_offset;
float beta_csi2_offset;
uint32_t nof_re;
bool csi_part2_present;
} srsran_uci_nr_pusch_cfg_t;

View File

@ -216,28 +216,26 @@ static uint32_t phch_cfg_rvd_to_str(const srsran_re_pattern_list_t* pattern_list
return len;
}
static uint32_t phch_cfg_uci_to_str(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len)
static uint32_t phch_cfg_uci_to_str(const srsran_uci_cfg_nr_t* uci, char* str, uint32_t str_len)
{
uint32_t len = 0;
if (srsran_uci_nr_total_bits(&sch_cfg->uci) == 0) {
if (srsran_uci_nr_total_bits(uci) == 0) {
return len;
}
len = srsran_print_check(str, str_len, len, " UCI:\n", sch_cfg->scaling);
len = srsran_print_check(str, str_len, len, " scaling=%.2f\n", sch_cfg->scaling);
len = srsran_print_check(str, str_len, len, " beta_csi_part1_offset=%.2f\n", sch_cfg->beta_csi_part1_offset);
len = srsran_print_check(str, str_len, len, " beta_csi_part2_offset=%.2f\n", sch_cfg->beta_csi_part2_offset);
len = srsran_print_check(str, str_len, len, " beta_harq_ack_offset=%.2f\n", sch_cfg->beta_harq_ack_offset);
len = srsran_print_check(
str, str_len, len, " o_csi1=%d\n", srsran_csi_part1_nof_bits(sch_cfg->uci.csi, sch_cfg->uci.nof_csi));
len = srsran_print_check(str, str_len, len, " o_ack=%d\n", sch_cfg->uci.o_ack);
len = srsran_print_check(str, str_len, len, " UCI:\n");
len = srsran_print_check(str, str_len, len, " alpha=%.2f\n", uci->pusch.alpha);
len = srsran_print_check(str, str_len, len, " beta_harq_ack_offset=%.2f\n", uci->pusch.beta_harq_ack_offset);
len = srsran_print_check(str, str_len, len, " beta_csi_part1_offset=%.2f\n", uci->pusch.beta_csi1_offset);
len = srsran_print_check(str, str_len, len, " beta_csi_part2_offset=%.2f\n", uci->pusch.beta_csi1_offset);
len = srsran_print_check(str, str_len, len, " o_csi1=%d\n", srsran_csi_part1_nof_bits(uci->csi, uci->nof_csi));
len = srsran_print_check(str, str_len, len, " o_ack=%d\n", uci->o_ack);
return len;
}
uint32_t srsran_phch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len)
uint32_t srsran_sch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len)
{
uint32_t len = 0;
@ -258,7 +256,7 @@ uint32_t srsran_phch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str,
len += phch_cfg_rvd_to_str(&sch_cfg->rvd_re, &str[len], str_len - len);
// UCI configuration
len += phch_cfg_uci_to_str(sch_cfg, &str[len], str_len - len);
len += phch_cfg_uci_to_str(&sch_cfg->uci, &str[len], str_len - len);
return len;
}

View File

@ -328,121 +328,6 @@ pusch_nr_cinit(const srsran_carrier_nr_t* carrier, const srsran_sch_cfg_nr_t* cf
return cinit;
}
static inline int pusch_nr_fill_uci_cfg(srsran_pusch_nr_t* q, const srsran_sch_cfg_nr_t* cfg)
{
if (cfg->grant.nof_prb == 0) {
ERROR("Invalid number of PRB (%d)", cfg->grant.nof_prb);
return SRSRAN_ERROR;
}
// Initially, copy all fields
q->uci_cfg = cfg->uci;
// Reset UCI PUSCH configuration
SRSRAN_MEM_ZERO(&q->uci_cfg.pusch, srsran_uci_nr_pusch_cfg_t, 1);
// Get DMRS symbol indexes
uint32_t nof_dmrs_l = 0;
uint32_t dmrs_l[SRSRAN_DMRS_SCH_MAX_SYMBOLS] = {};
int n = srsran_dmrs_sch_get_symbols_idx(&cfg->dmrs, &cfg->grant, dmrs_l);
if (n < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
nof_dmrs_l = (uint32_t)n;
// Find OFDM symbol index of the first OFDM symbol after the first set of consecutive OFDM symbol(s) carrying DMRS
// Starts at first OFDM symbol carrying DMRS
for (uint32_t l = dmrs_l[0], 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]) {
// Set value and stop iterating
q->uci_cfg.pusch.l0 = l;
break;
}
// Move to the next DMRS OFDM symbol index
if (dmrs_l_idx < nof_dmrs_l) {
dmrs_l_idx++;
}
}
// Find OFDM symbol index of the first OFDM symbol that does not carry DMRS
// Starts at first OFDM symbol of the PUSCH transmission
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]) {
q->uci_cfg.pusch.l1 = l;
break;
}
// Move to the next DMRS OFDM symbol index
if (dmrs_l_idx < nof_dmrs_l) {
dmrs_l_idx++;
}
}
// Number of DMRS per PRB
uint32_t n_sc_dmrs = SRSRAN_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 < SRSRAN_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)) {
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
q->uci_cfg.pusch.M_pusch_sc[l] = cfg->grant.nof_prb * (SRSRAN_NRE - n_sc_dmrs);
// The Number of RE candidates for UCI are 0
q->uci_cfg.pusch.M_uci_sc[l] = 0;
// Advance DMRS symbol index
dmrs_l_idx++;
// Skip to next symbol
continue;
}
// Number of RE for Phase Tracking Reference Signals (PT-RS)
uint32_t M_ptrs_sc = 0; // Not implemented yet
// Number of RE given by the grant
q->uci_cfg.pusch.M_pusch_sc[l] = cfg->grant.nof_prb * SRSRAN_NRE;
// Calculate the number of UCI candidates
q->uci_cfg.pusch.M_uci_sc[l] = q->uci_cfg.pusch.M_pusch_sc[l] - M_ptrs_sc;
}
// Generate SCH Transport block information
srsran_sch_nr_tb_info_t sch_tb_info = {};
if (srsran_sch_nr_fill_tb_info(&q->carrier, &cfg->sch_cfg, &cfg->grant.tb[0], &sch_tb_info) < SRSRAN_SUCCESS) {
ERROR("Generating TB info");
return SRSRAN_ERROR;
}
// Calculate the sum of codeblock sizes
for (uint32_t i = 0; i < sch_tb_info.C; i++) {
// Accumulate codeblock size if mask is enabled
q->uci_cfg.pusch.K_sum += (sch_tb_info.mask[i]) ? sch_tb_info.Kr : 0;
}
// Set other PUSCH parameters
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_csi1_offset = cfg->beta_csi_part1_offset;
q->uci_cfg.pusch.nof_re = cfg->grant.tb[0].nof_re;
return SRSRAN_SUCCESS;
}
// Implements TS 38.212 6.2.7 Data and control multiplexing (for NR-PUSCH)
static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t* cfg)
{
@ -479,7 +364,7 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t*
if (cfg->o_ack <= 2) {
// the number of reserved resource elements for potential HARQ-ACK transmission is calculated according to Clause
// 6.3.2.4.2.1, by setting O_ACK = 2 ;
G_ack_rvd = srsran_uci_nr_pusch_ack_nof_bits(&q->uci_cfg.pusch, 2);
G_ack_rvd = srsran_uci_nr_pusch_ack_nof_bits(&cfg->pusch, 2);
// Disable non reserved HARQ-ACK bits
G_ack = 0;
@ -695,7 +580,7 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q,
}
// Encode HARQ-ACK bits
int E_uci_ack = srsran_uci_nr_encode_pusch_ack(&q->uci, &q->uci_cfg, uci, q->g_ack);
int E_uci_ack = srsran_uci_nr_encode_pusch_ack(&q->uci, &cfg->uci, uci, q->g_ack);
if (E_uci_ack < SRSRAN_SUCCESS) {
ERROR("Error encoding HARQ-ACK bits");
return SRSRAN_ERROR;
@ -703,7 +588,7 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q,
q->G_ack = (uint32_t)E_uci_ack;
// Encode CSI part 1
int E_uci_csi1 = srsran_uci_nr_encode_pusch_csi1(&q->uci, &q->uci_cfg, uci, q->g_csi1);
int E_uci_csi1 = srsran_uci_nr_encode_pusch_csi1(&q->uci, &cfg->uci, uci, q->g_csi1);
if (E_uci_csi1 < SRSRAN_SUCCESS) {
ERROR("Error encoding HARQ-ACK bits");
return SRSRAN_ERROR;
@ -715,7 +600,7 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q,
q->G_csi2 = 0;
// Generate PUSCH UCI/UL-SCH multiplexing
if (pusch_nr_gen_mux_uci(q, &q->uci_cfg) < SRSRAN_SUCCESS) {
if (pusch_nr_gen_mux_uci(q, &cfg->uci) < SRSRAN_SUCCESS) {
ERROR("Error generating PUSCH mux tables");
return SRSRAN_ERROR;
}
@ -727,7 +612,8 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q,
}
// Multiplex UL-SCH with UCI only if it is necessary
uint8_t* b = q->g_ulsch;
uint32_t nof_bits = tb->nof_re * srsran_mod_bits_x_symbol(tb->mod);
uint8_t* b = q->g_ulsch;
if (q->uci_mux) {
// Change b location
b = q->b[tb->cw_idx];
@ -755,15 +641,15 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q,
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
DEBUG("b=");
srsran_vec_fprint_b(stdout, b, tb->nof_bits);
srsran_vec_fprint_b(stdout, b, nof_bits);
}
// 7.3.1.1 Scrambling
uint32_t cinit = pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx);
srsran_sequence_apply_bit(b, q->b[tb->cw_idx], tb->nof_bits, cinit);
srsran_sequence_apply_bit(b, q->b[tb->cw_idx], nof_bits, cinit);
// Special Scrambling condition
if (q->uci_cfg.o_ack <= 2) {
if (cfg->uci.o_ack <= 2) {
for (uint32_t i = 0; i < q->G_ack; i++) {
uint32_t idx = q->pos_ack[i];
if (q->g_ack[i] == (uint8_t)UCI_BIT_REPETITION) {
@ -777,7 +663,7 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q,
}
// 7.3.1.2 Modulation
srsran_mod_modulate(&q->modem_tables[tb->mod], q->b[tb->cw_idx], q->d[tb->cw_idx], tb->nof_bits);
srsran_mod_modulate(&q->modem_tables[tb->mod], q->b[tb->cw_idx], q->d[tb->cw_idx], nof_bits);
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
DEBUG("d=");
@ -795,6 +681,7 @@ int srsran_pusch_nr_encode(srsran_pusch_nr_t* q,
{
// Check input pointers
if (!q || !cfg || !grant || !data || !sf_symbols) {
ERROR("Invalid inputs");
return SRSRAN_ERROR_INVALID_INPUTS;
}
@ -815,12 +702,6 @@ int srsran_pusch_nr_encode(srsran_pusch_nr_t* q,
return SRSRAN_ERROR;
}
// Fill UCI configuration for PUSCH configuration
if (pusch_nr_fill_uci_cfg(q, cfg) < SRSRAN_SUCCESS) {
ERROR("Error filling UCI configuration for PUSCH");
return SRSRAN_ERROR;
}
// 7.3.1.1 and 7.3.1.2
uint32_t nof_cw = 0;
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
@ -895,8 +776,11 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
srsran_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re);
}
// Total number of bits
uint32_t nof_bits = tb->nof_re * srsran_mod_bits_x_symbol(tb->mod);
// Calculate HARQ-ACK bits
int n = srsran_uci_nr_pusch_ack_nof_bits(&q->uci_cfg.pusch, q->uci_cfg.o_ack);
int n = srsran_uci_nr_pusch_ack_nof_bits(&cfg->uci.pusch, cfg->uci.o_ack);
if (n < SRSRAN_SUCCESS) {
ERROR("Calculating G_ack");
return SRSRAN_ERROR;
@ -904,7 +788,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
q->G_ack = (uint32_t)n;
// Calculate CSI part 1 bits
n = srsran_uci_nr_pusch_csi1_nof_bits(&q->uci_cfg);
n = srsran_uci_nr_pusch_csi1_nof_bits(&cfg->uci);
if (n < SRSRAN_SUCCESS) {
ERROR("Calculating G_csi1");
return SRSRAN_ERROR;
@ -916,7 +800,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
q->G_csi2 = 0;
// Generate PUSCH UCI/UL-SCH multiplexing
if (pusch_nr_gen_mux_uci(q, &q->uci_cfg) < SRSRAN_SUCCESS) {
if (pusch_nr_gen_mux_uci(q, &cfg->uci) < SRSRAN_SUCCESS) {
ERROR("Error generating PUSCH mux tables");
return SRSRAN_ERROR;
}
@ -929,16 +813,15 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
// EVM
if (q->evm_buffer != NULL) {
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);
res->evm[tb->cw_idx] = srsran_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, nof_bits);
}
// Descrambling
srsran_sequence_apply_c(llr, llr, tb->nof_bits, pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx));
srsran_sequence_apply_c(llr, llr, nof_bits, pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx));
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
DEBUG("b=");
srsran_vec_fprint_bs(stdout, llr, tb->nof_bits);
srsran_vec_fprint_bs(stdout, llr, nof_bits);
}
// Demultiplex UCI only if necessary
@ -948,7 +831,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
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++) {
for (uint32_t i = q->G_ulsch; i < nof_bits; i++) {
g_ulsch[i] = 0;
}
@ -972,7 +855,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
// Decode HARQ-ACK
if (q->G_ack) {
if (srsran_uci_nr_decode_pusch_ack(&q->uci, &q->uci_cfg, g_ack, &res->uci)) {
if (srsran_uci_nr_decode_pusch_ack(&q->uci, &cfg->uci, g_ack, &res->uci)) {
ERROR("Error in UCI decoding");
return SRSRAN_ERROR;
}
@ -980,7 +863,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
// Decode CSI part 1
if (q->G_csi1) {
if (srsran_uci_nr_decode_pusch_csi1(&q->uci, &q->uci_cfg, g_csi1, &res->uci)) {
if (srsran_uci_nr_decode_pusch_csi1(&q->uci, &cfg->uci, g_csi1, &res->uci)) {
ERROR("Error in UCI decoding");
return SRSRAN_ERROR;
}
@ -992,13 +875,13 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
// Change LLR pointer
llr = g_ulsch;
} else {
for (uint32_t i = 0; i < tb->nof_bits; i++) {
for (uint32_t i = 0; i < nof_bits; i++) {
llr[i] *= -1;
}
}
// Decode Ul-SCH
if (tb->nof_bits != 0) {
if (nof_bits != 0) {
if (srsran_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, &res->tb[tb->cw_idx]) < SRSRAN_SUCCESS) {
ERROR("Error in SCH decoding");
return SRSRAN_ERROR;
@ -1037,12 +920,6 @@ int srsran_pusch_nr_decode(srsran_pusch_nr_t* q,
return SRSRAN_ERROR;
}
// Fill UCI configuration for PUSCH configuration
if (pusch_nr_fill_uci_cfg(q, cfg) < SRSRAN_SUCCESS) {
ERROR("Error filling UCI configuration for PUSCH");
return SRSRAN_ERROR;
}
uint32_t nof_cw = 0;
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
nof_cw += grant->tb[tb].enabled ? 1 : 0;

View File

@ -16,6 +16,7 @@
#include "srsran/phy/phch/pdsch_nr.h"
#include "srsran/phy/phch/ra_dl_nr.h"
#include "srsran/phy/phch/ra_ul_nr.h"
#include "srsran/phy/phch/uci_nr.h"
#include "srsran/phy/utils/debug.h"
typedef struct {
@ -814,6 +815,10 @@ int srsran_ra_ul_dci_to_grant_nr(const srsran_carrier_nr_t* carrier,
static float ra_ul_beta_offset_ack_semistatic(const srsran_beta_offsets_t* beta_offsets,
const srsran_uci_cfg_nr_t* uci_cfg)
{
if (isnormal(beta_offsets->fix_ack)) {
return beta_offsets->fix_ack;
}
// Select Beta Offset index from the number of HARQ-ACK bits
uint32_t beta_offset_index = beta_offsets->ack_index1;
if (uci_cfg->o_ack > 11) {
@ -843,6 +848,11 @@ static float ra_ul_beta_offset_csi_semistatic(const srsran_beta_offsets_t* beta_
const srsran_uci_cfg_nr_t* uci_cfg,
bool part2)
{
float fix_beta_offset = part2 ? beta_offsets->fix_csi2 : beta_offsets->fix_csi1;
if (isnormal(fix_beta_offset)) {
return fix_beta_offset;
}
// Calculate number of CSI bits; CSI part 2 is not supported.
uint32_t O_csi = part2 ? 0 : srsran_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi);
@ -865,35 +875,162 @@ static float ra_ul_beta_offset_csi_semistatic(const srsran_beta_offsets_t* beta_
return ra_nr_beta_offset_csi_table[beta_offset_index];
}
int srsran_ra_ul_set_grant_uci_nr(const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg,
int srsran_ra_ul_set_grant_uci_nr(const srsran_carrier_nr_t* carrier,
const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg,
const srsran_uci_cfg_nr_t* uci_cfg,
srsran_sch_cfg_nr_t* pusch_cfg)
{
// Select beta offsets
pusch_cfg->beta_harq_ack_offset = ra_ul_beta_offset_ack_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg);
if (!isnormal(pusch_cfg->beta_harq_ack_offset)) {
if (pusch_cfg->grant.nof_prb == 0) {
ERROR("Invalid number of PRB (%d)", pusch_cfg->grant.nof_prb);
return SRSRAN_ERROR;
}
pusch_cfg->beta_csi_part1_offset = ra_ul_beta_offset_csi_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg, false);
if (!isnormal(pusch_cfg->beta_csi_part1_offset)) {
return SRSRAN_ERROR;
}
pusch_cfg->beta_csi_part2_offset = ra_ul_beta_offset_csi_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg, true);
if (!isnormal(pusch_cfg->beta_csi_part2_offset)) {
return SRSRAN_ERROR;
}
// pusch_cfg->beta_csi_part2_offset = pusch_hl_cfg->beta_offset_csi2;
pusch_cfg->scaling = pusch_hl_cfg->scaling;
if (!isnormal(pusch_cfg->scaling)) {
ERROR("Invalid Scaling (%f)", pusch_cfg->scaling);
return SRSRAN_ERROR;
}
// Copy UCI configuration
// Initially, copy all fields
pusch_cfg->uci = *uci_cfg;
// Reset UCI PUSCH configuration
SRSRAN_MEM_ZERO(&pusch_cfg->uci.pusch, srsran_uci_nr_pusch_cfg_t, 1);
// Get DMRS symbol indexes
uint32_t nof_dmrs_l = 0;
uint32_t dmrs_l[SRSRAN_DMRS_SCH_MAX_SYMBOLS] = {};
int n = srsran_dmrs_sch_get_symbols_idx(&pusch_cfg->dmrs, &pusch_cfg->grant, dmrs_l);
if (n < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
nof_dmrs_l = (uint32_t)n;
// Find OFDM symbol index of the first OFDM symbol after the first set of consecutive OFDM symbol(s) carrying DMRS
// Starts at first OFDM symbol carrying DMRS
for (uint32_t l = dmrs_l[0], dmrs_l_idx = 0; l < pusch_cfg->grant.S + pusch_cfg->grant.L; l++) {
// Check if it is not carrying DMRS...
if (l != dmrs_l[dmrs_l_idx]) {
// Set value and stop iterating
pusch_cfg->uci.pusch.l0 = l;
break;
}
// Move to the next DMRS OFDM symbol index
if (dmrs_l_idx < nof_dmrs_l) {
dmrs_l_idx++;
}
}
// Find OFDM symbol index of the first OFDM symbol that does not carry DMRS
// Starts at first OFDM symbol of the PUSCH transmission
for (uint32_t l = pusch_cfg->grant.S, dmrs_l_idx = 0; l < pusch_cfg->grant.S + pusch_cfg->grant.L; l++) {
// Check if it is not carrying DMRS...
if (l != dmrs_l[dmrs_l_idx]) {
pusch_cfg->uci.pusch.l1 = l;
break;
}
// Move to the next DMRS OFDM symbol index
if (dmrs_l_idx < nof_dmrs_l) {
dmrs_l_idx++;
}
}
// Number of DMRS per PRB
uint32_t n_sc_dmrs = SRSRAN_DMRS_SCH_SC(pusch_cfg->grant.nof_dmrs_cdm_groups_without_data, pusch_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 < SRSRAN_NSYMB_PER_SLOT_NR; l++) {
// Skip if OFDM symbol is outside of the PUSCH transmission
if (l < pusch_cfg->grant.S || l >= (pusch_cfg->grant.S + pusch_cfg->grant.L)) {
pusch_cfg->uci.pusch.M_pusch_sc[l] = 0;
pusch_cfg->uci.pusch.M_uci_sc[l] = 0;
continue;
}
// OFDM symbol carries DMRS
if (l == dmrs_l[dmrs_l_idx]) {
// Calculate PUSCH RE candidates
pusch_cfg->uci.pusch.M_pusch_sc[l] = pusch_cfg->grant.nof_prb * (SRSRAN_NRE - n_sc_dmrs);
// The Number of RE candidates for UCI are 0
pusch_cfg->uci.pusch.M_uci_sc[l] = 0;
// Advance DMRS symbol index
dmrs_l_idx++;
// Skip to next symbol
continue;
}
// Number of RE for Phase Tracking Reference Signals (PT-RS)
uint32_t M_ptrs_sc = 0; // Not implemented yet
// Number of RE given by the grant
pusch_cfg->uci.pusch.M_pusch_sc[l] = pusch_cfg->grant.nof_prb * SRSRAN_NRE;
// Calculate the number of UCI candidates
pusch_cfg->uci.pusch.M_uci_sc[l] = pusch_cfg->uci.pusch.M_pusch_sc[l] - M_ptrs_sc;
}
// Generate SCH Transport block information
srsran_sch_nr_tb_info_t sch_tb_info = {};
if (srsran_sch_nr_fill_tb_info(carrier, &pusch_cfg->sch_cfg, &pusch_cfg->grant.tb[0], &sch_tb_info) <
SRSRAN_SUCCESS) {
ERROR("Generating TB info");
return SRSRAN_ERROR;
}
// Calculate the sum of codeblock sizes
for (uint32_t i = 0; i < sch_tb_info.C; i++) {
// Accumulate codeblock size if mask is enabled
pusch_cfg->uci.pusch.K_sum += (sch_tb_info.mask[i]) ? sch_tb_info.Kr : 0;
}
// Set other PUSCH parameters
pusch_cfg->uci.pusch.modulation = pusch_cfg->grant.tb[0].mod;
pusch_cfg->uci.pusch.nof_layers = pusch_cfg->grant.nof_layers;
pusch_cfg->uci.pusch.R = (float)pusch_cfg->grant.tb[0].R;
pusch_cfg->uci.pusch.nof_re = pusch_cfg->grant.tb[0].nof_re;
// Select beta offsets
pusch_cfg->uci.pusch.beta_harq_ack_offset = ra_ul_beta_offset_ack_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg);
if (!isnormal(pusch_cfg->uci.pusch.beta_harq_ack_offset)) {
return SRSRAN_ERROR;
}
pusch_cfg->uci.pusch.beta_csi1_offset = ra_ul_beta_offset_csi_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg, false);
if (!isnormal(pusch_cfg->uci.pusch.beta_csi1_offset)) {
return SRSRAN_ERROR;
}
pusch_cfg->uci.pusch.beta_csi2_offset = ra_ul_beta_offset_csi_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg, true);
if (!isnormal(pusch_cfg->uci.pusch.beta_csi2_offset)) {
return SRSRAN_ERROR;
}
pusch_cfg->uci.pusch.alpha = pusch_hl_cfg->scaling;
if (!isnormal(pusch_cfg->uci.pusch.alpha)) {
ERROR("Invalid Scaling (%f)", pusch_cfg->uci.pusch.alpha);
return SRSRAN_ERROR;
}
// Calculate number of UCI encoded bits
int Gack = 0;
if (pusch_cfg->uci.o_ack > 2) {
Gack = srsran_uci_nr_pusch_ack_nof_bits(&pusch_cfg->uci.pusch, pusch_cfg->uci.o_ack);
if (Gack < SRSRAN_SUCCESS) {
ERROR("Error calculating Qdack");
return SRSRAN_ERROR;
}
}
int Gcsi1 = srsran_uci_nr_pusch_csi1_nof_bits(&pusch_cfg->uci);
if (Gcsi1 < SRSRAN_SUCCESS) {
ERROR("Error calculating Qdack");
return SRSRAN_ERROR;
}
int Gcsi2 = 0; // NOT supported
// Update Number of TB encoded bits
for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) {
pusch_cfg->grant.tb[i].nof_bits =
pusch_cfg->grant.tb[i].nof_re * srsran_mod_bits_x_symbol(pusch_cfg->grant.tb[i].mod) - Gack - Gcsi1 - Gcsi2;
}
return SRSRAN_SUCCESS;
}

View File

@ -187,9 +187,11 @@ int main(int argc, char** argv)
mcs_end = SRSRAN_MIN(mcs + 1, mcs_end);
}
pusch_cfg.scaling = 0.5f;
pusch_cfg.beta_harq_ack_offset = 2.0f;
pusch_cfg.beta_csi_part1_offset = 2.0f;
srsran_sch_hl_cfg_nr_t sch_hl_cfg = {};
sch_hl_cfg.scaling = 1.0f;
sch_hl_cfg.beta_offsets.fix_ack = 12.625f;
sch_hl_cfg.beta_offsets.fix_csi1 = 2.25f;
sch_hl_cfg.beta_offsets.fix_csi2 = 2.25f;
if (srsran_chest_dl_res_init(&chest, carrier.nof_prb) < SRSRAN_SUCCESS) {
ERROR("Initiating chest");
@ -245,6 +247,11 @@ int main(int argc, char** argv)
data_rx.uci.csi[0].none = csi_report_rx;
}
if (srsran_ra_ul_set_grant_uci_nr(&carrier, &sch_hl_cfg, &pusch_cfg.uci, &pusch_cfg) < SRSRAN_SUCCESS) {
ERROR("Setting UCI");
goto clean_exit;
}
if (srsran_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_cfg.grant, &data_tx, sf_symbols) < SRSRAN_SUCCESS) {
ERROR("Error encoding");
goto clean_exit;
@ -345,7 +352,7 @@ int main(int argc, char** argv)
srsran_pusch_nr_rx_info(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &data_rx, str, (uint32_t)sizeof(str));
char str_extra[2048];
srsran_phch_cfg_nr_info(&pusch_cfg, str_extra, (uint32_t)sizeof(str_extra));
srsran_sch_cfg_nr_info(&pusch_cfg, str_extra, (uint32_t)sizeof(str_extra));
INFO("PUSCH: %s\n%s", str, str_extra);
}

View File

@ -383,16 +383,18 @@ static int uci_nr_decode_1_bit(srsran_uci_nr_t* q,
}
// Correlate LLR
float corr = 0.0f;
float pwr = 0.0f;
float corr = 0.0f;
float pwr = 0.0f;
uint32_t count = 0;
for (uint32_t i = 0; i < E; i += Qm) {
float t = (float)llr[i];
corr += t;
pwr += t * t;
count++;
}
// Normalise correlation
float norm_corr = Qm * corr / (E * sqrtf(pwr));
float norm_corr = fabsf(corr) / sqrtf(pwr * count);
// Take decoded decision with threshold
*decoded_ok = (norm_corr > q->one_bit_threshold);

View File

@ -453,7 +453,7 @@ int main(int argc, char** argv)
srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, &pdsch_res, str, (uint32_t)sizeof(str));
char str_extra[2048];
srsran_phch_cfg_nr_info(&pdsch_cfg, str_extra, (uint32_t)sizeof(str_extra));
srsran_sch_cfg_nr_info(&pdsch_cfg, str_extra, (uint32_t)sizeof(str_extra));
INFO("PDSCH: %s\n%s", str, str_extra);
}

View File

@ -276,7 +276,7 @@ bool cc_worker::work_dl()
if (logger.debug.enabled()) {
str_extra_t str_extra;
srsran_phch_cfg_nr_info(&pdsch_cfg, str_extra.data(), (uint32_t)str_extra.size());
srsran_sch_cfg_nr_info(&pdsch_cfg, str_extra.data(), (uint32_t)str_extra.size());
logger.info(pdsch_res.tb[0].payload,
pdsch_cfg.grant.tb[0].tbs / 8,
"PDSCH: cc=%d, %s\n%s",
@ -392,7 +392,7 @@ bool cc_worker::work_ul()
}
// Set UCI configuration following procedures
srsran_ra_ul_set_grant_uci_nr(&phy->cfg.pusch, &uci_data.cfg, &pusch_cfg);
srsran_ra_ul_set_grant_uci_nr(&phy->carrier, &phy->cfg.pusch, &uci_data.cfg, &pusch_cfg);
// Assigning MAC provided values to PUSCH config structs
pusch_cfg.grant.tb[0].softbuffer.tx = ul_action.tb.softbuffer;
@ -415,7 +415,7 @@ bool cc_worker::work_ul()
if (logger.debug.enabled()) {
str_extra_t str_extra;
srsran_phch_cfg_nr_info(&pusch_cfg, str_extra.data(), (uint32_t)str_extra.size());
srsran_sch_cfg_nr_info(&pusch_cfg, str_extra.data(), (uint32_t)str_extra.size());
logger.info(ul_action.tb.payload->msg,
pusch_cfg.grant.tb[0].tbs / 8,
"PUSCH: cc=%d %s tti_tx=%d\n%s",