diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 7764b0ee8f..3cc3844cc4 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -76,6 +76,8 @@ static inline const char *rnti_types(nr_rnti_type_t rr) } #undef R +#define NR_MAX_NB_LAYERS 4 // 8 + typedef enum { nr_FR1 = 0, nr_FR2 diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 8f4d083256..a70e18af11 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -74,17 +74,17 @@ typedef enum { NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION= 0X89, //RESERVED 0X8a ~ 0xff NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST = 0x0100, - NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE = 0x0101, - NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST= 0x0102, - NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE= 0x0103, - NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST= 0x0104, - NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE= 0x0105, - NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST= 0x0106, - NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE= 0x0107, + NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE = 0x0101, + NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST= 0x0102, + NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE= 0x0103, + NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST= 0x0104, + NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE= 0x0105, + NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST= 0x0106, + NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE= 0x0107, NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC = 0x0180, - NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, - NFAPI_NR_PHY_MSG_TYPE_TIMING_INFO + NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, + NFAPI_NR_PHY_MSG_TYPE_TIMING_INFO } nfapi_nr_phy_msg_type_e; // SCF222_5G-FAPI_PHY_SPI_Specificayion.pdf Section 3.3 @@ -449,6 +449,26 @@ typedef struct } nfapi_nr_measurement_config_t; +// Table 3–62 Precoding matrix (PM) PDU (v.222.10.04) +typedef struct { + int16_t precoder_weight_Re; + int16_t precoder_weight_Im; +} nfapi_nr_pm_weights_t; + + +typedef struct { + uint16_t pm_idx; + uint16_t numLayers; + uint16_t num_ant_ports; + nfapi_nr_pm_weights_t weights[4][4]; // TODO temporary hardcoding +} nfapi_nr_pm_pdu_t; + + +typedef struct { + uint16_t num_pm_idx; + nfapi_nr_pm_pdu_t *pmi_pdu; +} nfapi_nr_pm_list_t; + // ERROR enums typedef enum { // Table 2-22 NFAPI_NR_PARAM_MSG_OK = 0, @@ -560,6 +580,7 @@ typedef struct { nfapi_nr_tdd_table_t tdd_table; nfapi_nr_measurement_config_t measurement_config; nfapi_nr_nfapi_t nfapi_config; + nfapi_nr_pm_list_t pmi_list; } nfapi_nr_config_request_scf_t; @@ -592,24 +613,24 @@ typedef struct { //3.3.4 STOP typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; + nfapi_p4_p5_message_header_t header; + nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_stop_request_t; typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; + nfapi_p4_p5_message_header_t header; + nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_stop_indication_t; typedef enum { - NFAPI_NR_STOP_MSG_INVALID_STATE + NFAPI_NR_STOP_MSG_INVALID_STATE } nfapi_nr_stop_errors_e; //3.3.5 PHY Notifications typedef enum { NFAPI_NR_PHY_API_MSG_OK =0x0, - NFAPI_NR_PHY_API_MSG_INVALID_STATE =0x1, + NFAPI_NR_PHY_API_MSG_INVALID_STATE =0x1, NFAPI_NR_PHY_API_MSG_INVALID_CONFIG =0x2, NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC =0X3, NFAPI_NR_PHY_API_MSG_SLOR_ERR =0X4, @@ -620,7 +641,7 @@ typedef enum { } nfapi_nr_phy_notifications_errors_e; typedef struct { - uint16_t sfn; //0~1023 + uint16_t sfn; //0~1023 uint16_t slot;//0~319 nfapi_nr_phy_msg_type_e msg_id;//Indicate which message received by the PHY has an error. Values taken from Table 3-4. nfapi_nr_phy_notifications_errors_e error_code; @@ -632,42 +653,22 @@ typedef struct { //table 3-32 //? typedef struct { - uint16_t beam_idx; //0~65535 + uint16_t beam_idx; //0~65535 } nfapi_nr_dig_beam_t; typedef struct { - uint16_t dig_beam_weight_Re; + uint16_t dig_beam_weight_Re; uint16_t dig_beam_weight_Im; } nfapi_nr_txru_t; typedef struct { - uint16_t num_dig_beams; //0~65535 + uint16_t num_dig_beams; //0~65535 uint16_t num_txrus; //0~65535 nfapi_nr_dig_beam_t* dig_beam_list; nfapi_nr_txru_t* txru_list; } nfapi_nr_dbt_pdu_t; -//table 3-33 -//? -typedef struct { - uint16_t num_ant_ports; - int16_t precoder_weight_Re; - int16_t precoder_weight_Im; -} nfapi_nr_num_ant_ports_t; - -typedef struct { - uint16_t numLayers; //0~65535 - nfapi_nr_num_ant_ports_t* num_ant_ports_list; -} nfapi_nr_num_layers_t; - -typedef struct { - uint16_t pm_idx; //0~65535 - nfapi_nr_num_layers_t* num_layers_list; //0~65535 - //nfapi_nr_num_ant_ports_t* num_ant_ports_list; -} nfapi_nr_pm_pdu_t; - - // Section 3.4 // Section 3.4.1 slot indication @@ -678,7 +679,7 @@ typedef struct { typedef struct { nfapi_p7_message_header_t header; - uint16_t sfn; //0->1023 + uint16_t sfn; //0->1023 uint16_t slot;//0->319 } nfapi_nr_slot_indication_scf_t; @@ -1441,7 +1442,7 @@ typedef struct { //3.4.5 slot_errors typedef enum { - NFAPI_NR_SLOT_UL_TTI_MSG_INVALID_STATE, + NFAPI_NR_SLOT_UL_TTI_MSG_INVALID_STATE, NFAPI_NR_SLOT_UL_TTI_SFN_OUT_OF_SYNC, NFAPI_NR_SLOT_UL_TTI_MSG_BCH_MISSING, NFAPI_NR_SLOT_UL_TTI_MSG_SLOT_ERR @@ -1449,14 +1450,14 @@ typedef enum { } nfapi_nr_slot_errors_ul_tti_e; typedef enum { - NFAPI_NR_SLOT_DL_TTI_MSG_INVALID_STATE, + NFAPI_NR_SLOT_DL_TTI_MSG_INVALID_STATE, NFAPI_NR_SLOT_DL_TTI_MSG_SLOT_ERR } nfapi_nr_slot_errors_dl_tti_e; typedef enum { - NFAPI_NR_SLOT_UL_DCI_MSG_INVALID_STATE, + NFAPI_NR_SLOT_UL_DCI_MSG_INVALID_STATE, NFAPI_NR_SLOT_UL_DCI_MSG_INVALID_SFN, NFAPI_NR_SLOT_UL_DCI_MSG_UL_DCI_ERR diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 9a83ed801b..06c26b6923 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -99,381 +99,6 @@ void reset_active_stats(PHY_VARS_gNB *gNB, int frame) } } -int init_codebook_gNB(PHY_VARS_gNB *gNB) { - - if(gNB->frame_parms.nb_antennas_tx>1){ - int CSI_RS_antenna_ports = gNB->frame_parms.nb_antennas_tx; - //NR Codebook Generation for codebook type1 SinglePanel - int N1 = gNB->ap_N1; - int N2 = gNB->ap_N2; - //Uniform Planner Array: UPA - // X X X X ... X - // X X X X ... X - // N2 . . . . ... . - // X X X X ... X - // |<-----N1---->| - int x_polarization = gNB->ap_XP; - AssertFatal(CSI_RS_antenna_ports == N1 * N2 * x_polarization, - "Nb of antenna ports at PHY %d does not correspond to what passed down with fapi %d\n", - N1 * N2 * x_polarization, CSI_RS_antenna_ports); - - //Get the uniform planar array parameters - // To be confirmed - int O2 = N2 > 1 ? 4 : 1; //Vertical beam oversampling (1 or 4) - int O1 = CSI_RS_antenna_ports > 2 ? 4 : 1; //Horizontal beam oversampling (1 or 4) - - // num of allowed k1 and k2 according to 5.2.2.2.1-3 and -4 in 38.214 - int K1; - if(N2 == N1 || N1 == 2) - K1 = 2; - else if (N2 == 1) - K1 = 5; - else - K1 = 3; - int K2 = N2 > 1 ? 2 : 1; - - // Generation of codebook Type1 with codebookMode 1 (CSI_RS_antenna_ports < 16) - if (CSI_RS_antenna_ports < 16) { - //Generate DFT vertical beams - //ll: index of a vertical beams vector (represented by i1_1 in TS 38.214) - const int max_l = N1 * O1 + (K1 - 1) * O1; - double complex v[max_l][N1]; - for (int ll = 0; ll < max_l; ll++) { //i1_1 - for (int nn = 0; nn < N1; nn++) { - v[ll][nn] = cexp(I * (2 * M_PI * nn * ll) / (N1 * O1)); - LOG_D(PHY,"v[%d][%d] = %f +j %f\n", ll, nn, creal(v[ll][nn]), cimag(v[ll][nn])); - } - } - //Generate DFT Horizontal beams - //mm: index of a Horizontal beams vector (represented by i1_2 in TS 38.214) - const int max_m = N2 * O2 + (K2 - 1) * O2; - double complex u[max_m][N2]; - for (int mm = 0; mm < max_m; mm++) { //i1_2 - for (int nn = 0; nn < N2; nn++) { - u[mm][nn] = cexp(I * (2 * M_PI * nn * mm) / (N2 * O2)); - LOG_D(PHY,"u[%d][%d] = %f +j %f\n", mm, nn, creal(u[mm][nn]), cimag(u[mm][nn])); - } - } - //Generate co-phasing angles - //i_2: index of a co-phasing vector - //i1_1, i1_2, and i_2 are reported from UEs - double complex theta_n[4]; - for (int nn = 0; nn < 4; nn++) { - theta_n[nn] = cexp(I * M_PI * nn / 2); - LOG_D(PHY,"theta_n[%d] = %f +j %f\n", nn, creal(theta_n[nn]), cimag(theta_n[nn])); - } - //Kronecker product v_lm - double complex v_lm[max_l][max_m][N2 * N1]; - //v_ll_mm_codebook denotes the elements of a precoding matrix W_i1,1_i_1,2 - for(int ll = 0; ll < max_l; ll++) { //i_1_1 - for (int mm = 0; mm < max_m; mm++) { //i_1_2 - for (int nn1 = 0; nn1 < N1; nn1++) { - for (int nn2 = 0; nn2 < N2; nn2++) { - v_lm[ll][mm][nn1 * N2 + nn2] = v[ll][nn1] * u[mm][nn2]; - LOG_D(PHY,"v_lm[%d][%d][%d] = %f +j %f\n",ll, mm, nn1 * N2 + nn2, creal(v_lm[ll][mm][nn1*N2+nn2]), cimag(v_lm[ll][mm][nn1*N2+nn2])); - } - } - } - } - - int max_mimo_layers = (CSI_RS_antenna_ports < NR_MAX_NB_LAYERS) ? CSI_RS_antenna_ports : NR_MAX_NB_LAYERS; - AssertFatal(max_mimo_layers <= 4, "Max number of layers supported is 4\n"); - - gNB->nr_mimo_precoding_matrix = (int32_t ***)malloc16(max_mimo_layers * sizeof(int32_t **)); - int32_t ***mat = gNB->nr_mimo_precoding_matrix; - double complex res_code; - - //Table 5.2.2.2.1-5: - //Codebook for 1-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS - gNB->pmiq_size[0] = N1*O1*N2*O2*4+1; - mat[0] = (int32_t **)malloc16(gNB->pmiq_size[0]*sizeof(int32_t *)); - - //pmi=0 corresponds to unit matrix - mat[0][0] = (int32_t *)calloc(2*N1*N2,sizeof(int32_t)); - for(int j_col=0; j_col<1; j_col++) { //1 layer - for (int i_rows=0; i_rows<2*N1*N2; i_rows++) { //2-x polarized antenna - if(j_col==i_rows) { - mat[0][0][i_rows+j_col] = 0x7fff; - } - } - } - - for(int ll=0; ll0) - ((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15 - if (cimag(res_code)>0) - ((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15 - LOG_D(PHY, "1 Layer Precoding Matrix[0][pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n", - pmiq, len, creal(res_code), cimag(res_code),((short*) &mat[0][pmiq][len])[0],((short*) &mat[0][pmiq][len])[1]); - } - - for(int len=N1*N2; len<2*N1*N2; len++) { - res_code=sqrt(1/(double)CSI_RS_antenna_ports)*theta_n[nn]*v_lm[ll][mm][len-N1*N2]; - if (creal(res_code)>0) - ((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15 - if (cimag(res_code)>0) - ((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15 - LOG_D(PHY, "1 Layer Precoding Matrix[0][pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n", - pmiq, len, creal(res_code), cimag(res_code),((short*) &mat[0][pmiq][len])[0],((short*) &mat[0][pmiq][len])[1]); - } - } - } - } - - int llc = 0; - int mmc = 0; - double complex phase_sign = 0; - //Table 5.2.2.2.1-6: - //Codebook for 2-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS - //Compute the code book size for generating 2 layers out of Tx antenna ports - - //pmi_size is computed as follows - gNB->pmiq_size[1] = 1 + (2 * N1 * O1 * N2 * O2 * K1 * K2); - mat[1] = (int32_t **)malloc16(gNB->pmiq_size[1] * sizeof(int32_t *)); - - //pmi=0 corresponds to unit matrix - mat[1][0] = (int32_t *)calloc((2 * N1 * N2) * 2, sizeof(int32_t)); - for(int j_col=0; j_col<2; j_col++) { //2 layers - for (int i_rows=0; i_rows<2*N1*N2; i_rows++) { //2-x polarized antenna - if(j_col==i_rows) { - mat[1][0][i_rows*2+j_col] = 0x7fff; - } - } - } - - //pmi=1,...,pmi_size, we construct - int pmiq = 0; - for(int ll = 0; ll < N1 * O1; ll++) { //i_1_1 - for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2 - for(int k1 = 0; k1 < K1; k1++) { - for (int k2 = 0; k2 < K2; k2++) { - for (int nn = 0; nn < 2; nn++) { // i_2 - pmiq += 1; - mat[1][pmiq] = (int32_t *)malloc16((2 * N1 * N2) * 2 * sizeof(int32_t)); - LOG_D(PHY, "layer 2 Codebook pmiq = %d\n", pmiq); - for(int j_col = 0; j_col < 2; j_col++) { - if (j_col == 0) { - llc = ll; - mmc = mm; - phase_sign = 1; - } - if (j_col == 1) { - llc = ll + k1 * O1; - mmc = mm + k2 * O2; - phase_sign = -1; - } - for (int i_rows=0; i_rows0) - ((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15 - if (cimag(res_code)>0) - ((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15 - LOG_D(PHY, "2 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", - pmiq, i_rows, j_col, creal(res_code), cimag(res_code), ((short*) &mat[1][pmiq][i_rows*2+j_col])[0], ((short*) &mat[1][pmiq][i_rows*2+j_col])[1]); - } - for (int i_rows=N1*N2; i_rows<2*N1*N2; i_rows++) { - res_code=sqrt(1/(double)(2*CSI_RS_antenna_ports))*(phase_sign)*theta_n[nn]*v_lm[llc][mmc][i_rows-N1*N2]; - if (creal(res_code)>0) - ((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15 - if (cimag(res_code)>0) - ((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15 - LOG_D(PHY, "2 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", - pmiq, i_rows, j_col, creal(res_code), cimag(res_code), ((short*) &mat[1][pmiq][i_rows*2+j_col])[0], ((short*) &mat[1][pmiq][i_rows*2+j_col])[1]); - } - } - } - } - } - } - } - - //Table 5.2.2.2.1-7: - //Codebook for 3-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS - if(max_mimo_layers >= 3) { - - //pmi_size is computed as follows - gNB->pmiq_size[2] = 1 + (2 * N1 * O1 * N2 * O2 * K1 * K2); - mat[2] = (int32_t **)malloc16(gNB->pmiq_size[2] * sizeof(int32_t *)); - //pmi=0 corresponds to unit matrix - mat[2][0] = (int32_t *)calloc(2 * N1 * N2 * 3, sizeof(int32_t)); - for(int j_col = 0; j_col < 3; j_col++) { //3 layers - for (int i_rows = 0; i_rows < 2 * N1 * N2; i_rows++) { //2-x polarized antenna - if(j_col == i_rows) { - mat[2][0][i_rows * 3 + j_col] = 0x7fff; - } - } - } - - pmiq = 0; - //pmi=1,...,pmi_size are computed as follows - for(int ll = 0; ll < N1 * O1; ll++) { //i_1_1 - for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2 - for(int k1 = 0; k1 < K1; k1++) { - for (int k2 = 0; k2 < K2; k2++) { - for (int nn = 0; nn < 2; nn++) { // i_2 - pmiq += 1; - mat[2][pmiq] = (int32_t *)malloc16((2 * N1 * N2 * 3) * sizeof(int32_t)); - LOG_D(PHY, "layer 3 Codebook pmiq = %d\n",pmiq); - for(int j_col = 0; j_col < 3; j_col++) { - if (j_col == 0) { - llc = ll; - mmc = mm; - phase_sign = 1; - } - if (j_col==1) { - llc = ll + k1 * O1; - mmc = mm + k2 * O2; - phase_sign = 1; - } - if (j_col==2) { - llc = ll; - mmc = mm; - phase_sign = -1; - } - for (int i_rows=0; i_rows0) - ((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15 - if (cimag(res_code)>0) - ((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15 - LOG_D(PHY, "3 Layer Precoding Matrix[2][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", - pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[2][pmiq][i_rows*3+j_col])[0],((short*) &mat[2][pmiq][i_rows*3+j_col])[1]); - } - for (int i_rows=N1*N2; i_rows<2*N1*N2; i_rows++) { - res_code=sqrt(1/(double)(3*CSI_RS_antenna_ports))*(phase_sign)*theta_n[nn]*v_lm[llc][mmc][i_rows-N1*N2]; - if (creal(res_code)>0) - ((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15 - if (cimag(res_code)>0) - ((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15 - LOG_D(PHY, "3 Layer Precoding Matrix[2][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", - pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[2][pmiq][i_rows*3+j_col])[0],((short*) &mat[2][pmiq][i_rows*3+j_col])[1]); - } - } - } - } - } - } - } - } - - //Table 5.2.2.2.1-8: - //Codebook for 4-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS - if(max_mimo_layers >= 4) { - //pmi_size is computed as follows - gNB->pmiq_size[3] = 1 + (2 * N1 * O1 * N2 * O2 * K1 * K2); - mat[3] = (int32_t **)malloc16(gNB->pmiq_size[3] * sizeof(int32_t *)); - //pmi=0 corresponds to unit matrix - mat[3][0] = (int32_t *)calloc((2 * N1 * N2 * 4), sizeof(int32_t)); - for(int j_col = 0; j_col < 4; j_col++) { //4 layers - for (int i_rows = 0; i_rows < 2 * N1 * N2; i_rows++) { //2-x polarized antenna - if(j_col == i_rows) { - mat[3][0][i_rows * 4 + j_col] = 0x7fff; - } - } - } - - pmiq = 0; - //pmi=1,...,pmi_size are computed as follows - for(int ll = 0; ll < N1 * O1; ll++) { //i_1_1 - for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2 - for(int k1 = 0; k1 < K1; k1++) { - for (int k2 = 0; k2 < K2; k2++) { - for (int nn = 0; nn < 2; nn++) { // i_2 - pmiq += 1; - mat[3][pmiq] = (int32_t *)malloc16((2*N1*N2)*4*sizeof(int32_t)); - LOG_D(PHY, "layer 4 pmiq = %d\n",pmiq); - for(int j_col=0; j_col<4; j_col++) { - if (j_col==0) { - llc = ll; - mmc = mm; - phase_sign = 1; - } - if (j_col==1) { - llc = ll + k1 * O1; - mmc = mm + k2 * O2; - phase_sign = 1; - } - if (j_col==2) { - llc = ll; - mmc = mm; - phase_sign = -1; - } - if (j_col==3) { - llc = ll + k1 * O1; - mmc = mm + k2 * O2; - phase_sign = -1; - } - for (int i_rows=0; i_rows0) - ((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15 - if (cimag(res_code)>0) - ((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15 - LOG_D(PHY, "4 Layer Precoding Matrix[3][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", - pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[3][pmiq][i_rows*4+j_col])[0],((short*) &mat[3][pmiq][i_rows*4+j_col])[1]); - } - for (int i_rows=N1*N2; i_rows<2*N1*N2; i_rows++) { - res_code=sqrt(1/(double)(4*CSI_RS_antenna_ports))*(phase_sign)*theta_n[nn]*v_lm[llc][mmc][i_rows-N1*N2]; - if (creal(res_code)>0) - ((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15 - if (cimag(res_code)>0) - ((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15 - else - ((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15 - LOG_D(PHY, "4 Layer Precoding Matrix[3][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", - pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[3][pmiq][i_rows*4+j_col])[0],((short*) &mat[3][pmiq][i_rows*4+j_col])[1]); - } - } - } - } - } - } - } - } - } - else - AssertFatal(false, "Max number of antenna ports supported is 16\n"); - } - return 0; -} - // A global var to reduce the changes size ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0}; @@ -509,8 +134,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) if (gNB->ldpc_offload_flag) load_LDPClib("_t2", &ldpc_interface_offload); gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB; - - init_codebook_gNB(gNB); init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table); // PBCH DMRS gold sequences generation @@ -698,23 +321,15 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) void phy_free_nr_gNB(PHY_VARS_gNB *gNB) { - NR_DL_FRAME_PARMS* const fp = &gNB->frame_parms; + NR_DL_FRAME_PARMS* const fp = &gNB->frame_parms; const int Ptx = gNB->gNB_config.carrier_config.num_tx_ant.value; const int Prx = gNB->gNB_config.carrier_config.num_rx_ant.value; const int max_ul_mimo_layers = 4; // taken from phy_init_nr_gNB() const int n_buf = Prx * max_ul_mimo_layers; - PHY_MEASUREMENTS_gNB *meas=&gNB->measurements; + + PHY_MEASUREMENTS_gNB *meas = &gNB->measurements; free_and_zero(meas->n0_subband_power); free_and_zero(meas->n0_subband_power_dB); - int max_dl_mimo_layers =(fp->nb_antennas_txnb_antennas_tx : NR_MAX_NB_LAYERS; - if (fp->nb_antennas_tx>1) { - for (int nl = 0; nl < max_dl_mimo_layers; nl++) { - for(int size = 0; size < gNB->pmiq_size[nl]; size++) - free_and_zero(gNB->nr_mimo_precoding_matrix[nl][size]); - free_and_zero(gNB->nr_mimo_precoding_matrix[nl]); - } - free_and_zero(gNB->nr_mimo_precoding_matrix); - } uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs; for (int slot = 0; slot < fp->slots_per_frame; slot++) { diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 92a1d94fd4..e5f28d1c50 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -703,13 +703,17 @@ c16_t nr_layer_precoder_cm(int n_layers, int n_symbols, int symSz, c16_t datatx_F_precoding[n_layers][n_symbols][symSz], - c16_t *prec_matrix, + int ap, + nfapi_nr_pm_pdu_t *pmi_pdu, int symbol, int offset) { c16_t precodatatx_F = {0}; - for (int al = 0; al < n_layers; al++) - precodatatx_F = c16maddShift(datatx_F_precoding[al][symbol][offset], prec_matrix[al], precodatatx_F, 15); + for (int al = 0; al < n_layers; al++) { + nfapi_nr_pm_weights_t *w = &pmi_pdu->weights[al][ap]; + c16_t prec_weight = {.r = w->precoder_weight_Re, .i = w->precoder_weight_Im}; + precodatatx_F = c16maddShift(datatx_F_precoding[al][symbol][offset], prec_weight, precodatatx_F, 15); + } return precodatatx_F; } @@ -717,69 +721,77 @@ void nr_layer_precoder_simd(const int n_layers, const int n_symbols, const int symSz, const c16_t txdataF_res_mapped[n_layers][n_symbols][symSz], - const c16_t prec_matrix[n_layers], + const int ant, + const nfapi_nr_pm_pdu_t *pmi_pdu, const int symbol, const int sc_offset, const int re_cnt, c16_t *txdataF_precoded) { uint32_t sc = sc_offset; - + c16_t prec_weight = {0}; // For x86, use 256 SIMD for every 8 RE and 128 SIMD for last 4 RE // For aarch64, use 128 SIMD for every 4 RE // 256 SIMD: Do 8 RE in one iteration, 3 iterations for 2 RB - #ifdef __AVX2__ - const uint32_t re_cnt_align8 = re_cnt & ~7; - for(; scweights[nl][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[nl][ant].precoder_weight_Im; - // Rearrange precoding matrix weight to match complex multiplication and broadcast it to match SIMD size - const simde__m256i w_c = simde_mm256_set1_epi32(c16toI32(c16conj(prec_matrix[nl]))); // broadcast conjugate of w - const simde__m256i w_s = simde_mm256_set1_epi32(c16toI32(c16swap(prec_matrix[nl]))); // broadcast swapped real and img of w + const simde__m256i x = simde_mm256_loadu_epi32(&txdataF_res_mapped[nl][symbol][sc]); - // Multiplication and shift - const simde__m256i reals = simde_mm256_srai_epi32(simde_mm256_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 - const simde__m256i imags = simde_mm256_slli_epi32(simde_mm256_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 + // Rearrange precoding matrix weight to match complex multiplication and broadcast it to match SIMD size + const simde__m256i w_c = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - // Re-arrange to match c16_t format - const simde__m256i produ = simde_mm256_blend_epi16(reals, imags, 0xAA); + // Multiplication and shift + const simde__m256i reals = simde_mm256_srai_epi32(simde_mm256_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 + const simde__m256i imags = simde_mm256_slli_epi32(simde_mm256_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 - // Accumulate the product - y = simde_mm256_adds_epi16(y, produ); - } - // Store the result to txdataF - simde_mm256_storeu_si256(&txdataF_precoded[sc], y); + // Re-arrange to match c16_t format + const simde__m256i produ = simde_mm256_blend_epi16(reals, imags, 0xAA); + + // Accumulate the product + y = simde_mm256_adds_epi16(y, produ); } - #endif + // Store the result to txdataF + simde_mm256_storeu_si256(&txdataF_precoded[sc], y); + } +#endif // 128 SIMD: Do 4 RE in one iteration, 3 iterations for 1 RB const uint32_t re_cnt_align4 = re_cnt & ~3; - for(; scweights[nl][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[nl][ant].precoder_weight_Im; + const simde__m128i x = simde_mm_loadu_epi32(&txdataF_res_mapped[nl][symbol][sc]); // Rearrange precoding matrix weight to match complex multiplication and broadcast it to match SIMD size - const simde__m128i w_c = simde_mm_set1_epi32(c16toI32(c16conj(prec_matrix[nl]))); // broadcast conjugate of w - const simde__m128i w_s = simde_mm_set1_epi32(c16toI32(c16swap(prec_matrix[nl]))); // broadcast swapped real and img of w + const simde__m128i w_c = simde_mm_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m128i w_s = simde_mm_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w // Multiplication and shift const simde__m128i reals = simde_mm_srai_epi32(simde_mm_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index c129369221..7196994726 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -138,11 +138,13 @@ void apply_nr_rotation_RX(NR_DL_FRAME_PARMS *frame_parms, @param[in] n_layers, number of DLSCH layers */ int nr_layer_precoder(int16_t **datatx_F_precoding, const char *prec_matrix, uint8_t n_layers, int32_t re_offset); + c16_t nr_layer_precoder_cm(int n_layers, int n_symbols, int symSz, c16_t datatx_F_precoding[n_layers][n_symbols][symSz], - c16_t *prec_matrix, + int ap, + nfapi_nr_pm_pdu_t *pmi_pdu, int symbol, int offset); @@ -156,7 +158,8 @@ void nr_layer_precoder_simd(const int n_layers, const int n_symbols, const int symSz, const c16_t txdataF_res_mapped[n_layers][n_symbols][symSz], - const c16_t prec_matrix[n_layers], + const int ant, + const nfapi_nr_pm_pdu_t *pmi_pdu, const int symbol, const int sc_offset, const int re_cnt, diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 51a2059586..514f284e4c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -535,58 +535,52 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) } } else { // non-unitary Precoding - if(frame_parms->nb_antennas_tx == 1){ // no precoding matrix defined - memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], - &txdataF_precoding[ant][l_symbol][subCarrier], - re_cnt * sizeof(**txdataF)); + AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n"); + //get the precoding matrix weights: + nfapi_nr_pm_pdu_t *pmi_pdu = &gNB->gNB_config.pmi_list.pmi_pdu[pmi - 1]; // pmi 0 is identity matrix + AssertFatal(pmi == pmi_pdu->pm_idx, "PMI %d doesn't match to the one in precoding matrix %d\n", + pmi, pmi_pdu->pm_idx); + AssertFatal(ant < pmi_pdu->num_ant_ports, "Antenna port index %d exceeds precoding matrix AP size %d\n", + ant, pmi_pdu->num_ant_ports); + AssertFatal(rel15->nrOfLayers == pmi_pdu->numLayers, "Number of layers %d doesn't match to the one in precoding matrix %d\n", + rel15->nrOfLayers, pmi_pdu->numLayers); + if((subCarrier + re_cnt) < frame_parms->ofdm_symbol_size){ // within ofdm_symbol_size, use SIMDe + nr_layer_precoder_simd(rel15->nrOfLayers, + NR_SYMBOLS_PER_SLOT, + frame_parms->ofdm_symbol_size, + txdataF_precoding, + ant, + pmi_pdu, + l_symbol, + subCarrier, + re_cnt, + &txdataF[ant][txdataF_offset_per_symbol]); subCarrier += re_cnt; - if (subCarrier >= frame_parms->ofdm_symbol_size) { - subCarrier -= frame_parms->ofdm_symbol_size; - } } - else { // precoding with more than 1 tx - //get the precoding matrix weights: - c16_t **mat = (c16_t**)gNB->nr_mimo_precoding_matrix[rel15->nrOfLayers - 1]; - //i_row =0,...,dl_antenna_port - //j_col =0,...,nrOfLayers - //mat[pmi][i_rows*2+j_col] - c16_t *W_prec = &mat[pmi][ant * rel15->nrOfLayers]; - if((subCarrier + re_cnt) < frame_parms->ofdm_symbol_size){ // within ofdm_symbol_size, use SIMDe - nr_layer_precoder_simd(rel15->nrOfLayers, - NR_SYMBOLS_PER_SLOT, - frame_parms->ofdm_symbol_size, - txdataF_precoding, - W_prec, - l_symbol, - subCarrier, - re_cnt, - &txdataF[ant][txdataF_offset_per_symbol]); - subCarrier += re_cnt; - } - else{ // crossing ofdm_symbol_size, use simple arithmetic operations - for (int i = 0; i < re_cnt; i++) { - txdataF[ant][txdataF_offset_per_symbol + subCarrier] = - nr_layer_precoder_cm(rel15->nrOfLayers, - NR_SYMBOLS_PER_SLOT, - frame_parms->ofdm_symbol_size, - txdataF_precoding, - W_prec, - l_symbol, - subCarrier); + else{ // crossing ofdm_symbol_size, use simple arithmetic operations + for (int i = 0; i < re_cnt; i++) { + txdataF[ant][txdataF_offset_per_symbol + subCarrier] = + nr_layer_precoder_cm(rel15->nrOfLayers, + NR_SYMBOLS_PER_SLOT, + frame_parms->ofdm_symbol_size, + txdataF_precoding, + ant, + pmi_pdu, + l_symbol, + subCarrier); #ifdef DEBUG_DLSCH_MAPPING - printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n", - ant, - symbol, - subCarrier, - txdataF[ant][l_symbol * frame_parms->ofdm_symbol_size + subCarrier + txdataF_offset].r, - txdataF[ant][l_symbol * frame_parms->ofdm_symbol_size + subCarrier + txdataF_offset].i); + printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n", + ant, + symbol, + subCarrier, + txdataF[ant][l_symbol * frame_parms->ofdm_symbol_size + subCarrier + txdataF_offset].r, + txdataF[ant][l_symbol * frame_parms->ofdm_symbol_size + subCarrier + txdataF_offset].i); #endif - if (++subCarrier >= frame_parms->ofdm_symbol_size) { - subCarrier -= frame_parms->ofdm_symbol_size; - } + if (++subCarrier >= frame_parms->ofdm_symbol_size) { + subCarrier -= frame_parms->ofdm_symbol_size; } - } // else{ // crossing ofdm_symbol_size, use simple arithmetic operations - } // else { // precoding with more than 1 tx + } + } // else{ // crossing ofdm_symbol_size, use simple arithmetic operations } // else { // non-unitary Precoding rb += rb_step; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 20985cb08a..d66a1e4520 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -619,13 +619,6 @@ typedef struct PHY_VARS_gNB_s { /// PDSCH DMRS sequence uint32_t ****nr_gold_pdsch_dmrs; - /// PDSCH codebook I precoding LUTs - /// first dimension: Rank number [0,...,noOfLayers-1[ - /// second dimension: PMI [0,...,CodeSize-1[ - /// third dimension: [i_rows*noOfLayers+j_col], i_rows=0,...pdsch_AntennaPorts-1 and j_col=0,...,noOfLayers-1 - int32_t ***nr_mimo_precoding_matrix; - int pmiq_size[NR_MAX_NB_LAYERS]; - /// PUSCH DMRS uint32_t ****nr_gold_pusch_dmrs; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index c5af8b8415..c4d6e2ff91 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -79,7 +79,6 @@ #define NR_MAX_PDCCH_AGG_LEVEL 16 // 3GPP TS 38.211 V15.8 Section 7.3.2 Table 7.3.2.1-1: Supported PDCCH aggregation levels -#define NR_MAX_NB_LAYERS 4 // 8 #define NR_MAX_NB_PORTS 32 #define NR_MAX_PDSCH_TBS 3824 diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 30e84a8837..f60c27ded8 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -223,35 +223,21 @@ nrUE_params_t *get_nrUE_params(void) { } -void validate_input_pmi(nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, int nrOfLayers, int pmi) +void validate_input_pmi(nfapi_nr_config_request_scf_t *gNB_config, + nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, + int nrOfLayers, + int pmi) { if (pmi == 0) return; + nfapi_nr_pm_pdu_t *pmi_pdu = &gNB_config->pmi_list.pmi_pdu[pmi - 1]; // pmi 0 is identity matrix + AssertFatal(pmi == pmi_pdu->pm_idx, "PMI %d doesn't match to the one in precoding matrix %d\n", pmi, pmi_pdu->pm_idx); + AssertFatal(nrOfLayers == pmi_pdu->numLayers, "Number of layers %d doesn't match to the one in precoding matrix %d for PMI %d\n", + nrOfLayers, pmi_pdu->numLayers, pmi); int num_antenna_ports = pdsch_AntennaPorts.N1 * pdsch_AntennaPorts.N2 * pdsch_AntennaPorts.XP; - int N1 = pdsch_AntennaPorts.N1; - int N2 = pdsch_AntennaPorts.N2; - int O1 = N1 > 1 ? 4 : 1; - int O2 = N2 > 1 ? 4 : 1; - int K1, K2; - if (num_antenna_ports > 2) - get_K1_K2(N1, N2, &K1, &K2); - else { - K1 = 1; K2 = 1; - } - int num_pmi = 1; // pmi = 0 is the identity matrix - switch (nrOfLayers) { - case 1 : - num_pmi += N1 * O1 * N2 * O2 * 4; - AssertFatal(pmi < num_pmi, "Input PMI index %d exceeds the limit of configured matrices %d for %d layers\n", pmi, num_pmi, nrOfLayers); - return; - case 2 : - num_pmi += N1 * O1 * N2 * O2 * K1 * K2 * 2; - AssertFatal(pmi < num_pmi, "Input PMI index %d exceeds the limit of conigured matrices %d for %d layers\n", pmi, num_pmi, nrOfLayers); - break; - default : - AssertFatal(false, "Precoding with more than 2 nrOfLayers not yet supported\n"); - } + AssertFatal(num_antenna_ports == pmi_pdu->num_ant_ports, "Configured antenna ports %d does not match precoding matrix AP size %d for PMI %d\n", + num_antenna_ports, pmi_pdu->num_ant_ports, pmi); } @@ -709,7 +695,7 @@ int main(int argc, char **argv) gNB->ap_N2 = pdsch_AntennaPorts.N2; gNB->ap_XP = pdsch_AntennaPorts.XP; - validate_input_pmi(pdsch_AntennaPorts, g_nrOfLayers, g_pmi); + validate_input_pmi(&gNB_mac->config[0], pdsch_AntennaPorts, g_nrOfLayers, g_pmi); NR_UE_NR_Capability_t* UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t)); prepare_sim_uecap(UE_Capability_nr,scc,mu, diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 3b738eed28..b989a5c1c6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -50,11 +50,319 @@ #include "../../../../nfapi/oai_integration/vendor_ext.h" /* Softmodem params */ #include "executables/softmodem-common.h" +#include extern RAN_CONTEXT_t RC; //extern int l2_init_gNB(void); extern uint8_t nfapi_mode; +c16_t convert_precoder_weight(double complex c_in) +{ + double cr = creal(c_in) * 32768 + 0.5; + if (cr < 0) + cr -= 1; + double ci = cimag(c_in) * 32768 + 0.5; + if (ci < 0) + ci -= 1; + return (c16_t) {.r = (short)cr, .i = (short)ci}; +} + +nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPorts_t antenna_ports) +{ + int num_antenna_ports = antenna_ports.N1 * antenna_ports.N2 * antenna_ports.XP; + if (num_antenna_ports < 2) + return (nfapi_nr_pm_list_t) {0}; + + //NR Codebook Generation for codebook type1 SinglePanel + int N1 = antenna_ports.N1; + int N2 = antenna_ports.N2; + //Uniform Planner Array: UPA + // X X X X ... X + // X X X X ... X + // N2 . . . . ... . + // X X X X ... X + // |<-----N1---->| + + //Get the uniform planar array parameters + // To be confirmed + int O2 = N2 > 1 ? 4 : 1; //Vertical beam oversampling (1 or 4) + int O1 = num_antenna_ports > 2 ? 4 : 1; //Horizontal beam oversampling (1 or 4) + + int K1, K2; + get_K1_K2(N1, N2, &K1, &K2); + + int max_mimo_layers = (num_antenna_ports < NR_MAX_NB_LAYERS) ? num_antenna_ports : NR_MAX_NB_LAYERS; + AssertFatal(max_mimo_layers <= 4, "Max number of layers supported is 4\n"); + + gNB->precoding_matrix_size[0] = N1 * O1 * N2 * O2 * 4; + nfapi_nr_pm_list_t mat = {.num_pm_idx = gNB->precoding_matrix_size[0]}; + for (int i = 1; i < max_mimo_layers; i++) { + gNB->precoding_matrix_size[i] = 2 * N1 * O1 * N2 * O2 * K1 * K2; + mat.num_pm_idx += gNB->precoding_matrix_size[i]; + } + + nfapi_nr_pm_pdu_t *pmi_pdu = malloc16(mat.num_pm_idx * sizeof(*pmi_pdu)); + AssertFatal(pmi_pdu != NULL, "out of memory\n"); + mat.pmi_pdu = pmi_pdu; + + // Generation of codebook Type1 with codebookMode 1 (num_antenna_ports < 16) + if (num_antenna_ports < 16) { + //Generate DFT vertical beams + //ll: index of a vertical beams vector (represented by i1_1 in TS 38.214) + const int max_l = N1 * O1 + (K1 - 1) * O1; + double complex v[max_l][N1]; + for (int ll = 0; ll < max_l; ll++) { //i1_1 + for (int nn = 0; nn < N1; nn++) { + v[ll][nn] = cexp(I * (2 * M_PI * nn * ll) / (N1 * O1)); + LOG_D(PHY,"v[%d][%d] = %f +j %f\n", ll, nn, creal(v[ll][nn]), cimag(v[ll][nn])); + } + } + //Generate DFT Horizontal beams + //mm: index of a Horizontal beams vector (represented by i1_2 in TS 38.214) + const int max_m = N2 * O2 + (K2 - 1) * O2; + double complex u[max_m][N2]; + for (int mm = 0; mm < max_m; mm++) { //i1_2 + for (int nn = 0; nn < N2; nn++) { + u[mm][nn] = cexp(I * (2 * M_PI * nn * mm) / (N2 * O2)); + LOG_D(PHY,"u[%d][%d] = %f +j %f\n", mm, nn, creal(u[mm][nn]), cimag(u[mm][nn])); + } + } + //Generate co-phasing angles + //i_2: index of a co-phasing vector + //i1_1, i1_2, and i_2 are reported from UEs + double complex theta_n[4]; + for (int nn = 0; nn < 4; nn++) { + theta_n[nn] = cexp(I * M_PI * nn / 2); + LOG_D(PHY,"theta_n[%d] = %f +j %f\n", nn, creal(theta_n[nn]), cimag(theta_n[nn])); + } + //Kronecker product v_lm + double complex v_lm[max_l][max_m][N2 * N1]; + //v_ll_mm_codebook denotes the elements of a precoding matrix W_i1,1_i_1,2 + for(int ll = 0; ll < max_l; ll++) { //i_1_1 + for (int mm = 0; mm < max_m; mm++) { //i_1_2 + for (int nn1 = 0; nn1 < N1; nn1++) { + for (int nn2 = 0; nn2 < N2; nn2++) { + v_lm[ll][mm][nn1 * N2 + nn2] = v[ll][nn1] * u[mm][nn2]; + LOG_D(PHY,"v_lm[%d][%d][%d] = %f +j %f\n",ll, mm, nn1 * N2 + nn2, creal(v_lm[ll][mm][nn1*N2+nn2]), cimag(v_lm[ll][mm][nn1*N2+nn2])); + } + } + } + } + + double complex res_code; + + //Table 5.2.2.2.1-5: + int pmiq = 0; + //Codebook for 1-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS + for(int ll = 0; ll < N1 * O1; ll++) { //i_1_1 + for (int mm = 0; mm < N2 * O2; mm++) { //i_1_2 + for (int nn = 0; nn < 4; nn++) { + pmiq = ll * N2 * O2 * 4 + mm * 4 + nn; + pmi_pdu[pmiq].pm_idx = pmiq + 1; // index 0 is the identity matrix + pmi_pdu[pmiq].numLayers = 1; + pmi_pdu[pmiq].num_ant_ports = num_antenna_ports; + LOG_D(PHY, "layer 1 Codebook pmiq = %d\n", pmiq); + for (int len = 0; len < N1 * N2; len++) { + nfapi_nr_pm_weights_t *weights = &pmi_pdu[pmiq].weights[0][len]; + res_code = sqrt( 1 /(double)num_antenna_ports) * v_lm[ll][mm][len]; + c16_t precoder_weight = convert_precoder_weight(res_code); + weights->precoder_weight_Re = precoder_weight.r; + weights->precoder_weight_Im = precoder_weight.i; + LOG_D(PHY, "1 Layer Precoding Matrix[0][pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n", + pmiq, len, creal(res_code), cimag(res_code), weights->precoder_weight_Re, weights->precoder_weight_Im); + } + + for(int len = N1 * N2; len < 2 * N1 * N2; len++) { + nfapi_nr_pm_weights_t *weights = &pmi_pdu[pmiq].weights[0][len]; + res_code = sqrt(1 / (double)num_antenna_ports) * theta_n[nn] * v_lm[ll][mm][len-N1*N2]; + c16_t precoder_weight = convert_precoder_weight(res_code); + weights->precoder_weight_Re = precoder_weight.r; + weights->precoder_weight_Im = precoder_weight.i; + LOG_D(PHY, "1 Layer Precoding Matrix[0][pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n", + pmiq, len, creal(res_code), cimag(res_code), weights->precoder_weight_Re, weights->precoder_weight_Im); + } + } + } + } + int llc = 0; + int mmc = 0; + double complex phase_sign = 0; + //Table 5.2.2.2.1-6: + //Codebook for 2-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS + //Compute the code book size for generating 2 layers out of Tx antenna ports + + //pmi=1,...,pmi_size, we construct + for(int ll = 0; ll < N1 * O1; ll++) { //i_1_1 + for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2 + for(int k1 = 0; k1 < K1; k1++) { + for (int k2 = 0; k2 < K2; k2++) { + for (int nn = 0; nn < 2; nn++) { // i_2 + pmiq ++; + pmi_pdu[pmiq].pm_idx = pmiq + 1; // index 0 is the identity matrix + pmi_pdu[pmiq].numLayers = 2; + pmi_pdu[pmiq].num_ant_ports = num_antenna_ports; + LOG_D(PHY, "layer 2 Codebook pmiq = %d\n", pmiq); + for(int j_col = 0; j_col < 2; j_col++) { + if (j_col == 0) { + llc = ll; + mmc = mm; + phase_sign = 1; + } + if (j_col == 1) { + llc = ll + k1 * O1; + mmc = mm + k2 * O2; + phase_sign = -1; + } + for (int i_rows = 0; i_rows < N1 * N2; i_rows++) { + nfapi_nr_pm_weights_t *weights = &pmi_pdu[pmiq].weights[j_col][i_rows]; + res_code = sqrt(1 / (double)(2 * num_antenna_ports)) * v_lm[llc][mmc][i_rows]; + c16_t precoder_weight = convert_precoder_weight(res_code); + weights->precoder_weight_Re = precoder_weight.r; + weights->precoder_weight_Im = precoder_weight.i; + LOG_D(PHY, "2 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", + pmiq, i_rows, j_col, creal(res_code), cimag(res_code), weights->precoder_weight_Re, weights->precoder_weight_Im); + } + for (int i_rows = N1 * N2; i_rows < 2 * N1 * N2; i_rows++) { + nfapi_nr_pm_weights_t *weights = &pmi_pdu[pmiq].weights[j_col][i_rows]; + res_code = sqrt(1 / (double)(2 * num_antenna_ports)) * (phase_sign) * theta_n[nn] * v_lm[llc][mmc][i_rows - N1 * N2]; + c16_t precoder_weight = convert_precoder_weight(res_code); + weights->precoder_weight_Re = precoder_weight.r; + weights->precoder_weight_Im = precoder_weight.i; + LOG_D(PHY, "2 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", + pmiq, i_rows, j_col, creal(res_code), cimag(res_code), weights->precoder_weight_Re, weights->precoder_weight_Im); + } + } + } + } + } + } + } + + if(max_mimo_layers < 3) + return mat; + + //Table 5.2.2.2.1-7: + //Codebook for 3-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS + + //pmi=1,...,pmi_size are computed as follows + for(int ll = 0; ll < N1 * O1; ll++) { //i_1_1 + for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2 + for(int k1 = 0; k1 < K1; k1++) { + for (int k2 = 0; k2 < K2; k2++) { + for (int nn = 0; nn < 2; nn++) { // i_2 + pmiq ++; + pmi_pdu[pmiq].pm_idx = pmiq + 1; // index 0 is the identity matrix + pmi_pdu[pmiq].numLayers = 3; + pmi_pdu[pmiq].num_ant_ports = num_antenna_ports; + LOG_D(PHY, "layer 3 Codebook pmiq = %d\n",pmiq); + for(int j_col = 0; j_col < 3; j_col++) { + if (j_col == 0) { + llc = ll; + mmc = mm; + phase_sign = 1; + } + if (j_col==1) { + llc = ll + k1 * O1; + mmc = mm + k2 * O2; + phase_sign = 1; + } + if (j_col==2) { + llc = ll; + mmc = mm; + phase_sign = -1; + } + for (int i_rows = 0; i_rows < N1 * N2; i_rows++) { + nfapi_nr_pm_weights_t *weights = &pmi_pdu[pmiq].weights[j_col][i_rows]; + res_code = sqrt(1 / (double)(3 * num_antenna_ports)) * v_lm[llc][mmc][i_rows]; + c16_t precoder_weight = convert_precoder_weight(res_code); + weights->precoder_weight_Re = precoder_weight.r; + weights->precoder_weight_Im = precoder_weight.i; + LOG_D(PHY, "3 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", + pmiq, i_rows, j_col, creal(res_code), cimag(res_code), weights->precoder_weight_Re, weights->precoder_weight_Im); + } + for (int i_rows = N1 * N2; i_rows < 2 * N1 * N2; i_rows++) { + nfapi_nr_pm_weights_t *weights = &pmi_pdu[pmiq].weights[j_col][i_rows]; + res_code=sqrt(1 / (double)(3 * num_antenna_ports)) * (phase_sign) * theta_n[nn] * v_lm[llc][mmc][i_rows - N1 * N2]; + c16_t precoder_weight = convert_precoder_weight(res_code); + weights->precoder_weight_Re = precoder_weight.r; + weights->precoder_weight_Im = precoder_weight.i; + LOG_D(PHY, "3 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", + pmiq, i_rows, j_col, creal(res_code), cimag(res_code), weights->precoder_weight_Re, weights->precoder_weight_Im); + } + } + } + } + } + } + } + + if(max_mimo_layers < 4) + return mat; + + //Table 5.2.2.2.1-8: + //Codebook for 4-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS + + for(int ll = 0; ll < N1 * O1; ll++) { //i_1_1 + for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2 + for(int k1 = 0; k1 < K1; k1++) { + for (int k2 = 0; k2 < K2; k2++) { + for (int nn = 0; nn < 2; nn++) { // i_2 + pmiq ++; + pmi_pdu[pmiq].pm_idx = pmiq + 1; // index 0 is the identity matrix + pmi_pdu[pmiq].numLayers = 4; + pmi_pdu[pmiq].num_ant_ports = num_antenna_ports; + LOG_D(PHY, "layer 4 pmiq = %d\n", pmiq); + for(int j_col = 0; j_col < 4; j_col++) { + if (j_col == 0) { + llc = ll; + mmc = mm; + phase_sign = 1; + } + if (j_col == 1) { + llc = ll + k1 * O1; + mmc = mm + k2 * O2; + phase_sign = 1; + } + if (j_col == 2) { + llc = ll; + mmc = mm; + phase_sign = -1; + } + if (j_col == 3) { + llc = ll + k1 * O1; + mmc = mm + k2 * O2; + phase_sign = -1; + } + for (int i_rows = 0; i_rows < N1 * N2; i_rows++) { + nfapi_nr_pm_weights_t *weights = &pmi_pdu[pmiq].weights[j_col][i_rows]; + res_code=sqrt(1 / (double)(4 * num_antenna_ports)) * v_lm[llc][mmc][i_rows]; + c16_t precoder_weight = convert_precoder_weight(res_code); + weights->precoder_weight_Re = precoder_weight.r; + weights->precoder_weight_Im = precoder_weight.i; + LOG_D(PHY, "4 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", + pmiq, i_rows, j_col, creal(res_code), cimag(res_code), weights->precoder_weight_Re, weights->precoder_weight_Im); + } + for (int i_rows = N1 * N2; i_rows < 2 * N1 * N2; i_rows++) { + nfapi_nr_pm_weights_t *weights = &pmi_pdu[pmiq].weights[j_col][i_rows]; + res_code=sqrt(1 / (double)(4 * num_antenna_ports)) * (phase_sign) * theta_n[nn] * v_lm[llc][mmc][i_rows - N1 * N2]; + c16_t precoder_weight = convert_precoder_weight(res_code); + weights->precoder_weight_Re = precoder_weight.r; + weights->precoder_weight_Im = precoder_weight.i; + LOG_D(PHY, "4 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", + pmiq, i_rows, j_col, creal(res_code), cimag(res_code), weights->precoder_weight_Re, weights->precoder_weight_Im); + } + } + } + } + } + } + } + return mat; + } + else + AssertFatal(false, "Max number of antenna ports supported is currently 16\n"); +} + static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list, struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_bearer2release_list, NR_UE_sched_ctrl_t *sched_ctrl) @@ -122,30 +430,30 @@ void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_info_t *UE) process_rlcBearerConfig(CellGroup->rlc_BearerToAddModList, CellGroup->rlc_BearerToReleaseList, &UE->UE_sched_ctrl); } -static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) +static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) { - nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; - nrmac->common_channels[0].ServingCellConfigCommon = scc; + nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; + nrmac->common_channels[0].ServingCellConfigCommon = scc; - // Carrier configuration - struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; - int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - *frequencyInfoDL->frequencyBandList.list.array[0], - frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); - cfg->carrier_config.dl_bandwidth.value = + // Carrier configuration + struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; + int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + *frequencyInfoDL->frequencyBandList.list.array[0], + frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + cfg->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(*frequencyInfoDL->frequencyBandList.list.array[0] > 256 ? FR2 : FR1, bw_index); - cfg->carrier_config.dl_bandwidth.tl.tag = NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG; // temporary - cfg->num_tlv++; - LOG_I(NR_MAC, "%s() dl_BandwidthP:%d\n", __FUNCTION__, cfg->carrier_config.dl_bandwidth.value); + cfg->carrier_config.dl_bandwidth.tl.tag = NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG; // temporary + cfg->num_tlv++; + LOG_I(NR_MAC, "DL_Bandwidth:%d\n", cfg->carrier_config.dl_bandwidth.value); - cfg->carrier_config.dl_frequency.value = from_nrarfcn(*frequencyInfoDL->frequencyBandList.list.array[0], - *scc->ssbSubcarrierSpacing, - frequencyInfoDL->absoluteFrequencyPointA) + cfg->carrier_config.dl_frequency.value = from_nrarfcn(*frequencyInfoDL->frequencyBandList.list.array[0], + *scc->ssbSubcarrierSpacing, + frequencyInfoDL->absoluteFrequencyPointA) / 1000; // freq in kHz - cfg->carrier_config.dl_frequency.tl.tag = NFAPI_NR_CONFIG_DL_FREQUENCY_TAG; - cfg->num_tlv++; + cfg->carrier_config.dl_frequency.tl.tag = NFAPI_NR_CONFIG_DL_FREQUENCY_TAG; + cfg->num_tlv++; - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) { if (i == frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { cfg->carrier_config.dl_grid_size[i].value = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; cfg->carrier_config.dl_k0[i].value = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; @@ -157,31 +465,31 @@ static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch cfg->carrier_config.dl_grid_size[i].value = 0; cfg->carrier_config.dl_k0[i].value = 0; } - } - struct NR_FrequencyInfoUL *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL; - bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - *frequencyInfoUL->frequencyBandList->list.array[0], - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); - cfg->carrier_config.uplink_bandwidth.value = + } + struct NR_FrequencyInfoUL *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL; + bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + *frequencyInfoUL->frequencyBandList->list.array[0], + frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + cfg->carrier_config.uplink_bandwidth.value = get_supported_bw_mhz(*frequencyInfoUL->frequencyBandList->list.array[0] > 256 ? FR2 : FR1, bw_index); - cfg->carrier_config.uplink_bandwidth.tl.tag = NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG; // temporary - cfg->num_tlv++; - LOG_I(NR_MAC, "%s() dl_BandwidthP:%d\n", __FUNCTION__, cfg->carrier_config.uplink_bandwidth.value); + cfg->carrier_config.uplink_bandwidth.tl.tag = NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG; // temporary + cfg->num_tlv++; + LOG_I(NR_MAC, "DL_Bandwidth:%d\n", cfg->carrier_config.uplink_bandwidth.value); - int UL_pointA; - if (frequencyInfoUL->absoluteFrequencyPointA == NULL) + int UL_pointA; + if (frequencyInfoUL->absoluteFrequencyPointA == NULL) UL_pointA = frequencyInfoDL->absoluteFrequencyPointA; - else + else UL_pointA = *frequencyInfoUL->absoluteFrequencyPointA; - cfg->carrier_config.uplink_frequency.value = from_nrarfcn(*frequencyInfoUL->frequencyBandList->list.array[0], - *scc->ssbSubcarrierSpacing, - UL_pointA) - / 1000; // freq in kHz - cfg->carrier_config.uplink_frequency.tl.tag = NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG; - cfg->num_tlv++; + cfg->carrier_config.uplink_frequency.value = from_nrarfcn(*frequencyInfoUL->frequencyBandList->list.array[0], + *scc->ssbSubcarrierSpacing, + UL_pointA) + / 1000; // freq in kHz + cfg->carrier_config.uplink_frequency.tl.tag = NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG; + cfg->num_tlv++; - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) { if (i == frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { cfg->carrier_config.ul_grid_size[i].value = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; cfg->carrier_config.ul_k0[i].value = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; @@ -193,61 +501,61 @@ static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch cfg->carrier_config.ul_grid_size[i].value = 0; cfg->carrier_config.ul_k0[i].value = 0; } - } + } - uint32_t band = *frequencyInfoDL->frequencyBandList.list.array[0]; - frequency_range_t frequency_range = band < 100 ? FR1 : FR2; + uint32_t band = *frequencyInfoDL->frequencyBandList.list.array[0]; + frequency_range_t frequency_range = band < 100 ? FR1 : FR2; - frame_type_t frame_type = get_frame_type(*frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); - nrmac->common_channels[0].frame_type = frame_type; + frame_type_t frame_type = get_frame_type(*frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); + nrmac->common_channels[0].frame_type = frame_type; - // Cell configuration - cfg->cell_config.phy_cell_id.value = *scc->physCellId; - cfg->cell_config.phy_cell_id.tl.tag = NFAPI_NR_CONFIG_PHY_CELL_ID_TAG; - cfg->num_tlv++; + // Cell configuration + cfg->cell_config.phy_cell_id.value = *scc->physCellId; + cfg->cell_config.phy_cell_id.tl.tag = NFAPI_NR_CONFIG_PHY_CELL_ID_TAG; + cfg->num_tlv++; - cfg->cell_config.frame_duplex_type.value = frame_type; - cfg->cell_config.frame_duplex_type.tl.tag = NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG; - cfg->num_tlv++; + cfg->cell_config.frame_duplex_type.value = frame_type; + cfg->cell_config.frame_duplex_type.tl.tag = NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG; + cfg->num_tlv++; - // SSB configuration - cfg->ssb_config.ss_pbch_power.value = scc->ss_PBCH_BlockPower; - cfg->ssb_config.ss_pbch_power.tl.tag = NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG; - cfg->num_tlv++; + // SSB configuration + cfg->ssb_config.ss_pbch_power.value = scc->ss_PBCH_BlockPower; + cfg->ssb_config.ss_pbch_power.tl.tag = NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG; + cfg->num_tlv++; - cfg->ssb_config.bch_payload.value = 1; - cfg->ssb_config.bch_payload.tl.tag = NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG; - cfg->num_tlv++; + cfg->ssb_config.bch_payload.value = 1; + cfg->ssb_config.bch_payload.tl.tag = NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG; + cfg->num_tlv++; - cfg->ssb_config.scs_common.value = *scc->ssbSubcarrierSpacing; - cfg->ssb_config.scs_common.tl.tag = NFAPI_NR_CONFIG_SCS_COMMON_TAG; - cfg->num_tlv++; + cfg->ssb_config.scs_common.value = *scc->ssbSubcarrierSpacing; + cfg->ssb_config.scs_common.tl.tag = NFAPI_NR_CONFIG_SCS_COMMON_TAG; + cfg->num_tlv++; - // PRACH configuration + // PRACH configuration - uint8_t nb_preambles = 64; - NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - if (rach_ConfigCommon->totalNumberOfRA_Preambles != NULL) + uint8_t nb_preambles = 64; + NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + if (rach_ConfigCommon->totalNumberOfRA_Preambles != NULL) nb_preambles = *rach_ConfigCommon->totalNumberOfRA_Preambles; - cfg->prach_config.prach_sequence_length.value = rach_ConfigCommon->prach_RootSequenceIndex.present - 1; - cfg->prach_config.prach_sequence_length.tl.tag = NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG; - cfg->num_tlv++; + cfg->prach_config.prach_sequence_length.value = rach_ConfigCommon->prach_RootSequenceIndex.present - 1; + cfg->prach_config.prach_sequence_length.tl.tag = NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG; + cfg->num_tlv++; - if (rach_ConfigCommon->msg1_SubcarrierSpacing) + if (rach_ConfigCommon->msg1_SubcarrierSpacing) cfg->prach_config.prach_sub_c_spacing.value = *rach_ConfigCommon->msg1_SubcarrierSpacing; - else + else cfg->prach_config.prach_sub_c_spacing.value = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - cfg->prach_config.prach_sub_c_spacing.tl.tag = NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG; - cfg->num_tlv++; - cfg->prach_config.restricted_set_config.value = rach_ConfigCommon->restrictedSetConfig; - cfg->prach_config.restricted_set_config.tl.tag = NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG; - cfg->num_tlv++; - cfg->prach_config.prach_ConfigurationIndex.value = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; - cfg->prach_config.prach_ConfigurationIndex.tl.tag = NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG; - cfg->num_tlv++; + cfg->prach_config.prach_sub_c_spacing.tl.tag = NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG; + cfg->num_tlv++; + cfg->prach_config.restricted_set_config.value = rach_ConfigCommon->restrictedSetConfig; + cfg->prach_config.restricted_set_config.tl.tag = NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG; + cfg->num_tlv++; + cfg->prach_config.prach_ConfigurationIndex.value = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; + cfg->prach_config.prach_ConfigurationIndex.tl.tag = NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG; + cfg->num_tlv++; - switch (rach_ConfigCommon->rach_ConfigGeneric.msg1_FDM) { + switch (rach_ConfigCommon->rach_ConfigGeneric.msg1_FDM) { case 0: cfg->prach_config.num_prach_fd_occasions.value = 1; break; @@ -262,17 +570,17 @@ static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch break; default: AssertFatal(1 == 0, "msg1 FDM identifier %ld undefined (0,1,2,3) \n", rach_ConfigCommon->rach_ConfigGeneric.msg1_FDM); - } - cfg->prach_config.num_prach_fd_occasions.tl.tag = NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG; - cfg->num_tlv++; + } + cfg->prach_config.num_prach_fd_occasions.tl.tag = NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG; + cfg->num_tlv++; - cfg->prach_config.prach_ConfigurationIndex.value = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; - cfg->prach_config.prach_ConfigurationIndex.tl.tag = NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG; - cfg->num_tlv++; + cfg->prach_config.prach_ConfigurationIndex.value = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; + cfg->prach_config.prach_ConfigurationIndex.tl.tag = NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG; + cfg->num_tlv++; - cfg->prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *)malloc( + cfg->prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *)malloc( cfg->prach_config.num_prach_fd_occasions.value * sizeof(nfapi_nr_num_prach_fd_occasions_t)); - for (int i = 0; i < cfg->prach_config.num_prach_fd_occasions.value; i++) { + for (int i = 0; i < cfg->prach_config.num_prach_fd_occasions.value; i++) { nfapi_nr_num_prach_fd_occasions_t *prach_fd_occasion = &cfg->prach_config.num_prach_fd_occasions_list[i]; // prach_fd_occasion->num_prach_fd_occasions = i; if (cfg->prach_config.prach_sequence_length.value) @@ -311,44 +619,45 @@ static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch prach_fd_occasion->num_unused_root_sequences.tl.tag = NFAPI_NR_CONFIG_NUM_UNUSED_ROOT_SEQUENCES_TAG; prach_fd_occasion->num_unused_root_sequences.value = 0; cfg->num_tlv++; - } + } - cfg->prach_config.ssb_per_rach.value = rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present - 1; - cfg->prach_config.ssb_per_rach.tl.tag = NFAPI_NR_CONFIG_SSB_PER_RACH_TAG; - cfg->num_tlv++; + cfg->prach_config.ssb_per_rach.value = rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present - 1; + cfg->prach_config.ssb_per_rach.tl.tag = NFAPI_NR_CONFIG_SSB_PER_RACH_TAG; + cfg->num_tlv++; - // SSB Table Configuration + // SSB Table Configuration - cfg->ssb_table.ssb_offset_point_a.value = + cfg->ssb_table.ssb_offset_point_a.value = get_ssb_offset_to_pointA(*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB, scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, *scc->ssbSubcarrierSpacing, frequency_range); - cfg->ssb_table.ssb_offset_point_a.tl.tag = NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG; - cfg->num_tlv++; - cfg->ssb_table.ssb_period.value = *scc->ssb_periodicityServingCell; - cfg->ssb_table.ssb_period.tl.tag = NFAPI_NR_CONFIG_SSB_PERIOD_TAG; - cfg->num_tlv++; - cfg->ssb_table.ssb_subcarrier_offset.value = + cfg->ssb_table.ssb_offset_point_a.tl.tag = NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG; + cfg->num_tlv++; + cfg->ssb_table.ssb_period.value = *scc->ssb_periodicityServingCell; + cfg->ssb_table.ssb_period.tl.tag = NFAPI_NR_CONFIG_SSB_PERIOD_TAG; + cfg->num_tlv++; + cfg->ssb_table.ssb_subcarrier_offset.value = get_ssb_subcarrier_offset(*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB, scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); - AssertFatal(cfg->ssb_table.ssb_subcarrier_offset.value < 16, - "cannot handle ssb_subcarrier_offset %d resulting from Point A %ld SSB %ld: please increase dl_absoluteFrequencyPointA " - "in the config by 16\n", - cfg->ssb_table.ssb_subcarrier_offset.value, - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, - *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB); - cfg->ssb_table.ssb_subcarrier_offset.tl.tag = NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG; - cfg->num_tlv++; - nrmac->ssb_SubcarrierOffset = cfg->ssb_table.ssb_subcarrier_offset.value; - nrmac->ssb_OffsetPointA = cfg->ssb_table.ssb_offset_point_a.value; - LOG_I(NR_MAC, - "ssb_OffsetPointA %d, ssb_SubcarrierOffset %d\n", - cfg->ssb_table.ssb_offset_point_a.value, - cfg->ssb_table.ssb_subcarrier_offset.value); + AssertFatal(cfg->ssb_table.ssb_subcarrier_offset.value < 16, + "cannot handle ssb_subcarrier_offset %d resulting from Point A %ld SSB %ld: please increase dl_absoluteFrequencyPointA " + "in the config by 16\n", + cfg->ssb_table.ssb_subcarrier_offset.value, + scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, + *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB); + cfg->ssb_table.ssb_subcarrier_offset.tl.tag = NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG; + cfg->num_tlv++; - switch (scc->ssb_PositionsInBurst->present) { + nrmac->ssb_SubcarrierOffset = cfg->ssb_table.ssb_subcarrier_offset.value; + nrmac->ssb_OffsetPointA = cfg->ssb_table.ssb_offset_point_a.value; + LOG_I(NR_MAC, + "ssb_OffsetPointA %d, ssb_SubcarrierOffset %d\n", + cfg->ssb_table.ssb_offset_point_a.value, + cfg->ssb_table.ssb_subcarrier_offset.value); + + switch (scc->ssb_PositionsInBurst->present) { case 1: cfg->ssb_table.ssb_mask_list[0].ssb_mask.value = scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] << 24; cfg->ssb_table.ssb_mask_list[1].ssb_mask.value = 0; @@ -369,19 +678,20 @@ static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch break; default: AssertFatal(1 == 0, "SSB bitmap size value %d undefined (allowed values 1,2,3) \n", scc->ssb_PositionsInBurst->present); - } + } - cfg->ssb_table.ssb_mask_list[0].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG; - cfg->ssb_table.ssb_mask_list[1].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG; - cfg->num_tlv += 2; + cfg->ssb_table.ssb_mask_list[0].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG; + cfg->ssb_table.ssb_mask_list[1].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG; + cfg->num_tlv += 2; - // logical antenna ports - cfg->carrier_config.num_tx_ant.value = pdsch_AntennaPorts; - AssertFatal(pdsch_AntennaPorts > 0 && pdsch_AntennaPorts < 33, "pdsch_AntennaPorts in 1...32\n"); - cfg->carrier_config.num_tx_ant.tl.tag = NFAPI_NR_CONFIG_NUM_TX_ANT_TAG; + // logical antenna ports + int num_pdsch_antenna_ports = pdsch_AntennaPorts.N1 * pdsch_AntennaPorts.N2 * pdsch_AntennaPorts.XP; + cfg->carrier_config.num_tx_ant.value = num_pdsch_antenna_ports; + AssertFatal(num_pdsch_antenna_ports > 0 && num_pdsch_antenna_ports < 33, "pdsch_AntennaPorts in 1...32\n"); + cfg->carrier_config.num_tx_ant.tl.tag = NFAPI_NR_CONFIG_NUM_TX_ANT_TAG; - int num_ssb = 0; - for (int i = 0; i < 32; i++) { + int num_ssb = 0; + for (int i = 0; i < 32; i++) { cfg->ssb_table.ssb_beam_id_list[i].beam_id.tl.tag = NFAPI_NR_CONFIG_BEAM_ID_TAG; if ((cfg->ssb_table.ssb_mask_list[0].ssb_mask.value >> (31 - i)) & 1) { cfg->ssb_table.ssb_beam_id_list[i].beam_id.value = num_ssb; @@ -396,26 +706,26 @@ static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch num_ssb++; } cfg->num_tlv++; - } + } - cfg->carrier_config.num_rx_ant.value = pusch_AntennaPorts; - AssertFatal(pusch_AntennaPorts > 0 && pusch_AntennaPorts < 13, "pusch_AntennaPorts in 1...12\n"); - cfg->carrier_config.num_rx_ant.tl.tag = NFAPI_NR_CONFIG_NUM_RX_ANT_TAG; - LOG_I(NR_MAC, - "Set RX antenna number to %d, Set TX antenna number to %d (num ssb %d: %x,%x)\n", - cfg->carrier_config.num_tx_ant.value, - cfg->carrier_config.num_rx_ant.value, - num_ssb, - cfg->ssb_table.ssb_mask_list[0].ssb_mask.value, - cfg->ssb_table.ssb_mask_list[1].ssb_mask.value); - AssertFatal(cfg->carrier_config.num_tx_ant.value > 0, - "carrier_config.num_tx_ant.value %d !\n", - cfg->carrier_config.num_tx_ant.value); - cfg->num_tlv++; - cfg->num_tlv++; + cfg->carrier_config.num_rx_ant.value = pusch_AntennaPorts; + AssertFatal(pusch_AntennaPorts > 0 && pusch_AntennaPorts < 13, "pusch_AntennaPorts in 1...12\n"); + cfg->carrier_config.num_rx_ant.tl.tag = NFAPI_NR_CONFIG_NUM_RX_ANT_TAG; + LOG_I(NR_MAC, + "Set RX antenna number to %d, Set TX antenna number to %d (num ssb %d: %x,%x)\n", + cfg->carrier_config.num_tx_ant.value, + cfg->carrier_config.num_rx_ant.value, + num_ssb, + cfg->ssb_table.ssb_mask_list[0].ssb_mask.value, + cfg->ssb_table.ssb_mask_list[1].ssb_mask.value); + AssertFatal(cfg->carrier_config.num_tx_ant.value > 0, + "carrier_config.num_tx_ant.value %d !\n", + cfg->carrier_config.num_tx_ant.value); + cfg->num_tlv++; + cfg->num_tlv++; - // TDD Table Configuration - if (cfg->cell_config.frame_duplex_type.value == TDD) { + // TDD Table Configuration + if (cfg->cell_config.frame_duplex_type.value == TDD) { cfg->tdd_table.tdd_period.tl.tag = NFAPI_NR_CONFIG_TDD_PERIOD_TAG; cfg->num_tlv++; if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 == NULL) { @@ -440,7 +750,10 @@ static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch LOG_I(NR_MAC, "TDD has been properly configurated\n"); nrmac->tdd_beam_association = (int16_t *)malloc16(periods_per_frame * sizeof(int16_t)); } - } + } + + // precoding matrix configuration (to be improved) + cfg->pmi_list = init_DL_MIMO_codebook(nrmac, pdsch_AntennaPorts); } void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config) @@ -464,8 +777,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c LOG_I(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n"); - int num_pdsch_antenna_ports = config->pdsch_AntennaPorts.N1 * config->pdsch_AntennaPorts.N2 * config->pdsch_AntennaPorts.XP; - config_common(nrmac, num_pdsch_antenna_ports, config->pusch_AntennaPorts, scc); + config_common(nrmac, config->pdsch_AntennaPorts, config->pusch_AntennaPorts, scc); if (NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) { // fake that the gNB is configured in nFAPI mode, which would normally be diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index b3a4396410..66fda58122 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -668,8 +668,7 @@ static void pf_dl(module_id_t module_id, else sched_pdsch->mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->dl_bler_stats, max_mcs, frame); sched_pdsch->nrOfLayers = get_dl_nrOfLayers(sched_ctrl, current_BWP->dci_format); - sched_pdsch->pm_index = - mac->identity_pm ? 0 : get_pm_index(UE, sched_pdsch->nrOfLayers, mac->radio_config.pdsch_AntennaPorts.XP); + sched_pdsch->pm_index = mac->identity_pm ? 0 : get_pm_index(mac, UE, sched_pdsch->nrOfLayers, mac->radio_config.pdsch_AntennaPorts.XP); const uint8_t Qm = nr_get_Qm_dl(sched_pdsch->mcs, current_BWP->mcsTableIdx); const uint16_t R = nr_get_code_rate_dl(sched_pdsch->mcs, current_BWP->mcsTableIdx); uint32_t tbs = nr_compute_tbs(Qm, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 89ac444e63..73cd0de6d2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -129,29 +129,36 @@ uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, } -uint16_t get_pm_index(const NR_UE_info_t *UE, +uint16_t get_pm_index(const gNB_MAC_INST *nrmac, + const NR_UE_info_t *UE, int layers, - int xp_pdsch_antenna_ports) { - - if (layers == 1) return 0; - + int xp_pdsch_antenna_ports) +{ const NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; const int report_id = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.csi_report_id; const nr_csi_report_t *csi_report = &UE->csi_report_template[report_id]; const int N1 = csi_report->N1; const int N2 = csi_report->N2; - const int antenna_ports = (N1*N2)<<1; + const int antenna_ports = (N1 * N2) << 1; - if (xp_pdsch_antenna_ports == 1 && - antenna_ports>1) + if (xp_pdsch_antenna_ports == 1) return 0; //identity matrix (basic 5G configuration handled by PMI report is with XP antennas) const int x1 = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x1; const int x2 = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x2; - LOG_D(NR_MAC,"PMI report: x1 %d x2 %d\n",x1,x2); + LOG_D(NR_MAC,"PMI report: x1 %d x2 %d layers: %d\n", x1, x2, layers); + int prev_layers_size = 0; + for (int i = 1; i < layers; i++) + prev_layers_size += nrmac->precoding_matrix_size[i - 1]; + + // need to return PM index to matrix initialized in init_DL_MIMO_codebook + // index 0 is for identity matrix + // order of matrices depends on layers to be transmitted + // elements from 1 to n for 1 layer + // elements from n+1 to m for 2 layers etc. if (antenna_ports == 2) - return x2; + return 1 + prev_layers_size + x2; // 0 for identity matrix else AssertFatal(1==0,"More than 2 antenna ports not yet supported\n"); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index f5f4d0beb1..1bdb08bb60 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -377,7 +377,8 @@ NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc, const NR_tda_info_t *tda_info, const int Layers); -uint16_t get_pm_index(const NR_UE_info_t *UE, +uint16_t get_pm_index(const gNB_MAC_INST *nrmac, + const NR_UE_info_t *UE, int layers, int xp_pdsch_antenna_ports); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 2f550e642a..f2c66bd99f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -852,6 +852,7 @@ typedef struct gNB_MAC_INST_s { uint8_t min_grant_prb; uint8_t min_grant_mcs; bool identity_pm; + int precoding_matrix_size[NR_MAX_NB_LAYERS]; nr_mac_rrc_ul_if_t mac_rrc; f1_config_t f1_config;