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:
Cédric Roux
2024-08-20 13:11:25 +00:00
42 changed files with 1463 additions and 691 deletions
+4
View File
@@ -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)
+1 -1
View File
@@ -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
-1
View File
@@ -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"
+9 -36
View File
@@ -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();
+38 -28
View File
@@ -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
View File
@@ -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);
+6 -6
View File
@@ -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;
}
-10
View File
@@ -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,
-2
View File
@@ -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,
+3
View File
@@ -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,
+1 -1
View File
@@ -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;
}
-2
View File
@@ -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
+6 -4
View File
@@ -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;
+1
View File
@@ -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);
+15
View File
@@ -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 } }, \
}
/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/
+9
View File
@@ -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;
+30 -28
View File
@@ -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)++;
}
}
+5 -2
View File
@@ -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;
+30 -12
View File
@@ -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);
+29 -16
View File
@@ -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);
}
+156 -127
View File
@@ -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);
}
+41 -33
View File
@@ -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;
+24 -9
View File
@@ -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;
+8 -2
View File
@@ -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);
+22 -4
View File
@@ -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];
+1 -3
View File
@@ -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;
}
+14 -2
View File
@@ -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;
+12 -3
View File
@@ -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;