Initial UCI bits multiplexing in PUSCH

This commit is contained in:
Xavier Arteaga 2021-03-03 19:54:55 +01:00 committed by Xavier Arteaga
parent f4e9d00ea8
commit 9dffad87f2
18 changed files with 617 additions and 191 deletions

View File

@ -37,6 +37,14 @@ SRSLTE_API int srslte_csi_generate_reports(const srslte_csi_hl_cfg_t* cfg,
*/
SRSLTE_API int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports);
/**
* @brief Checks if the report list contains part 2 CSI report
* @param report_list Report list
* @param nof_reports Number of reports in the list
* @return True if at least one report contains part 2, false otherwise
*/
SRSLTE_API bool srslte_csi_has_part2(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports);
/**
* @brief Pack CSI part 1 bits for a PUCCH transmission
* @param report_list Provides the CSI report list

View File

@ -130,6 +130,7 @@ typedef struct SRSLTE_API {
// Resource set context
uint32_t nof_ports; ///< Number of antenna ports
uint32_t K_csi_rs; ///< Number of CSI-RS in the corresponding resource set
bool has_part2; ///< Set to true if the report has part 2
} srslte_csi_report_cfg_t;
/**

View File

@ -208,6 +208,7 @@ typedef struct SRSLTE_API {
float beta_harq_ack_offset;
float beta_csi_part1_offset;
float scaling;
bool freq_hopping_enabled;
} srslte_sch_cfg_nr_t;
#endif // SRSLTE_PHCH_CFG_NR_H

View File

@ -50,8 +50,17 @@ typedef struct SRSLTE_API {
srslte_evm_buffer_t* evm_buffer;
bool meas_time_en;
uint32_t meas_time_us;
uint8_t* uci_ack;
uint8_t* uci_csi;
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
uint8_t* g_csi2; ///< Temporal Encoded CSI part 2 bits
uint32_t* pos_ulsch; ///< Reserved resource elements for HARQ-ACK multiplexing position
uint32_t* pos_ack; ///< Reserved resource elements for HARQ-ACK multiplexing position
uint32_t* pos_csi1; ///< Reserved resource elements for CSI part 1 multiplexing position
uint32_t* pos_csi2; ///< Reserved resource elements for CSI part 1 multiplexing position
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
} srslte_pusch_nr_t;
/**

View File

@ -52,7 +52,7 @@ SRSLTE_API int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int
srslte_ra_ul_nr_pdsch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant);
srslte_ra_ul_nr_pusch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the number of PUSCH-DMRS CDM groups without data for DCI format 0_0

View File

@ -107,10 +107,10 @@ SRSLTE_API srslte_basegraph_t srslte_sch_nr_select_basegraph(uint32_t tbs, doubl
* @param cfg SCH object
* @return
*/
SRSLTE_API int srslte_sch_nr_fill_cfg(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
srslte_sch_nr_tb_info_t* cfg);
SRSLTE_API int srslte_sch_nr_fill_tb_info(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
srslte_sch_nr_tb_info_t* cfg);
/**
* @brief Initialises an SCH object as transmitter

View File

@ -14,7 +14,7 @@
#define SRSLTE_UCI_CFG_NR_H
#include "csi_cfg.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/common/phy_common_nr.h"
#include <stdbool.h>
#include <stdint.h>
@ -35,6 +35,37 @@
*/
#define SRSLTE_UCI_NR_MAX_CSI1_BITS 10
/**
* @brief Uplink Control Information bits configuration for PUCCH transmission
*/
typedef struct {
uint16_t rnti; ///< RNTI
uint32_t resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1
uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception
uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or 1_1
uint32_t sr_resource_id; ///< Scheduling request resource identifier, only valid if positive SR
bool sr_positive_present; ///< Set to true if there is at least one positive SR
} srslte_uci_nr_pucch_cfg_t;
/**
* @brief Uplink Control Information bits configuration for PUSCH transmission
*/
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
float beta_harq_ack_offset;
float beta_csi_part1_offset;
uint32_t nof_re;
} srslte_uci_nr_pusch_cfg_t;
/**
* @brief Uplink Control Information (UCI) message configuration
*/
@ -44,18 +75,10 @@ typedef struct SRSLTE_API {
uint32_t o_sr; ///< Number of SR bits
srslte_csi_report_cfg_t csi[SRSLTE_CSI_MAX_NOF_REPORT]; ///< CSI report configuration
uint32_t nof_csi; ///< Number of CSI reports
/// PUSCH only parameters
bool without_ul_sch; ///< Set to true if no UL-SCH data is scheduled
bool has_csi_part2; ///< Set to true if the CSI reports have part 2
/// PUCCH only parameters
uint16_t rnti; ///< RNTI
uint32_t pucch_resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1
uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception
uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or 1_1
uint32_t sr_resource_id; ///< Scheduling request resource identifier, only valid if positive SR
bool sr_positive_present; ///< Set to true if there is at least one positive SR
union {
srslte_uci_nr_pucch_cfg_t pucch; ///< Configuration for transmission in PUCCH
srslte_uci_nr_pusch_cfg_t pusch; ///< Configuration for transmission in PUSCH
};
} srslte_uci_cfg_nr_t;
/**

View File

@ -125,23 +125,33 @@ SRSLTE_API int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
srslte_uci_value_nr_t* value);
/**
* @brief Calculates the total number of encoded bits for HARQ-ACK
* @brief Calculates total number of resource elements for HARQ-ACK multiplexing in PUSCH
* @remark Implementation according to TS 38.312 clause 6.3.2.4.1.1 for UCI encoded by polar code
* @remark Implementation according to TS 38.312 clause 6.3.2.4.2.1 for UCI encoded by channel codig of small lengths
* @param cfg UCI NR PUSCH configuration
* @param O_ack Number of ACK
* @return The number of resource elements for HARQ-ACK in a PUSCH transmission
*/
SRSLTE_API int srslte_uci_nr_pusch_ack_nof_re(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack);
/**
* @brief Calculates total number of ebncoded bits for HARQ-ACK multiplexing in PUSCH
* @param[in,out] q NR-UCI object
* @param[in] cfg PUSCH transmission configuration
* @return The number of encoded bits if successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_uci_nr_pusch_E_uci_ack(srslte_uci_nr_t* q, const srslte_sch_cfg_nr_t* cfg);
SRSLTE_API int srslte_uci_nr_pusch_ack_nof_bits(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack);
/**
* @brief Encodes HARQ-ACK bits for PUSCH transmission
* @param[in,out] q NR-UCI object
* @param[in] cfg PUSCH transmission configuration
* @param[in] cfg UCI configuration
* @param[in] value UCI value
* @param[out] o_ack Encoded ack bits
* @return The number of encoded bits if successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_uci_cfg_nr_t* cfg,
const srslte_uci_value_nr_t* value,
uint8_t* o_ack);

View File

@ -172,6 +172,20 @@ int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof
return (int)count;
}
bool srslte_csi_has_part2(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports)
{
if (report_list == NULL || nof_reports == 0) {
return false;
}
for (uint32_t i = 0; i < nof_reports; i++) {
if (report_list[i].has_part2) {
return true;
}
}
return false;
}
int srslte_csi_part1_pack(const srslte_csi_report_cfg_t* report_cfg,
const srslte_csi_report_value_t* report_value,
uint32_t nof_reports,

View File

@ -194,7 +194,7 @@ static void srslte_pdsch_re_cp(cf_t* sf_symbols, cf_t* symbols, uint32_t count,
* As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with group 2:
*
* +---+---+---+---+---+---+---+---+---+---+---+---+
* | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 |
* | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* -- k -->
*

View File

@ -538,7 +538,7 @@ static uint32_t pucch_nr_format2_cinit(const srslte_carrier_nr_t* carri
{
uint32_t n_id = (pucch_cfg->scrambling_id_present) ? pucch_cfg->scrambling_id_present : carrier->id;
return ((uint32_t)uci_cfg->rnti << 15U) + n_id;
return ((uint32_t)uci_cfg->pucch.rnti << 15U) + n_id;
}
// Implements TS 38.211 section 6.3.2.5 PUCCH format 2

View File

@ -33,6 +33,24 @@ int pusch_nr_init_common(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* arg
return SRSLTE_ERROR;
}
q->g_ulsch = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->g_ack = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->g_csi1 = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->g_csi2 = srslte_vec_u8_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
if (q->g_ack == NULL || q->g_csi1 == NULL || q->g_csi2 == NULL || q->g_ulsch == NULL) {
ERROR("Malloc");
return SRSLTE_ERROR;
}
q->pos_ulsch = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->pos_ack = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->pos_csi1 = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
q->pos_csi2 = srslte_vec_u32_malloc(SRSLTE_SLOT_MAX_LEN_RE_NR);
if (q->pos_ack == NULL || q->pos_csi1 == NULL || q->pos_csi2 == NULL || q->pos_ulsch == NULL) {
ERROR("Malloc");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
@ -151,6 +169,32 @@ void srslte_pusch_nr_free(srslte_pusch_nr_t* q)
return;
}
if (q->g_ulsch != NULL) {
free(q->g_ulsch);
}
if (q->g_ack != NULL) {
free(q->g_ack);
}
if (q->g_csi1 != NULL) {
free(q->g_csi1);
}
if (q->g_csi2 != NULL) {
free(q->g_csi2);
}
if (q->pos_ulsch != NULL) {
free(q->pos_ulsch);
}
if (q->pos_ack != NULL) {
free(q->pos_ack);
}
if (q->pos_csi1 != NULL) {
free(q->pos_csi1);
}
if (q->pos_csi2 != NULL) {
free(q->pos_csi2);
}
for (uint32_t cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) {
if (q->b[cw]) {
free(q->b[cw]);
@ -176,6 +220,8 @@ void srslte_pusch_nr_free(srslte_pusch_nr_t* q)
if (q->evm_buffer != NULL) {
srslte_evm_free(q->evm_buffer);
}
SRSLTE_MEM_ZERO(q, srslte_pusch_nr_t, 1);
}
/**
@ -420,13 +466,302 @@ pusch_nr_cinit(const srslte_carrier_nr_t* carrier, const srslte_sch_cfg_nr_t* cf
return cinit;
}
// int pusch_nr_mux_uci(srslte_pusch_nr_t* q) {
// uint8_t *g_ul_sch; // coded bits for UL-SCH
// uint8_t *g_ack; // coded bits for HARQ-ACK
// uint8_t *g_csi_p1; // coded bits for CSI part 1
// uint8_t *g_csi_p2; // coded bits for CSI part 2
//
//}
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)
{
// Initially, copy all fields
*uci_cfg = cfg->uci;
// Reset UCI PUSCH configuration
SRSLTE_MEM_ZERO(&uci_cfg->pusch, srslte_uci_nr_pusch_cfg_t, 1);
// Get DMRS symbol indexes
uint32_t nof_dmrs_l = 0;
uint32_t dmrs_l[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int n = srslte_dmrs_sch_get_symbols_idx(&cfg->dmrs, &cfg->grant, dmrs_l);
if (n < SRSLTE_SUCCESS) {
return SRSLTE_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
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]) {
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
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;
// 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;
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];
// The Number of RE candidates for UCI are 0
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
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;
}
// Generate SCH Transport block information
srslte_sch_nr_tb_info_t sch_tb_info = {};
if (srslte_sch_nr_fill_tb_info(&q->carrier, &cfg->sch_cfg, &cfg->grant.tb[0], &sch_tb_info) < SRSLTE_SUCCESS) {
ERROR("Generating TB info");
return SRSLTE_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
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;
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)
{
// Bit positions
uint32_t* pos_ulsch = q->pos_ulsch; // coded bits for UL-SCH
uint32_t* pos_ack = q->pos_ack; // coded bits for HARQ-ACK
uint32_t* pos_csi1 = q->pos_csi1; // coded bits for CSI part 1
uint32_t* pos_csi2 = q->pos_csi2; // coded bits for CSI part 2
// Key OFDM symbol indexes
uint32_t l1 =
cfg->pusch.l0; // First OFDM symbol that does not carry DMRS of the PUSCH, after the first DMRS symbol(s)
uint32_t l1_csi = cfg->pusch.l1; // OFDM symbol index of the first OFDM symbol that does not carry DMRS
// Number of UCI bits
uint32_t G_ack = q->G_ack;
uint32_t G_csi1 = q->G_csi1;
uint32_t G_csi2 = q->G_csi2;
// Other...
uint32_t Nl = cfg->pusch.nof_layers;
uint32_t Qm = srslte_mod_bits_x_symbol(cfg->pusch.modulation);
// If 2 or less HARQ-ACK bits, use reserve
uint32_t G_ack_rvd = 0;
if (cfg->o_ack <= 2) {
G_ack_rvd = G_ack;
G_ack = 0;
}
// Counters
uint32_t m_ack_count = 0;
uint32_t m_csi1_count = 0;
uint32_t m_csi2_count = 0;
uint32_t m_ulsch_count = 0;
uint32_t m_all_count = 0;
for (uint32_t l = 0; l < SRSLTE_NSYMB_PER_SLOT_NR; l++) {
// Skip if symbol has potential for data
if (cfg->pusch.M_pusch_sc[l] == 0) {
continue;
}
// Put UL-SCH only if this OFDM symbol has no potential for UCI
if (cfg->pusch.M_uci_sc[l] == 0) {
for (uint32_t i = 0; i < cfg->pusch.M_pusch_sc[l] * Qm * Nl; i++) {
pos_ulsch[m_ulsch_count++] = m_all_count++;
}
continue;
}
uint32_t M_ulsch_sc = cfg->pusch.M_pusch_sc[l];
uint32_t M_uci_sc = cfg->pusch.M_uci_sc[l];
uint32_t M_uci_rvd = 0;
// 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) {
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);
}
M_uci_rvd = ack_m_re_count;
} else {
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;
}
M_uci_sc -= ack_m_re_count;
}
}
// Compute CSI part 1 bits multiplexing
uint32_t csi1_d = 0;
uint32_t csi1_m_re_count = 0;
if (l >= l1_csi && M_uci_sc > M_uci_rvd && m_csi1_count < G_csi1) {
csi1_d = 1;
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);
}
M_uci_sc -= csi1_m_re_count;
}
// Compute CSI part 2 bits multiplexing
uint32_t csi2_d = 0;
uint32_t csi2_m_re_count = 0;
if (l >= l1_csi && M_uci_sc > M_uci_rvd && m_csi2_count < G_csi2) {
csi2_d = 1;
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);
}
M_uci_sc -= csi2_m_re_count;
}
// 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++) {
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++;
}
ack_m_re_count--;
} else if (csi1_m_re_count != 0 && csi1_i % csi1_d == 0 && m_csi1_count < G_csi1) {
for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_csi1[m_csi1_count++] = m_all_count++;
}
csi1_m_re_count--;
csi1_i++;
} else if (csi2_m_re_count != 0 && csi2_i % csi2_d == 0 && m_csi2_count < G_csi2) {
for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_csi2[m_csi2_count++] = m_all_count++;
}
csi2_m_re_count--;
csi1_i++;
csi2_i++;
} else {
for (uint32_t j = 0; j < Nl * Qm; j++) {
pos_ulsch[m_ulsch_count++] = m_all_count++;
}
ulsch_m_re_count--;
csi1_i++;
csi2_i++;
}
// Set reserved bits
if (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++;
}
ack_m_re_count--;
}
}
// Checks that all RE are allocated as planned
if (ack_m_re_count != 0) {
ERROR("ack_m_re_count=%d", ack_m_re_count);
}
if (csi1_m_re_count != 0) {
ERROR("csi1_m_re_count=%d", csi1_m_re_count);
}
if (csi2_m_re_count != 0) {
ERROR("csi2_m_re_count=%d", csi2_m_re_count);
}
if (ulsch_m_re_count != 0) {
ERROR("ulsch_m_re_count=%d", ulsch_m_re_count);
}
}
if (G_ack_rvd != 0 && G_ack_rvd != m_ack_count) {
ERROR("Not matched %d!=%d", G_ack_rvd, m_ack_count);
}
if (G_ack != 0 && G_ack != m_ack_count) {
ERROR("Not matched %d!=%d", G_ack, m_ack_count);
}
if (G_csi1 != 0 && G_csi1 != m_csi1_count) {
ERROR("Not matched %d!=%d", G_csi1, m_csi1_count);
}
if (G_csi2 != 0 && G_csi2 != m_csi2_count) {
ERROR("Not matched %d!=%d", G_csi2, m_csi2_count);
}
return SRSLTE_SUCCESS;
}
static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
@ -453,7 +788,7 @@ static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
}
// Encode SCH
if (srslte_ulsch_nr_encode(&q->sch, &cfg->sch_cfg, tb, data, q->b[tb->cw_idx]) < SRSLTE_SUCCESS) {
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;
}
@ -463,6 +798,30 @@ static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q,
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++) {
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++) {
q->b[tb->cw_idx][q->pos_csi1[i]] = q->g_csi1[i];
}
// Multiplex CSI part 2
for (uint32_t i = 0; i < q->G_csi2; i++) {
q->b[tb->cw_idx][q->pos_csi2[i]] = q->g_csi2[i];
}
// Multiplex HARQ-ACK
for (uint32_t i = 0; i < q->G_ack; i++) {
q->b[tb->cw_idx][q->pos_ack[i]] = q->g_ack[i];
}
// 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);
@ -500,12 +859,26 @@ int srslte_pusch_nr_encode(srslte_pusch_nr_t* q,
return SRSLTE_ERROR;
}
// 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) {
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, cfg, &data[0].uci, q->uci_ack);
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;
@ -592,21 +965,26 @@ 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);
}
// Change LLR sign
// 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++) {
llr[i] = -llr[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(llr, llr, tb->nof_bits, pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx));
srslte_sequence_apply_c(g_ulsch_llr, g_ulsch_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_b(stdout, q->b[tb->cw_idx], tb->nof_bits);
srslte_vec_fprint_bs(stdout, g_ulsch_llr, tb->nof_bits);
}
// Decode SCH
if (srslte_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, res->payload, &res->crc) < SRSLTE_SUCCESS) {
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;
}
@ -631,6 +1009,25 @@ int srslte_pusch_nr_decode(srslte_pusch_nr_t* q,
gettimeofday(&t[1], NULL);
}
// Check number of layers
if (q->max_layers < grant->nof_layers) {
ERROR("Error number of layers (%d) exceeds configured maximum (%d)", grant->nof_layers, q->max_layers);
return SRSLTE_ERROR;
}
// 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) {
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

@ -42,7 +42,7 @@ static const ue_ra_time_resource_t ue_ul_default_A_lut[16] = {{srslte_sch_mappin
{srslte_sch_mapping_type_A, 3, 0, 14},
{srslte_sch_mapping_type_A, 3, 0, 10}};
int srslte_ra_ul_nr_pdsch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant)
int srslte_ra_ul_nr_pusch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant)
{
uint32_t j[4] = {1, 1, 2, 3};
@ -141,7 +141,7 @@ int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
if (ss_type == srslte_search_space_type_rar) {
// Row 1
if (cfg->nof_common_time_ra == 0) {
srslte_ra_ul_nr_pdsch_time_resource_default_A(cfg->scs_cfg, m, grant);
srslte_ra_ul_nr_pusch_time_resource_default_A(cfg->scs_cfg, m, grant);
} else if (m < SRSLTE_MAX_NOF_DL_ALLOCATION && m < cfg->nof_common_time_ra) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
} else {
@ -154,7 +154,7 @@ int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id == 0) {
// Row 2
if (cfg->nof_common_time_ra == 0) {
srslte_ra_ul_nr_pdsch_time_resource_default_A(cfg->scs_cfg, m, grant);
srslte_ra_ul_nr_pusch_time_resource_default_A(cfg->scs_cfg, m, grant);
} else if (m < SRSLTE_MAX_NOF_DL_ALLOCATION) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
}
@ -168,7 +168,7 @@ int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
} else if (cfg->nof_common_time_ra > 0) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
} else {
srslte_ra_ul_nr_pdsch_time_resource_default_A(cfg->scs_cfg, m, grant);
srslte_ra_ul_nr_pusch_time_resource_default_A(cfg->scs_cfg, m, grant);
}
} else {
ERROR("Unhandled case");
@ -461,9 +461,9 @@ int srslte_ra_ul_nr_pucch_resource(const srslte_pucch_nr_hl_cfg_t* pucch_cfg,
// - At least one positive SR
// - up to 2 HARQ-ACK
// - No CSI report
if (uci_cfg->sr_positive_present > 0 && uci_cfg->o_ack <= SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS &&
if (uci_cfg->pucch.sr_positive_present > 0 && uci_cfg->o_ack <= SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS &&
uci_cfg->nof_csi == 0) {
uint32_t sr_resource_id = uci_cfg->sr_resource_id;
uint32_t sr_resource_id = uci_cfg->pucch.sr_resource_id;
if (sr_resource_id >= SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES) {
ERROR("SR resource ID (%d) exceeds the maximum ID (%d)", sr_resource_id, SRSLTE_PUCCH_MAX_NOF_SR_RESOURCES);
return SRSLTE_ERROR;
@ -486,7 +486,7 @@ int srslte_ra_ul_nr_pucch_resource(const srslte_pucch_nr_hl_cfg_t* pucch_cfg,
// - More than 2 HARQ-ACK
// - No CSI report
if (uci_cfg->o_sr > 0 && uci_cfg->o_ack > SRSLTE_PUCCH_NR_FORMAT1_MAX_NOF_BITS && uci_cfg->nof_csi == 0) {
return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch_resource_id, resource);
return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch.resource_id, resource);
}
// Use format 2, 3 or 4 CSI report resource from higher layers
@ -502,10 +502,10 @@ int srslte_ra_ul_nr_pucch_resource(const srslte_pucch_nr_hl_cfg_t* pucch_cfg,
// a PUCCH resource set is provided by pucch-ResourceCommon through an index to a row of Table 9.2.1-1 for size
// transmission of HARQ-ACK information on PUCCH in an initial UL BWP of N BWP PRBs.
if (!pucch_cfg->enabled) {
uint32_t r_pucch = (2 * uci_cfg->n_cce_0) + 2 * uci_cfg->pucch_resource_id;
uint32_t r_pucch = (2 * uci_cfg->pucch.n_cce_0) + 2 * uci_cfg->pucch.resource_id;
return ra_ul_nr_pucch_resource_default(r_pucch, resource);
}
return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch_resource_id, resource);
return ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch.resource_id, resource);
}
uint32_t srslte_ra_ul_nr_nof_sr_bits(uint32_t K)

View File

@ -65,10 +65,10 @@ uint32_t sch_nr_n_prb_lbrm(uint32_t nof_prb)
return 273;
}
int srslte_sch_nr_fill_cfg(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
srslte_sch_nr_tb_info_t* cfg)
int srslte_sch_nr_fill_tb_info(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_t* sch_cfg,
const srslte_sch_tb_t* tb,
srslte_sch_nr_tb_info_t* cfg)
{
if (!sch_cfg || !tb || !cfg) {
return SRSLTE_ERROR_INVALID_INPUTS;
@ -372,7 +372,7 @@ static inline int sch_nr_encode(srslte_sch_nr_t* q,
uint8_t* output_ptr = e_bits;
srslte_sch_nr_tb_info_t cfg = {};
if (srslte_sch_nr_fill_cfg(&q->carrier, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) {
if (srslte_sch_nr_fill_tb_info(&q->carrier, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
@ -514,7 +514,7 @@ int sch_nr_decode(srslte_sch_nr_t* q,
int8_t* input_ptr = e_bits;
srslte_sch_nr_tb_info_t cfg = {};
if (srslte_sch_nr_fill_cfg(&q->carrier, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) {
if (srslte_sch_nr_fill_tb_info(&q->carrier, sch_cfg, tb, &cfg) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}

View File

@ -27,13 +27,12 @@ static srslte_carrier_nr_t carrier = {
1 // max_mimo_layers
};
static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering
static srslte_sch_cfg_nr_t pusch_cfg = {};
static srslte_sch_grant_nr_t pusch_grant = {};
static uint16_t rnti = 0x1234;
static uint32_t nof_ack_bits = 0;
static uint32_t nof_csi_bits = 0;
static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering
static srslte_sch_cfg_nr_t pusch_cfg = {};
static uint16_t rnti = 0x1234;
static uint32_t nof_ack_bits = 0;
static uint32_t nof_csi_bits = 0;
void usage(char* prog)
{
@ -159,20 +158,20 @@ int main(int argc, char** argv)
}
// Use grant default A time resources with m=0
if (srslte_ra_ul_nr_pdsch_time_resource_default_A(carrier.numerology, 0, &pusch_grant) < SRSLTE_SUCCESS) {
if (srslte_ra_ul_nr_pusch_time_resource_default_A(carrier.numerology, 0, &pusch_cfg.grant) < SRSLTE_SUCCESS) {
ERROR("Error loading default grant");
goto clean_exit;
}
// Load number of DMRS CDM groups without data
if (srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(&pusch_cfg, &pusch_grant) < SRSLTE_SUCCESS) {
if (srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(&pusch_cfg, &pusch_cfg.grant) < SRSLTE_SUCCESS) {
ERROR("Error loading number of DMRS CDM groups without data");
goto clean_exit;
}
pusch_grant.nof_layers = carrier.max_mimo_layers;
pusch_grant.dci_format = srslte_dci_format_nr_1_0;
pusch_grant.rnti = rnti;
pusch_cfg.grant.nof_layers = carrier.max_mimo_layers;
pusch_cfg.grant.dci_format = srslte_dci_format_nr_1_0;
pusch_cfg.grant.rnti = rnti;
uint32_t n_prb_start = 1;
uint32_t n_prb_end = carrier.nof_prb + 1;
@ -188,6 +187,10 @@ 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;
if (srslte_chest_dl_res_init(&chest, carrier.nof_prb) < SRSLTE_SUCCESS) {
ERROR("Initiating chest");
goto clean_exit;
@ -196,11 +199,11 @@ int main(int argc, char** argv)
for (n_prb = n_prb_start; n_prb < n_prb_end; n_prb++) {
for (mcs = mcs_start; mcs < mcs_end; mcs++) {
for (uint32_t n = 0; n < SRSLTE_MAX_PRB_NR; n++) {
pusch_grant.prb_idx[n] = (n < n_prb);
pusch_cfg.grant.prb_idx[n] = (n < n_prb);
}
pusch_grant.dci_format = srslte_dci_format_nr_0_0;
if (srslte_ra_nr_fill_tb(&pusch_cfg, &pusch_grant, mcs, &pusch_grant.tb[0]) < SRSLTE_SUCCESS) {
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) {
ERROR("Error filing tb");
goto clean_exit;
}
@ -212,10 +215,10 @@ int main(int argc, char** argv)
continue;
}
for (uint32_t i = 0; i < pusch_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)srslte_random_uniform_int_dist(rand_gen, 0, UINT8_MAX);
}
pusch_grant.tb[tb].softbuffer.tx = &softbuffer_tx;
pusch_cfg.grant.tb[tb].softbuffer.tx = &softbuffer_tx;
}
// Generate HARQ ACK bits
@ -238,22 +241,23 @@ int main(int argc, char** argv)
}
}
if (srslte_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_grant, data_tx, sf_symbols) < SRSLTE_SUCCESS) {
if (srslte_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_cfg.grant, data_tx, sf_symbols) < SRSLTE_SUCCESS) {
ERROR("Error encoding");
goto clean_exit;
}
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
pusch_grant.tb[tb].softbuffer.rx = &softbuffer_rx;
srslte_softbuffer_rx_reset(pusch_grant.tb[tb].softbuffer.rx);
pusch_cfg.grant.tb[tb].softbuffer.rx = &softbuffer_rx;
srslte_softbuffer_rx_reset(pusch_cfg.grant.tb[tb].softbuffer.rx);
}
for (uint32_t i = 0; i < pusch_grant.tb->nof_re; i++) {
for (uint32_t i = 0; i < pusch_cfg.grant.tb->nof_re; i++) {
chest.ce[0][0][i] = 1.0f;
}
chest.nof_re = pusch_grant.tb->nof_re;
chest.nof_re = pusch_cfg.grant.tb->nof_re;
if (srslte_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_grant, &chest, sf_symbols, data_rx) < SRSLTE_SUCCESS) {
if (srslte_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &chest, sf_symbols, data_rx) <
SRSLTE_SUCCESS) {
ERROR("Error encoding");
goto clean_exit;
}
@ -264,18 +268,18 @@ int main(int argc, char** argv)
}
float mse = 0.0f;
uint32_t nof_re = srslte_ra_dl_nr_slot_nof_re(&pusch_cfg, &pusch_grant);
for (uint32_t i = 0; i < pusch_grant.nof_layers; i++) {
uint32_t nof_re = srslte_ra_dl_nr_slot_nof_re(&pusch_cfg, &pusch_cfg.grant);
for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) {
for (uint32_t j = 0; j < nof_re; j++) {
mse += cabsf(pusch_tx.d[i][j] - pusch_rx.d[i][j]);
}
}
if (nof_re * pusch_grant.nof_layers > 0) {
mse = mse / (nof_re * pusch_grant.nof_layers);
if (nof_re * pusch_cfg.grant.nof_layers > 0) {
mse = mse / (nof_re * pusch_cfg.grant.nof_layers);
}
if (mse > 0.001) {
ERROR("MSE error (%f) is too high", mse);
for (uint32_t i = 0; i < pusch_grant.nof_layers; i++) {
for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) {
printf("d_tx[%d]=", i);
srslte_vec_fprint_c(stdout, pusch_tx.d[i], nof_re);
printf("d_rx[%d]=", i);
@ -285,20 +289,20 @@ int main(int argc, char** argv)
}
if (!data_rx[0].crc) {
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pusch_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;
}
if (memcmp(data_tx[0].payload, data_rx[0].payload, pusch_grant.tb[0].tbs / 8) != 0) {
ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pusch_grant.tb[0].tbs);
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: ");
srslte_vec_fprint_byte(stdout, data_tx[0].payload, pusch_grant.tb[0].tbs / 8);
srslte_vec_fprint_byte(stdout, data_tx[0].payload, pusch_cfg.grant.tb[0].tbs / 8);
printf("Rx data: ");
srslte_vec_fprint_byte(stdout, data_tx[0].payload, pusch_grant.tb[0].tbs / 8);
srslte_vec_fprint_byte(stdout, data_tx[0].payload, pusch_cfg.grant.tb[0].tbs / 8);
goto clean_exit;
}
printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pusch_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[0].evm);
}
}

View File

@ -11,11 +11,9 @@
*/
#include "srslte/phy/phch/uci_nr.h"
#include "srslte/phy/ch_estimation/dmrs_sch.h"
#include "srslte/phy/fec/block/block.h"
#include "srslte/phy/fec/polar/polar_chanalloc.h"
#include "srslte/phy/phch/csi.h"
#include "srslte/phy/phch/sch_nr.h"
#include "srslte/phy/phch/uci_cfg.h"
#include "srslte/phy/utils/bit.h"
#include "srslte/phy/utils/vector.h"
@ -258,13 +256,12 @@ static int uci_nr_unpack_pucch(const srslte_uci_cfg_nr_t* cfg, uint8_t* sequence
return SRSLTE_ERROR;
}
static int
uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, srslte_mod_t modulation, uint8_t* o, uint32_t E)
static int uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint8_t* o, uint32_t E)
{
uint32_t i = 0;
srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1;
switch (modulation) {
switch (cfg->pusch.modulation) {
case SRSLTE_MOD_BPSK:
while (i < E) {
o[i++] = c0;
@ -317,15 +314,14 @@ uci_nr_encode_1bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, srslte_mo
return E;
}
static int
uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, srslte_mod_t modulation, uint8_t* o, uint32_t E)
static int uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg, uint8_t* o, uint32_t E)
{
uint32_t i = 0;
srslte_uci_bit_type_t c0 = (q->bit_sequence[0] == 0) ? UCI_BIT_0 : UCI_BIT_1;
srslte_uci_bit_type_t c1 = (q->bit_sequence[1] == 0) ? UCI_BIT_0 : UCI_BIT_1;
srslte_uci_bit_type_t c2 = ((q->bit_sequence[0] ^ q->bit_sequence[1]) == 0) ? UCI_BIT_0 : UCI_BIT_1;
switch (modulation) {
switch (cfg->pusch.modulation) {
case SRSLTE_MOD_BPSK:
case SRSLTE_MOD_QPSK:
while (i < E) {
@ -643,21 +639,16 @@ static int uci_nr_decode_11_1706_bit(srslte_uci_nr_t* q,
return SRSLTE_SUCCESS;
}
static int uci_nr_encode(srslte_uci_nr_t* q,
const srslte_uci_cfg_nr_t* uci_cfg,
srslte_mod_t mod,
uint32_t A,
uint8_t* o,
uint32_t E_uci)
static int uci_nr_encode(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* uci_cfg, uint32_t A, uint8_t* o, uint32_t E_uci)
{
// 5.3.3.1 Encoding of 1-bit information
if (A == 1) {
return uci_nr_encode_1bit(q, uci_cfg, mod, o, E_uci);
return uci_nr_encode_1bit(q, uci_cfg, o, E_uci);
}
// 5.3.3.2 Encoding of 2-bit information
if (A == 2) {
return uci_nr_encode_2bit(q, uci_cfg, mod, o, E_uci);
return uci_nr_encode_2bit(q, uci_cfg, o, E_uci);
}
// 5.3.3.3 Encoding of other small block lengths
@ -781,7 +772,7 @@ int srslte_uci_nr_encode_pucch(srslte_uci_nr_t* q,
return SRSLTE_ERROR;
}
return uci_nr_encode(q, uci_cfg, SRSLTE_MOD_NITEMS, A, o, E_uci);
return uci_nr_encode(q, uci_cfg, A, o, E_uci);
}
int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
@ -816,7 +807,7 @@ uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uin
{
uint32_t len = 0;
len = srslte_print_check(str, str_len, len, "rnti=0x%x", uci_data->cfg.rnti);
len = srslte_print_check(str, str_len, len, "rnti=0x%x", uci_data->cfg.pucch.rnti);
if (uci_data->cfg.o_ack > 0) {
char str2[10];
@ -835,92 +826,59 @@ uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uin
return len;
}
static int uci_nr_Q_ack_prime(srslte_uci_nr_t* q, const srslte_sch_cfg_nr_t* sch_cfg, uint32_t A)
int srslte_uci_nr_pusch_ack_nof_re(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack)
{
// Get UL-SCH TB information
srslte_sch_nr_tb_info_t tb_info = {};
if (srslte_sch_nr_fill_cfg(&q->carrier, &sch_cfg->sch_cfg, &sch_cfg->grant.tb[0], &tb_info) < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
// Get DMRS symbol indexes
uint32_t nof_dmrs_l = 0;
uint32_t dmrs_l[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {};
int n = srslte_dmrs_sch_get_symbols_idx(&sch_cfg->dmrs, &sch_cfg->grant, dmrs_l);
if (n < SRSLTE_SUCCESS) {
return SRSLTE_ERROR;
}
nof_dmrs_l = (uint32_t)n;
uint32_t O_ack = A; // Number of HARQ-ACK bits
uint32_t L_ack = srslte_uci_nr_crc_len(A); // Number of CRC bits
float beta_pusch_offset = sch_cfg->beta_harq_ack_offset; // Beta offset given by higher layers
uint32_t C_ulsch = tb_info.C; // number of code blocks for UL-SCH of the PUSCH
float alpha = sch_cfg->scaling; // Higher layer parameter scaling
float R = (float)sch_cfg->grant.tb[0].R; // code rate of the PUSCH
float Qm = srslte_mod_bits_x_symbol(sch_cfg->grant.tb[0].mod); // modulation order of the PUSCH
uint32_t K_sum = 0;
for (uint32_t i = 0; i < SRSLTE_MIN(C_ulsch, SRSLTE_SCH_NR_MAX_NOF_CB_LDPC); i++) {
K_sum += tb_info.mask[i] ? 0 : tb_info.Kr;
}
uint32_t dmrs_l_idx = 0;
uint32_t M_uci_sum = 0;
uint32_t M_uci_l0_sum = 0;
for (uint32_t l = sch_cfg->grant.S; l < sch_cfg->grant.S + sch_cfg->grant.L; l++) {
uint32_t M_ptrs_sc = 0; // Not implemented yet
uint32_t M_pusch_sc = sch_cfg->grant.nof_prb * SRSLTE_NRE;
uint32_t M_uci_sc = M_pusch_sc - M_ptrs_sc;
// If the OFDM symbol contains DMRS, no UCI is mapped
if (l == dmrs_l[dmrs_l_idx] && dmrs_l_idx < nof_dmrs_l) {
M_uci_sc = 0;
dmrs_l_idx++;
}
// Add subcarriers that can contain UCI RE
M_uci_sum += M_uci_sc;
// Start adding after the first DMRS symbol
if (dmrs_l_idx > 0) {
M_uci_l0_sum += M_uci_sc;
}
}
if (sch_cfg->uci.without_ul_sch) {
return (int)SRSLTE_MIN(ceilf(((O_ack + L_ack) * beta_pusch_offset) / (Qm * R)), alpha * M_uci_l0_sum);
}
return (int)SRSLTE_MIN(ceilf(((O_ack + L_ack) * beta_pusch_offset * M_uci_sum) / (float)K_sum), alpha * M_uci_l0_sum);
}
int srslte_uci_nr_pusch_E_uci_ack(srslte_uci_nr_t* q, const srslte_sch_cfg_nr_t* cfg)
{
int A = cfg->uci.o_ack;
// Check inputs
if (q == NULL || cfg == NULL) {
if (cfg == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
if (cfg->uci.without_ul_sch && cfg->uci.nof_csi > 1 && !cfg->uci.has_csi_part2 && cfg->uci.o_ack < 2) {
A = 2;
uint32_t L_ack = srslte_uci_nr_crc_len(O_ack); // Number of CRC bits
uint32_t Qm = srslte_mod_bits_x_symbol(cfg->modulation); // modulation order of the PUSCH
uint32_t M_uci_sum = 0;
uint32_t M_uci_l0_sum = 0;
for (uint32_t l = 0; l < SRSLTE_NSYMB_PER_SLOT_NR; l++) {
M_uci_sum += cfg->M_uci_sc[l];
if (l >= cfg->l0) {
M_uci_l0_sum += cfg->M_uci_sc[l];
}
}
int Q_ack_prime = uci_nr_Q_ack_prime(q, cfg, A);
if (!isnormal(cfg->R)) {
ERROR("Invalid Rate (%f)", cfg->R);
return SRSLTE_ERROR;
}
if (cfg->K_sum == 0) {
return (int)SRSLTE_MIN(ceilf(((O_ack + L_ack) * cfg->beta_harq_ack_offset) / (Qm * cfg->R)),
cfg->alpha * M_uci_l0_sum);
}
return (int)SRSLTE_MIN(ceilf(((O_ack + L_ack) * cfg->beta_harq_ack_offset * M_uci_sum) / cfg->K_sum),
cfg->alpha * M_uci_l0_sum);
}
int srslte_uci_nr_pusch_ack_nof_bits(const srslte_uci_nr_pusch_cfg_t* cfg, uint32_t O_ack)
{
// Check inputs
if (cfg == NULL) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
int Q_ack_prime = srslte_uci_nr_pusch_ack_nof_re(cfg, O_ack);
if (Q_ack_prime < SRSLTE_SUCCESS) {
ERROR("Error calculating number of RE");
return Q_ack_prime;
}
return (int)(Q_ack_prime * cfg->grant.nof_layers * srslte_mod_bits_x_symbol(cfg->grant.tb[0].mod));
return (int)(Q_ack_prime * cfg->nof_layers * srslte_mod_bits_x_symbol(cfg->modulation));
}
int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q,
const srslte_sch_cfg_nr_t* cfg,
const srslte_uci_cfg_nr_t* cfg,
const srslte_uci_value_nr_t* value,
uint8_t* o)
{
int A = cfg->uci.o_ack;
int A = cfg->o_ack;
// Check inputs
if (q == NULL || cfg == NULL || value == NULL || o == NULL) {
@ -929,20 +887,21 @@ int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q,
// 6.3.2.1 UCI bit sequence generation
// 6.3.2.1.1 HARQ-ACK
if (cfg->uci.without_ul_sch && cfg->uci.nof_csi > 1 && !cfg->uci.has_csi_part2 && cfg->uci.o_ack < 2) {
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;
q->bit_sequence[0] = (cfg->uci.o_ack == 0) ? 0 : value->ack[0];
q->bit_sequence[0] = (cfg->o_ack == 0) ? 0 : value->ack[0];
q->bit_sequence[1] = 0;
} else {
srslte_vec_u8_copy(q->bit_sequence, value->ack, cfg->uci.o_ack);
srslte_vec_u8_copy(q->bit_sequence, value->ack, cfg->o_ack);
}
// Compute total of encoded bits according to 6.3.2.4 Rate matching
int E_uci = srslte_uci_nr_pusch_E_uci_ack(q, cfg);
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;
}
return uci_nr_encode(q, &cfg->uci, cfg->grant.tb[0].mod, A, o, E_uci);
return uci_nr_encode(q, cfg, A, o, E_uci);
}

View File

@ -574,8 +574,8 @@ static int ue_dl_nr_gen_ack_type2(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
} else {
if (ack->present) {
// Load ACK resource data into UCI info
uci_data->cfg.pucch_resource_id = ack_info->cc[c].m[m].resource.pucch_resource_id;
uci_data->cfg.rnti = ack_info->cc[c].m[m].resource.rnti;
uci_data->cfg.pucch.resource_id = ack_info->cc[c].m[m].resource.pucch_resource_id;
uci_data->cfg.pucch.rnti = ack_info->cc[c].m[m].resource.rnti;
if (V_DL_CDAI <= V_temp) {
j = j + 1;

View File

@ -73,9 +73,9 @@ public:
carrier.max_mimo_layers = 1;
// Hard-coded values, this should be set when the measurements take place
csi_measurements[0].K_csi_rs = 1;
csi_measurements[0].K_csi_rs = 1;
csi_measurements[0].nof_ports = 1;
csi_measurements[1].K_csi_rs = 4;
csi_measurements[1].K_csi_rs = 4;
csi_measurements[0].nof_ports = 1;
}
@ -294,10 +294,10 @@ public:
}
// Configure SR fields in UCI data
uci_data.cfg.sr_resource_id = sr_resource_id[0];
uci_data.cfg.o_sr = srslte_ra_ul_nr_nof_sr_bits(sr_count_all);
uci_data.cfg.sr_positive_present = sr_count_positive > 0;
uci_data.value.sr = sr_count_positive;
uci_data.cfg.pucch.sr_resource_id = sr_resource_id[0];
uci_data.cfg.o_sr = srslte_ra_ul_nr_nof_sr_bits(sr_count_all);
uci_data.cfg.pucch.sr_positive_present = sr_count_positive > 0;
uci_data.value.sr = sr_count_positive;
}
void get_periodic_csi(const uint32_t& tti, srslte_uci_data_nr_t& uci_data)
@ -307,7 +307,7 @@ public:
uci_data.cfg.nof_csi = n;
}
uci_data.cfg.rnti = stack->get_ul_sched_rnti_nr(tti).id;
uci_data.cfg.pucch.rnti = stack->get_ul_sched_rnti_nr(tti).id;
}
};
} // namespace nr