Merge branch 'integration_2024_w33' into 'develop'
Integration: `2024.w33` See merge request oai/openairinterface5g!2911 - !2784 Reworking beam structures at NR MAC gNB - !2889 Fix delta for PUSCH DMRS type 2 - !2908 NR MAC UE CSI improvements - !2896 Fix for llr functions reading/writing outside buffers - !2902 nr rlc: reduce "SDU rejected" logging - !2884 NR UE: Cleanup global variables used for command line parameter storage - !2910 NR gNB DMRS symbol race - CI: Update phytest-timing test threshold
This commit is contained in:
@@ -1152,6 +1152,10 @@ add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON})
|
||||
add_library(PHY_NR ${PHY_NR_SRC})
|
||||
target_link_libraries(PHY_NR nr_phy_common nr_common)
|
||||
|
||||
add_library(PHY_NR_NO_AVX_256 ${PHY_NR_SRC})
|
||||
target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common)
|
||||
target_compile_definitions(PHY_NR_NO_AVX_256 PUBLIC USE_128BIT)
|
||||
|
||||
add_library(PHY_NR_UE ${PHY_NR_UE_SRC})
|
||||
target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs nr_phy_common nr_common)
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Ref :
|
||||
L1 Tx processing : 400.0
|
||||
DLSCH encoding : 177.0
|
||||
L1 Rx processing : 345.0
|
||||
PUSCH inner-receiver : 210.0
|
||||
PUSCH inner-receiver : 200.0
|
||||
Schedule Response : 3.0
|
||||
DL & UL scheduling timing : 13.0
|
||||
UL Indication : 3.0
|
||||
|
||||
@@ -80,7 +80,6 @@
|
||||
#define CONFIG_HLP_TNOFORK "to ease debugging with gdb\n"
|
||||
#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n"
|
||||
#define CONFIG_HLP_DISABLETIMECORR "disable UE timing correction\n"
|
||||
#define CONFIG_HLP_RRC_CFG_PATH "path for RRC configuration\n"
|
||||
#define CONFIG_HLP_RE_CFG_FILE "filename for reconfig.raw in phy-test mode\n"
|
||||
#define CONFIG_HLP_RB_CFG_FILE "filename for rbconfig.raw in phy-test mode\n"
|
||||
#define CONFIG_HLP_UECAP_FILE "path for UE Capabilities file\n"
|
||||
|
||||
@@ -89,7 +89,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
|
||||
extern const char *duplex_mode[];
|
||||
THREAD_STRUCT thread_struct;
|
||||
nrUE_params_t nrUE_params;
|
||||
nrUE_params_t nrUE_params = {0};
|
||||
|
||||
// Thread variables
|
||||
pthread_cond_t nfapi_sync_cond;
|
||||
@@ -113,31 +113,12 @@ int oai_exit = 0;
|
||||
|
||||
static int tx_max_power[MAX_NUM_CCs] = {0};
|
||||
|
||||
int vcdflag = 0;
|
||||
|
||||
double rx_gain_off = 0.0;
|
||||
char *usrp_args = NULL;
|
||||
char *tx_subdev = NULL;
|
||||
char *rx_subdev = NULL;
|
||||
char *rrc_config_path = NULL;
|
||||
char *reconfig_file = NULL;
|
||||
char *rbconfig_file = NULL;
|
||||
char *uecap_file = NULL;
|
||||
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
uint64_t sidelink_frequency[MAX_NUM_CCs][4];
|
||||
|
||||
#if MAX_NUM_CCs == 1
|
||||
rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
|
||||
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
|
||||
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
|
||||
#else
|
||||
rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
|
||||
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
|
||||
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
|
||||
#endif
|
||||
|
||||
// UE and OAI config variables
|
||||
|
||||
openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
@@ -221,10 +202,7 @@ static void get_options(configmodule_interface_t *cfg)
|
||||
paramdef_t cmdline_params[] =CMDLINE_NRUEPARAMS_DESC ;
|
||||
int numparams = sizeofArray(cmdline_params);
|
||||
config_get(cfg, cmdline_params, numparams, NULL);
|
||||
|
||||
AssertFatal(rrc_config_path == NULL, "the option \"rrc_config_path\" is deprecated. Please use --reconfig-file and --rbconfig-file separately to point to files reconfig.raw and rbconfig.raw\n");
|
||||
|
||||
if (vcdflag > 0)
|
||||
if (nrUE_params.vcdflag > 0)
|
||||
ouput_vcd = 1;
|
||||
}
|
||||
|
||||
@@ -232,15 +210,10 @@ static void get_options(configmodule_interface_t *cfg)
|
||||
void set_options(int CC_id, PHY_VARS_NR_UE *UE){
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
|
||||
// Init power variables
|
||||
tx_max_power[CC_id] = tx_max_power[0];
|
||||
rx_gain[0][CC_id] = rx_gain[0][0];
|
||||
tx_gain[0][CC_id] = tx_gain[0][0];
|
||||
|
||||
// Set UE variables
|
||||
UE->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off;
|
||||
UE->tx_total_gain_dB = (int)tx_gain[CC_id][0];
|
||||
UE->tx_power_max_dBm = tx_max_power[CC_id];
|
||||
UE->rx_total_gain_dB = (int)nrUE_params.rx_gain + rx_gain_off;
|
||||
UE->tx_total_gain_dB = (int)nrUE_params.tx_gain;
|
||||
UE->tx_power_max_dBm = nrUE_params.tx_max_power;
|
||||
UE->rf_map.card = 0;
|
||||
UE->rf_map.chain = CC_id + 0;
|
||||
UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations;
|
||||
@@ -317,9 +290,9 @@ void init_openair0()
|
||||
|
||||
openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
|
||||
|
||||
if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;
|
||||
if (tx_subdev) openair0_cfg[card].tx_subdev = tx_subdev;
|
||||
if (rx_subdev) openair0_cfg[card].rx_subdev = rx_subdev;
|
||||
if (get_nrUE_params()->usrp_args) openair0_cfg[card].sdr_addrs = get_nrUE_params()->usrp_args;
|
||||
if (get_nrUE_params()->tx_subdev) openair0_cfg[card].tx_subdev = get_nrUE_params()->tx_subdev;
|
||||
if (get_nrUE_params()->rx_subdev) openair0_cfg[card].rx_subdev = get_nrUE_params()->rx_subdev;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -483,7 +456,7 @@ int main(int argc, char **argv)
|
||||
else
|
||||
init_pdcp(mode_offset + ue_id_g);
|
||||
|
||||
init_NR_UE(NB_UE_INST, uecap_file, reconfig_file, rbconfig_file);
|
||||
init_NR_UE(NB_UE_INST, get_nrUE_params()->uecap_file, get_nrUE_params()->reconfig_file, get_nrUE_params()->rbconfig_file);
|
||||
|
||||
if (get_softmodem_params()->emulate_l1) {
|
||||
RCconfig_nr_ue_macrlc();
|
||||
|
||||
@@ -30,27 +30,26 @@
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
// clang-format off
|
||||
#define CMDLINE_NRUEPARAMS_DESC { \
|
||||
{"usrp-args", CONFIG_HLP_USRP_ARGS, 0, .strptr=&usrp_args, .defstrval="type=b200", TYPE_STRING, 0}, \
|
||||
{"tx_subdev", CONFIG_HLP_TX_SUBDEV, 0, .strptr=&tx_subdev, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{"rx_subdev", CONFIG_HLP_RX_SUBDEV, 0, .strptr=&rx_subdev, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{"usrp-args", CONFIG_HLP_USRP_ARGS, 0, .strptr=&nrUE_params.usrp_args, .defstrval="type=b200", TYPE_STRING, 0}, \
|
||||
{"tx_subdev", CONFIG_HLP_TX_SUBDEV, 0, .strptr=&nrUE_params.tx_subdev, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{"rx_subdev", CONFIG_HLP_RX_SUBDEV, 0, .strptr=&nrUE_params.rx_subdev, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{"dlsch-parallel", CONFIG_HLP_DLSCH_PARA, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{"offset-divisor", CONFIG_HLP_OFFSET_DIV, 0, .uptr=&nrUE_params.ofdm_offset_divisor, .defuintval=8, TYPE_UINT32, 0}, \
|
||||
{"max-ldpc-iterations", CONFIG_HLP_MAX_LDPC_ITERATIONS, 0, .iptr=&nrUE_params.max_ldpc_iterations, .defuintval=8, TYPE_UINT8, 0}, \
|
||||
{"ldpc-offload-enable", CONFIG_HLP_LDPC_OFFLOAD, PARAMFLAG_BOOL, .iptr=&(nrUE_params.ldpc_offload_flag), .defintval=0, TYPE_INT, 0}, \
|
||||
{"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, .iptr=&vcdflag, .defintval=0, TYPE_INT, 0}, \
|
||||
{"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \
|
||||
{"rrc_config_path", CONFIG_HLP_RRC_CFG_PATH, 0, .strptr=&rrc_config_path, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{"reconfig-file", CONFIG_HLP_RE_CFG_FILE, 0, .strptr=&reconfig_file, .defstrval="./reconfig.raw", TYPE_STRING, 0}, \
|
||||
{"rbconfig-file", CONFIG_HLP_RB_CFG_FILE, 0, .strptr=&rbconfig_file, .defstrval="./rbconfig.raw", TYPE_STRING, 0}, \
|
||||
{"ue-idx-standalone", NULL, 0, .u16ptr=&ue_idx_standalone, .defuintval=0xFFFF, TYPE_UINT16, 0}, \
|
||||
{"ue-rxgain", CONFIG_HLP_UERXG, 0, .dblptr=&(rx_gain[0][0]), .defdblval=110, TYPE_DOUBLE, 0}, \
|
||||
{"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, .dblptr=&rx_gain_off, .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
{"ue-txgain", CONFIG_HLP_UETXG, 0, .dblptr=&(tx_gain[0][0]), .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
{"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, .iptr=&nrUE_params.vcdflag, .defintval=0, TYPE_INT, 0}, \
|
||||
{"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&nrUE_params.uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \
|
||||
{"reconfig-file", CONFIG_HLP_RE_CFG_FILE, 0, .strptr=&nrUE_params.reconfig_file, .defstrval="./reconfig.raw", TYPE_STRING, 0}, \
|
||||
{"rbconfig-file", CONFIG_HLP_RB_CFG_FILE, 0, .strptr=&nrUE_params.rbconfig_file, .defstrval="./rbconfig.raw", TYPE_STRING, 0}, \
|
||||
{"ue-idx-standalone", NULL, 0, .u16ptr=&ue_idx_standalone, .defuintval=0xFFFF, TYPE_UINT16, 0}, \
|
||||
{"ue-rxgain", CONFIG_HLP_UERXG, 0, .dblptr=&nrUE_params.rx_gain, .defdblval=110, TYPE_DOUBLE, 0}, \
|
||||
{"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, .dblptr=&nrUE_params.rx_gain_off, .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
{"ue-txgain", CONFIG_HLP_UETXG, 0, .dblptr=&nrUE_params.tx_gain, .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
{"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, .iptr=&(nrUE_params.nb_antennas_rx), .defuintval=1, TYPE_UINT8, 0}, \
|
||||
{"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, .iptr=&(nrUE_params.nb_antennas_tx), .defuintval=1, TYPE_UINT8, 0}, \
|
||||
{"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, .iptr=&(nrUE_params.UE_scan_carrier), .defintval=0, TYPE_INT, 0}, \
|
||||
{"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, .iptr=&(nrUE_params.UE_fo_compensation), .defintval=0, TYPE_INT, 0}, \
|
||||
{"ue-max-power", NULL, 0, .iptr=&(tx_max_power[0]), .defintval=90, TYPE_INT, 0}, \
|
||||
{"ue-max-power", NULL, 0, .iptr=&(nrUE_params.tx_max_power), .defintval=90, TYPE_INT, 0}, \
|
||||
{"r" , CONFIG_HLP_PRB_SA, 0, .iptr=&(nrUE_params.N_RB_DL), .defintval=106, TYPE_UINT, 0}, \
|
||||
{"ssb", CONFIG_HLP_SSC, 0, .iptr=&(nrUE_params.ssb_start_subcarrier), .defintval=516, TYPE_UINT16, 0}, \
|
||||
{"if_freq" , CONFIG_HLP_IF_FREQ, 0, .u64ptr=&(nrUE_params.if_freq), .defuintval=0, TYPE_UINT64, 0}, \
|
||||
@@ -67,25 +66,36 @@
|
||||
// clang-format on
|
||||
|
||||
typedef struct {
|
||||
uint64_t optmask; //mask to store boolean config options
|
||||
uint32_t ofdm_offset_divisor; // Divisor for sample offset computation for each OFDM symbol
|
||||
int max_ldpc_iterations; // number of maximum LDPC iterations
|
||||
tpool_t Tpool; // thread pool
|
||||
int UE_scan_carrier;
|
||||
uint64_t optmask; // mask to store boolean config options
|
||||
uint32_t ofdm_offset_divisor; // Divisor for sample offset computation for each OFDM symbol
|
||||
int max_ldpc_iterations; // number of maximum LDPC iterations
|
||||
tpool_t Tpool; // thread pool
|
||||
int UE_scan_carrier;
|
||||
int UE_fo_compensation;
|
||||
uint64_t if_freq;
|
||||
int if_freq_off;
|
||||
int chest_freq;
|
||||
int chest_time;
|
||||
int no_timing_correction;
|
||||
int nb_antennas_rx;
|
||||
uint64_t if_freq;
|
||||
int if_freq_off;
|
||||
int chest_freq;
|
||||
int chest_time;
|
||||
int no_timing_correction;
|
||||
int nb_antennas_rx;
|
||||
int nb_antennas_tx;
|
||||
int N_RB_DL;
|
||||
int ssb_start_subcarrier;
|
||||
int N_RB_DL;
|
||||
int ssb_start_subcarrier;
|
||||
int ldpc_offload_flag;
|
||||
unsigned int ntn_koffset;
|
||||
double ntn_ta_common;
|
||||
unsigned int ntn_koffset;
|
||||
double ntn_ta_common;
|
||||
int agc;
|
||||
char *usrp_args;
|
||||
char *tx_subdev;
|
||||
char *rx_subdev;
|
||||
char *reconfig_file;
|
||||
char *rbconfig_file;
|
||||
char *uecap_file;
|
||||
double tx_gain;
|
||||
double rx_gain;
|
||||
double rx_gain_off;
|
||||
int vcdflag;
|
||||
int tx_max_power;
|
||||
} nrUE_params_t;
|
||||
extern uint64_t get_nrUE_optmask(void);
|
||||
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
|
||||
|
||||
@@ -54,7 +54,7 @@ typedef struct {
|
||||
uint32_t rsrp;
|
||||
int rsrp_dBm;
|
||||
uint8_t rank_indicator;
|
||||
uint8_t i1;
|
||||
uint16_t i1;
|
||||
uint8_t i2;
|
||||
uint8_t cqi;
|
||||
rlm_t radiolink_monitoring;
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
add_subdirectory(nr_phy_common)
|
||||
add_subdirectory(TOOLS)
|
||||
add_subdirectory(NR_TRANSPORT)
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/filt16a_32.h"
|
||||
|
||||
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
|
||||
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "nr_phy_common.h"
|
||||
@@ -86,16 +86,15 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ul_id];
|
||||
c16_t **ul_ch_estimates = (c16_t **)pusch_vars->ul_ch_estimates;
|
||||
const int symbolSize = gNB->frame_parms.ofdm_symbol_size;
|
||||
const int soffset = (Ns & 3) * gNB->frame_parms.symbols_per_slot*symbolSize;
|
||||
const int nushift = (p >> 1) & 1;
|
||||
int ch_offset = symbolSize*symbol;
|
||||
const int symbol_offset = symbolSize*symbol;
|
||||
const int slot_offset = (Ns & 3) * gNB->frame_parms.symbols_per_slot * symbolSize;
|
||||
const int delta = get_delta(p, pusch_pdu->dmrs_config_type);
|
||||
const int symbol_offset = symbolSize * symbol;
|
||||
const int k0 = bwp_start_subcarrier;
|
||||
const int nb_rb_pusch = pusch_pdu->rb_size;
|
||||
|
||||
LOG_D(PHY, "ch_offset %d, soffset %d, symbol_offset %d, OFDM size %d, Ns = %d, k0 = %d, symbol %d\n",
|
||||
ch_offset, soffset,
|
||||
LOG_D(PHY, "symbol_offset %d, slot_offset %d, OFDM size %d, Ns = %d, k0 = %d, symbol %d\n",
|
||||
symbol_offset,
|
||||
slot_offset,
|
||||
symbolSize,
|
||||
Ns,
|
||||
k0,
|
||||
@@ -154,25 +153,27 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
memset(delay, 0, sizeof(*delay));
|
||||
|
||||
for (int aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {
|
||||
c16_t *rxdataF = (c16_t *)&gNB->common_vars.rxdataF[aarx][symbol_offset];
|
||||
c16_t *ul_ch = &ul_ch_estimates[nl * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset];
|
||||
c16_t *rxdataF = (c16_t *)&gNB->common_vars.rxdataF[aarx][symbol_offset + slot_offset];
|
||||
c16_t *ul_ch = &ul_ch_estimates[nl * gNB->frame_parms.nb_antennas_rx + aarx][symbol_offset];
|
||||
|
||||
memset(ul_ch,0,sizeof(*ul_ch)*symbolSize);
|
||||
memset(ul_ch, 0, sizeof(*ul_ch) * symbolSize);
|
||||
#ifdef DEBUG_PUSCH
|
||||
LOG_I(PHY, "In %s symbol_offset %d, nushift %d\n", __FUNCTION__, symbol_offset, nushift);
|
||||
LOG_I(PHY, "In %s ch est pilot, N_RB_UL %d\n", __FUNCTION__, gNB->frame_parms.N_RB_UL);
|
||||
LOG_I(PHY, "In %s bwp_start_subcarrier %d, k0 %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k0, gNB->frame_parms.first_carrier_offset, nb_rb_pusch);
|
||||
LOG_I(PHY, "In %s ul_ch addr %p nushift %d\n", __FUNCTION__, ul_ch, nushift);
|
||||
LOG_I(PHY, "symbol_offset %d, delta %d\n", symbol_offset, delta);
|
||||
LOG_I(PHY, "ch est pilot, N_RB_UL %d\n", gNB->frame_parms.N_RB_UL);
|
||||
LOG_I(PHY,
|
||||
"bwp_start_subcarrier %d, k0 %d, first_carrier %d, nb_rb_pusch %d\n",
|
||||
bwp_start_subcarrier,
|
||||
k0,
|
||||
gNB->frame_parms.first_carrier_offset,
|
||||
nb_rb_pusch);
|
||||
LOG_I(PHY, "ul_ch addr %p \n", ul_ch);
|
||||
#endif
|
||||
|
||||
if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && chest_freq == 0) {
|
||||
c16_t *pil = pilot;
|
||||
int re_offset = k0;
|
||||
LOG_D(PHY,"PUSCH estimation DMRS type 1, Freq-domain interpolation");
|
||||
// For configuration type 1: k = 4*n + 2*k' + delta,
|
||||
// where k' is 0 or 1, and delta is in Table 6.4.1.1.3-1 from TS 38.211
|
||||
int pilot_cnt = 0;
|
||||
int delta = nr_pusch_dmrs_delta(pusch_dmrs_type1, p);
|
||||
|
||||
for (int n = 0; n < 3 * nb_rb_pusch; n++) {
|
||||
// LS estimation
|
||||
@@ -180,7 +181,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
for (int k_line = 0; k_line <= 1; k_line++) {
|
||||
re_offset = (k0 + (n << 2) + (k_line << 1) + delta) % symbolSize;
|
||||
ch = c32x16maddShift(*pil, rxdataF[soffset + re_offset], ch, 16);
|
||||
ch = c32x16maddShift(*pil, rxdataF[re_offset], ch, 16);
|
||||
pil++;
|
||||
}
|
||||
|
||||
@@ -212,9 +213,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize;
|
||||
c16_t *rxF = &rxdataF[soffset + re_offset];
|
||||
c16_t *rxF = &rxdataF[re_offset];
|
||||
printf("pilot %4d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d)\n",
|
||||
pilot_cnt, pil->r, pil->i, rxF->r, rxF->i, ch.r, ch.i);
|
||||
pilot_cnt, pil->r, pil->i, rxF->r, rxF->i, ch16.r, ch16.i);
|
||||
#endif
|
||||
|
||||
if (pilot_cnt == 0) {
|
||||
@@ -236,7 +237,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
// Revert delay
|
||||
pilot_cnt = 0;
|
||||
ul_ch = &ul_ch_estimates[nl * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset];
|
||||
ul_ch = &ul_ch_estimates[nl * gNB->frame_parms.nb_antennas_rx + aarx][symbol_offset];
|
||||
int inv_delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP);
|
||||
c16_t *ul_inv_delay_table = gNB->frame_parms.delay_table[inv_delay_idx];
|
||||
for (int n = 0; n < 3 * nb_rb_pusch; n++) {
|
||||
@@ -249,7 +250,6 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize;
|
||||
c16_t *rxF = &rxdataF[soffset + re_offset];
|
||||
printf("ch -> (%4d,%4d), ch_inter -> (%4d,%4d)\n", ul_ls_est[k].r, ul_ls_est[k].i, ul_ch[k].r, ul_ch[k].i);
|
||||
#endif
|
||||
pilot_cnt++;
|
||||
@@ -260,7 +260,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
} else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && chest_freq == 0) { // pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d|
|
||||
LOG_D(PHY, "PUSCH estimation DMRS type 2, Freq-domain interpolation\n");
|
||||
c16_t *pil = pilot;
|
||||
c16_t *rx = &rxdataF[soffset + nushift];
|
||||
c16_t *rx = &rxdataF[delta];
|
||||
for (int n = 0; n < nb_rb_pusch * NR_NB_SC_PER_RB; n += 6) {
|
||||
c16_t ch0 = c16mulShift(*pil, rx[(k0 + n) % symbolSize], 15);
|
||||
pil++;
|
||||
@@ -284,16 +284,16 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB
|
||||
// this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB
|
||||
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) {
|
||||
LOG_D(PHY,"PUSCH estimation DMRS type 1, no Freq-domain interpolation\n");
|
||||
c16_t *rxF = &rxdataF[soffset + nushift];
|
||||
c16_t *rxF = &rxdataF[delta];
|
||||
int pil_offset = 0;
|
||||
int re_offset = k0;
|
||||
c16_t ch;
|
||||
|
||||
// First PRB
|
||||
ch=c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
|
||||
ch = c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
|
||||
|
||||
#if NO_INTERP
|
||||
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++)
|
||||
@@ -308,7 +308,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
#endif
|
||||
|
||||
for (int pilot_cnt=6; pilot_cnt<6*(nb_rb_pusch-1); pilot_cnt += 6) {
|
||||
ch=c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
|
||||
ch = c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
|
||||
*max_ch = max(*max_ch, max(abs(ch.r), abs(ch.i)));
|
||||
|
||||
#if NO_INTERP
|
||||
@@ -344,32 +344,21 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
#endif
|
||||
} else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB
|
||||
LOG_D(PHY,"PUSCH estimation DMRS type 2, no Freq-domain interpolation");
|
||||
c16_t *pil = pilot;
|
||||
int re_offset = k0;
|
||||
c32_t ch0={0};
|
||||
c16_t *pil = pilot;
|
||||
int re_offset = (k0 + delta) % symbolSize;
|
||||
c32_t ch0 = {0};
|
||||
//First PRB
|
||||
ch0=c32x16mulShift(*pil,
|
||||
rxdataF[soffset + nushift + re_offset],
|
||||
15);
|
||||
ch0 = c32x16mulShift(*pil, rxdataF[re_offset], 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
ch0=c32x16maddShift(*pil,
|
||||
rxdataF[nushift+re_offset],
|
||||
ch0,
|
||||
15);
|
||||
re_offset = (re_offset + 1) % symbolSize;
|
||||
ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
ch0=c32x16maddShift(*pil,
|
||||
rxdataF[nushift+re_offset],
|
||||
ch0,
|
||||
15);
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
ch0=c32x16maddShift(*pil,
|
||||
rxdataF[nushift+re_offset],
|
||||
ch0,
|
||||
15);
|
||||
re_offset = (re_offset + 5) % symbolSize;
|
||||
ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15);
|
||||
re_offset = (re_offset + 1) % symbolSize;
|
||||
ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
re_offset = (re_offset + 5) % symbolSize;
|
||||
|
||||
c16_t ch=c16x32div(ch0, 4);
|
||||
#if NO_INTERP
|
||||
@@ -386,19 +375,19 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
|
||||
for (int pilot_cnt=4; pilot_cnt<4*(nb_rb_pusch-1); pilot_cnt += 4) {
|
||||
c32_t ch0;
|
||||
ch0=c32x16mulShift(*pil, rxdataF[nushift+re_offset], 15);
|
||||
ch0 = c32x16mulShift(*pil, rxdataF[re_offset], 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
re_offset = (re_offset + 1) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
re_offset = (re_offset + 5) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
re_offset = (re_offset + 1) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
|
||||
@@ -421,21 +410,21 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
}
|
||||
|
||||
// Last PRB
|
||||
ch0=c32x16mulShift(*pil, rxdataF[nushift+re_offset], 15);
|
||||
ch0 = c32x16mulShift(*pil, rxdataF[re_offset], 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
re_offset = (re_offset + 1) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
re_offset = (re_offset + 5) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+1) % symbolSize;
|
||||
re_offset = (re_offset + 1) % symbolSize;
|
||||
|
||||
ch0=c32x16maddShift(*pil, rxdataF[nushift+re_offset], ch0, 15);
|
||||
ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15);
|
||||
pil++;
|
||||
re_offset = (re_offset+5) % symbolSize;
|
||||
re_offset = (re_offset + 5) % symbolSize;
|
||||
|
||||
ch=c16x32div(ch0, 4);
|
||||
#if NO_INTERP
|
||||
@@ -451,7 +440,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
ul_ch = &ul_ch_estimates[nl * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset];
|
||||
ul_ch = &ul_ch_estimates[nl * gNB->frame_parms.nb_antennas_rx + aarx][symbol_offset];
|
||||
for (int idxP = 0; idxP < ceil((float)nb_rb_pusch * 12 / 8); idxP++) {
|
||||
for (int idxI = 0; idxI < 8; idxI++) {
|
||||
printf("%d\t%d\t", ul_ch[idxP * 8 + idxI].r, ul_ch[idxP * 8 + idxI].i);
|
||||
|
||||
@@ -299,7 +299,7 @@ uint16_t get_dmrs_freq_idx_ul(uint16_t n, uint8_t k_prime, uint8_t delta, uint8_
|
||||
int8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol)
|
||||
{
|
||||
for(uint8_t symbol = counter; symbol < end_symbol; symbol++) {
|
||||
if((ul_dmrs_symb_pos >> symbol) & 0x01 ) {
|
||||
if((ul_dmrs_symb_pos >> symbol) & 0x01) {
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
@@ -318,23 +318,23 @@ uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb, uint8
|
||||
}
|
||||
|
||||
/* return the position of valid dmrs symbol in a slot for channel compensation */
|
||||
int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter)
|
||||
int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter)
|
||||
{
|
||||
int8_t symbIdx = -1;
|
||||
/* if current symbol is DMRS then return this index */
|
||||
if(is_dmrs_symbol(counter, dmrs_symb_pos ) ==1) {
|
||||
if(is_dmrs_symbol(counter, dmrs_symb_pos) == 1) {
|
||||
return counter;
|
||||
}
|
||||
/* find previous DMRS symbol */
|
||||
for(int8_t symbol = counter;symbol >=0 ; symbol--) {
|
||||
if((1<<symbol & dmrs_symb_pos)> 0) {
|
||||
for(int8_t symbol = counter; symbol >= 0 ; symbol--) {
|
||||
if((1 << symbol & dmrs_symb_pos) > 0) {
|
||||
symbIdx = symbol;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* if there is no previous dmrs available then find the next possible*/
|
||||
if(symbIdx == -1) {
|
||||
symbIdx = get_next_dmrs_symbol_in_slot(dmrs_symb_pos,counter,15);
|
||||
symbIdx = get_next_dmrs_symbol_in_slot(dmrs_symb_pos, counter, 15);
|
||||
}
|
||||
return symbIdx;
|
||||
}
|
||||
|
||||
@@ -41,10 +41,8 @@
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
|
||||
|
||||
// Table 6.4.1.1.3-1/2 from TS 38.211
|
||||
static const int delta1[8] = {0, 0, 1, 1, 0, 0, 1, 1};
|
||||
static const int wf1[8][2] = {{1, 1}, {1, -1}, {1, 1}, {1, -1}, {1, 1}, {1, -1}, {1, 1}, {1, -1}};
|
||||
static const int wt1[8][2] = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, -1}, {1, -1}, {1, -1}, {1, -1}};
|
||||
static const int delta2[12] = {0, 0, 2, 2, 4, 4, 0, 0, 2, 2, 4, 4};
|
||||
static const int wf2[12][2] =
|
||||
{{1, 1}, {1, -1}, {1, 1}, {1, -1}, {1, 1}, {1, -1}, {1, 1}, {1, -1}, {1, 1}, {1, -1}, {1, 1}, {1, -1}};
|
||||
static const int wt2[12][2] =
|
||||
@@ -56,14 +54,6 @@ static const c16_t nr_rx_mod_table[7] =
|
||||
static const c16_t nr_rx_nmod_table[7] =
|
||||
{{0, 0}, {-23170, 23170}, {23170, -23170}, {-23170, 23170}, {-23170, -23170}, {23170, 23170}, {23170, -23170}};
|
||||
|
||||
int nr_pusch_dmrs_delta(uint8_t dmrs_config_type, unsigned short p) {
|
||||
if (dmrs_config_type == pusch_dmrs_type1) {
|
||||
return delta1[p];
|
||||
} else {
|
||||
return delta2[p];
|
||||
}
|
||||
}
|
||||
|
||||
int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
|
||||
unsigned int Ns,
|
||||
const uint32_t *nr_gold_pusch,
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "openair1/PHY/NR_REFSIG/nr_refsig_common.h"
|
||||
|
||||
int nr_pusch_dmrs_delta(uint8_t dmrs_config_type, unsigned short p);
|
||||
|
||||
int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
|
||||
unsigned int Ns,
|
||||
const uint32_t *nr_gold_pusch,
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
if (ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
@@ -276,16 +276,16 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
|
||||
|
||||
}
|
||||
|
||||
static void nr_ulsch_extract_rbs (c16_t* const rxdataF,
|
||||
c16_t* const chF,
|
||||
c16_t *rxFext,
|
||||
c16_t *chFext,
|
||||
int rxoffset,
|
||||
int choffset,
|
||||
int aarx,
|
||||
int is_dmrs_symbol,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
NR_DL_FRAME_PARMS *frame_parms)
|
||||
static void nr_ulsch_extract_rbs(c16_t* const rxdataF,
|
||||
c16_t* const chF,
|
||||
c16_t *rxFext,
|
||||
c16_t *chFext,
|
||||
int rxoffset,
|
||||
int choffset,
|
||||
int aarx,
|
||||
int is_dmrs_symbol,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
NR_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
uint8_t delta = 0;
|
||||
|
||||
@@ -301,8 +301,7 @@ static void nr_ulsch_extract_rbs (c16_t* const rxdataF,
|
||||
if (is_dmrs_symbol == 0) {
|
||||
if (start_re + nb_re_pusch <= frame_parms->ofdm_symbol_size)
|
||||
memcpy(rxF_ext, &rxF[start_re], nb_re_pusch * sizeof(c16_t));
|
||||
else
|
||||
{
|
||||
else {
|
||||
int neg_length = frame_parms->ofdm_symbol_size - start_re;
|
||||
int pos_length = nb_re_pusch - neg_length;
|
||||
memcpy(rxF_ext, &rxF[start_re], neg_length * sizeof(c16_t));
|
||||
@@ -310,57 +309,47 @@ static void nr_ulsch_extract_rbs (c16_t* const rxdataF,
|
||||
}
|
||||
memcpy(ul_ch0_ext, ul_ch0, nb_re_pusch * sizeof(c16_t));
|
||||
}
|
||||
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) // 6 REs / PRB
|
||||
{
|
||||
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) { // 6 REs / PRB
|
||||
AssertFatal(delta == 0 || delta == 1, "Illegal delta %d\n",delta);
|
||||
c16_t *rxF32 = &rxF[start_re];
|
||||
if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) {
|
||||
for (int idx = 1 - delta; idx < nb_re_pusch; idx += 2)
|
||||
{
|
||||
for (int idx = 1 - delta; idx < nb_re_pusch; idx += 2) {
|
||||
*rxF_ext++ = rxF32[idx];
|
||||
*ul_ch0_ext++ = ul_ch0[idx];
|
||||
}
|
||||
}
|
||||
else // handle the two pieces around DC
|
||||
{
|
||||
else { // handle the two pieces around DC
|
||||
int neg_length = frame_parms->ofdm_symbol_size - start_re;
|
||||
int pos_length = nb_re_pusch - neg_length;
|
||||
int idx, idx2;
|
||||
for (idx = 1 - delta; idx < neg_length; idx += 2)
|
||||
{
|
||||
for (idx = 1 - delta; idx < neg_length; idx += 2) {
|
||||
*rxF_ext++ = rxF32[idx];
|
||||
*ul_ch0_ext++= ul_ch0[idx];
|
||||
}
|
||||
rxF32 = rxF;
|
||||
idx2 = idx;
|
||||
for (idx = 1 - delta; idx < pos_length; idx += 2, idx2 += 2)
|
||||
{
|
||||
for (idx = 1 - delta; idx < pos_length; idx += 2, idx2 += 2) {
|
||||
*rxF_ext++ = rxF32[idx];
|
||||
*ul_ch0_ext++ = ul_ch0[idx2];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2) // 8 REs / PRB
|
||||
{
|
||||
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2) { // 8 REs / PRB
|
||||
AssertFatal(delta==0||delta==2||delta==4,"Illegal delta %d\n",delta);
|
||||
if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size)
|
||||
{
|
||||
for (int idx = 0; idx < nb_re_pusch; idx ++)
|
||||
{
|
||||
if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) {
|
||||
for (int idx = 0; idx < nb_re_pusch; idx ++) {
|
||||
if (idx % 6 == 2 * delta || idx % 6 == 2 * delta + 1)
|
||||
continue;
|
||||
*rxF_ext++ = rxF[idx];
|
||||
*ul_ch0_ext++ = ul_ch0[idx];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
int neg_length = frame_parms->ofdm_symbol_size - start_re;
|
||||
int pos_length = nb_re_pusch - neg_length;
|
||||
c16_t *rxF64 = &rxF[start_re];
|
||||
int idx, idx2;
|
||||
for (idx = 0; idx < neg_length; idx ++)
|
||||
{
|
||||
for (idx = 0; idx < neg_length; idx ++) {
|
||||
if (idx % 6 == 2 * delta || idx % 6 == 2 * delta + 1)
|
||||
continue;
|
||||
*rxF_ext++ = rxF64[idx];
|
||||
@@ -368,8 +357,7 @@ static void nr_ulsch_extract_rbs (c16_t* const rxdataF,
|
||||
}
|
||||
rxF64 = rxF;
|
||||
idx2 = idx;
|
||||
for (idx = 0; idx < pos_length; idx++, idx2++)
|
||||
{
|
||||
for (idx = 0; idx < pos_length; idx++, idx2++) {
|
||||
if (idx % 6 == 2 * delta || idx % 6 == 2 * delta + 1)
|
||||
continue;
|
||||
*rxF_ext++ = rxF64[idx];
|
||||
@@ -1282,19 +1270,26 @@ static void inner_rx(PHY_VARS_gNB *gNB,
|
||||
|
||||
memset(rxFext, 0, sizeof(c16_t) * nb_rx_ant * buffer_length);
|
||||
memset(chFext, 0, sizeof(c16_t) * nb_layer * nb_rx_ant* buffer_length);
|
||||
int dmrs_symbol;
|
||||
if (gNB->chest_time == 0)
|
||||
dmrs_symbol = dmrs_symbol_flag ? symbol : get_valid_dmrs_idx_for_channel_est(rel15_ul->ul_dmrs_symb_pos, symbol);
|
||||
else { // average of channel estimates stored in first symbol
|
||||
int end_symbol = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols;
|
||||
dmrs_symbol = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, end_symbol);
|
||||
}
|
||||
|
||||
for (int aarx = 0; aarx < nb_rx_ant; aarx++) {
|
||||
for (int aatx = 0; aatx < nb_layer; aatx++) {
|
||||
nr_ulsch_extract_rbs(rxF[aarx],
|
||||
(c16_t *)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx],
|
||||
rxFext[aarx],
|
||||
chFext[aatx][aarx],
|
||||
soffset+(symbol * frame_parms->ofdm_symbol_size),
|
||||
pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size,
|
||||
aarx,
|
||||
dmrs_symbol_flag,
|
||||
rel15_ul,
|
||||
frame_parms);
|
||||
(c16_t *)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx],
|
||||
rxFext[aarx],
|
||||
chFext[aatx][aarx],
|
||||
soffset+(symbol * frame_parms->ofdm_symbol_size),
|
||||
dmrs_symbol * frame_parms->ofdm_symbol_size,
|
||||
aarx,
|
||||
dmrs_symbol_flag,
|
||||
rel15_ul,
|
||||
frame_parms);
|
||||
}
|
||||
}
|
||||
c16_t rho[nb_layer][nb_layer][buffer_length] __attribute__((aligned(32)));
|
||||
@@ -1362,10 +1357,10 @@ static void inner_rx(PHY_VARS_gNB *gNB,
|
||||
else {
|
||||
nr_ulsch_mmse_2layers(frame_parms,
|
||||
(int32_t **)pusch_vars->rxdataF_comp,
|
||||
(int **)rxF_ch_maga,
|
||||
(int **)rxF_ch_magb,
|
||||
(int **)rxF_ch_magc,
|
||||
(int **)chFext,
|
||||
(int **)rxF_ch_maga,
|
||||
(int **)rxF_ch_magb,
|
||||
(int **)rxF_ch_magc,
|
||||
(int **)chFext,
|
||||
rel15_ul->rb_size,
|
||||
frame_parms->nb_antennas_rx,
|
||||
rel15_ul->qam_mod_order,
|
||||
@@ -1412,15 +1407,7 @@ static void nr_pusch_symbol_processing(void *arg)
|
||||
int ulsch_id = rdata->ulsch_id;
|
||||
int slot = rdata->slot;
|
||||
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
|
||||
for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol+rdata->numSymbols; symbol++) {
|
||||
int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
|
||||
if (dmrs_symbol_flag == 1)
|
||||
{
|
||||
if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01)
|
||||
AssertFatal(1==0,"Double DMRS configuration is not yet supported\n");
|
||||
gNB->pusch_vars[ulsch_id].dmrs_symbol = symbol;
|
||||
}
|
||||
|
||||
for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol + rdata->numSymbols; symbol++) {
|
||||
if (gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol] == 0)
|
||||
continue;
|
||||
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
@@ -1428,14 +1415,14 @@ static void nr_pusch_symbol_processing(void *arg)
|
||||
ulsch_id,
|
||||
slot,
|
||||
frame_parms,
|
||||
pusch_vars,
|
||||
pusch_vars,
|
||||
rel15_ul,
|
||||
gNB->common_vars.rxdataF,
|
||||
(c16_t**)gNB->pusch_vars[ulsch_id].ul_ch_estimates,
|
||||
gNB->common_vars.rxdataF,
|
||||
(c16_t**)gNB->pusch_vars[ulsch_id].ul_ch_estimates,
|
||||
rdata->llr_layers,
|
||||
soffset,
|
||||
gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol],
|
||||
symbol,
|
||||
symbol,
|
||||
gNB->pusch_vars[ulsch_id].log2_maxh,
|
||||
rdata->nvar);
|
||||
|
||||
@@ -1469,7 +1456,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_pusch_pdu_t *rel15_ul = &gNB->ulsch[ulsch_id].harq_process->ulsch_pdu;
|
||||
|
||||
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
|
||||
pusch_vars->dmrs_symbol = INVALID_VALUE;
|
||||
int nbSymb = 0;
|
||||
uint32_t bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start) * NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size;
|
||||
LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset);
|
||||
@@ -1481,13 +1467,12 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
|
||||
start_meas(&gNB->ulsch_channel_estimation_stats);
|
||||
int max_ch = 0;
|
||||
uint32_t nvar = 0;
|
||||
for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) {
|
||||
int end_symbol = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols;
|
||||
for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < end_symbol; symbol++) {
|
||||
uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
|
||||
LOG_D(PHY, "symbol %d, dmrs_symbol_flag :%d\n", symbol, dmrs_symbol_flag);
|
||||
|
||||
if (dmrs_symbol_flag == 1) {
|
||||
if (pusch_vars->dmrs_symbol == INVALID_VALUE)
|
||||
pusch_vars->dmrs_symbol = symbol;
|
||||
|
||||
for (int nl = 0; nl < rel15_ul->nrOfLayers; nl++) {
|
||||
uint32_t nvar_tmp = 0;
|
||||
@@ -1505,9 +1490,9 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
|
||||
}
|
||||
// measure the SNR from the channel estimation
|
||||
nr_gnb_measurements(gNB,
|
||||
&gNB->ulsch[ulsch_id],
|
||||
pusch_vars,
|
||||
symbol,
|
||||
&gNB->ulsch[ulsch_id],
|
||||
pusch_vars,
|
||||
symbol,
|
||||
rel15_ul->nrOfLayers);
|
||||
allocCast2D(n0_subband_power,
|
||||
unsigned int,
|
||||
@@ -1535,18 +1520,13 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
|
||||
nvar /= (rel15_ul->nr_of_symbols * rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx);
|
||||
|
||||
// averaging time domain channel estimates
|
||||
if (gNB->chest_time == 1)
|
||||
{
|
||||
if (gNB->chest_time == 1)
|
||||
nr_chest_time_domain_avg(frame_parms,
|
||||
pusch_vars->ul_ch_estimates,
|
||||
rel15_ul->nr_of_symbols,
|
||||
rel15_ul->start_symbol_index,
|
||||
rel15_ul->ul_dmrs_symb_pos,
|
||||
rel15_ul->rb_size);
|
||||
pusch_vars->dmrs_symbol = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos,
|
||||
rel15_ul->start_symbol_index,
|
||||
rel15_ul->nr_of_symbols);
|
||||
}
|
||||
|
||||
stop_meas(&gNB->ulsch_channel_estimation_stats);
|
||||
|
||||
@@ -1554,7 +1534,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
|
||||
|
||||
// Scrambling initialization
|
||||
int number_dmrs_symbols = 0;
|
||||
for (int l = rel15_ul->start_symbol_index; l < rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols; l++)
|
||||
for (int l = rel15_ul->start_symbol_index; l < end_symbol; l++)
|
||||
number_dmrs_symbols += ((rel15_ul->ul_dmrs_symb_pos)>>l) & 0x01;
|
||||
int nb_re_dmrs;
|
||||
if (rel15_ul->dmrs_config_type == pusch_dmrs_type1)
|
||||
@@ -1593,32 +1573,38 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
|
||||
// first the computation of channel levels
|
||||
|
||||
int nb_re_pusch = 0, meas_symbol = -1;
|
||||
for(meas_symbol = rel15_ul->start_symbol_index;
|
||||
meas_symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols);
|
||||
meas_symbol++)
|
||||
if ((nb_re_pusch = get_nb_re_pusch(frame_parms,rel15_ul,meas_symbol)) > 0)
|
||||
for(meas_symbol = rel15_ul->start_symbol_index; meas_symbol < end_symbol; meas_symbol++)
|
||||
if ((nb_re_pusch = get_nb_re_pusch(frame_parms, rel15_ul, meas_symbol)) > 0)
|
||||
break;
|
||||
|
||||
AssertFatal(nb_re_pusch>0 && meas_symbol>=0,"nb_re_pusch %d cannot be 0 or meas_symbol %d cannot be negative here\n",nb_re_pusch,meas_symbol);
|
||||
AssertFatal(nb_re_pusch > 0 && meas_symbol >= 0,
|
||||
"nb_re_pusch %d cannot be 0 or meas_symbol %d cannot be negative here\n",
|
||||
nb_re_pusch,
|
||||
meas_symbol);
|
||||
|
||||
// extract the first dmrs for the channel level computation
|
||||
// extract the data in the OFDM frame, to the start of the array
|
||||
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
|
||||
nb_re_pusch = (nb_re_pusch + 15) & ~15;
|
||||
int dmrs_symbol;
|
||||
if (gNB->chest_time == 0)
|
||||
dmrs_symbol = get_valid_dmrs_idx_for_channel_est(rel15_ul->ul_dmrs_symb_pos, meas_symbol);
|
||||
else // average of channel estimates stored in first symbol
|
||||
dmrs_symbol = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, end_symbol);
|
||||
|
||||
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++)
|
||||
for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++)
|
||||
nr_ulsch_extract_rbs(gNB->common_vars.rxdataF[aarx],
|
||||
(c16_t *)pusch_vars->ul_ch_estimates[aatx * frame_parms->nb_antennas_rx + aarx],
|
||||
(c16_t*)&pusch_vars->rxdataF_ext[aarx][meas_symbol * nb_re_pusch],
|
||||
(c16_t*)&pusch_vars->ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][meas_symbol * nb_re_pusch],
|
||||
soffset + meas_symbol * frame_parms->ofdm_symbol_size,
|
||||
pusch_vars->dmrs_symbol * frame_parms->ofdm_symbol_size,
|
||||
aarx,
|
||||
(rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01,
|
||||
rel15_ul,
|
||||
frame_parms);
|
||||
(c16_t*)pusch_vars->ul_ch_estimates[aatx * frame_parms->nb_antennas_rx + aarx],
|
||||
(c16_t*)&pusch_vars->rxdataF_ext[aarx][meas_symbol * nb_re_pusch],
|
||||
(c16_t*)&pusch_vars->ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx+aarx][meas_symbol * nb_re_pusch],
|
||||
soffset + meas_symbol * frame_parms->ofdm_symbol_size,
|
||||
dmrs_symbol * frame_parms->ofdm_symbol_size,
|
||||
aarx,
|
||||
(rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01,
|
||||
rel15_ul,
|
||||
frame_parms);
|
||||
|
||||
int avgs = 0;
|
||||
int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers];
|
||||
@@ -1662,12 +1648,9 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
|
||||
start_meas(&gNB->rx_pusch_symbol_processing_stats);
|
||||
int numSymbols = gNB->num_pusch_symbols_per_thread;
|
||||
|
||||
for(uint8_t symbol = rel15_ul->start_symbol_index;
|
||||
symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols);
|
||||
symbol += numSymbols)
|
||||
{
|
||||
for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < end_symbol; symbol += numSymbols) {
|
||||
int total_res = 0;
|
||||
for (int s = 0; s < numSymbols;s++) {
|
||||
for (int s = 0; s < numSymbols; s++) {
|
||||
pusch_vars->ul_valid_re_per_slot[symbol+s] = get_nb_re_pusch(frame_parms,rel15_ul,symbol+s);
|
||||
pusch_vars->llr_offset[symbol+s] = ((symbol+s) == rel15_ul->start_symbol_index) ?
|
||||
0 :
|
||||
|
||||
@@ -39,6 +39,19 @@
|
||||
#define USE_128BIT
|
||||
#endif
|
||||
|
||||
int16_t saturating_sub(int16_t a, int16_t b)
|
||||
{
|
||||
int32_t result = (int32_t)a - (int32_t)b;
|
||||
|
||||
if (result < INT16_MIN) {
|
||||
return INT16_MIN;
|
||||
} else if (result > INT16_MAX) {
|
||||
return INT16_MAX;
|
||||
} else {
|
||||
return (int16_t)result;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// QPSK
|
||||
//----------------------------------------------------------------------------------------------
|
||||
@@ -59,48 +72,27 @@ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp,
|
||||
// 16-QAM
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
void nr_ulsch_16qam_llr(int32_t *rxdataF_comp,
|
||||
int32_t *ul_ch_mag,
|
||||
int16_t *ulsch_llr,
|
||||
uint32_t nb_re,
|
||||
uint8_t symbol)
|
||||
void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, int32_t *ul_ch_mag, int16_t *ulsch_llr, uint32_t nb_re, uint8_t symbol)
|
||||
{
|
||||
#ifdef USE_128BIT
|
||||
simde__m128i *rxF = (simde__m128i*)rxdataF_comp;
|
||||
simde__m128i *ch_mag;
|
||||
simde__m128i *ulsch_llr_128 = (simde__m128i*) ulsch_llr;
|
||||
int i;
|
||||
|
||||
ch_mag = (simde__m128i*)ul_ch_mag;
|
||||
nb_re >>= 2; // length in quad words (4 REs)
|
||||
nb_re += ((nb_re&3) == 0 ? 0 : 1);
|
||||
|
||||
// Each iteration does 4 RE (gives 16 16bit-llrs)
|
||||
for (i=0; i<nb_re; i++) {
|
||||
simde__m128i xmm0 = simde_mm_abs_epi16(rxF[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
xmm0 = simde_mm_subs_epi16(ch_mag[i],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
|
||||
ulsch_llr_128[0] = simde_mm_unpacklo_epi32(rxF[i],xmm0); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs
|
||||
ulsch_llr_128[1] = simde_mm_unpackhi_epi32(rxF[i],xmm0); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs
|
||||
ulsch_llr_128 += 2;
|
||||
}
|
||||
#else
|
||||
simde__m256i *rxF_256 = (simde__m256i*)rxdataF_comp;
|
||||
simde__m256i *ch_mag = (simde__m256i*)ul_ch_mag;
|
||||
int64_t *llr_64 = (int64_t*)ulsch_llr;
|
||||
simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp;
|
||||
simde__m256i *ch_mag = (simde__m256i *)ul_ch_mag;
|
||||
int64_t *llr_64 = (int64_t *)ulsch_llr;
|
||||
|
||||
#ifndef USE_128BIT
|
||||
simde__m256i xmm0, xmm1, xmm2;
|
||||
|
||||
for (int i = 0; i < ((nb_re + 7) >> 3); i++) {
|
||||
xmm0 = simde_mm256_abs_epi16(rxF_256[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
xmm0 = simde_mm256_subs_epi16(ch_mag[i], xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
|
||||
xmm1 = simde_mm256_unpacklo_epi32(rxF_256[i], xmm0);
|
||||
xmm2 = simde_mm256_unpackhi_epi32(rxF_256[i], xmm0);
|
||||
for (int i = 0; i < (nb_re >> 3); i++) {
|
||||
// registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
xmm0 = simde_mm256_abs_epi16(*rxF_256);
|
||||
// registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
xmm0 = simde_mm256_subs_epi16(*ch_mag, xmm0);
|
||||
|
||||
xmm1 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0);
|
||||
xmm2 = simde_mm256_unpackhi_epi32(*rxF_256, xmm0);
|
||||
|
||||
// xmm1 |1st 2ed 3rd 4th 9th 10th 13rd 14th|
|
||||
// xmm2 |5th 6th 7th 8th 11st 12ed 15th 16th|
|
||||
|
||||
|
||||
*llr_64++ = simde_mm256_extract_epi64(xmm1, 0);
|
||||
*llr_64++ = simde_mm256_extract_epi64(xmm1, 1);
|
||||
*llr_64++ = simde_mm256_extract_epi64(xmm2, 0);
|
||||
@@ -109,9 +101,47 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp,
|
||||
*llr_64++ = simde_mm256_extract_epi64(xmm1, 3);
|
||||
*llr_64++ = simde_mm256_extract_epi64(xmm2, 2);
|
||||
*llr_64++ = simde_mm256_extract_epi64(xmm2, 3);
|
||||
rxF_256++;
|
||||
ch_mag++;
|
||||
}
|
||||
|
||||
nb_re &= 0x7;
|
||||
#endif
|
||||
|
||||
simde__m128i *rxF_128 = (simde__m128i *)rxF_256;
|
||||
simde__m128i *ch_mag_128 = (simde__m128i *)ch_mag;
|
||||
simde__m128i *ulsch_llr_128 = (simde__m128i *)llr_64;
|
||||
|
||||
// Each iteration does 4 RE (gives 16 16bit-llrs)
|
||||
for (int i = 0; i < (nb_re >> 2); i++) {
|
||||
// registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
simde__m128i xmm0 = simde_mm_abs_epi16(*rxF_128);
|
||||
// registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
xmm0 = simde_mm_subs_epi16(*ch_mag_128, xmm0);
|
||||
|
||||
ulsch_llr_128[0] = simde_mm_unpacklo_epi32(*rxF_128, xmm0); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs
|
||||
ulsch_llr_128[1] = simde_mm_unpackhi_epi32(*rxF_128, xmm0); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs
|
||||
ulsch_llr_128 += 2;
|
||||
rxF_128++;
|
||||
ch_mag_128++;
|
||||
}
|
||||
|
||||
simde_mm_empty();
|
||||
|
||||
nb_re &= 0x3;
|
||||
int16_t *rxDataF_i16 = (int16_t *)rxF_128;
|
||||
int16_t *ul_ch_mag_i16 = (int16_t *)ch_mag_128;
|
||||
int16_t *ulsch_llr_i16 = (int16_t *)ulsch_llr_128;
|
||||
for (uint i = 0U; i < nb_re; i++) {
|
||||
int16_t real = rxDataF_i16[2 * i];
|
||||
int16_t imag = rxDataF_i16[2 * i + 1];
|
||||
int16_t mag_real = ul_ch_mag_i16[2 * i];
|
||||
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
|
||||
ulsch_llr_i16[4 * i] = real;
|
||||
ulsch_llr_i16[4 * i + 1] = imag;
|
||||
ulsch_llr_i16[4 * i + 2] = saturating_sub(mag_real, abs(real));
|
||||
ulsch_llr_i16[4 * i + 3] = saturating_sub(mag_imag, abs(imag));
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
@@ -121,89 +151,116 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp,
|
||||
void nr_ulsch_64qam_llr(int32_t *rxdataF_comp,
|
||||
int32_t *ul_ch_mag,
|
||||
int32_t *ul_ch_magb,
|
||||
int16_t *ulsch_llr,
|
||||
int16_t *ulsch_llr,
|
||||
uint32_t nb_re,
|
||||
uint8_t symbol)
|
||||
uint8_t symbol)
|
||||
{
|
||||
#ifdef USE_128BIT
|
||||
simde__m128i *rxF = (simde__m128i*)rxdataF_comp;
|
||||
simde__m128i *ch_mag = (simde__m128i*)ul_ch_mag;
|
||||
simde__m128i *ch_magb = (simde__m128i*)ul_ch_magb;
|
||||
int i;
|
||||
simde__m256i *rxF = (simde__m256i *)rxdataF_comp;
|
||||
|
||||
nb_re = nb_re>>2; // length in 128-bit words (4 REs)
|
||||
nb_re += ((nb_re&3) == 0 ? 0 : 1);
|
||||
simde__m64 *llr64 = (simde__m64 *) ulsch_llr;
|
||||
|
||||
// Each iteration does 4 RE (gives 24 16bit-llrs)
|
||||
for (i=0; i<nb_re; i++) {
|
||||
simde__m128i xmm0, xmm1, xmm2;
|
||||
xmm0 = rxF[i];
|
||||
xmm1 = simde_mm_abs_epi16(xmm0);
|
||||
xmm1 = simde_mm_subs_epi16(ch_mag[i],xmm1);
|
||||
xmm2 = simde_mm_abs_epi16(xmm1);
|
||||
xmm2 = simde_mm_subs_epi16(ch_magb[i],xmm2);
|
||||
|
||||
llr64[0] = simde_mm_set_pi32(simde_mm_extract_epi32(xmm1, 0), simde_mm_extract_epi32(xmm0, 0));
|
||||
llr64[1] = simde_mm_set_pi32(simde_mm_extract_epi32(xmm0, 1), simde_mm_extract_epi32(xmm2, 0));
|
||||
llr64[2] = simde_mm_set_pi32(simde_mm_extract_epi32(xmm2, 1), simde_mm_extract_epi32(xmm1, 1));
|
||||
llr64[3] = simde_mm_set_pi32(simde_mm_extract_epi32(xmm1, 2), simde_mm_extract_epi32(xmm0, 2));
|
||||
llr64[4] = simde_mm_set_pi32(simde_mm_extract_epi32(xmm0, 3), simde_mm_extract_epi32(xmm2, 2));
|
||||
llr64[5] = simde_mm_set_pi32(simde_mm_extract_epi32(xmm2, 3), simde_mm_extract_epi32(xmm1, 3));
|
||||
llr64 += 6;
|
||||
}
|
||||
#else
|
||||
simde__m256i *rxF = (simde__m256i*)rxdataF_comp;
|
||||
simde__m256i xmm0, xmm1, xmm2;
|
||||
|
||||
simde__m256i *ch_maga = (simde__m256i*)ul_ch_mag;
|
||||
simde__m256i *ch_magb = (simde__m256i*)ul_ch_magb;
|
||||
simde__m256i *ch_maga = (simde__m256i *)ul_ch_mag;
|
||||
simde__m256i *ch_magb = (simde__m256i *)ul_ch_magb;
|
||||
|
||||
int32_t *llr_32 = (int32_t *)ulsch_llr;
|
||||
|
||||
for (int i = 0; i < ((nb_re + 7) >> 3); i++) {
|
||||
xmm0 = rxF[i];
|
||||
xmm1 = simde_mm256_abs_epi16(xmm0); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
xmm1 = simde_mm256_subs_epi16(ch_maga[i], xmm1); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
#ifndef USE_128BIT
|
||||
simde__m256i xmm0, xmm1, xmm2;
|
||||
for (int i = 0; i < (nb_re >> 3); i++) {
|
||||
xmm0 = *rxF;
|
||||
// registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
xmm1 = simde_mm256_abs_epi16(xmm0);
|
||||
// registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
xmm1 = simde_mm256_subs_epi16(*ch_maga, xmm1);
|
||||
xmm2 = simde_mm256_abs_epi16(xmm1);
|
||||
xmm2 = simde_mm256_subs_epi16(ch_magb[i], xmm2);
|
||||
xmm2 = simde_mm256_subs_epi16(*ch_magb, xmm2);
|
||||
// xmm0 |1st 4th 7th 10th 13th 16th 19th 22ed|
|
||||
// xmm1 |2ed 5th 8th 11th 14th 17th 20th 23rd|
|
||||
// xmm2 |3rd 6th 9th 12th 15th 18th 21st 24th|
|
||||
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0,0);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1,0);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2,0);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0, 0);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1, 0);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2, 0);
|
||||
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0,1);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1,1);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2,1);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0, 1);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1, 1);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2, 1);
|
||||
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0,2);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1,2);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2,2);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0, 2);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1, 2);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2, 2);
|
||||
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0,3);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1,3);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2,3);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0, 3);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1, 3);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2, 3);
|
||||
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0,4);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1,4);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2,4);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0, 4);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1, 4);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2, 4);
|
||||
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0,5);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1,5);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2,5);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0, 5);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1, 5);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2, 5);
|
||||
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0,6);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1,6);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2,6);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0, 6);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1, 6);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2, 6);
|
||||
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0,7);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1,7);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2,7);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm0, 7);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm1, 7);
|
||||
*llr_32++ = simde_mm256_extract_epi32(xmm2, 7);
|
||||
rxF++;
|
||||
ch_maga++;
|
||||
ch_magb++;
|
||||
}
|
||||
|
||||
nb_re &= 0x7;
|
||||
#endif
|
||||
|
||||
simde__m128i *rxF_128 = (simde__m128i *)rxF;
|
||||
simde__m128i *ch_mag_128 = (simde__m128i *)ch_maga;
|
||||
simde__m128i *ch_magb_128 = (simde__m128i *)ch_magb;
|
||||
|
||||
simde__m64 *llr64 = (simde__m64 *)llr_32;
|
||||
|
||||
// Each iteration does 4 RE (gives 24 16bit-llrs)
|
||||
for (int i = 0; i < (nb_re >> 2); i++) {
|
||||
simde__m128i xmm0, xmm1, xmm2;
|
||||
xmm0 = *rxF_128;
|
||||
xmm1 = simde_mm_abs_epi16(xmm0);
|
||||
xmm1 = simde_mm_subs_epi16(*ch_mag_128, xmm1);
|
||||
xmm2 = simde_mm_abs_epi16(xmm1);
|
||||
xmm2 = simde_mm_subs_epi16(*ch_magb_128, xmm2);
|
||||
|
||||
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm1, 0), simde_mm_extract_epi32(xmm0, 0));
|
||||
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm0, 1), simde_mm_extract_epi32(xmm2, 0));
|
||||
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm2, 1), simde_mm_extract_epi32(xmm1, 1));
|
||||
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm1, 2), simde_mm_extract_epi32(xmm0, 2));
|
||||
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm0, 3), simde_mm_extract_epi32(xmm2, 2));
|
||||
*llr64++ = simde_mm_set_pi32(simde_mm_extract_epi32(xmm2, 3), simde_mm_extract_epi32(xmm1, 3));
|
||||
rxF_128++;
|
||||
ch_mag_128++;
|
||||
ch_magb_128++;
|
||||
}
|
||||
|
||||
nb_re &= 0x3;
|
||||
|
||||
int16_t *rxDataF_i16 = (int16_t *)rxF_128;
|
||||
int16_t *ul_ch_mag_i16 = (int16_t *)ch_mag_128;
|
||||
int16_t *ul_ch_magb_i16 = (int16_t *)ch_magb_128;
|
||||
int16_t *llr_i16 = (int16_t *)llr64;
|
||||
for (int i = 0; i < nb_re; i++) {
|
||||
int16_t real = rxDataF_i16[2 * i];
|
||||
int16_t imag = rxDataF_i16[2 * i + 1];
|
||||
int16_t mag_real = ul_ch_mag_i16[2 * i];
|
||||
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
|
||||
llr_i16[6 * i] = real;
|
||||
llr_i16[6 * i + 1] = imag;
|
||||
llr_i16[6 * i + 2] = saturating_sub(mag_real, abs(real));
|
||||
llr_i16[6 * i + 3] = saturating_sub(mag_imag, abs(imag));
|
||||
int16_t mag_realb = ul_ch_magb_i16[2 * i];
|
||||
int16_t mag_imagb = ul_ch_magb_i16[2 * i + 1];
|
||||
llr_i16[6 * i + 4] = saturating_sub(mag_realb, abs(llr_i16[6 * i + 2]));
|
||||
llr_i16[6 * i + 5] = saturating_sub(mag_imagb, abs(llr_i16[6 * i + 3]));
|
||||
}
|
||||
simde_mm_empty();
|
||||
}
|
||||
|
||||
@@ -211,94 +268,37 @@ void nr_ulsch_256qam_llr(int32_t *rxdataF_comp,
|
||||
int32_t *ul_ch_mag,
|
||||
int32_t *ul_ch_magb,
|
||||
int32_t *ul_ch_magc,
|
||||
int16_t *ulsch_llr,
|
||||
int16_t *ulsch_llr,
|
||||
uint32_t nb_re,
|
||||
uint8_t symbol)
|
||||
uint8_t symbol)
|
||||
{
|
||||
#ifdef USE_128BIT
|
||||
simde__m128i *rxF = (simde__m128i*)rxdataF_comp;
|
||||
simde__m128i *llr128=(simde__m128i*)ulsch_llr;
|
||||
simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp;
|
||||
simde__m256i *llr256 = (simde__m256i *)ulsch_llr;
|
||||
|
||||
simde__m128i* ch_mag = (simde__m128i*)ul_ch_mag;
|
||||
simde__m128i* ch_magb = (simde__m128i*)ul_ch_magb;
|
||||
simde__m128i* ch_magc = (simde__m128i*)ul_ch_magc;
|
||||
int len_mod4 = nb_re & 3;
|
||||
int nb_re128 = nb_re >> 2; // length in 128-bit words (4 REs)
|
||||
simde__m256i *ch_maga = (simde__m256i *)ul_ch_mag;
|
||||
simde__m256i *ch_magb = (simde__m256i *)ul_ch_magb;
|
||||
simde__m256i *ch_magc = (simde__m256i *)ul_ch_magc;
|
||||
#ifndef USE_128BIT
|
||||
simde__m256i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6;
|
||||
|
||||
for (int i=0; i<nb_re128; i++) {
|
||||
simde__m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6;
|
||||
xmm0 = simde_mm_abs_epi16(rxF[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
xmm0 = simde_mm_subs_epi16(ch_mag[i], xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
xmm1 = simde_mm_abs_epi16(xmm0);
|
||||
xmm1 = simde_mm_subs_epi16(ch_magb[i], xmm1); // contains 8 LLRs
|
||||
xmm2 = simde_mm_abs_epi16(xmm1);
|
||||
xmm2 = simde_mm_subs_epi16(ch_magc[i], xmm2); // contains 8 LLRs
|
||||
// rxF[i] A0 A1 A2 A3
|
||||
// xmm0 B0 B1 B2 B3
|
||||
// xmm1 C0 C1 C2 C3
|
||||
// xmm2 D0 D1 D2 D3
|
||||
xmm3 = simde_mm_unpacklo_epi32(rxF[i], xmm0); // A0 B0 A1 B1
|
||||
xmm4 = simde_mm_unpackhi_epi32(rxF[i], xmm0); // A2 B2 A3 B3
|
||||
xmm5 = simde_mm_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1
|
||||
xmm6 = simde_mm_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3
|
||||
|
||||
llr128[0] = simde_mm_unpacklo_epi64(xmm3,xmm5); // A0 B0 C0 D0
|
||||
llr128[1] = simde_mm_unpackhi_epi64(xmm3,xmm5); // A1 B1 C1 D1
|
||||
llr128[2] = simde_mm_unpacklo_epi64(xmm4,xmm6); // A2 B2 C2 D2
|
||||
llr128[3] = simde_mm_unpackhi_epi64(xmm4,xmm6); // A3 B3 C3 D3
|
||||
llr128+=4;
|
||||
}
|
||||
|
||||
if (len_mod4) {
|
||||
int last_2_re = (nb_re >> 1) - 1;
|
||||
simde__m64 *llr64 = (simde__m64 *)llr128;
|
||||
simde__m64 xmm0,xmm1,xmm2;
|
||||
simde__m64 *rxF = (simde__m64*)rxdataF_comp;
|
||||
simde__m64 *ch_mag = (simde__m64*)ul_ch_mag;
|
||||
simde__m64 *ch_magb = (simde__m64*)ul_ch_magb;
|
||||
simde__m64 *ch_magc = (simde__m64*)ul_ch_magc;
|
||||
|
||||
xmm0 = simde_mm_abs_pi16(rxF[last_2_re]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
xmm0 = simde_mm_subs_pi16(ch_mag[last_2_re],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
// xmmtmpD2 contains 4 LLRs
|
||||
xmm1 = simde_mm_abs_pi16(xmm0);
|
||||
xmm1 = simde_mm_subs_pi16(ch_magb[last_2_re],xmm1); // contains 4 LLRs
|
||||
xmm2 = simde_mm_abs_pi16(xmm1);
|
||||
xmm2 = simde_mm_subs_pi16(ch_magc[last_2_re],xmm2); // contains 4 LLRs
|
||||
// rxF[i] A0 A1
|
||||
// xmm0 B0 B1
|
||||
// xmm1 C0 C1
|
||||
// xmm2 D0 D1
|
||||
llr64[0] = simde_mm_unpacklo_pi32(rxF[last_2_re],xmm0); // A0 B0
|
||||
llr64[2] = simde_mm_unpackhi_pi32(rxF[last_2_re],xmm0); // A1 B1
|
||||
llr64[1] = simde_mm_unpacklo_pi32(xmm1,xmm2); // C0 D0
|
||||
llr64[3] = simde_mm_unpackhi_pi32(xmm1,xmm2); // C1 D1
|
||||
}
|
||||
#else
|
||||
simde__m256i *rxF = (simde__m256i*)rxdataF_comp;
|
||||
simde__m256i xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6;
|
||||
simde__m256i *llr256=(simde__m256i*)ulsch_llr;
|
||||
|
||||
simde__m256i* ch_maga = (simde__m256i*)ul_ch_mag;
|
||||
simde__m256i* ch_magb = (simde__m256i*)ul_ch_magb;
|
||||
simde__m256i* ch_magc = (simde__m256i*)ul_ch_magc;
|
||||
|
||||
for (int i = 0; i < ((nb_re + 7) >> 3); i++) {
|
||||
xmm0 = simde_mm256_abs_epi16(rxF[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
xmm0 = simde_mm256_subs_epi16(ch_maga[i], xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
for (int i = 0; i < (nb_re >> 3); i++) {
|
||||
// registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
xmm0 = simde_mm256_abs_epi16(*rxF_256);
|
||||
// registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
xmm0 = simde_mm256_subs_epi16(*ch_maga, xmm0);
|
||||
// xmmtmpD2 contains 16 LLRs
|
||||
xmm1 = simde_mm256_abs_epi16(xmm0);
|
||||
xmm1 = simde_mm256_subs_epi16(ch_magb[i], xmm1); // contains 16 LLRs
|
||||
xmm1 = simde_mm256_subs_epi16(*ch_magb, xmm1); // contains 16 LLRs
|
||||
xmm2 = simde_mm256_abs_epi16(xmm1);
|
||||
xmm2 = simde_mm256_subs_epi16(ch_magc[i], xmm2); // contains 16 LLRs
|
||||
xmm2 = simde_mm256_subs_epi16(*ch_magc, xmm2); // contains 16 LLRs
|
||||
// rxF[i] A0 A1 A2 A3 A4 A5 A6 A7 bits 7,6
|
||||
// xmm0 B0 B1 B2 B3 B4 B5 B6 B7 bits 5,4
|
||||
// xmm1 C0 C1 C2 C3 C4 C5 C6 C7 bits 3,2
|
||||
// xmm2 D0 D1 D2 D3 D4 D5 D6 D7 bits 1,0
|
||||
xmm3 = simde_mm256_unpacklo_epi32(rxF[i], xmm0); // A0 B0 A1 B1 A4 B4 A5 B5
|
||||
xmm4 = simde_mm256_unpackhi_epi32(rxF[i], xmm0); // A2 B2 A3 B3 A6 B6 A7 B7
|
||||
xmm5 = simde_mm256_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1 C4 D4 C5 D5
|
||||
xmm6 = simde_mm256_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3 C6 D6 C7 D7
|
||||
xmm3 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0); // A0 B0 A1 B1 A4 B4 A5 B5
|
||||
xmm4 = simde_mm256_unpackhi_epi32(*rxF_256, xmm0); // A2 B2 A3 B3 A6 B6 A7 B7
|
||||
xmm5 = simde_mm256_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1 C4 D4 C5 D5
|
||||
xmm6 = simde_mm256_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3 C6 D6 C7 D7
|
||||
|
||||
xmm0 = simde_mm256_unpacklo_epi64(xmm3, xmm5); // A0 B0 C0 D0 A4 B4 C4 D4
|
||||
xmm1 = simde_mm256_unpackhi_epi64(xmm3, xmm5); // A1 B1 C1 D1 A5 B5 C5 D5
|
||||
@@ -308,8 +308,77 @@ void nr_ulsch_256qam_llr(int32_t *rxdataF_comp,
|
||||
*llr256++ = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x20); // A2 B2 C2 D2 A3 B3 C3 D3
|
||||
*llr256++ = simde_mm256_permute2x128_si256(xmm0, xmm1, 0x31); // A4 B4 C4 D4 A5 B5 C5 D5
|
||||
*llr256++ = simde_mm256_permute2x128_si256(xmm2, xmm3, 0x31); // A6 B6 C6 D6 A7 B7 C7 D7
|
||||
ch_magc++;
|
||||
ch_magb++;
|
||||
ch_maga++;
|
||||
rxF_256++;
|
||||
}
|
||||
|
||||
nb_re &= 0x7;
|
||||
#endif
|
||||
|
||||
simde__m128i *rxF_128 = (simde__m128i *)rxF_256;
|
||||
simde__m128i *llr_128 = (simde__m128i *)llr256;
|
||||
|
||||
simde__m128i *ch_maga_128 = (simde__m128i *)ch_maga;
|
||||
simde__m128i *ch_magb_128 = (simde__m128i *)ch_magb;
|
||||
simde__m128i *ch_magc_128 = (simde__m128i *)ch_magc;
|
||||
|
||||
for (int i = 0; i < (nb_re >> 2); i++) {
|
||||
simde__m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6;
|
||||
// registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I|
|
||||
xmm0 = simde_mm_abs_epi16(*rxF_128);
|
||||
// registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2
|
||||
xmm0 = simde_mm_subs_epi16(*ch_maga_128, xmm0);
|
||||
xmm1 = simde_mm_abs_epi16(xmm0);
|
||||
xmm1 = simde_mm_subs_epi16(*ch_magb_128, xmm1); // contains 8 LLRs
|
||||
xmm2 = simde_mm_abs_epi16(xmm1);
|
||||
xmm2 = simde_mm_subs_epi16(*ch_magc_128, xmm2); // contains 8 LLRs
|
||||
// rxF[i] A0 A1 A2 A3
|
||||
// xmm0 B0 B1 B2 B3
|
||||
// xmm1 C0 C1 C2 C3
|
||||
// xmm2 D0 D1 D2 D3
|
||||
xmm3 = simde_mm_unpacklo_epi32(*rxF_128, xmm0); // A0 B0 A1 B1
|
||||
xmm4 = simde_mm_unpackhi_epi32(*rxF_128, xmm0); // A2 B2 A3 B3
|
||||
xmm5 = simde_mm_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1
|
||||
xmm6 = simde_mm_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3
|
||||
|
||||
*llr_128++ = simde_mm_unpacklo_epi64(xmm3, xmm5); // A0 B0 C0 D0
|
||||
*llr_128++ = simde_mm_unpackhi_epi64(xmm3, xmm5); // A1 B1 C1 D1
|
||||
*llr_128++ = simde_mm_unpacklo_epi64(xmm4, xmm6); // A2 B2 C2 D2
|
||||
*llr_128++ = simde_mm_unpackhi_epi64(xmm4, xmm6); // A3 B3 C3 D3
|
||||
|
||||
rxF_128++;
|
||||
ch_maga_128++;
|
||||
ch_magb_128++;
|
||||
ch_magc_128++;
|
||||
}
|
||||
|
||||
if (nb_re & 3) {
|
||||
for (int i = 0; i < (nb_re & 0x3); i++) {
|
||||
int16_t *rxDataF_i16 = (int16_t *)rxF_128;
|
||||
int16_t *ul_ch_mag_i16 = (int16_t *)ch_maga_128;
|
||||
int16_t *ul_ch_magb_i16 = (int16_t *)ch_magb_128;
|
||||
int16_t *ul_ch_magc_i16 = (int16_t *)ch_magc_128;
|
||||
int16_t *ulsch_llr_i16 = (int16_t *)llr_128;
|
||||
int16_t real = rxDataF_i16[2 * i + 0];
|
||||
int16_t imag = rxDataF_i16[2 * i + 1];
|
||||
int16_t mag_real = ul_ch_mag_i16[2 * i];
|
||||
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
|
||||
ulsch_llr_i16[8 * i] = real;
|
||||
ulsch_llr_i16[8 * i + 1] = imag;
|
||||
ulsch_llr_i16[8 * i + 2] = saturating_sub(mag_real, abs(real));
|
||||
ulsch_llr_i16[8 * i + 3] = saturating_sub(mag_imag, abs(imag));
|
||||
int16_t magb_real = ul_ch_magb_i16[2 * i];
|
||||
int16_t magb_imag = ul_ch_magb_i16[2 * i + 1];
|
||||
ulsch_llr_i16[8 * i + 4] = saturating_sub(magb_real, abs(ulsch_llr_i16[8 * i + 2]));
|
||||
ulsch_llr_i16[8 * i + 5] = saturating_sub(magb_imag, abs(ulsch_llr_i16[8 * i + 3]));
|
||||
int16_t magc_real = ul_ch_magc_i16[2 * i];
|
||||
int16_t magc_imag = ul_ch_magc_i16[2 * i + 1];
|
||||
ulsch_llr_i16[8 * i + 6] = saturating_sub(magc_real, abs(ulsch_llr_i16[8 * i + 4]));
|
||||
ulsch_llr_i16[8 * i + 7] = saturating_sub(magc_imag, abs(ulsch_llr_i16[8 * i + 5]));
|
||||
}
|
||||
}
|
||||
simde_mm_empty();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
add_executable(test_llr test_llr.cpp)
|
||||
target_link_libraries(test_llr PRIVATE PHY_NR GTest::gtest minimal_lib)
|
||||
add_dependencies(tests test_llr)
|
||||
add_test(NAME test_llr
|
||||
COMMAND ./test_llr)
|
||||
|
||||
add_executable(test_llr_no_avx_256 test_llr.cpp)
|
||||
target_link_libraries(test_llr_no_avx_256 PRIVATE PHY_NR_NO_AVX_256 GTest::gtest minimal_lib)
|
||||
add_dependencies(tests test_llr_no_avx_256)
|
||||
add_test(NAME test_llr_no_avx_256
|
||||
COMMAND ./test_llr_no_avx_256)
|
||||
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
extern "C" {
|
||||
void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, int32_t *ul_ch_mag, int16_t *ulsch_llr, uint32_t nb_re, uint8_t symbol);
|
||||
void nr_ulsch_64qam_llr(int32_t *rxdataF_comp,
|
||||
int32_t *ul_ch_mag,
|
||||
int32_t *ul_ch_magb,
|
||||
int16_t *ulsch_llr,
|
||||
uint32_t nb_re,
|
||||
uint8_t symbol);
|
||||
void nr_ulsch_256qam_llr(int32_t *rxdataF_comp,
|
||||
int32_t *ul_ch_mag,
|
||||
int32_t *ul_ch_magb,
|
||||
int32_t *ul_ch_magc,
|
||||
int16_t *ulsch_llr,
|
||||
uint32_t nb_re,
|
||||
uint8_t symbol);
|
||||
struct configmodule_interface_s;
|
||||
struct configmodule_interface_s *uniqCfg = NULL;
|
||||
|
||||
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
||||
{
|
||||
if (assert) {
|
||||
abort();
|
||||
} else {
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
#include "openair1/PHY/TOOLS/tools_defs.h"
|
||||
}
|
||||
#include <cstdio>
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
|
||||
constexpr bool is_power_of_two(uint64_t n)
|
||||
{
|
||||
return n > 0 && (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
size_t align_up(size_t a, size_t b)
|
||||
{
|
||||
return (a + b - 1) / b * b;
|
||||
}
|
||||
|
||||
int16_t saturating_sub(int16_t a, int16_t b)
|
||||
{
|
||||
int32_t result = (int32_t)a - (int32_t)b;
|
||||
|
||||
if (result < INT16_MIN) {
|
||||
return INT16_MIN;
|
||||
} else if (result > INT16_MAX) {
|
||||
return INT16_MAX;
|
||||
} else {
|
||||
return (int16_t)result;
|
||||
}
|
||||
}
|
||||
|
||||
// Template adaptations for std::vector. This is needed because the avx functions expect 256 bit alignment.
|
||||
template <typename T, size_t alignment>
|
||||
class AlignedAllocator {
|
||||
public:
|
||||
static_assert(is_power_of_two(alignment), "Alignment should be power of 2");
|
||||
static_assert(alignment >= 8, "Alignment must be at least 8 bits");
|
||||
using value_type = T;
|
||||
|
||||
AlignedAllocator() = default;
|
||||
|
||||
AlignedAllocator(const AlignedAllocator &) = default;
|
||||
|
||||
AlignedAllocator &operator=(const AlignedAllocator &) = default;
|
||||
|
||||
template <typename U>
|
||||
struct rebind {
|
||||
using other = AlignedAllocator<U, alignment>;
|
||||
};
|
||||
|
||||
T *allocate(size_t n)
|
||||
{
|
||||
size_t alignment_bytes = alignment / 8;
|
||||
void *ptr = ::aligned_alloc(alignment_bytes, align_up(n * sizeof(T), alignment_bytes));
|
||||
return static_cast<T *>(ptr);
|
||||
}
|
||||
|
||||
void deallocate(T *p, size_t n)
|
||||
{
|
||||
::free(p);
|
||||
}
|
||||
};
|
||||
|
||||
// Using 512-aligned vector in case some functions use avx-512
|
||||
template <typename T>
|
||||
using AlignedAllocator512 = AlignedAllocator<T, 512>;
|
||||
template <typename T>
|
||||
using AlignedVector512 = std::vector<T, AlignedAllocator512<T>>;
|
||||
|
||||
void nr_ulsch_16qam_llr_ref(c16_t *rxdataF_comp, int32_t *ul_ch_mag, int16_t *ulsch_llr, uint32_t nb_re, uint8_t symbol)
|
||||
{
|
||||
int16_t *ul_ch_mag_i16 = (int16_t *)ul_ch_mag;
|
||||
for (auto i = 0U; i < nb_re; i++) {
|
||||
int16_t real = rxdataF_comp[i].r;
|
||||
int16_t imag = rxdataF_comp[i].i;
|
||||
int16_t mag_real = ul_ch_mag_i16[2 * i];
|
||||
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
|
||||
ulsch_llr[4 * i] = real;
|
||||
ulsch_llr[4 * i + 1] = imag;
|
||||
ulsch_llr[4 * i + 2] = saturating_sub(mag_real, std::abs(real));
|
||||
ulsch_llr[4 * i + 3] = saturating_sub(mag_imag, std::abs(imag));
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ulsch_64qam_llr_ref(c16_t *rxdataF_comp,
|
||||
int32_t *ul_ch_mag,
|
||||
int32_t *ul_ch_magb,
|
||||
int16_t *ulsch_llr,
|
||||
uint32_t nb_re,
|
||||
uint8_t symbol)
|
||||
{
|
||||
int16_t *ul_ch_mag_i16 = (int16_t *)ul_ch_mag;
|
||||
int16_t *ul_ch_magb_i16 = (int16_t *)ul_ch_magb;
|
||||
for (auto i = 0U; i < nb_re; i++) {
|
||||
int16_t real = rxdataF_comp[i].r;
|
||||
int16_t imag = rxdataF_comp[i].i;
|
||||
int16_t mag_real = ul_ch_mag_i16[2 * i];
|
||||
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
|
||||
ulsch_llr[6 * i] = real;
|
||||
ulsch_llr[6 * i + 1] = imag;
|
||||
ulsch_llr[6 * i + 2] = saturating_sub(mag_real, std::abs(real));
|
||||
ulsch_llr[6 * i + 3] = saturating_sub(mag_imag, std::abs(imag));
|
||||
int16_t mag_realb = ul_ch_magb_i16[2 * i];
|
||||
int16_t mag_imagb = ul_ch_magb_i16[2 * i + 1];
|
||||
ulsch_llr[6 * i + 4] = saturating_sub(mag_realb, std::abs(ulsch_llr[6 * i + 2]));
|
||||
ulsch_llr[6 * i + 5] = saturating_sub(mag_imagb, std::abs(ulsch_llr[6 * i + 3]));
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ulsch_256qam_llr_ref(c16_t *rxdataF_comp,
|
||||
int32_t *ul_ch_mag,
|
||||
int32_t *ul_ch_magb,
|
||||
int32_t *ul_ch_magc,
|
||||
int16_t *ulsch_llr,
|
||||
uint32_t nb_re,
|
||||
uint8_t symbol)
|
||||
{
|
||||
int16_t *ul_ch_mag_i16 = (int16_t *)ul_ch_mag;
|
||||
int16_t *ul_ch_magb_i16 = (int16_t *)ul_ch_magb;
|
||||
int16_t *ul_ch_magc_i16 = (int16_t *)ul_ch_magc;
|
||||
for (auto i = 0U; i < nb_re; i++) {
|
||||
int16_t real = rxdataF_comp[i].r;
|
||||
int16_t imag = rxdataF_comp[i].i;
|
||||
int16_t mag_real = ul_ch_mag_i16[2 * i];
|
||||
int16_t mag_imag = ul_ch_mag_i16[2 * i + 1];
|
||||
ulsch_llr[8 * i] = real;
|
||||
ulsch_llr[8 * i + 1] = imag;
|
||||
ulsch_llr[8 * i + 2] = saturating_sub(mag_real, std::abs(real));
|
||||
ulsch_llr[8 * i + 3] = saturating_sub(mag_imag, std::abs(imag));
|
||||
int16_t magb_real = ul_ch_magb_i16[2 * i];
|
||||
int16_t magb_imag = ul_ch_magb_i16[2 * i + 1];
|
||||
ulsch_llr[8 * i + 4] = saturating_sub(magb_real, std::abs(ulsch_llr[8 * i + 2]));
|
||||
ulsch_llr[8 * i + 5] = saturating_sub(magb_imag, std::abs(ulsch_llr[8 * i + 3]));
|
||||
int16_t magc_real = ul_ch_magc_i16[2 * i];
|
||||
int16_t magc_imag = ul_ch_magc_i16[2 * i + 1];
|
||||
ulsch_llr[8 * i + 6] = saturating_sub(magc_real, std::abs(ulsch_llr[8 * i + 4]));
|
||||
ulsch_llr[8 * i + 7] = saturating_sub(magc_imag, std::abs(ulsch_llr[8 * i + 5]));
|
||||
}
|
||||
}
|
||||
|
||||
AlignedVector512<c16_t> generate_random_c16(size_t num)
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 rng(rd());
|
||||
std::uniform_int_distribution<int16_t> dist(INT16_MIN, INT16_MAX);
|
||||
AlignedVector512<c16_t> vec;
|
||||
vec.resize(num);
|
||||
auto gen = [&]() { return (c16_t){dist(rng), dist(rng)}; };
|
||||
std::generate(vec.begin(), vec.end(), gen);
|
||||
return vec;
|
||||
}
|
||||
|
||||
AlignedVector512<uint16_t> generate_random_uint16(size_t num)
|
||||
{
|
||||
AlignedVector512<uint16_t> vec;
|
||||
vec.resize(num);
|
||||
auto gen = [&]() { return static_cast<uint16_t>(std::rand()); };
|
||||
std::generate(vec.begin(), vec.end(), gen);
|
||||
return vec;
|
||||
}
|
||||
|
||||
void test_function_16_qam(AlignedVector512<uint32_t> nb_res)
|
||||
{
|
||||
for (auto i = 0U; i < nb_res.size(); i++) {
|
||||
uint32_t nb_re = nb_res[i];
|
||||
auto rf_data = generate_random_c16(nb_re);
|
||||
auto magnitude_data = generate_random_uint16(nb_re * 2);
|
||||
AlignedVector512<uint64_t> ulsch_llr_ref;
|
||||
ulsch_llr_ref.resize(nb_re);
|
||||
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0);
|
||||
nr_ulsch_16qam_llr_ref((c16_t *)rf_data.data(), (int32_t *)magnitude_data.data(), (int16_t *)ulsch_llr_ref.data(), nb_re, 0);
|
||||
|
||||
AlignedVector512<uint64_t> ulsch_llr;
|
||||
ulsch_llr.resize(nb_re);
|
||||
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0);
|
||||
nr_ulsch_16qam_llr((int32_t *)rf_data.data(), (int32_t *)magnitude_data.data(), (int16_t *)ulsch_llr.data(), nb_re, 0);
|
||||
|
||||
int num_errors = 0;
|
||||
for (auto i = 0U; i < nb_re; i++) {
|
||||
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i])
|
||||
<< "Mismatch 16qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i;
|
||||
if (ulsch_llr_ref[i] != ulsch_llr[i]) {
|
||||
num_errors++;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(num_errors, 0) << " Errors during testing 16qam llr " << num_errors << " nb res " << nb_re;
|
||||
}
|
||||
}
|
||||
|
||||
void test_function_64_qam(AlignedVector512<uint32_t> nb_res)
|
||||
{
|
||||
for (auto i = 0U; i < nb_res.size(); i++) {
|
||||
uint32_t nb_re = nb_res[i];
|
||||
auto rf_data = generate_random_c16(nb_re);
|
||||
auto magnitude_data = generate_random_uint16(nb_re * 2);
|
||||
auto magnitude_b_data = generate_random_uint16(nb_re * 2);
|
||||
AlignedVector512<uint32_t> ulsch_llr_ref;
|
||||
ulsch_llr_ref.resize(nb_re * 3);
|
||||
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0);
|
||||
nr_ulsch_64qam_llr_ref((c16_t *)rf_data.data(),
|
||||
(int32_t *)magnitude_data.data(),
|
||||
(int32_t *)magnitude_b_data.data(),
|
||||
(int16_t *)ulsch_llr_ref.data(),
|
||||
nb_re,
|
||||
0);
|
||||
|
||||
AlignedVector512<uint32_t> ulsch_llr;
|
||||
ulsch_llr.resize(nb_re * 3);
|
||||
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0);
|
||||
nr_ulsch_64qam_llr((int32_t *)rf_data.data(),
|
||||
(int32_t *)magnitude_data.data(),
|
||||
(int32_t *)magnitude_b_data.data(),
|
||||
(int16_t *)ulsch_llr.data(),
|
||||
nb_re,
|
||||
0);
|
||||
|
||||
int num_errors = 0;
|
||||
for (auto i = 0U; i < nb_re * 3; i++) {
|
||||
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i])
|
||||
<< "Mismatch 64qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i;
|
||||
if (ulsch_llr_ref[i] != ulsch_llr[i]) {
|
||||
num_errors++;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(num_errors, 0) << " Errors during testing 64qam llr " << num_errors << " nb res " << nb_re;
|
||||
}
|
||||
}
|
||||
|
||||
void test_function_256_qam(AlignedVector512<uint32_t> nb_res)
|
||||
{
|
||||
for (auto i = 0U; i < nb_res.size(); i++) {
|
||||
uint32_t nb_re = nb_res[i];
|
||||
auto rf_data = generate_random_c16(nb_re);
|
||||
auto magnitude_data = generate_random_uint16(nb_re * 2);
|
||||
auto magnitude_b_data = generate_random_uint16(nb_re * 2);
|
||||
auto magnitude_c_data = generate_random_uint16(nb_re * 2);
|
||||
AlignedVector512<uint32_t> ulsch_llr_ref;
|
||||
ulsch_llr_ref.resize(nb_re * 4);
|
||||
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0);
|
||||
nr_ulsch_256qam_llr_ref((c16_t *)rf_data.data(),
|
||||
(int32_t *)magnitude_data.data(),
|
||||
(int32_t *)magnitude_b_data.data(),
|
||||
(int32_t *)magnitude_c_data.data(),
|
||||
(int16_t *)ulsch_llr_ref.data(),
|
||||
nb_re,
|
||||
0);
|
||||
|
||||
AlignedVector512<uint32_t> ulsch_llr;
|
||||
ulsch_llr.resize(nb_re * 4);
|
||||
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0);
|
||||
nr_ulsch_256qam_llr((int32_t *)rf_data.data(),
|
||||
(int32_t *)magnitude_data.data(),
|
||||
(int32_t *)magnitude_b_data.data(),
|
||||
(int32_t *)magnitude_c_data.data(),
|
||||
(int16_t *)ulsch_llr.data(),
|
||||
nb_re,
|
||||
0);
|
||||
|
||||
int num_errors = 0;
|
||||
for (auto i = 0U; i < nb_re * 4; i++) {
|
||||
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i])
|
||||
<< "Mismatch 256qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i;
|
||||
if (ulsch_llr_ref[i] != ulsch_llr[i]) {
|
||||
num_errors++;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(num_errors, 0) << " Errors during testing 256qam llr " << num_errors << " nb res " << nb_re;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(test_llr, verify_reference_implementation_16qam)
|
||||
{
|
||||
test_function_16_qam({16, 32, 24, 40, 48, 8 * 300});
|
||||
}
|
||||
|
||||
TEST(test_llr, test_8_res_16qam)
|
||||
{
|
||||
test_function_16_qam({8});
|
||||
}
|
||||
|
||||
TEST(test_llr, test_4_res_16qam)
|
||||
{
|
||||
test_function_16_qam({4});
|
||||
}
|
||||
|
||||
TEST(test_llr, test_5_res_16qam)
|
||||
{
|
||||
test_function_16_qam({5});
|
||||
}
|
||||
|
||||
// This is a "normal" segfault because the function assumed extra buffer for reading non-existent REs
|
||||
TEST(test_llr, no_segmentation_fault_at_12_res_16qam)
|
||||
{
|
||||
test_function_16_qam({12});
|
||||
}
|
||||
|
||||
// This is a "normal" segfault because the function assumed extra buffer for reading non-existent REs
|
||||
TEST(test_llr, no_segmentation_fault_at_36_res_16qam)
|
||||
{
|
||||
test_function_16_qam({36});
|
||||
}
|
||||
|
||||
// any number of REs should work
|
||||
TEST(test_llr, no_segfault_any_number_of_re_16qam)
|
||||
{
|
||||
for (uint32_t i = 0U; i < 1000U; i++) {
|
||||
test_function_16_qam({i});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(test_llr, verify_reference_implementation_64qam)
|
||||
{
|
||||
test_function_64_qam({16, 24, 32, 80, 8 * 300});
|
||||
}
|
||||
|
||||
TEST(test_llr, test_8_res_64qam)
|
||||
{
|
||||
test_function_64_qam({8});
|
||||
}
|
||||
|
||||
TEST(test_llr, test_4_res_64qam)
|
||||
{
|
||||
test_function_64_qam({4});
|
||||
}
|
||||
|
||||
// This is a "normal" segfault because the function assumed extra buffer for reading non-existent REs
|
||||
TEST(test_llr, no_segmentation_fault_at_12_res_64qam)
|
||||
{
|
||||
test_function_64_qam({12});
|
||||
}
|
||||
|
||||
// This is a "normal" segfault because the function assumed extra buffer for reading non-existent REs
|
||||
TEST(test_llr, no_segmentation_fault_at_36_res_64qam)
|
||||
{
|
||||
test_function_64_qam({36});
|
||||
}
|
||||
|
||||
// any number of REs should work
|
||||
TEST(test_llr, no_segfault_any_number_of_re_64qam)
|
||||
{
|
||||
for (uint32_t i = 0U; i < 1000U; i++) {
|
||||
test_function_64_qam({i});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(test_llr, verify_reference_implementation_256qam)
|
||||
{
|
||||
test_function_256_qam({16, 24, 32, 80, 8 * 300});
|
||||
}
|
||||
|
||||
TEST(test_llr, test_8_res_256qam)
|
||||
{
|
||||
test_function_256_qam({8});
|
||||
}
|
||||
|
||||
TEST(test_llr, test_4_res_256qam)
|
||||
{
|
||||
test_function_256_qam({4});
|
||||
}
|
||||
|
||||
// This is a "normal" segfault because the function assumed extra buffer for reading non-existent REs
|
||||
TEST(test_llr, no_segmentation_fault_at_12_res_256qam)
|
||||
{
|
||||
test_function_256_qam({12});
|
||||
}
|
||||
|
||||
// This is a "normal" segfault because the function assumed extra buffer for reading non-existent REs
|
||||
TEST(test_llr, no_segmentation_fault_at_36_res_256qam)
|
||||
{
|
||||
test_function_256_qam({36});
|
||||
}
|
||||
|
||||
// any number of REs should work
|
||||
TEST(test_llr, no_segfault_any_number_of_re_256qam)
|
||||
{
|
||||
for (uint32_t i = 0U; i < 1000U; i++) {
|
||||
test_function_256_qam({i});
|
||||
}
|
||||
}
|
||||
|
||||
// It is possible to implement an AVX accelerated llr computation for multiples of 2REs.
|
||||
// This testcase can be used to verify this implementation as it visualizes LLR data with printfs
|
||||
TEST(test_llr, check_2_res_256_qam)
|
||||
{
|
||||
AlignedVector512<c16_t> rf_data = {{1, 1}, {2, 2}};
|
||||
AlignedVector512<int16_t> magnitude_data = {1, 1, 1, 1};
|
||||
AlignedVector512<int16_t> magnitude_b_data = {2, 2, 2, 2};
|
||||
AlignedVector512<int16_t> magnitude_c_data = {3, 3, 3, 3};
|
||||
AlignedVector512<int16_t> ulsch_llr_ref;
|
||||
ulsch_llr_ref.resize(2 * 8);
|
||||
std::fill(ulsch_llr_ref.begin(), ulsch_llr_ref.end(), 0);
|
||||
nr_ulsch_256qam_llr_ref((c16_t *)rf_data.data(),
|
||||
(int32_t *)magnitude_data.data(),
|
||||
(int32_t *)magnitude_b_data.data(),
|
||||
(int32_t *)magnitude_c_data.data(),
|
||||
(int16_t *)ulsch_llr_ref.data(),
|
||||
2,
|
||||
0);
|
||||
|
||||
AlignedVector512<int16_t> ulsch_llr;
|
||||
ulsch_llr.resize(2 * 8);
|
||||
std::fill(ulsch_llr.begin(), ulsch_llr.end(), 0);
|
||||
nr_ulsch_256qam_llr((int32_t *)rf_data.data(),
|
||||
(int32_t *)magnitude_data.data(),
|
||||
(int32_t *)magnitude_b_data.data(),
|
||||
(int32_t *)magnitude_c_data.data(),
|
||||
(int16_t *)ulsch_llr.data(),
|
||||
2,
|
||||
0);
|
||||
|
||||
printf("\nDUT:\n");
|
||||
for (auto i = 0U; i < 2; i++) {
|
||||
printf("%d %d %d %d %d %d %d %d\n",
|
||||
ulsch_llr[i * 8],
|
||||
ulsch_llr[i * 8 + 1],
|
||||
ulsch_llr[i * 8 + 2],
|
||||
ulsch_llr[i * 8 + 3],
|
||||
ulsch_llr[i * 8 + 4],
|
||||
ulsch_llr[i * 8 + 5],
|
||||
ulsch_llr[i * 8 + 6],
|
||||
ulsch_llr[i * 8 + 7]);
|
||||
}
|
||||
|
||||
printf("\nREF:\n");
|
||||
for (auto i = 0U; i < 2; i++) {
|
||||
printf("%d %d %d %d %d %d %d %d\n",
|
||||
ulsch_llr_ref[i * 8],
|
||||
ulsch_llr_ref[i * 8 + 1],
|
||||
ulsch_llr_ref[i * 8 + 2],
|
||||
ulsch_llr_ref[i * 8 + 3],
|
||||
ulsch_llr_ref[i * 8 + 4],
|
||||
ulsch_llr_ref[i * 8 + 5],
|
||||
ulsch_llr_ref[i * 8 + 6],
|
||||
ulsch_llr_ref[i * 8 + 7]);
|
||||
}
|
||||
|
||||
int num_errors = 0;
|
||||
for (auto i = 0U; i < 2 * 8; i++) {
|
||||
EXPECT_EQ(ulsch_llr_ref[i], ulsch_llr[i])
|
||||
<< "Mismatch 256qam REF " << std::hex << ulsch_llr_ref[i] << " != DUT " << ulsch_llr[i] << " at " << std::dec << i;
|
||||
if (ulsch_llr_ref[i] != ulsch_llr[i]) {
|
||||
num_errors++;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(num_errors, 0) << " Errors during testing 256qam llr " << num_errors << " nb res " << 2;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
logInit();
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -1402,6 +1402,7 @@ void NFAPI_NR_DMRS_TYPE2_average_prb(NR_DL_FRAME_PARMS *frame_parms,
|
||||
c16multaddVectRealComplex(filt8_avlip6, &ch, dl_ch, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int nl,
|
||||
|
||||
@@ -877,7 +877,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
LOG_I(NR_PHY, "csirs_config_pdu->power_control_offset_ss = %i\n", csirs_config_pdu->power_control_offset_ss);
|
||||
#endif
|
||||
|
||||
if(csirs_config_pdu->measurement_bitmap == 0) {
|
||||
if(csirs_config_pdu->csi_type == 0) {
|
||||
LOG_E(NR_PHY, "Handling of CSI-RS for tracking not handled yet at PHY\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -357,8 +357,6 @@ typedef struct {
|
||||
/// - first index: ? [0..3] (hard coded)
|
||||
/// - first index: ? [0..1179743] (hard coded)
|
||||
int16_t **llr_layers;
|
||||
/// DMRS symbol index, to be updated every DMRS symbol within a slot.
|
||||
uint8_t dmrs_symbol;
|
||||
// PTRS symbol index, to be updated every PTRS symbol within a slot.
|
||||
uint8_t ptrs_symbol_index;
|
||||
/// bit mask of PT-RS ofdm symbol indicies
|
||||
|
||||
@@ -51,10 +51,12 @@
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int set_tdd_config_nr( nfapi_nr_config_request_scf_t *cfg,
|
||||
int mu,
|
||||
int nrofDownlinkSlots, int nrofDownlinkSymbols,
|
||||
int nrofUplinkSlots, int nrofUplinkSymbols)
|
||||
int set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg,
|
||||
int mu,
|
||||
int nrofDownlinkSlots,
|
||||
int nrofDownlinkSymbols,
|
||||
int nrofUplinkSlots,
|
||||
int nrofUplinkSymbols)
|
||||
{
|
||||
|
||||
int slot_number = 0;
|
||||
|
||||
@@ -153,6 +153,7 @@ void nr_dlsim_preprocessor(module_id_t module_id,
|
||||
/* CC_id = */ 0,
|
||||
sched_ctrl->aggregation_level,
|
||||
nr_of_candidates,
|
||||
0,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
sched_ctrl->coreset,
|
||||
Y);
|
||||
|
||||
@@ -72,6 +72,9 @@
|
||||
#define CONFIG_STRING_MACRLC_MIN_GRANT_PRB "min_grant_prb"
|
||||
#define CONFIG_STRING_MACRLC_MIN_GRANT_MCS "min_grant_mcs"
|
||||
#define CONFIG_STRING_MACRLC_IDENTITY_PM "identity_precoding_matrix"
|
||||
#define CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING "set_analog_beamforming"
|
||||
#define CONFIG_STRING_MACRLC_BEAM_DURATION "beam_duration"
|
||||
#define CONFIG_STRING_MACRLC_BEAMS_PERIOD "beams_per_period"
|
||||
|
||||
#define HLP_MACRLC_UL_PRBBLACK "SNR threshold to decide whether a PRB will be blacklisted or not"
|
||||
#define HLP_MACRLC_DL_BLER_UP "Upper threshold of BLER to decrease DL MCS"
|
||||
@@ -85,6 +88,9 @@
|
||||
#define HLP_MACRLC_MIN_GRANT_PRB "Minimal Periodic ULSCH Grant PRBs"
|
||||
#define HLP_MACRLC_MIN_GRANT_MCS "Minimal Periodic ULSCH Grant MCS"
|
||||
#define HLP_MACRLC_IDENTITY_PM "Flag to use only identity matrix in DL precoding"
|
||||
#define HLP_MACRLC_AB "Flag to enable analog beamforming"
|
||||
#define HLP_MACRLC_BEAM_DURATION "number of consecutive slots for a given set of beams"
|
||||
#define HLP_MACRLC_BEAMS_PERIOD "set of beams that can be simultaneously allocated in a period"
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* MacRLC configuration parameters */
|
||||
@@ -127,6 +133,9 @@
|
||||
{CONFIG_STRING_MACRLC_LOCAL_N_ADDRESS_F1U, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{CONFIG_STRING_MACRLC_TRANSPORT_S_SHM_PREFIX, NULL, 0, .strptr=NULL, .defstrval="nvipc", TYPE_STRING, 0}, \
|
||||
{CONFIG_STRING_MACRLC_TRANSPORT_S_POLL_CORE, NULL, 0, .i8ptr=NULL, .defintval=-1, TYPE_INT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING, HLP_MACRLC_AB, PARAMFLAG_BOOL, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_BEAM_DURATION, HLP_MACRLC_BEAM_DURATION, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_BEAMS_PERIOD, HLP_MACRLC_BEAMS_PERIOD, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
|
||||
}
|
||||
// clang-format off
|
||||
|
||||
@@ -165,6 +174,9 @@
|
||||
#define MACRLC_LOCAL_N_ADDRESS_F1U_IDX 32
|
||||
#define MACRLC_TRANSPORT_S_SHM_PREFIX 33
|
||||
#define MACRLC_TRANSPORT_S_POLL_CORE 34
|
||||
#define MACRLC_ANALOG_BEAMFORMING_IDX 35
|
||||
#define MACRLC_ANALOG_BEAM_DURATION_IDX 36
|
||||
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 37
|
||||
|
||||
#define MACRLCPARAMS_CHECK { \
|
||||
{ .s5 = { NULL } }, \
|
||||
@@ -202,6 +214,9 @@
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s2 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -1405,6 +1405,15 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
RC.nrmac[j]->identity_pm = *(MacRLC_ParamList.paramarray[j][MACRLC_IDENTITY_PM_IDX].u8ptr);
|
||||
RC.nrmac[j]->num_ulprbbl = num_prbbl;
|
||||
memcpy(RC.nrmac[j]->ulprbbl, prbbl, 275 * sizeof(prbbl[0]));
|
||||
bool ab = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMFORMING_IDX].u8ptr;
|
||||
if (ab) {
|
||||
NR_beam_info_t *beam_info = &RC.nrmac[j]->beam_info;
|
||||
int beams_per_period = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMS_PERIOD_IDX].u8ptr;
|
||||
beam_info->beam_allocation = malloc16(beams_per_period * sizeof(int *));
|
||||
beam_info->beam_duration = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAM_DURATION_IDX].u8ptr;
|
||||
beam_info->beams_per_period = beams_per_period;
|
||||
beam_info->beam_allocation_size = -1; // to be initialized once we have information on frame configuration
|
||||
}
|
||||
} // for (j=0;j<RC.nb_nr_macrlc_inst;j++)
|
||||
|
||||
uint64_t gnb_du_id = 0;
|
||||
|
||||
@@ -1787,8 +1787,8 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
uint8_t *N_dur,
|
||||
uint16_t *RA_sfn_index,
|
||||
uint8_t *N_RA_slot,
|
||||
uint8_t *config_period) {
|
||||
|
||||
uint8_t *config_period)
|
||||
{
|
||||
int x,y;
|
||||
int64_t s_map;
|
||||
uint8_t format2 = 0xff;
|
||||
@@ -1800,20 +1800,20 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
y = table_6_3_3_2_4_prachConfig_Index[index][3];
|
||||
y2 = table_6_3_3_2_4_prachConfig_Index[index][4];
|
||||
// checking n_sfn mod x = y
|
||||
if ( (frame%x)==y || (frame%x)==y2 ) {
|
||||
slot_60khz = slot >> (mu-2); // in table slots are numbered wrt 60kHz
|
||||
if ((frame % x) == y || (frame % x) == y2) {
|
||||
slot_60khz = slot >> (mu - 2); // in table slots are numbered wrt 60kHz
|
||||
s_map = table_6_3_3_2_4_prachConfig_Index[index][5];
|
||||
if ((s_map >> slot_60khz) & 0x01 ) {
|
||||
if ((s_map >> slot_60khz) & 0x01) {
|
||||
for(int i = 0; i <= slot_60khz ;i++) {
|
||||
if ( (s_map >> i) & 0x01) {
|
||||
if ((s_map >> i) & 0x01) {
|
||||
(*RA_sfn_index)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ((s_map>>slot_60khz)&0x01) ) {
|
||||
if (((s_map >> slot_60khz) & 0x01)) {
|
||||
*N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe
|
||||
if (mu == 3) {
|
||||
if ( (*N_RA_slot == 1) && (slot%2 == 0) )
|
||||
if ((*N_RA_slot == 1) && (slot % 2 == 0) )
|
||||
return 0; // no prach in even slots @ 120kHz for 1 prach per 60khz slot
|
||||
}
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
@@ -1850,23 +1850,23 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
if (unpaired) {
|
||||
x = table_6_3_3_2_3_prachConfig_Index[index][2];
|
||||
y = table_6_3_3_2_3_prachConfig_Index[index][3];
|
||||
if ( (frame%x)==y ) {
|
||||
if ((frame % x) == y) {
|
||||
subframe = slot >> mu;
|
||||
s_map = table_6_3_3_2_3_prachConfig_Index[index][4];
|
||||
if ((s_map >> subframe) & 0x01 ) {
|
||||
if ((s_map >> subframe) & 0x01) {
|
||||
for(int i = 0; i <= subframe ;i++) {
|
||||
if ( (s_map >> i) & 0x01) {
|
||||
if ((s_map >> i) & 0x01) {
|
||||
(*RA_sfn_index)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( (s_map>>subframe)&0x01 ) {
|
||||
if ((s_map >> subframe) & 0x01 ) {
|
||||
*N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe
|
||||
if (mu == 1 && index >= 67) {
|
||||
if ( (*N_RA_slot <= 1) && (slot%2 == 0) )
|
||||
if ((*N_RA_slot <= 1) && (slot % 2 == 0))
|
||||
return 0; // no prach in even slots @ 30kHz for 1 prach per subframe
|
||||
}
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
|
||||
if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL) {
|
||||
*config_period = x;
|
||||
*start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5];
|
||||
*N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7];
|
||||
@@ -1874,17 +1874,19 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1)
|
||||
format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1];
|
||||
*format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n", frame,
|
||||
slot,
|
||||
index, table_6_3_3_2_3_prachConfig_Index[index][6],
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur,
|
||||
*N_RA_slot,
|
||||
*RA_sfn_index);
|
||||
LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n",
|
||||
frame,
|
||||
slot,
|
||||
index,
|
||||
table_6_3_3_2_3_prachConfig_Index[index][6],
|
||||
pointa,
|
||||
mu,
|
||||
unpaired,
|
||||
*start_symbol,
|
||||
*N_t_slot,
|
||||
*N_dur,
|
||||
*N_RA_slot,
|
||||
*RA_sfn_index);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1897,10 +1899,10 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
else { // FDD
|
||||
x = table_6_3_3_2_2_prachConfig_Index[index][2];
|
||||
y = table_6_3_3_2_2_prachConfig_Index[index][3];
|
||||
if ( (frame%x)==y ) {
|
||||
if ((frame % x) == y) {
|
||||
subframe = slot >> mu;
|
||||
s_map = table_6_3_3_2_2_prachConfig_Index[index][4];
|
||||
if ( (s_map>>subframe)&0x01 ) {
|
||||
if ((s_map>>subframe) & 0x01) {
|
||||
*N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; // Number of RACH slots within a subframe
|
||||
if (mu == 1) {
|
||||
if ((*N_RA_slot <= 1) && (slot % 2 == 0)){
|
||||
@@ -1908,7 +1910,7 @@ int get_nr_prach_info_from_index(uint8_t index,
|
||||
}
|
||||
}
|
||||
for(int i = 0; i <= subframe ; i++) {
|
||||
if ( (s_map >> i) & 0x01) {
|
||||
if ((s_map >> i) & 0x01) {
|
||||
(*RA_sfn_index)++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2628,7 +2628,7 @@ void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot)
|
||||
uint16_t bwp_size = current_DL_BWP->BWPSize;
|
||||
uint16_t bwp_start = current_DL_BWP->BWPStart;
|
||||
|
||||
for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++){
|
||||
for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++) {
|
||||
NR_NZP_CSI_RS_Resource_t *nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id];
|
||||
int period, offset;
|
||||
csi_period_offset(NULL, nzpcsi->periodicityAndOffset, &period, &offset);
|
||||
@@ -2644,7 +2644,10 @@ void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot)
|
||||
csirs_config_pdu->subcarrier_spacing = mu;
|
||||
csirs_config_pdu->cyclic_prefix = current_DL_BWP->cyclicprefix ? *current_DL_BWP->cyclicprefix : 0;
|
||||
|
||||
csirs_config_pdu->csi_type = 1; // NZP-CSI-RS
|
||||
if (csi_res_id > NR_maxNrofCSI_ResourceConfigurations)
|
||||
csirs_config_pdu->csi_type = 0; // TRS
|
||||
else
|
||||
csirs_config_pdu->csi_type = 1; // NZP-CSI-RS
|
||||
|
||||
csirs_config_pdu->scramb_id = nzpcsi->scramblingID;
|
||||
csirs_config_pdu->power_control_offset = nzpcsi->powerControlOffset + 8;
|
||||
|
||||
@@ -587,20 +587,31 @@ static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_Ant
|
||||
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols);
|
||||
|
||||
AssertFatal(periods_per_frame > 0, "TDD configuration cannot be configured\n");
|
||||
if (frequency_range == FR2) {
|
||||
LOG_I(NR_MAC, "Configuring TDD beam association to default\n");
|
||||
nrmac->tdd_beam_association = malloc16(periods_per_frame * sizeof(int16_t));
|
||||
for (int i = 0; i < periods_per_frame; ++i)
|
||||
nrmac->tdd_beam_association[i] = -1; /* default: beams not configured */
|
||||
} else {
|
||||
nrmac->tdd_beam_association = NULL; /* default: no beams */
|
||||
}
|
||||
}
|
||||
|
||||
// precoding matrix configuration (to be improved)
|
||||
cfg->pmi_list = init_DL_MIMO_codebook(nrmac, pdsch_AntennaPorts);
|
||||
}
|
||||
|
||||
static void initialize_beam_information(NR_beam_info_t *beam_info, int mu, int slots_per_frame)
|
||||
{
|
||||
if(!beam_info->beam_allocation)
|
||||
return;
|
||||
|
||||
int size = mu == 0 ? slots_per_frame << 1 : slots_per_frame;
|
||||
// slots in beam duration gives the number of consecutive slots tied the the same beam
|
||||
AssertFatal(size % beam_info->beam_duration == 0,
|
||||
"Beam duration %d should be divider of number of slots per frame %d\n",
|
||||
beam_info->beam_duration,
|
||||
slots_per_frame);
|
||||
beam_info->beam_allocation_size = size / beam_info->beam_duration;
|
||||
for (int i = 0; i < beam_info->beams_per_period; i++) {
|
||||
beam_info->beam_allocation[i] = malloc16(beam_info->beam_allocation_size * sizeof(int));
|
||||
for (int j = 0; j < beam_info->beam_allocation_size; j++)
|
||||
beam_info->beam_allocation[i][j] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config)
|
||||
{
|
||||
DevAssert(nrmac != NULL);
|
||||
@@ -614,16 +625,23 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
|
||||
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
|
||||
const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
const int size = n << (int)ceil(log2((NTN_gNB_Koffset + 13) / n + 1)); // 13 is upper limit for max_fb_time
|
||||
|
||||
nrmac->vrb_map_UL_size = size;
|
||||
nrmac->common_channels[0].vrb_map_UL = calloc(size * MAX_BWP_SIZE, sizeof(uint16_t));
|
||||
AssertFatal(nrmac->common_channels[0].vrb_map_UL,
|
||||
"could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n");
|
||||
|
||||
int num_beams = 1;
|
||||
if(nrmac->beam_info.beam_allocation)
|
||||
num_beams = nrmac->beam_info.beams_per_period;
|
||||
for (int i = 0; i < num_beams; i++) {
|
||||
nrmac->common_channels[0].vrb_map_UL[i] = calloc(size * MAX_BWP_SIZE, sizeof(uint16_t));
|
||||
AssertFatal(nrmac->common_channels[0].vrb_map_UL[i],
|
||||
"could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL[%d]\n", i);
|
||||
}
|
||||
|
||||
nrmac->UL_tti_req_ahead_size = size;
|
||||
nrmac->UL_tti_req_ahead[0] = calloc(size, sizeof(nfapi_nr_ul_tti_request_t));
|
||||
AssertFatal(nrmac->UL_tti_req_ahead[0], "could not allocate memory for nrmac->UL_tti_req_ahead[0]\n");
|
||||
|
||||
initialize_beam_information(&nrmac->beam_info, *scc->ssbSubcarrierSpacing, n);
|
||||
|
||||
LOG_I(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n");
|
||||
|
||||
config_common(nrmac, config->pdsch_AntennaPorts, config->pusch_AntennaPorts, scc);
|
||||
|
||||
@@ -146,6 +146,24 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB,
|
||||
TX_req[CC_idP].Number_of_PDUs = 0;
|
||||
}
|
||||
|
||||
void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slot, int mu)
|
||||
{
|
||||
// for now we use the same logic of UL_tti_req_ahead
|
||||
// reset after 1 frame with the exception of 15kHz
|
||||
if(!beam_info->beam_allocation)
|
||||
return;
|
||||
// initialization done only once
|
||||
const int slots_per_frame = nr_slots_per_frame[mu];
|
||||
AssertFatal(beam_info->beam_allocation_size >= 0, "Beam information not initialized\n");
|
||||
int idx_to_clear = (frame * slots_per_frame + slot) / beam_info->beam_duration;
|
||||
idx_to_clear = (idx_to_clear + beam_info->beam_allocation_size - 1) % beam_info->beam_allocation_size;
|
||||
if (slot % beam_info->beam_duration == 0) {
|
||||
// resetting previous period allocation
|
||||
for (int i = 0; i < beam_info->beams_per_period; i++)
|
||||
beam_info->beam_allocation[i][idx_to_clear] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) {
|
||||
return (bitmap >> (slot % 64)) & 0x01;
|
||||
}
|
||||
@@ -195,19 +213,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_
|
||||
|
||||
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = gNB->common_channels;
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
|
||||
NR_SCHED_LOCK(&gNB->sched_lock);
|
||||
|
||||
if (slot==0 && (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]>=257)) {
|
||||
//FR2
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
|
||||
AssertFatal(tdd,"Dynamic TDD not handled yet\n");
|
||||
const int nb_periods_per_frame = get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
|
||||
// re-initialization of tdd_beam_association at beginning of frame
|
||||
for (int i=0; i<nb_periods_per_frame; i++)
|
||||
gNB->tdd_beam_association[i] = -1;
|
||||
}
|
||||
clear_beam_information(&gNB->beam_info, frame, slot, *scc->ssbSubcarrierSpacing);
|
||||
|
||||
gNB->frame = frame;
|
||||
start_meas(&gNB->eNB_scheduler);
|
||||
@@ -224,17 +234,20 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_
|
||||
}
|
||||
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
//mbsfn_status[CC_id] = 0;
|
||||
|
||||
int num_beams = 1;
|
||||
if(gNB->beam_info.beam_allocation)
|
||||
num_beams = gNB->beam_info.beams_per_period;
|
||||
// clear vrb_maps
|
||||
memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * MAX_BWP_SIZE);
|
||||
for (int i = 0; i < num_beams; i++)
|
||||
memset(cc[CC_id].vrb_map[i], 0, sizeof(uint16_t) * MAX_BWP_SIZE);
|
||||
// clear last scheduled slot's content (only)!
|
||||
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
const int size = gNB->vrb_map_UL_size;
|
||||
const int prev_slot = frame * num_slots + slot + size - 1;
|
||||
uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL;
|
||||
memcpy(&vrb_map_UL[prev_slot % size * MAX_BWP_SIZE], &gNB->ulprbbl, sizeof(uint16_t) * MAX_BWP_SIZE);
|
||||
|
||||
for (int i = 0; i < num_beams; i++) {
|
||||
uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL[i];
|
||||
memcpy(&vrb_map_UL[prev_slot % size * MAX_BWP_SIZE], &gNB->ulprbbl, sizeof(uint16_t) * MAX_BWP_SIZE);
|
||||
}
|
||||
clear_nr_nfapi_information(gNB, CC_id, frame, slot, &sched_info->DL_req, &sched_info->TX_req, &sched_info->UL_dci_req);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,13 +81,13 @@ static int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
NR_COMMON_channels_t *cc = &gNB->common_channels[0];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
|
||||
|
||||
uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
|
||||
uint8_t config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
|
||||
|
||||
uint8_t total_RApreambles = MAX_NUM_NR_PRACH_PREAMBLES;
|
||||
if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL)
|
||||
total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles;
|
||||
if (rach_ConfigCommon->totalNumberOfRA_Preambles != NULL)
|
||||
total_RApreambles = *rach_ConfigCommon->totalNumberOfRA_Preambles;
|
||||
|
||||
float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];
|
||||
uint16_t start_symbol_index = 0;
|
||||
@@ -97,8 +97,8 @@ static int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
uint16_t prach_occasion_id = -1;
|
||||
uint8_t num_active_ssb = cc->num_active_ssb;
|
||||
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
|
||||
mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
|
||||
if (rach_ConfigCommon->msg1_SubcarrierSpacing)
|
||||
mu = *rach_ConfigCommon->msg1_SubcarrierSpacing;
|
||||
else
|
||||
mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
|
||||
@@ -115,13 +115,13 @@ static int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
&RA_sfn_index,
|
||||
&N_RA_slot,
|
||||
&config_period);
|
||||
uint8_t index = 0,slot_index = 0;
|
||||
for (slot_index = 0;slot_index < N_RA_slot; slot_index++) {
|
||||
uint8_t index = 0, slot_index = 0;
|
||||
for (slot_index = 0; slot_index < N_RA_slot; slot_index++) {
|
||||
if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
|
||||
if((mu == 1) || (mu == 3))
|
||||
slot_index = 1; //For scs = 30khz and 120khz
|
||||
}
|
||||
for (int i=0; i< N_t_slot; i++) {
|
||||
for (int i = 0; i < N_t_slot; i++) {
|
||||
temp_start_symbol = (start_symbol + i * N_dur + 14 * slot_index) % 14;
|
||||
if(symbol == temp_start_symbol) {
|
||||
start_symbol_index = i;
|
||||
@@ -134,18 +134,18 @@ static int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
slot_index = 0; //For scs = 30khz and 120khz
|
||||
}
|
||||
|
||||
// prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index;
|
||||
prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period)*cc->total_prach_occasions_per_config_period) +
|
||||
(RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index;
|
||||
// prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index;
|
||||
prach_occasion_id = (((frameP % (cc->max_association_period * config_period)) / config_period) * cc->total_prach_occasions_per_config_period) +
|
||||
(RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index;
|
||||
|
||||
//one RO is shared by one or more SSB
|
||||
if(num_ssb_per_RO <= 1 )
|
||||
index = (int) (prach_occasion_id / (int)(1/num_ssb_per_RO)) % num_active_ssb;
|
||||
//one SSB have more than one continuous RO
|
||||
else if ( num_ssb_per_RO > 1) {
|
||||
index = (prach_occasion_id * (int)num_ssb_per_RO)% num_active_ssb ;
|
||||
for(int j = 0;j < num_ssb_per_RO;j++) {
|
||||
if(preamble_index < (((j+1) * total_RApreambles) / num_ssb_per_RO))
|
||||
if(num_ssb_per_RO <= 1)
|
||||
index = (int) (prach_occasion_id / (int)(1 / num_ssb_per_RO)) % num_active_ssb;
|
||||
//one RO is shared by one or more SSB
|
||||
else if (num_ssb_per_RO > 1) {
|
||||
index = (prach_occasion_id * (int)num_ssb_per_RO) % num_active_ssb;
|
||||
for(int j = 0; j < num_ssb_per_RO; j++) {
|
||||
if(preamble_index < ((j + 1) * cc->cb_preambles_per_ssb))
|
||||
index = index + j;
|
||||
}
|
||||
}
|
||||
@@ -165,14 +165,14 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac)
|
||||
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0];
|
||||
|
||||
uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
|
||||
uint8_t config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex;
|
||||
uint8_t mu,N_dur=0,N_t_slot=0,start_symbol=0,N_RA_slot = 0;
|
||||
uint16_t format,N_RA_sfn = 0,unused_RA_occasion,repetition = 0;
|
||||
uint8_t num_active_ssb = 0;
|
||||
uint8_t max_association_period = 1;
|
||||
|
||||
struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *ssb_perRACH_OccasionAndCB_PreamblesPerSSB = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB;
|
||||
struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *ssb_perRACH_OccasionAndCB_PreamblesPerSSB = rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB;
|
||||
|
||||
switch (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present){
|
||||
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
|
||||
@@ -204,8 +204,8 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac)
|
||||
break;
|
||||
}
|
||||
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
|
||||
mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
|
||||
if (rach_ConfigCommon->msg1_SubcarrierSpacing)
|
||||
mu = *rach_ConfigCommon->msg1_SubcarrierSpacing;
|
||||
else
|
||||
mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
|
||||
@@ -227,24 +227,24 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac)
|
||||
uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ;
|
||||
uint32_t total_RA_occasions = N_RA_sfn * N_t_slot * N_RA_slot * fdm;
|
||||
|
||||
for(int i = 0;i < 64;i++) {
|
||||
if ((L_ssb >> (63-i)) & 0x01) { // only if the bit of L_ssb at current ssb index is 1
|
||||
cc->ssb_index[num_active_ssb] = i;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if ((L_ssb >> (63 - i)) & 0x01) { // only if the bit of L_ssb at current ssb index is 1
|
||||
cc->ssb_index[num_active_ssb] = i;
|
||||
num_active_ssb++;
|
||||
}
|
||||
}
|
||||
|
||||
cc->total_prach_occasions_per_config_period = total_RA_occasions;
|
||||
for(int i=1; (1 << (i-1)) <= max_association_period; i++) {
|
||||
cc->max_association_period = (1 <<(i-1));
|
||||
for(int i = 1; (1 << (i-1)) <= max_association_period; i++) {
|
||||
cc->max_association_period = (1 << (i - 1));
|
||||
total_RA_occasions = total_RA_occasions * cc->max_association_period;
|
||||
if(total_RA_occasions >= (int) (num_active_ssb/num_ssb_per_RO)) {
|
||||
repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO )/num_active_ssb);
|
||||
if(total_RA_occasions >= (int) (num_active_ssb / num_ssb_per_RO)) {
|
||||
repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO) / num_active_ssb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition)/num_ssb_per_RO);
|
||||
unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition) / num_ssb_per_RO);
|
||||
cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion;
|
||||
cc->num_active_ssb = num_active_ssb;
|
||||
|
||||
@@ -308,24 +308,41 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
uint16_t format1 = (format >> 8) & 0xff; // second column of format from table
|
||||
|
||||
if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe
|
||||
if (slotP%2 == 1)
|
||||
if (slotP % 2 == 1)
|
||||
slot_index = 1;
|
||||
else
|
||||
slot_index = 0;
|
||||
}else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
|
||||
} else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
|
||||
slot_index = 0;
|
||||
}
|
||||
|
||||
UL_tti_req->SFN = frameP;
|
||||
UL_tti_req->Slot = slotP;
|
||||
UL_tti_req->rach_present = 1;
|
||||
for (int fdm_index=0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion
|
||||
for (int td_index=0; td_index<N_t_slot; td_index++) {
|
||||
NR_beam_alloc_t beam = {0};
|
||||
for (int fdm_index = 0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion
|
||||
for (int td_index = 0; td_index < N_t_slot; td_index++) {
|
||||
|
||||
prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) +
|
||||
(RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index;
|
||||
|
||||
if((prach_occasion_id < cc->total_prach_occasions) && (td_index == 0)){
|
||||
if (prach_occasion_id >= cc->total_prach_occasions) // to be confirmed: unused occasion?
|
||||
continue;
|
||||
|
||||
float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];
|
||||
if(num_ssb_per_RO <= 1) {
|
||||
int ssb_index = (int) (prach_occasion_id / (int)(1 / num_ssb_per_RO)) % cc->num_active_ssb;
|
||||
beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, ssb_index, nr_slots_per_frame[mu]);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate PRACH corresponding to SSB %d in any available beam\n", ssb_index);
|
||||
}
|
||||
else {
|
||||
int first_ssb_index = (prach_occasion_id * (int)num_ssb_per_RO) % cc->num_active_ssb;
|
||||
for(int j = first_ssb_index; j < first_ssb_index + num_ssb_per_RO; j++) {
|
||||
beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, j, nr_slots_per_frame[mu]);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate PRACH corresponding to SSB %d in any available beam\n", j);
|
||||
}
|
||||
}
|
||||
if(td_index == 0) {
|
||||
AssertFatal(UL_tti_req->n_pdus < sizeof(UL_tti_req->pdus_list) / sizeof(UL_tti_req->pdus_list[0]),
|
||||
"Invalid UL_tti_req->n_pdus %d\n", UL_tti_req->n_pdus);
|
||||
|
||||
@@ -414,11 +431,10 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
}
|
||||
|
||||
// block resources in vrb_map_UL
|
||||
const uint8_t mu_pusch =
|
||||
scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
const int mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch);
|
||||
index = ul_buffer_index(frameP, slotP, mu, gNB->vrb_map_UL_size);
|
||||
uint16_t *vrb_map_UL = &cc->vrb_map_UL[index * MAX_BWP_SIZE];
|
||||
uint16_t *vrb_map_UL = &cc->vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
|
||||
for (int i = 0; i < n_ra_rb * fdm; ++i)
|
||||
vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] |= SL_to_bitmap(start_symbol, N_t_slot * N_dur);
|
||||
}
|
||||
@@ -551,20 +567,6 @@ static void start_ra_contention_resolution_timer(NR_RA_t *ra, const long ra_Cont
|
||||
ra->contention_resolution_timer);
|
||||
}
|
||||
|
||||
static bool beam_is_active(const NR_TDD_UL_DL_Pattern_t *tdd, int mu, const int16_t *tdd_beam_association, int slot, int16_t ra_beam)
|
||||
{
|
||||
if (tdd_beam_association == NULL) // no beams configured
|
||||
return true;
|
||||
DevAssert(tdd != NULL);
|
||||
|
||||
const int n_slots_frame = nr_slots_per_frame[mu];
|
||||
uint8_t tdd_period_slot = n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
|
||||
int num_tdd_period = slot / tdd_period_slot;
|
||||
int16_t current_beam = tdd_beam_association[num_tdd_period];
|
||||
return current_beam == -1 /* no beams */
|
||||
|| current_beam == ra_beam;
|
||||
}
|
||||
|
||||
static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
@@ -585,14 +587,19 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
|
||||
|
||||
if (is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) {
|
||||
// beam association for FR2
|
||||
if (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257) {
|
||||
// FR2
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
if (!beam_is_active(tdd, mu, nr_mac->tdd_beam_association, sched_slot, ra->beam_id))
|
||||
return;
|
||||
const int n_slots_frame = nr_slots_per_frame[mu];
|
||||
NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info,
|
||||
sched_frame,
|
||||
sched_slot,
|
||||
ra->beam_id,
|
||||
n_slots_frame);
|
||||
if (beam_ul.idx < 0)
|
||||
return;
|
||||
NR_beam_alloc_t beam_dci = beam_allocation_procedure(&nr_mac->beam_info, frame, slot, ra->beam_id, n_slots_frame);
|
||||
if (beam_dci.idx < 0) {
|
||||
reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, ra->beam_id, n_slots_frame, beam_ul.new_beam);
|
||||
return;
|
||||
}
|
||||
|
||||
int fh = 0;
|
||||
int startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength;
|
||||
int StartSymbolIndex, NrOfSymbols;
|
||||
@@ -600,7 +607,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
int mappingtype = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->mappingType;
|
||||
|
||||
int buffer_index = ul_buffer_index(sched_frame, sched_slot, mu, nr_mac->vrb_map_UL_size);
|
||||
uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
|
||||
uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[beam_ul.idx][buffer_index * MAX_BWP_SIZE];
|
||||
|
||||
const int BWPSize = sc_info->initial_ul_BWPSize;
|
||||
const int BWPStart = sc_info->initial_ul_BWPStart;
|
||||
@@ -674,6 +681,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
int CCEIndex = get_cce_index(nr_mac,
|
||||
CC_id, slot, 0,
|
||||
&aggregation_level,
|
||||
beam_dci.idx,
|
||||
ss,
|
||||
coreset,
|
||||
&ra->sched_pdcch,
|
||||
@@ -724,7 +732,8 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
CC_id,
|
||||
&ra->sched_pdcch,
|
||||
CCEIndex,
|
||||
aggregation_level);
|
||||
aggregation_level,
|
||||
beam_dci.idx);
|
||||
|
||||
for (int rb = 0; rb < ra->msg3_nb_rb; rb++) {
|
||||
vrb_map_UL[rbStart + BWPStart + rb] |= SL_to_bitmap(StartSymbolIndex, NrOfSymbols);
|
||||
@@ -746,37 +755,38 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
}
|
||||
}
|
||||
|
||||
static int get_feasible_msg3_tda(frame_type_t frame_type,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
int mu_delta,
|
||||
uint64_t ulsch_slot_bitmap[3],
|
||||
const NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list,
|
||||
int slots_per_frame,
|
||||
int slot,
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd)
|
||||
static bool get_feasible_msg3_tda(frame_type_t frame_type,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
int mu_delta,
|
||||
uint64_t ulsch_slot_bitmap[3],
|
||||
const NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list,
|
||||
int slots_per_frame,
|
||||
int frame,
|
||||
int slot,
|
||||
NR_RA_t *ra,
|
||||
NR_beam_info_t *beam_info,
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd)
|
||||
{
|
||||
DevAssert(tda_list != NULL);
|
||||
|
||||
if (frame_type == FDD) {
|
||||
int tda = 0; // the first occasion is good enough
|
||||
return tda;
|
||||
}
|
||||
|
||||
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
|
||||
|
||||
// TDD
|
||||
DevAssert(tdd != NULL);
|
||||
uint8_t tdd_period_slot = slots_per_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
|
||||
int tdd_period_slot = tdd ? slots_per_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : slots_per_frame;
|
||||
for (int i = 0; i < tda_list->list.count; i++) {
|
||||
// check if it is UL
|
||||
long k2 = *tda_list->list.array[i]->k2 + NTN_gNB_Koffset;
|
||||
int temp_slot = (slot + k2 + mu_delta) % slots_per_frame; // msg3 slot according to 8.3 in 38.213
|
||||
if (!is_xlsch_in_slot(ulsch_slot_bitmap[temp_slot / 64], temp_slot))
|
||||
int abs_slot = slot + k2 + mu_delta;
|
||||
int temp_frame = (frame + (abs_slot / slots_per_frame)) & 1023;
|
||||
int temp_slot = abs_slot % slots_per_frame; // msg3 slot according to 8.3 in 38.213
|
||||
if ((frame_type == TDD) && !is_xlsch_in_slot(ulsch_slot_bitmap[temp_slot / 64], temp_slot))
|
||||
continue;
|
||||
|
||||
// check if enough symbols in case of mixed slot
|
||||
bool has_mixed = tdd->nrofUplinkSymbols != 0 || tdd->nrofDownlinkSymbols != 0;
|
||||
bool is_mixed = has_mixed && ((temp_slot % tdd_period_slot) == tdd->nrofDownlinkSlots);
|
||||
bool is_mixed = false;
|
||||
if (frame_type == TDD) {
|
||||
bool has_mixed = tdd->nrofUplinkSymbols != 0 || tdd->nrofDownlinkSymbols != 0;
|
||||
is_mixed = has_mixed && ((temp_slot % tdd_period_slot) == tdd->nrofDownlinkSlots);
|
||||
}
|
||||
// if the mixed slot has not enough symbols, skip
|
||||
if (is_mixed && tdd->nrofUplinkSymbols < 3)
|
||||
continue;
|
||||
@@ -791,12 +801,20 @@ static int get_feasible_msg3_tda(frame_type_t frame_type,
|
||||
if ((slot_mask & msg3_mask) != msg3_mask)
|
||||
continue;
|
||||
|
||||
// check if it is possible to allocate MSG3 in a beam in this slot
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(beam_info, temp_frame, temp_slot, ra->beam_id, slots_per_frame);
|
||||
if (beam.idx < 0)
|
||||
continue;
|
||||
|
||||
// is in mixed slot with more or equal than 3 symbols, or UL slot
|
||||
int tda = i;
|
||||
return tda;
|
||||
ra->Msg3_frame = temp_frame;
|
||||
ra->Msg3_slot = temp_slot;
|
||||
ra->Msg3_tda_id = i;
|
||||
ra->Msg3_beam = beam;
|
||||
return true;
|
||||
}
|
||||
|
||||
return -1; // invalid
|
||||
return false;
|
||||
}
|
||||
|
||||
static void nr_get_Msg3alloc(module_id_t module_id,
|
||||
@@ -804,8 +822,7 @@ static void nr_get_Msg3alloc(module_id_t module_id,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
sub_frame_t current_slot,
|
||||
frame_t current_frame,
|
||||
NR_RA_t *ra,
|
||||
int16_t *tdd_beam_association)
|
||||
NR_RA_t *ra)
|
||||
{
|
||||
// msg3 is scheduled in mixed slot in the following TDD period
|
||||
DevAssert(ra->Msg3_tda_id >= 0 && ra->Msg3_tda_id < 16);
|
||||
@@ -818,27 +835,20 @@ static void nr_get_Msg3alloc(module_id_t module_id,
|
||||
|
||||
const NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common;
|
||||
int mu = ul_bwp->scs;
|
||||
const int n_slots_frame = nr_slots_per_frame[mu];
|
||||
|
||||
int startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength;
|
||||
SLIV2SL(startSymbolAndLength, &ra->msg3_startsymb, &ra->msg3_nbSymb);
|
||||
|
||||
long k2 = *pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc);
|
||||
int abs_slot = current_slot + k2 + DELTA[mu];
|
||||
ra->Msg3_slot = abs_slot % n_slots_frame;
|
||||
ra->Msg3_frame = (current_frame + (abs_slot / n_slots_frame)) % MAX_FRAME_NUMBER;
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"UE %04x: Msg3 scheduled at %d.%d (%d.%d k2 %ld TDA %u)\n",
|
||||
"UE %04x: Msg3 scheduled at %d.%d (%d.%d TDA %u)\n",
|
||||
ra->rnti,
|
||||
ra->Msg3_frame,
|
||||
ra->Msg3_slot,
|
||||
current_frame,
|
||||
current_slot,
|
||||
k2,
|
||||
ra->Msg3_tda_id);
|
||||
const int buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, mu, mac->vrb_map_UL_size);
|
||||
uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
|
||||
uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[ra->Msg3_beam.idx][buffer_index * MAX_BWP_SIZE];
|
||||
|
||||
int bwpSize = sc_info->initial_ul_BWPSize;
|
||||
int bwpStart = sc_info->initial_ul_BWPStart;
|
||||
@@ -993,7 +1003,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_f
|
||||
const int scs = ul_bwp->scs;
|
||||
const uint16_t mask = SL_to_bitmap(ra->msg3_startsymb, ra->msg3_nbSymb);
|
||||
int buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, scs, mac->vrb_map_UL_size);
|
||||
uint16_t *vrb_map_UL = &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
|
||||
uint16_t *vrb_map_UL = &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_beam.idx][buffer_index * MAX_BWP_SIZE];
|
||||
for (int i = 0; i < ra->msg3_nb_rb; ++i) {
|
||||
AssertFatal(!(vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start] & mask),
|
||||
"RB %d in %4d.%2d is already taken, cannot allocate Msg3!\n",
|
||||
@@ -1219,23 +1229,28 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: Msg2 not monitored by UE\n", ra->RA_rnti, ra->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
const int n_slots_frame = nr_slots_per_frame[dl_bwp->scs];
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame);
|
||||
if (beam.idx < 0)
|
||||
return;
|
||||
|
||||
const NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP;
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
if (!beam_is_active(tdd, ul_bwp->scs, nr_mac->tdd_beam_association, slotP, ra->beam_id)) {
|
||||
LOG_I(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: beam %d inactive\n", ra->RA_rnti, ra->rnti, ra->beam_id);
|
||||
return;
|
||||
}
|
||||
|
||||
ra->Msg3_tda_id = get_feasible_msg3_tda(cc->frame_type,
|
||||
scc,
|
||||
DELTA[ul_bwp->scs],
|
||||
nr_mac->ulsch_slot_bitmap,
|
||||
ul_bwp->tdaList_Common,
|
||||
nr_slots_per_frame[ul_bwp->scs],
|
||||
slotP,
|
||||
tdd);
|
||||
if (ra->Msg3_tda_id < 0 || ra->Msg3_tda_id > 15) {
|
||||
bool ret = get_feasible_msg3_tda(cc->frame_type,
|
||||
scc,
|
||||
DELTA[ul_bwp->scs],
|
||||
nr_mac->ulsch_slot_bitmap,
|
||||
ul_bwp->tdaList_Common,
|
||||
nr_slots_per_frame[ul_bwp->scs],
|
||||
frameP,
|
||||
slotP,
|
||||
ra,
|
||||
&nr_mac->beam_info,
|
||||
tdd);
|
||||
if (!ret || ra->Msg3_tda_id > 15) {
|
||||
LOG_D(NR_MAC, "UE RNTI %04x %d.%d: infeasible Msg3 TDA\n", ra->rnti, frameP, slotP);
|
||||
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1274,7 +1289,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
if (!tda_info.valid_tda)
|
||||
return;
|
||||
|
||||
uint16_t *vrb_map = cc[CC_id].vrb_map;
|
||||
uint16_t *vrb_map = cc[CC_id].vrb_map[beam.idx];
|
||||
for (int i = 0; (i < rbSize) && (rbStart <= (BWPSize - rbSize)); i++) {
|
||||
if (vrb_map[BWPStart + rbStart + i] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) {
|
||||
rbStart += i;
|
||||
@@ -1283,7 +1298,9 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
}
|
||||
|
||||
if (rbStart > (BWPSize - rbSize)) {
|
||||
LOG_W(NR_MAC, "%s(): cannot find free vrb_map for RA RNTI %04x!\n", __func__, ra->RA_rnti);
|
||||
LOG_W(NR_MAC, "Cannot find free vrb_map for RA RNTI %04x!\n", ra->RA_rnti);
|
||||
reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam);
|
||||
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1291,14 +1308,18 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
|
||||
if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) {
|
||||
LOG_W(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", ra->rnti, frameP, slotP);
|
||||
reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam);
|
||||
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t aggregation_level;
|
||||
int CCEIndex = get_cce_index(nr_mac, CC_id, slotP, 0, &aggregation_level, ss, coreset, &ra->sched_pdcch, true);
|
||||
int CCEIndex = get_cce_index(nr_mac, CC_id, slotP, 0, &aggregation_level, beam.idx, ss, coreset, &ra->sched_pdcch, true);
|
||||
|
||||
if (CCEIndex < 0) {
|
||||
LOG_W(NR_MAC, "UE %04x: %d.%d cannot find free CCE for Msg2!\n", ra->rnti, frameP, slotP);
|
||||
reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam);
|
||||
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1462,7 +1483,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs];
|
||||
|
||||
// Program UL processing for Msg3
|
||||
nr_get_Msg3alloc(module_idP, CC_id, scc, slotP, frameP, ra, nr_mac->tdd_beam_association);
|
||||
nr_get_Msg3alloc(module_idP, CC_id, scc, slotP, frameP, ra);
|
||||
nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *)&tx_req->TLVs[0].value.direct[0]);
|
||||
|
||||
// Start RA contention resolution timer in Msg3 transmission slot (current slot + K2)
|
||||
@@ -1512,7 +1533,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
TX_req->Slot = slotP;
|
||||
|
||||
// Mark the corresponding symbols RBs as used
|
||||
fill_pdcch_vrb_map(nr_mac, CC_id, &ra->sched_pdcch, CCEIndex, aggregation_level);
|
||||
fill_pdcch_vrb_map(nr_mac, CC_id, &ra->sched_pdcch, CCEIndex, aggregation_level, beam.idx);
|
||||
for (int rb = 0; rb < rbSize; rb++) {
|
||||
vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
|
||||
}
|
||||
@@ -1762,6 +1783,11 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
mac_sdu_length = srb_status.bytes_in_buffer;
|
||||
}
|
||||
|
||||
const int n_slots_frame = nr_slots_per_frame[dl_bwp->scs];
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame);
|
||||
if (beam.idx < 0)
|
||||
return;
|
||||
|
||||
long BWPStart = 0;
|
||||
long BWPSize = 0;
|
||||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL;
|
||||
@@ -1779,13 +1805,15 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
int CCEIndex = get_cce_index(nr_mac,
|
||||
CC_id, slotP, 0,
|
||||
&aggregation_level,
|
||||
beam.idx,
|
||||
ss,
|
||||
coreset,
|
||||
&ra->sched_pdcch,
|
||||
true);
|
||||
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti);
|
||||
LOG_E(NR_MAC, "Cannot find free CCE for RA RNTI 0x%04x!\n", ra->rnti);
|
||||
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1793,6 +1821,7 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
|
||||
if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) {
|
||||
LOG_I(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", ra->rnti, frameP, slotP);
|
||||
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1809,10 +1838,7 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
if (!msg4_tda.valid_tda)
|
||||
return;
|
||||
|
||||
NR_pdsch_dmrs_t dmrs_info = get_dl_dmrs_params(scc,
|
||||
dl_bwp,
|
||||
&msg4_tda,
|
||||
1);
|
||||
NR_pdsch_dmrs_t dmrs_info = get_dl_dmrs_params(scc, dl_bwp, &msg4_tda, 1);
|
||||
|
||||
uint8_t mcsTableIdx = dl_bwp->mcsTableIdx;
|
||||
uint8_t mcsIndex = 0;
|
||||
@@ -1846,7 +1872,7 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
AssertFatal(tb_size >= pdu_length,"Cannot allocate Msg4\n");
|
||||
|
||||
int i = 0;
|
||||
uint16_t *vrb_map = cc[CC_id].vrb_map;
|
||||
uint16_t *vrb_map = cc[CC_id].vrb_map[beam.idx];
|
||||
while ((i < rbSize) && (rbStart + rbSize <= BWPSize)) {
|
||||
if (vrb_map[BWPStart + rbStart + i]&SL_to_bitmap(msg4_tda.startSymbolIndex, msg4_tda.nrOfSymbols)) {
|
||||
rbStart += i+1;
|
||||
@@ -1857,7 +1883,8 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
}
|
||||
|
||||
if (rbStart > (BWPSize - rbSize)) {
|
||||
LOG_E(NR_MAC, "%s(): cannot find free vrb_map for RNTI %04x!\n", __func__, ra->rnti);
|
||||
LOG_E(NR_MAC, "Cannot find free vrb_map for RNTI %04x!\n", ra->rnti);
|
||||
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1877,9 +1904,10 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
|
||||
LOG_D(NR_MAC, "Msg4 r_pucch %d (CCEIndex %d, delta_PRI %d)\n", r_pucch, CCEIndex, delta_PRI);
|
||||
|
||||
alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, r_pucch, 1);
|
||||
alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, ra->beam_id, r_pucch, 1);
|
||||
if (alloc < 0) {
|
||||
LOG_D(NR_MAC,"Couldn't find a pucch allocation for ack nack (msg4) in frame %d slot %d\n",frameP,slotP);
|
||||
LOG_D(NR_MAC,"Couldn't find a pucch allocation for ack nack (msg4) in frame %d slot %d\n", frameP, slotP);
|
||||
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1972,7 +2000,8 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
CC_id,
|
||||
&ra->sched_pdcch,
|
||||
CCEIndex,
|
||||
aggregation_level);
|
||||
aggregation_level,
|
||||
beam.idx);
|
||||
for (int rb = 0; rb < rbSize; rb++) {
|
||||
vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(msg4_tda.startSymbolIndex, msg4_tda.nrOfSymbols);
|
||||
}
|
||||
|
||||
@@ -89,13 +89,18 @@ static void schedule_ssb(frame_t frame,
|
||||
LOG_D(MAC,"Scheduling ssb %d at frame %d and slot %d\n",i_ssb,frame,slot);
|
||||
}
|
||||
|
||||
static void fill_ssb_vrb_map(NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id)
|
||||
static void fill_ssb_vrb_map(NR_COMMON_channels_t *cc,
|
||||
int rbStart,
|
||||
int ssb_subcarrier_offset,
|
||||
uint16_t symStart,
|
||||
int CC_id,
|
||||
int beam)
|
||||
{
|
||||
AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing !=
|
||||
NR_SubcarrierSpacing_kHz240,
|
||||
"240kHZ subcarrier won't work with current VRB map because a single SSB might be across 2 slots\n");
|
||||
|
||||
uint16_t *vrb_map = cc[CC_id].vrb_map;
|
||||
uint16_t *vrb_map = cc[CC_id].vrb_map[beam];
|
||||
const int extra_prb = ssb_subcarrier_offset > 0;
|
||||
for (int rb = 0; rb < 20 + extra_prb; rb++)
|
||||
vrb_map[rbStart + rb] = SL_to_bitmap(symStart % NR_NUMBER_OF_SYMBOLS_PER_SLOT, 4);
|
||||
@@ -115,10 +120,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
|
||||
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
|
||||
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req;
|
||||
uint8_t num_tdd_period,num_ssb;
|
||||
int CC_id;
|
||||
|
||||
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
NR_COMMON_channels_t *cc= &gNB->common_channels[CC_id];
|
||||
const NR_MIB_t *mib = cc->mib->message.choice.mib;
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
@@ -169,18 +172,21 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
|
||||
const BIT_STRING_t *longBitmap = &scc->ssb_PositionsInBurst->choice.longBitmap;
|
||||
|
||||
uint16_t ssb_start_symbol;
|
||||
const int n_slots_frame = nr_slots_per_frame[scs];
|
||||
|
||||
switch (scc->ssb_PositionsInBurst->present) {
|
||||
case 1:
|
||||
// short bitmap (<3GHz) max 4 SSBs
|
||||
for (int i_ssb=0; i_ssb<4; i_ssb++) {
|
||||
if ((shortBitmap->buf[0]>>(7-i_ssb))&0x01) {
|
||||
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
|
||||
for (int i_ssb = 0; i_ssb < 4; i_ssb++) {
|
||||
if ((shortBitmap->buf[0] >> (7 - i_ssb)) & 0x01) {
|
||||
ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb);
|
||||
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
|
||||
if ((ssb_start_symbol/14) == rel_slot){
|
||||
if ((ssb_start_symbol / 14) == rel_slot){
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, i_ssb, n_slots_frame);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
|
||||
const int prb_offset = offset_pointa >> scs;
|
||||
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, mib_pdu);
|
||||
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id);
|
||||
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id, beam.idx);
|
||||
if (get_softmodem_params()->sa == 1) {
|
||||
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
|
||||
frameP,
|
||||
@@ -202,14 +208,16 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
|
||||
break;
|
||||
case 2:
|
||||
// medium bitmap (<6GHz) max 8 SSBs
|
||||
for (int i_ssb=0; i_ssb<8; i_ssb++) {
|
||||
if ((mediumBitmap->buf[0]>>(7-i_ssb))&0x01) {
|
||||
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
|
||||
for (int i_ssb = 0; i_ssb < 8; i_ssb++) {
|
||||
if ((mediumBitmap->buf[0] >> (7 - i_ssb)) & 0x01) {
|
||||
ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb);
|
||||
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
|
||||
if ((ssb_start_symbol/14) == rel_slot){
|
||||
if ((ssb_start_symbol / 14) == rel_slot){
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, i_ssb, n_slots_frame);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
|
||||
const int prb_offset = offset_pointa >> scs;
|
||||
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, mib_pdu);
|
||||
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id);
|
||||
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id, beam.idx);
|
||||
if (get_softmodem_params()->sa == 1) {
|
||||
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
|
||||
frameP,
|
||||
@@ -231,23 +239,16 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
|
||||
break;
|
||||
case 3:
|
||||
// long bitmap FR2 max 64 SSBs
|
||||
num_ssb = 0;
|
||||
for (int i_ssb=0; i_ssb<64; i_ssb++) {
|
||||
if ((longBitmap->buf[i_ssb/8]>>(7-(i_ssb%8)))&0x01) {
|
||||
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
|
||||
for (int i_ssb = 0; i_ssb < 64; i_ssb++) {
|
||||
if ((longBitmap->buf[i_ssb / 8] >> (7 - (i_ssb % 8))) & 0x01) {
|
||||
ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb);
|
||||
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
|
||||
if ((ssb_start_symbol/14) == rel_slot){
|
||||
if ((ssb_start_symbol / 14) == rel_slot){
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, i_ssb, n_slots_frame);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
|
||||
const int prb_offset = offset_pointa >> (scs-2); // reference 60kHz
|
||||
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, mib_pdu);
|
||||
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset >> (scs - 2), ssb_start_symbol, CC_id);
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
|
||||
const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
// FR2 is only TDD, to be fixed for flexible TDD
|
||||
const int nr_slots_period = tdd ? n_slots_frame/get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity) : n_slots_frame;
|
||||
num_tdd_period = rel_slot/nr_slots_period;
|
||||
gNB->tdd_beam_association[num_tdd_period]=i_ssb;
|
||||
num_ssb++;
|
||||
AssertFatal(num_ssb<2,"beamforming currently not supported for more than one SSB per slot\n");
|
||||
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset >> (scs - 2), ssb_start_symbol, CC_id, beam.idx);
|
||||
if (get_softmodem_params()->sa == 1) {
|
||||
get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb],
|
||||
frameP,
|
||||
@@ -282,12 +283,13 @@ static uint32_t schedule_control_sib1(module_id_t module_id,
|
||||
NR_pdsch_dmrs_t *dmrs_parms,
|
||||
NR_tda_info_t *tda_info,
|
||||
uint8_t candidate_idx,
|
||||
int beam,
|
||||
uint16_t num_total_bytes)
|
||||
{
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
|
||||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
uint16_t *vrb_map = cc->vrb_map;
|
||||
uint16_t *vrb_map = cc->vrb_map[beam];
|
||||
|
||||
if (gNB_mac->sched_ctrlCommon == NULL){
|
||||
LOG_D(NR_MAC,"schedule_control_common: Filling nr_mac->sched_ctrlCommon\n");
|
||||
@@ -326,6 +328,7 @@ static uint32_t schedule_control_sib1(module_id_t module_id,
|
||||
CC_id,
|
||||
gNB_mac->sched_ctrlCommon->aggregation_level,
|
||||
nr_of_candidates,
|
||||
beam,
|
||||
&gNB_mac->sched_ctrlCommon->sched_pdcch,
|
||||
gNB_mac->sched_ctrlCommon->coreset,
|
||||
0);
|
||||
@@ -387,7 +390,8 @@ static uint32_t schedule_control_sib1(module_id_t module_id,
|
||||
CC_id,
|
||||
&gNB_mac->sched_ctrlCommon->sched_pdcch,
|
||||
gNB_mac->sched_ctrlCommon->cce_index,
|
||||
gNB_mac->sched_ctrlCommon->aggregation_level);
|
||||
gNB_mac->sched_ctrlCommon->aggregation_level,
|
||||
beam);
|
||||
for (int rb = 0; rb < pdsch->rbSize; rb++) {
|
||||
vrb_map[rb + rbStart] |= SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
|
||||
}
|
||||
@@ -571,15 +575,18 @@ void schedule_nr_sib1(module_id_t module_idP,
|
||||
scc->ssb_PositionsInBurst->present);
|
||||
}
|
||||
|
||||
for (int i=0; i<L_max; i++) {
|
||||
for (int i = 0; i < L_max; i++) {
|
||||
|
||||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[i];
|
||||
|
||||
if((frameP%2 == type0_PDCCH_CSS_config->sfn_c) &&
|
||||
if((frameP % 2 == type0_PDCCH_CSS_config->sfn_c) &&
|
||||
(slotP == type0_PDCCH_CSS_config->n_0) &&
|
||||
(type0_PDCCH_CSS_config->num_rbs > 0) &&
|
||||
(type0_PDCCH_CSS_config->active == true)) {
|
||||
|
||||
const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frameP, slotP, i, n_slots_frame);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate SIB1 corresponding to SSB %d in any available beam\n", i);
|
||||
LOG_D(NR_MAC,"(%d.%d) SIB1 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index);
|
||||
|
||||
default_table_type_t table_type = get_default_table_type(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern);
|
||||
@@ -602,6 +609,7 @@ void schedule_nr_sib1(module_id_t module_idP,
|
||||
&dmrs_parms,
|
||||
&tda_info,
|
||||
candidate_idx,
|
||||
beam.idx,
|
||||
cc->sib1_bcch_length);
|
||||
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
|
||||
|
||||
@@ -543,10 +543,14 @@ static bool allocate_dl_retransmission(module_id_t module_id,
|
||||
retInfo->tda_info = temp_tda;
|
||||
}
|
||||
|
||||
// TODO properly set the beam index (currently only done for RA)
|
||||
int beam = 0;
|
||||
|
||||
/* Find a free CCE */
|
||||
int CCEIndex = get_cce_index(nr_mac,
|
||||
CC_id, slot, UE->rnti,
|
||||
&sched_ctrl->aggregation_level,
|
||||
beam,
|
||||
sched_ctrl->search_space,
|
||||
sched_ctrl->coreset,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
@@ -565,8 +569,8 @@ static bool allocate_dl_retransmission(module_id_t module_id,
|
||||
int alloc = -1;
|
||||
if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, current_harq_pid)) {
|
||||
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex);
|
||||
alloc = nr_acknack_scheduling(nr_mac, UE, frame, slot, r_pucch, 0);
|
||||
if (alloc<0) {
|
||||
alloc = nr_acknack_scheduling(nr_mac, UE, frame, slot, beam, r_pucch, 0);
|
||||
if (alloc < 0) {
|
||||
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find PUCCH for DL DCI retransmission\n",
|
||||
UE->rnti,
|
||||
frame,
|
||||
@@ -580,7 +584,8 @@ static bool allocate_dl_retransmission(module_id_t module_id,
|
||||
/* CC_id = */ 0,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
sched_ctrl->aggregation_level,
|
||||
beam);
|
||||
/* just reuse from previous scheduling opportunity, set new start RB */
|
||||
sched_ctrl->sched_pdsch = *retInfo;
|
||||
sched_ctrl->sched_pdsch.rbStart = rbStart;
|
||||
@@ -736,9 +741,13 @@ static void pf_dl(module_id_t module_id,
|
||||
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
|
||||
sched_pdsch->dl_harq_pid = sched_ctrl->available_dl_harq.head;
|
||||
|
||||
// TODO properly set the beam index (currently only done for RA)
|
||||
int beam = 0;
|
||||
|
||||
int CCEIndex = get_cce_index(mac,
|
||||
CC_id, slot, iterator->UE->rnti,
|
||||
&sched_ctrl->aggregation_level,
|
||||
beam,
|
||||
sched_ctrl->search_space,
|
||||
sched_ctrl->coreset,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
@@ -758,8 +767,8 @@ static void pf_dl(module_id_t module_id,
|
||||
int alloc = -1;
|
||||
if (!get_FeedbackDisabled(iterator->UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) {
|
||||
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex);
|
||||
alloc = nr_acknack_scheduling(mac, iterator->UE, frame, slot, r_pucch, 0);
|
||||
if (alloc<0) {
|
||||
alloc = nr_acknack_scheduling(mac, iterator->UE, frame, slot, beam, r_pucch, 0);
|
||||
if (alloc < 0) {
|
||||
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find PUCCH for DL DCI\n",
|
||||
rnti,
|
||||
frame,
|
||||
@@ -774,7 +783,8 @@ static void pf_dl(module_id_t module_id,
|
||||
/* CC_id = */ 0,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
sched_ctrl->aggregation_level,
|
||||
beam);
|
||||
|
||||
/* MCS has been set above */
|
||||
sched_pdsch->time_domain_allocation = get_dl_tda(mac, scc, slot);
|
||||
@@ -874,7 +884,8 @@ static void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_
|
||||
const uint16_t BWPStart = current_BWP->BWPStart;
|
||||
|
||||
const uint16_t slbitmap = SL_to_bitmap(startSymbolIndex, nrOfSymbols);
|
||||
uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
|
||||
// TODO improve handling of beam in vrb_map (for now just using 0)
|
||||
uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map[0];
|
||||
uint16_t rballoc_mask[bwpSize];
|
||||
int n_rb_sched = 0;
|
||||
|
||||
|
||||
@@ -85,11 +85,14 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
||||
const int bwpSize = dl_bwp->BWPSize;
|
||||
const int BWPStart = dl_bwp->BWPStart;
|
||||
|
||||
// TODO implement beam procedures for phy-test mode
|
||||
int beam = 0;
|
||||
|
||||
int rbStart = 0;
|
||||
int rbSize = 0;
|
||||
if (target_dl_bw>bwpSize)
|
||||
target_dl_bw = bwpSize;
|
||||
uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
|
||||
uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map[beam];
|
||||
/* loop ensures that we allocate exactly target_dl_bw, or return */
|
||||
while (true) {
|
||||
/* advance to first free RB */
|
||||
@@ -133,6 +136,7 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
||||
int CCEIndex = get_cce_index(RC.nrmac[module_id],
|
||||
CC_id, slot, UE->rnti,
|
||||
&sched_ctrl->aggregation_level,
|
||||
beam,
|
||||
sched_ctrl->search_space,
|
||||
sched_ctrl->coreset,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
@@ -149,11 +153,10 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
||||
int alloc = -1;
|
||||
if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) {
|
||||
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, UE->current_UL_BWP.pucch_Config, CCEIndex);
|
||||
alloc = nr_acknack_scheduling(RC.nrmac[module_id], UE, frame, slot, r_pucch, 0);
|
||||
alloc = nr_acknack_scheduling(RC.nrmac[module_id], UE, frame, slot, 0, r_pucch, 0);
|
||||
if (alloc < 0) {
|
||||
LOG_D(MAC,
|
||||
"%s(): could not find PUCCH for UE %04x@%d.%d\n",
|
||||
__func__,
|
||||
"Could not find PUCCH for UE %04x@%d.%d\n",
|
||||
rnti,
|
||||
frame,
|
||||
slot);
|
||||
@@ -167,7 +170,8 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
||||
CC_id,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
sched_ctrl->aggregation_level,
|
||||
beam);
|
||||
|
||||
//AssertFatal(alloc,
|
||||
// "could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n",
|
||||
@@ -283,8 +287,12 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_
|
||||
return false;
|
||||
sched_ctrl->sched_pusch.tda_info = tda_info;
|
||||
sched_ctrl->sched_pusch.time_domain_allocation = tda;
|
||||
|
||||
// TODO implement beam procedures for phy-test mode
|
||||
int beam = 0;
|
||||
|
||||
const int buffer_index = ul_buffer_index(sched_frame, sched_slot, mu, nr_mac->vrb_map_UL_size);
|
||||
uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
|
||||
uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[beam][buffer_index * MAX_BWP_SIZE];
|
||||
for (int i = rbStart; i < rbStart + rbSize; ++i) {
|
||||
if ((vrb_map_UL[i+BWPStart] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) != 0) {
|
||||
LOG_E(MAC, "%4d.%2d RB %d is already reserved, cannot schedule UE\n", frame, slot, i);
|
||||
@@ -298,6 +306,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_
|
||||
int CCEIndex = get_cce_index(nr_mac,
|
||||
CC_id, slot, UE->rnti,
|
||||
&sched_ctrl->aggregation_level,
|
||||
beam,
|
||||
sched_ctrl->search_space,
|
||||
sched_ctrl->coreset,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
@@ -349,7 +358,8 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_
|
||||
CC_id,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
sched_ctrl->aggregation_level,
|
||||
beam);
|
||||
|
||||
for (int rb = rbStart; rb < rbStart + rbSize; rb++)
|
||||
vrb_map_UL[rb+BWPStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
|
||||
|
||||
@@ -501,11 +501,12 @@ int find_pdcch_candidate(const gNB_MAC_INST *mac,
|
||||
int cc_id,
|
||||
int aggregation,
|
||||
int nr_of_candidates,
|
||||
int beam_idx,
|
||||
const NR_sched_pdcch_t *pdcch,
|
||||
const NR_ControlResourceSet_t *coreset,
|
||||
uint32_t Y)
|
||||
{
|
||||
const uint16_t *vrb_map = mac->common_channels[cc_id].vrb_map;
|
||||
const uint16_t *vrb_map = mac->common_channels[cc_id].vrb_map[beam_idx];
|
||||
const int N_ci = 0;
|
||||
|
||||
const int N_rb = pdcch->n_rb; // nb of rbs of coreset per symbol
|
||||
@@ -546,6 +547,7 @@ int get_cce_index(const gNB_MAC_INST *nrmac,
|
||||
const int slot,
|
||||
const rnti_t rnti,
|
||||
uint8_t *aggregation_level,
|
||||
int beam_idx,
|
||||
const NR_SearchSpace_t *ss,
|
||||
const NR_ControlResourceSet_t *coreset,
|
||||
NR_sched_pdcch_t *sched_pdcch,
|
||||
@@ -567,6 +569,7 @@ int get_cce_index(const gNB_MAC_INST *nrmac,
|
||||
CC_id,
|
||||
*aggregation_level,
|
||||
nr_of_candidates,
|
||||
beam_idx,
|
||||
sched_pdcch,
|
||||
coreset,
|
||||
Y);
|
||||
@@ -577,9 +580,10 @@ void fill_pdcch_vrb_map(gNB_MAC_INST *mac,
|
||||
int CC_id,
|
||||
NR_sched_pdcch_t *pdcch,
|
||||
int first_cce,
|
||||
int aggregation){
|
||||
|
||||
uint16_t *vrb_map = mac->common_channels[CC_id].vrb_map;
|
||||
int aggregation,
|
||||
int beam)
|
||||
{
|
||||
uint16_t *vrb_map = mac->common_channels[CC_id].vrb_map[beam];
|
||||
|
||||
int N_rb = pdcch->n_rb; // nb of rbs of coreset per symbol
|
||||
int L = pdcch->RegBundleSize;
|
||||
@@ -2725,7 +2729,9 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo
|
||||
|
||||
NR_SCHED_ENSURE_LOCKED(&gNB_mac->sched_lock);
|
||||
|
||||
uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map;
|
||||
// TODO implement beam procedures
|
||||
int beam = 0;
|
||||
uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map[beam];
|
||||
|
||||
UE_info->sched_csirs = 0;
|
||||
|
||||
@@ -3110,6 +3116,43 @@ void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t
|
||||
}
|
||||
}
|
||||
|
||||
static inline int get_beam_index(const NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame)
|
||||
{
|
||||
return ((frame * slots_per_frame + slot) / beam_info->beam_duration) % beam_info->beam_allocation_size;
|
||||
}
|
||||
|
||||
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame)
|
||||
{
|
||||
// if no beam allocation for analog beamforming we always return beam index 0 (no multiple beams)
|
||||
if (!beam_info->beam_allocation)
|
||||
return (NR_beam_alloc_t) {.new_beam = false, .idx = 0};
|
||||
|
||||
const int index = get_beam_index(beam_info, frame, slot, beam_index, slots_per_frame);
|
||||
for (int i = 0; i < beam_info->beams_per_period; i++) {
|
||||
NR_beam_alloc_t beam_struct = {.new_beam = false, .idx = i};
|
||||
int *beam = &beam_info->beam_allocation[i][index];
|
||||
if (*beam == -1) {
|
||||
beam_struct.new_beam = true;
|
||||
*beam = beam_index;
|
||||
}
|
||||
if (*beam == beam_index)
|
||||
return beam_struct;
|
||||
}
|
||||
|
||||
return (NR_beam_alloc_t) {.new_beam = false, .idx = -1};
|
||||
}
|
||||
|
||||
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame, bool new_beam)
|
||||
{
|
||||
if(!new_beam) // need to reset only if the beam was allocated specifically for this instance
|
||||
return;
|
||||
const int index = get_beam_index(beam_info, frame, slot, beam_index, slots_per_frame);
|
||||
for (int i = 0; i < beam_info->beams_per_period; i++) {
|
||||
if (beam_info->beam_allocation[i][index] == beam_index)
|
||||
beam_info->beam_allocation[i][index] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_len, void *data)
|
||||
{
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
|
||||
@@ -470,7 +470,8 @@ static void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu,
|
||||
srs_pdu->beamforming.prg_size = 1;
|
||||
}
|
||||
|
||||
uint16_t *vrb_map_UL = &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
|
||||
// TODO properly use beam allocation
|
||||
uint16_t *vrb_map_UL = &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[0][buffer_index * MAX_BWP_SIZE];
|
||||
uint64_t mask = SL_to_bitmap(13 - srs_pdu->time_start_position, srs_pdu->num_symbols);
|
||||
for (int i = 0; i < srs_pdu->bwp_size; ++i)
|
||||
vrb_map_UL[i + srs_pdu->bwp_start] |= mask;
|
||||
|
||||
@@ -279,8 +279,9 @@ void nr_csi_meas_reporting(int Mod_idP,
|
||||
int bwp_start = ul_bwp->BWPStart;
|
||||
|
||||
// going through the list of PUCCH resources to find the one indexed by resource_id
|
||||
int beam_idx = 0; // TODO proper beam allocation
|
||||
const int index = ul_buffer_index(sched_frame, sched_slot, ul_bwp->scs, nrmac->vrb_map_UL_size);
|
||||
uint16_t *vrb_map_UL = &nrmac->common_channels[0].vrb_map_UL[index * MAX_BWP_SIZE];
|
||||
uint16_t *vrb_map_UL = &nrmac->common_channels[0].vrb_map_UL[beam_idx][index * MAX_BWP_SIZE];
|
||||
const int m = pucch_Config->resourceToAddModList->list.count;
|
||||
for (int j = 0; j < m; j++) {
|
||||
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j];
|
||||
@@ -1239,6 +1240,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
NR_UE_info_t *UE,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int beam_index,
|
||||
int r_pucch,
|
||||
int is_common)
|
||||
{
|
||||
@@ -1328,15 +1330,27 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
else { // unoccupied occasion
|
||||
// checking if in ul_slot the resources potentially to be assigned to this PUCCH are available
|
||||
set_pucch_allocation(ul_bwp, r_pucch, bwp_size, curr_pucch);
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, pucch_frame, pucch_slot, beam_index, n_slots_frame);
|
||||
if (beam.idx < 0) {
|
||||
LOG_D(NR_MAC,
|
||||
"DL %4d.%2d, UL_ACK %4d.%2d beam resources for this occasion are already occupied, move to the following occasion\n",
|
||||
frame,
|
||||
slot,
|
||||
pucch_frame,
|
||||
pucch_slot);
|
||||
continue;
|
||||
}
|
||||
const int index = ul_buffer_index(pucch_frame, pucch_slot, ul_bwp->scs, mac->vrb_map_UL_size);
|
||||
uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[index * MAX_BWP_SIZE];
|
||||
bool ret = test_pucch0_vrb_occupation(curr_pucch,
|
||||
vrb_map_UL,
|
||||
bwp_start,
|
||||
bwp_size);
|
||||
uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
|
||||
bool ret = test_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start, bwp_size);
|
||||
if(!ret) {
|
||||
LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d PRB resources for this occasion are already occupied, move to the following occasion\n",
|
||||
frame, slot, pucch_frame, pucch_slot);
|
||||
LOG_D(NR_MAC,
|
||||
"DL %4d.%2d, UL_ACK %4d.%2d PRB resources for this occasion are already occupied, move to the following occasion\n",
|
||||
frame,
|
||||
slot,
|
||||
pucch_frame,
|
||||
pucch_slot);
|
||||
reset_beam_status(&mac->beam_info, pucch_frame, pucch_slot, beam_index, n_slots_frame, beam.new_beam);
|
||||
continue;
|
||||
}
|
||||
// allocating a new PUCCH structure for this occasion
|
||||
@@ -1428,8 +1442,9 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
int beam_idx = 0; // TODO proper beam allocation
|
||||
const int index = ul_buffer_index(SFN, slot, ul_bwp->scs, nrmac->vrb_map_UL_size);
|
||||
uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[index * MAX_BWP_SIZE];
|
||||
uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam_idx][index * MAX_BWP_SIZE];
|
||||
const int bwp_start = ul_bwp->BWPStart;
|
||||
const int bwp_size = ul_bwp->BWPSize;
|
||||
set_pucch_allocation(ul_bwp, -1, bwp_size, curr_pucch);
|
||||
|
||||
@@ -1708,6 +1708,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac,
|
||||
int CCEIndex = get_cce_index(nrmac,
|
||||
CC_id, slot, UE->rnti,
|
||||
&sched_ctrl->aggregation_level,
|
||||
0, // TODO use beam index
|
||||
sched_ctrl->search_space,
|
||||
sched_ctrl->coreset,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
@@ -1725,7 +1726,8 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac,
|
||||
CC_id,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
sched_ctrl->aggregation_level,
|
||||
0); // TODO use beam index when implemented
|
||||
|
||||
/* frame/slot in sched_pusch has been set previously. In the following, we
|
||||
* overwrite the information in the retransmission information before storing
|
||||
@@ -1866,6 +1868,7 @@ static void pf_ul(module_id_t module_id,
|
||||
int CCEIndex = get_cce_index(nrmac,
|
||||
CC_id, slot, UE->rnti,
|
||||
&sched_ctrl->aggregation_level,
|
||||
0, // TODO use beam index
|
||||
sched_ctrl->search_space,
|
||||
sched_ctrl->coreset,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
@@ -1912,7 +1915,8 @@ static void pf_ul(module_id_t module_id,
|
||||
CC_id,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
sched_ctrl->aggregation_level,
|
||||
0); // TODO use beam index);
|
||||
|
||||
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
||||
sched_pusch->mcs = min(nrmac->min_grant_mcs, sched_pusch->mcs);
|
||||
@@ -1983,6 +1987,7 @@ static void pf_ul(module_id_t module_id,
|
||||
int CCEIndex = get_cce_index(nrmac,
|
||||
CC_id, slot, iterator->UE->rnti,
|
||||
&sched_ctrl->aggregation_level,
|
||||
0, // TODO use beam index
|
||||
sched_ctrl->search_space,
|
||||
sched_ctrl->coreset,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
@@ -2089,7 +2094,8 @@ static void pf_ul(module_id_t module_id,
|
||||
CC_id,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
sched_ctrl->aggregation_level,
|
||||
0); // TODO use beam index);
|
||||
|
||||
n_rb_sched -= sched_pusch->rbSize;
|
||||
for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
|
||||
@@ -2155,7 +2161,8 @@ static bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_
|
||||
* vrb_map_UL) overlap with the "default" tda and exclude those RBs.
|
||||
* Calculate largest contiguous RBs */
|
||||
const int index = ul_buffer_index(sched_frame, sched_slot, mu, nr_mac->vrb_map_UL_size);
|
||||
uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[index * MAX_BWP_SIZE];
|
||||
// TODO improve handling of beam in vrb_map (for now just using 0)
|
||||
uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[0][index * MAX_BWP_SIZE];
|
||||
|
||||
const uint16_t bwpSize = current_BWP->BWPSize;
|
||||
const uint16_t bwpStart = current_BWP->BWPStart;
|
||||
|
||||
@@ -175,6 +175,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
NR_UE_info_t *UE,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP,
|
||||
int beam_index,
|
||||
int r_pucch,
|
||||
int do_common);
|
||||
|
||||
@@ -214,6 +215,7 @@ int find_pdcch_candidate(const gNB_MAC_INST *mac,
|
||||
int cc_id,
|
||||
int aggregation,
|
||||
int nr_of_candidates,
|
||||
int beam_idx,
|
||||
const NR_sched_pdcch_t *pdcch,
|
||||
const NR_ControlResourceSet_t *coreset,
|
||||
uint32_t Y);
|
||||
@@ -222,7 +224,8 @@ void fill_pdcch_vrb_map(gNB_MAC_INST *mac,
|
||||
int CC_id,
|
||||
NR_sched_pdcch_t *pdcch,
|
||||
int first_cce,
|
||||
int aggregation);
|
||||
int aggregation,
|
||||
int beam);
|
||||
|
||||
void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo,
|
||||
const NR_UE_DL_BWP_t *current_DL_BWP,
|
||||
@@ -396,6 +399,7 @@ int get_cce_index(const gNB_MAC_INST *nrmac,
|
||||
const int slot,
|
||||
const rnti_t rnti,
|
||||
uint8_t *aggregation_level,
|
||||
int beam_idx,
|
||||
const NR_SearchSpace_t *ss,
|
||||
const NR_ControlResourceSet_t *coreset,
|
||||
NR_sched_pdcch_t *sched_pdcch,
|
||||
@@ -420,9 +424,11 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
|
||||
frame_t frame);
|
||||
|
||||
int ul_buffer_index(int frame, int slot, int scs, int size);
|
||||
|
||||
void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP);
|
||||
|
||||
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame);
|
||||
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame, bool new_beam);
|
||||
|
||||
void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP);
|
||||
|
||||
size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp);
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
#define MAX_NUM_OF_SSB 64
|
||||
#define MAX_NUM_NR_PRACH_PREAMBLES 64
|
||||
#define MIN_NUM_PRBS_TO_SCHEDULE 5
|
||||
#define MAX_NUM_BEAM_PERIODS 4
|
||||
|
||||
extern const uint8_t nr_rv_round_map[4];
|
||||
|
||||
@@ -120,8 +121,15 @@ typedef enum {
|
||||
nrRA_Msg4 = 4,
|
||||
nrRA_WAIT_Msg4_ACK = 5,
|
||||
} RA_gNB_state_t;
|
||||
|
||||
static const char *const nrra_text[] =
|
||||
{"IDLE", "Msg2", "WAIT_Msg3", "Msg3_retransmission", "Msg3_dcch_dtch", "Msg4", "WAIT_Msg4_ACK"};
|
||||
|
||||
typedef struct {
|
||||
int idx;
|
||||
bool new_beam;
|
||||
} NR_beam_alloc_t;
|
||||
|
||||
typedef struct nr_pdsch_AntennaPorts_t {
|
||||
int N1;
|
||||
int N2;
|
||||
@@ -203,6 +211,8 @@ typedef struct {
|
||||
frame_t Msg3_frame;
|
||||
/// Msg3 time domain allocation index
|
||||
int Msg3_tda_id;
|
||||
/// Msg3 beam matrix index
|
||||
NR_beam_alloc_t Msg3_beam;
|
||||
/// harq_pid used for Msg4 transmission
|
||||
uint8_t harq_pid;
|
||||
/// UE RNTI allocated during RAR
|
||||
@@ -261,10 +271,10 @@ typedef struct {
|
||||
/// Template for RA computations
|
||||
NR_RA_t ra[NR_NB_RA_PROC_MAX];
|
||||
/// VRB map for common channels
|
||||
uint16_t vrb_map[275];
|
||||
uint16_t vrb_map[MAX_NUM_BEAM_PERIODS][275];
|
||||
/// VRB map for common channels and PUSCH, dynamically allocated because
|
||||
/// length depends on number of slots and RBs
|
||||
uint16_t *vrb_map_UL;
|
||||
uint16_t *vrb_map_UL[MAX_NUM_BEAM_PERIODS];
|
||||
///Number of active SSBs
|
||||
int num_active_ssb;
|
||||
//Total available prach occasions per configuration period
|
||||
@@ -742,6 +752,14 @@ typedef struct {
|
||||
uid_allocator_t uid_allocator;
|
||||
} NR_UEs_t;
|
||||
|
||||
typedef struct {
|
||||
/// list of allocated beams per period
|
||||
int **beam_allocation;
|
||||
int beam_duration; // in slots
|
||||
int beams_per_period;
|
||||
int beam_allocation_size;
|
||||
} NR_beam_info_t;
|
||||
|
||||
#define UE_iterator(BaSe, VaR) NR_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++)))
|
||||
|
||||
typedef void (*nr_pp_impl_dl)(module_id_t mod_id,
|
||||
@@ -841,8 +859,8 @@ typedef struct gNB_MAC_INST_s {
|
||||
time_stats_t rx_ulsch_sdu; // include rlc_data_ind
|
||||
/// processing time of eNB PCH scheduler
|
||||
time_stats_t schedule_pch;
|
||||
/// list of allocated beams per period
|
||||
int16_t *tdd_beam_association;
|
||||
|
||||
NR_beam_info_t beam_info;
|
||||
|
||||
/// bitmap of DLSCH slots, can hold up to 160 slots
|
||||
uint64_t dlsch_slot_bitmap[3];
|
||||
|
||||
@@ -1765,9 +1765,7 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
/* log SDUs rejected, at most once per second */
|
||||
if (entity->sdu_rejected != 0
|
||||
&& entity->t_current > entity->t_log_buffer_full + 1000) {
|
||||
LOG_E(RLC, "%s:%d:%s: warning: %d SDU rejected, SDU buffer full\n",
|
||||
__FILE__, __LINE__, __FUNCTION__,
|
||||
entity->sdu_rejected);
|
||||
LOG_E(RLC, "%d SDU rejected, SDU buffer full\n", entity->sdu_rejected);
|
||||
entity->sdu_rejected = 0;
|
||||
entity->t_log_buffer_full = entity->t_current;
|
||||
}
|
||||
|
||||
@@ -136,9 +136,16 @@ void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* log SDUs rejected, at most once per second */
|
||||
if (entity->sdu_rejected != 0
|
||||
&& entity->t_current > entity->t_log_buffer_full + 1000) {
|
||||
LOG_E(RLC, "%d SDU rejected, SDU buffer full\n", entity->sdu_rejected);
|
||||
entity->sdu_rejected = 0;
|
||||
entity->t_log_buffer_full = entity->t_current;
|
||||
}
|
||||
|
||||
if (entity->tx_size + size > entity->tx_maxsize) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
entity->sdu_rejected++;
|
||||
|
||||
entity->common.stats.rxsdu_dd_pkts++;
|
||||
entity->common.stats.rxsdu_dd_bytes += size;
|
||||
@@ -181,6 +188,11 @@ void nr_rlc_entity_tm_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id)
|
||||
|
||||
static void clear_entity(nr_rlc_entity_tm_t *entity)
|
||||
{
|
||||
entity->t_current = 0;
|
||||
|
||||
entity->t_log_buffer_full = 0;
|
||||
entity->sdu_rejected = 0;
|
||||
|
||||
nr_rlc_free_sdu_segment_list(entity->tx_list);
|
||||
|
||||
entity->tx_list = NULL;
|
||||
|
||||
@@ -31,6 +31,10 @@ typedef struct {
|
||||
/* set to the latest know time by the user of the module. Unit: ms */
|
||||
uint64_t t_current;
|
||||
|
||||
/* deal with logging of buffer full */
|
||||
uint64_t t_log_buffer_full;
|
||||
int sdu_rejected;
|
||||
|
||||
/* tx management */
|
||||
nr_rlc_sdu_segment_t *tx_list;
|
||||
nr_rlc_sdu_segment_t *tx_end;
|
||||
|
||||
@@ -575,9 +575,16 @@ void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* log SDUs rejected, at most once per second */
|
||||
if (entity->sdu_rejected != 0
|
||||
&& entity->t_current > entity->t_log_buffer_full + 1000) {
|
||||
LOG_E(RLC, "%d SDU rejected, SDU buffer full\n", entity->sdu_rejected);
|
||||
entity->sdu_rejected = 0;
|
||||
entity->t_log_buffer_full = entity->t_current;
|
||||
}
|
||||
|
||||
if (entity->tx_size + size > entity->tx_maxsize) {
|
||||
LOG_W(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
entity->sdu_rejected++;
|
||||
|
||||
entity->common.stats.rxsdu_dd_pkts++;
|
||||
entity->common.stats.rxsdu_dd_bytes += size;
|
||||
@@ -712,11 +719,13 @@ static void clear_entity(nr_rlc_entity_um_t *entity)
|
||||
entity->rx_next_reassembly = 0;
|
||||
entity->rx_timer_trigger = 0;
|
||||
|
||||
|
||||
entity->tx_next = 0;
|
||||
|
||||
entity->t_current = 0;
|
||||
|
||||
entity->t_log_buffer_full = 0;
|
||||
entity->sdu_rejected = 0;
|
||||
|
||||
entity->t_reassembly_start = 0;
|
||||
|
||||
cur_rx = entity->rx_list;
|
||||
|
||||
@@ -47,6 +47,10 @@ typedef struct {
|
||||
/* set to the latest know time by the user of the module. Unit: ms */
|
||||
uint64_t t_current;
|
||||
|
||||
/* deal with logging of buffer full */
|
||||
uint64_t t_log_buffer_full;
|
||||
int sdu_rejected;
|
||||
|
||||
/* timers (stores the TTI of activation, 0 means not active) */
|
||||
uint64_t t_reassembly_start;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user