diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 79424435da47a1ce0f9683f97c372b25c4706110..33f005e51ab619373e1645236e8da80eea7a0598 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1293,8 +1293,8 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch.c - #${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c - #${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index a0da42fcdcbcaf470401396ce4efbdf11dec9f00..a3faead1788771b32e19fce632c36f62d2742cab 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -158,11 +158,17 @@ typedef struct { typedef struct { nfapi_uint16_tlv_t data_scrambling_id; + nfapi_uint16_tlv_t dmrs_typeA_position; + nfapi_uint16_tlv_t dmrs_additional_position; + nfapi_uint16_tlv_t dmrs_type; + nfapi_uint16_tlv_t dmrs_max_length; + nfapi_uint16_tlv_t mapping_type; + nfapi_uint16_tlv_t resource_allocation; + nfapi_uint16_tlv_t time_allocation_list; nfapi_uint16_tlv_t mcs_table; nfapi_uint16_tlv_t aggregation_factor; nfapi_uint16_tlv_t prb_bundling_type; nfapi_uint16_tlv_t rbg_size; - nfapi_uint16_tlv_t resource_allocation_config; nfapi_uint16_tlv_t vrb_to_prb_interleaver; nfapi_uint16_tlv_t code_block_groug_transmission; nfapi_uint16_tlv_t x_overhead; @@ -238,7 +244,7 @@ typedef struct { nfapi_nr_subframe_config_t subframe_config; nfapi_nr_rf_config_t rf_config; nfapi_nr_sch_config_t sch_config; - nfapi_nr_pdsch_config_t dlsch_config; + nfapi_nr_pdsch_config_t pdsch_config; nfapi_nr_rach_config_t rach_config; nfapi_nr_pusch_config_t pusch_config; nfapi_nr_pucch_config_t pucch_config; @@ -343,6 +349,16 @@ typedef enum { NFAPI_NR_PRB_BUNDLING_TYPE_DYNAMIC } nfapi_nr_prb_bundling_type_e; +typedef enum { + NFAPI_NR_MCS_TABLE_QAM64_LOW_SE=0, + NFAPI_NR_MCS_TABLE_QAM256 +} nfapi_nr_pdsch_mcs_table_e; + +typedef enum { + NFAPI_NR_DMRS_TYPE1=0, + NFAPI_NR_DMRS_TYPE2 +} nfapi_nr_dmrs_type_e; + // P7 Sub Structures typedef struct { @@ -485,13 +501,28 @@ typedef struct { uint16_t length; uint8_t pdu_index; uint16_t rnti; - uint8_t resource_allocation_type; + uint8_t time_allocation_type; + uint8_t freq_allocation_type; + uint8_t start_prb; + uint8_t n_prb; + uint8_t S; + uint8_t L; + uint8_t Imcs; + uint8_t n_codewords; + uint8_t n_layers; + /*uint8_t R; + uint8_t Qm; + uint16_t TBS; + uint8_t nb_layers;*/ + uint8_t time_alloc_list_flag; + uint8_t time_alloc_list; + uint8_t rbg_list; uint8_t virtual_resource_block_assignment_flag; uint32_t resource_block_coding; uint8_t modulation; uint8_t redundancy_version; uint8_t transport_blocks; - uint8_t transport_block_to_codeword_swap_flag; + //uint8_t transport_block_to_codeword_swap_flag; uint8_t transmission_scheme; uint8_t number_of_layers; uint8_t number_of_subbands; @@ -500,7 +531,6 @@ typedef struct { uint8_t pa; uint8_t delta_power_offset_index; uint8_t ngap; - uint8_t nprb; uint8_t transmission_mode; uint8_t num_bf_prb_per_subband; uint8_t num_bf_vector; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 53f0a7791bfce0dd89607f5d281d7b8ae01c5be5..c38486aec0f585f3391733c0763b027dbe3bbc81 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -33,6 +33,8 @@ #include "nr_dlsch.h" #include "nr_dci.h" +#define DEBUG_DLSCH + void nr_pdsch_codeword_scrambling(uint32_t *in, uint8_t size, uint8_t q, @@ -56,6 +58,31 @@ void nr_pdsch_codeword_scrambling(uint32_t *in, } +void nr_modulation(uint32_t *in, + uint16_t length, + nr_mod_t modulation_type, + int16_t *out) { + + uint16_t offset; + uint16_t order; + order = mod_order[modulation_type]; + offset = mod_offset[modulation_type]; + + for (int i=0; i<length/order; i++) { + uint8_t idx = 0, b_idx; + + for (int j=0; j<order; j++) { + b_idx = (i*order+j)&0x1f; + if (i && (!b_idx)) + in++; + idx ^= (((*in)>>b_idx)&1)<<(order-j-1); + } + + out[i<<1] = nr_mod_table[(offset+idx)<<1]; + out[(i<<1)+1] = nr_mod_table[((offset+idx)<<1)+1]; + } +} + void nr_pdsch_codeword_modulation(uint32_t *in, uint8_t Qm, uint32_t length, @@ -72,7 +99,7 @@ void nr_pdsch_codeword_modulation(uint32_t *in, b_idx = (i*Qm+j)&0x1f; if (i && (!b_idx)) in++; - idx ^= (((*in)>>b_idx)&1)<<(Qm-j); + idx ^= (((*in)>>b_idx)&1)<<(Qm-j-1); } out[i<<1] = nr_mod_table[(offset+idx)<<1]; @@ -153,22 +180,29 @@ void nr_pdsch_layer_mapping(uint16_t **mod_symbs, uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch, NR_gNB_DCI_ALLOC_t dci_alloc, + uint32_t *pdsch_dmrs, int32_t** txdataF, int16_t amp, NR_DL_FRAME_PARMS frame_parms, nfapi_nr_config_request_t config) { - NR_DL_gNB_HARQ_t *harq = dlsch.harq_processes[0]; + NR_DL_gNB_HARQ_t *harq = dlsch.harq_processes[dci_alloc.harq_pid]; + nfapi_nr_dl_config_dlsch_pdu_rel15_t *rel15 = &harq->dlsch_pdu.dlsch_pdu_rel15; + nfapi_nr_dl_config_pdcch_parameters_rel15_t pdcch_params = dci_alloc.pdcch_params; uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH]={0}; uint16_t mod_symbs[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>1] = {0}; uint16_t tx_layers[NR_MAX_NB_LAYERS][NR_MAX_PDSCH_ENCODED_LENGTH>>1]; + uint16_t n_symbs[NR_MAX_NB_CODEWORDS] = {0}; + int8_t Wf[2], Wt[2], l0[2], delta; /// CRC, coding, interleaving and rate matching /// scrambling - uint16_t n_RNTI = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? ((pdcch_params.scrambling_id)?pdcch_params.rnti:0) : 0; - uint16_t Nid = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? pdcch_params.scrambling_id : config.sch_config.physical_cell_id.value; - for (int q=0; q<harq->n_codewords; q++) + uint16_t n_RNTI = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? \ + ((pdcch_params.scrambling_id)?pdcch_params.rnti:0) : 0; + uint16_t Nid = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? \ + pdcch_params.scrambling_id : config.sch_config.physical_cell_id.value; + for (int q=0; q<rel15->nb_codewords; q++) nr_pdsch_codeword_scrambling(harq->f, harq->TBS, q, @@ -177,7 +211,7 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch, scrambled_output[q]); /// Modulation - for (int q=0; q<harq->n_codewords; q++) + for (int q=0; q<rel15->nb_codewords; q++) nr_pdsch_codeword_modulation(scrambled_output[q], harq->Qm, harq->TBS, @@ -185,15 +219,61 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch, /// Layer mapping nr_pdsch_layer_mapping(mod_symbs, - harq->n_codewords, - harq->Nl, + rel15->nb_codewords, + rel15->nb_layers, n_symbs, tx_layers); - /// Antenna port mapping -- Not yet necessary + /// Antenna port mapping + //to be moved to init phase potentially, for now tx_layers 1-8 are mapped on antenna ports 1000-1007 + + /// DMRS QPSK modulation + uint16_t n_dmrs = rel15->n_prb<<1; + uint16_t mod_dmrs[n_dmrs<<1] = {0}; + uint8_t dmrs_type = config.pdsch_config.dmrs_type.value; + nr_modulation(pdsch_dmrs, n_dmrs, QPSK, mod_dmrs); /// Resource mapping - - + AssertFatal(harq->Nl<=config.rf_config.tx_antenna_ports.value, "Not enough Tx antennas (%d) for %d layers\n",\ + config.rf_config.tx_antenna_ports.value, harq->Nl); + + // Non interleaved VRB to PRB mapping + uint8_t start_sc = frame_parms.first_carrier_offset + rel15->start_prb*NR_NB_SC_PER_RB +\ + ((pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_COMMON) && (pdcch_params.dci_format == NFAPI_NR_DL_DCI_FORMAT_1_0))?\ + (((int)floor(frame_parms.ssb_start_subcarrier/NR_NB_SC_PER_RB) + pdcch_params.rb_offset)*NR_NB_SC_PER_RB) : 0; + + for (int ap=0; ap<rel15->nb_layers; ap++) { + + // DMRS params for this ap + Wt = get_Wt(ap, dmrs_type); + Wf = get_Wf(ap, dmrs_type); + l0 = get_l0(0, config.pdsch_config.dmrs_typeA_position.value); + delta = get_delta(ap, dmrs_type); + uint8_t k_prime=0, n=0, dmrs_idx=0; + uint16_t m = 0; + + for (int l=rel15->S; l<rel15->L; l++) + for (int k=start_sc; k<rel15->n_prb*NR_NB_SC_PER_RB; k++) { + if (k >= frame_parms.ofdm_symbol_size) + k -= frame_parms.ofdm_symbol_size; + + if ((l==l0) && (k == ((dmrs_type)? (6*n+k_prime+delta):((n<<2)+(k_prime<<1)+delta)))) { + ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (Wt*Wf*amp*mod_dmrs[dmrs_idx<<1]) >> 15; + ((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (Wt*Wf*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; + mod_dmrs++; + n++; + k_prime = (++k_prime)&1; + } + + ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (amp * tx_layers[ap][m<<1]) >> 15; + ((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15; + m++; + } + } + +#ifdef DEBUG_DLSCH + write_output("txdataF_dlsch.m", "txdataF_dlsch", txdataF[0], frame_parms.samples_per_frame_wCP>>1, 1, 1); +#endif + return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h index 1728d1723ad0728f328bea72ffea534ec35604fa..a8ecba058247384ac66685b2f606ee131e5c1cad 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h @@ -35,11 +35,15 @@ extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT]; void nr_get_time_domain_allocation_type(nfapi_nr_config_request_t config, - NR_gNB_DCI_ALLOC_t dci_alloc, - NR_gNB_DLSCH_t* dlsch); + nfapi_nr_dl_config_dci_dl_pdu dci_pdu, + nfapi_nr_dl_config_dlsch_pdu *dlsch_pdu); void nr_check_time_alloc(uint8_t S, uint8_t L, nfapi_nr_config_request_t config); +uint16_t get_RIV(uint16_t rb_start, uint16_t L, uint16_t N_RB); + +uint16_t get_SLIV(uint8_t S, uint8_t L); + uint8_t nr_get_S(uint8_t row_idx, uint8_t CP, uint8_t time_alloc_type, uint8_t dmrs_typeA_position); void nr_get_rbg_parms(NR_BWP_PARMS* bwp, uint8_t config_type); @@ -52,6 +56,10 @@ uint8_t nr_get_Qm(uint8_t Imcs, uint8_t table_idx); uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx); +void nr_get_tbs(nfapi_nr_dl_config_dlsch_pdu *dlsch_pdu, + nfapi_nr_dl_config_dci_dl_pdu dci_pdu, + nfapi_nr_config_request_t config); + void nr_pdsch_codeword_scrambling(uint32_t *in, uint8_t size, uint8_t q, diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c index e1f7799f767c5dd206ac2499940cd9d67d820dea..bf57c946452e444354d0208427b165808015c027 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c @@ -45,23 +45,26 @@ uint8_t nr_pdsch_default_time_alloc_C_L[15] = {2,2,2,2,2,4,4,4,4,4,7,12,11,6,6}; /// Time domain allocation routines void nr_get_time_domain_allocation_type(nfapi_nr_config_request_t config, - NR_gNB_DCI_ALLOC_t dci_alloc, - NR_gNB_DLSCH_t* dlsch) { + nfapi_nr_dl_config_dci_dl_pdu dci_pdu, + nfapi_nr_dl_config_dlsch_pdu *dlsch_pdu) { - nfapi_nr_ssb_and_cset_mux_pattern_type_e mux_pattern = dci_alloc.pdcch_params.mux_pattern; + nfapi_nr_dl_config_pdcch_parameters_rel15_t params_rel15 = dci_pdu.pdcch_params_rel15; + uint8_t *alloc_type = &dlsch_pdu->dlsch_pdu_rel15.time_allocation_type; + uint8_t mux_pattern = params_rel15.mux_pattern; + uint8_t alloc_list_flag = dlsch_pdu->dlsch_pdu_rel15.time_alloc_list_flag; - switch(dci_alloc.pdcch_params.rnti_type) { + switch(params_rel15.rnti_type) { case NFAPI_NR_RNTI_SI: - AssertFatal(dci_alloc.pdcch_params.common_search_space_type == NFAPI_NR_COMMON_SEARCH_SPACE_TYPE_0, + AssertFatal(params_rel15.common_search_space_type == NFAPI_NR_COMMON_SEARCH_SPACE_TYPE_0, "Invalid common search space type %d for SI RNTI, expected %d\n", - dci_alloc.pdcch_params.common_search_space_type, NFAPI_NR_COMMON_SEARCH_SPACE_TYPE_0); + params_rel15.common_search_space_type, NFAPI_NR_COMMON_SEARCH_SPACE_TYPE_0); if (mux_pattern == NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1) AssertFatal(config.subframe_config.dl_cyclic_prefix_type.value == NFAPI_CP_NORMAL, "Invalid configuration CP extended for SI RNTI type 0 search space\n"); - dlsch->time_alloc_type = (mux_pattern == NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1)?NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A : + *alloc_type = (mux_pattern == NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1)?NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A : (mux_pattern == NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2)?NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_B : NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_C; break; @@ -71,7 +74,7 @@ void nr_get_time_domain_allocation_type(nfapi_nr_config_request_t config, /*AssertFatal(dci_alloc.pdcch_params.common_search_space_type == NFAPI_NR_COMMON_SEARCH_SPACE_TYPE_1, "Invalid common search space type %d for RNTI %d, expected %d\n",dci_alloc.pdcch_params.common_search_space_type, NFAPI_NR_COMMON_SEARCH_SPACE_TYPE_1, dci_alloc.rnti_type);*/ - dlsch->time_alloc_type = (dlsch->time_alloc_list_flag) ? NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_ALLOC_LIST : NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A; + *alloc_type = (alloc_list_flag) ? NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_ALLOC_LIST : NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A; break; case NFAPI_NR_RNTI_P: @@ -79,17 +82,17 @@ void nr_get_time_domain_allocation_type(nfapi_nr_config_request_t config, case NFAPI_NR_RNTI_C: case NFAPI_NR_RNTI_CS: - if (dci_alloc.pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_COMMON) - dlsch->time_alloc_type = (dlsch->time_alloc_list_flag)? NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_ALLOC_LIST : NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A; + if (params_rel15.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_COMMON) + *alloc_type = (alloc_list_flag)? NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_ALLOC_LIST : NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A; else - dlsch->time_alloc_type = NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_ALLOC_LIST; + *alloc_type = NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_ALLOC_LIST; break; } } -static inline uint16_t get_SLIV(uint8_t S, uint8_t L) { +uint16_t get_SLIV(uint8_t S, uint8_t L) { return ( (uint16_t)(((L-1)<=7)? (14*(L-1)+S) : (14*(15-L)+(13-S))) ); } @@ -129,11 +132,11 @@ void nr_check_time_alloc(uint8_t S, uint8_t L, nfapi_nr_config_request_t config) switch (config.subframe_config.dl_cyclic_prefix_type.value) { case NFAPI_CP_NORMAL: - if (config.pdsch_config.time_domain_alloc_mapping_type.value == NFAPI_NR_PDSCH_MAPPING_TYPE_A) { + if (config.pdsch_config.mapping_type.value == NFAPI_NR_PDSCH_MAPPING_TYPE_A) { AssertFatal(S<4, "Invalid value of S(%d) for mapping type A and normal CP\n", S); if (S==3) - AssertFatal(config.pdsch_config.dmrs_typeA_position.value == 3, "Invalid S %d for dmrs_typeA_position %d\n", + AssertFatal(config.pdsch_config.mapping_type.value == 3, "Invalid S %d for dmrs_typeA_position %d\n", S, config.pdsch_config.dmrs_typeA_position.value); AssertFatal((L>2)&&(L<15), "Invalid L %d for mapping type A and normal CP\n", L); @@ -150,7 +153,7 @@ void nr_check_time_alloc(uint8_t S, uint8_t L, nfapi_nr_config_request_t config) break; case NFAPI_CP_EXTENDED: - if (config.pdsch_config.time_domain_alloc_mapping_type.value == NFAPI_NR_PDSCH_MAPPING_TYPE_A) { + if (config.pdsch_config.mapping_type.value == NFAPI_NR_PDSCH_MAPPING_TYPE_A) { AssertFatal(S<4, "Invalid value of S(%d) for mapping type A and extended CP\n", S); if (S==3) @@ -205,7 +208,7 @@ void nr_get_rbg_list(uint32_t bitmap, uint8_t n_rbg, uint8_t* rbg_list) { // DL alloc type 1 -static inline uint16_t get_RIV(uint16_t rb_start, uint16_t L, uint16_t N_RB) { +uint16_t get_RIV(uint16_t rb_start, uint16_t L, uint16_t N_RB) { if ((L-1)<=(N_RB>>1)) return (N_RB*(L-1)+rb_start); else diff --git a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c new file mode 100644 index 0000000000000000000000000000000000000000..b016e4d0083271f5c5de831275b5dd0baf890f27 --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c @@ -0,0 +1,99 @@ +/* + * 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 + */ + +/*! \file PHY/NR_TRANSPORT/nr_sch_dmrs.c +* \brief +* \author +* \date +* \version +* \company Eurecom +* \email: +* \note +* \warning +*/ + +#include "nr_sch_dmrs.h" + + + + +/*Table 7.4.1.1.2-1 and 7.4.1.1.2-2 38211 Columns: ap - CDM group - Delta - Wf(0) - Wf(1) - Wt(0) - Wt(1)*/ +int8_t pdsch_dmrs_1[8][7] = {{0,0,0,1,1,1,1}, + {1,0,0,1,-1,1,1}, + {2,1,1,1,1,,1,1}, + {3,1,1,1,-1,1,1}, + {4,0,0,1,1,1,-1}, + {5,0,0,1,-1,1,-1}, + {6,1,1,1,1,1,-1}, + {7,1,1,1,-1,1,-1}}; + +int8_t pdsch_dmrs_2[12][7] = {{0,0,0,1,1,1,1}, + {1,0,0,1,-1,1,1}, + {2,1,2,1,1,1,1}, + {3,1,2,1,-1,1,1}, + {4,2,4,1,1,1,1}, + {5,2,4,1,-1,1,1}, + {6,0,0,1,1,1,-1}, + {7,0,0,1,-1,1,-1}, + {8,1,2,1,1,1,-1}, + {9,1,2,1,-1,1,-1}, + {10,2,4,1,1,1,-1}, + {11,2,4,1,-1,1,-1}}; + +static inline void *get_l_prime(uint8_t n_symbs) { + uint8_t *l_prime; + for (int i=0; i<nsymbs; i++) + *(l_prime+i) = i; + return l_prime; +} + +static inline void *get_antenna_ports(uint8_t n_symbs, uint8_t config) { + uint8_t *ap; + if (config == NFAPI_NR_DMRS_TYPE1) + for (int i=0; i<(4+4*(n_symbs-1); i++) + *(ap+i) = i; + else + for (int i=0; i<(7+4*(n_symbs-1); i++) + *(ap+i) = i; + return ap; +} + +int8_t *get_Wt(uint8_t ap, uint8_t config) { + int8_t *Wt; + for (int i=0; i<2; i++) + *(Wt+i)=(config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][3+i]):(pdsch_dmrs_2[ap][3+i]); + return Wt; +} + +int8_t *get_Wf(uint8_t ap, uint8_t config) { + int8_t *Wf; + for (int i=0; i<2; i++) + *(Wf+i)=(config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][5+i]):(pdsch_dmrs_2[ap][5+i]); + return Wf; +} + +uint8_t get_delta(uint8_t ap, uint8_t config) { + return ((config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][2]):(pdsch_dmrs_2[ap][2])); +} + +uint8_t *get_l0(uint8_t config, uint8_t dmrs_typeA_position) { + return ((config==NFAPI_NR_DMRS_TYPE1)?dmrs_typeA_position:0); +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h new file mode 100644 index 0000000000000000000000000000000000000000..daec8324b0544f137ba5d694bca47bfaba0b0202 --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h @@ -0,0 +1,44 @@ +/* + * 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 + */ + +/*! \file PHY/NR_TRANSPORT/nr_sch_dmrs.c +* \brief +* \author +* \date +* \version +* \company Eurecom +* \email: +* \note +* \warning +*/ + +#include "PHY/defs_gNB.h" + +#define NR_PDSCH_DMRS_ANTENNA_PORT0 1000 +#define NR_PDSCH_DMRS_NB_ANTENNA_PORTS 12 + +int8_t *get_Wt(uint8_t ap, uint8_t config); + +int8_t *get_Wf(uint8_t ap, uint8_t config); + +uint8_t get_delta(uint8_t ap, uint8_t config); + +uint8_t *get_l0(uint8_t config, uint8_t dmrs_typeA_position); diff --git a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c index 6282f7853eb214efd59dc8ef3eb8242027d65821..d8b8c10c2bf53cc0f2b42a83f581eaed0f8abeca 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c @@ -87,13 +87,72 @@ static inline uint8_t is_codeword_disabled(uint8_t format, uint8_t Imcs, uint8_t return ((format==NFAPI_NR_DL_DCI_FORMAT_1_1)&&(Imcs==26)&&(rv==1)); } -/*uint16_t nr_get_tbs(NR_gNB_DCI_ALLOC_t dci_alloc, nfapi_nr_config_request_t config) { +void nr_get_tbs(NR_gNB_DLSCH_t *dlsch, + nfapi_nr_dl_config_dci_dl_pdu dci_pdu, + nfapi_nr_config_request_t config) { +uint8_t N_PRB_DMRS=2; // tmp hardcoding - uint8_t rnti_type = dci_alloc.pdcch_params.rnti_type; + nfapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_rel15 = &dlsch->dlsch_pdu.dlsch_pdu_rel15; + nfapi_nr_dl_config_pdcch_parameters_rel15_t params_rel15 = dci_pdu.pdcch_params_rel15; + NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[dlsch_rel15->harq_pid]; + uint8_t rnti_type = params_rel15.rnti_type; + uint8_t dci_format = params_rel15.dci_format; + uint8_t ss_type = params_rel15.search_space_type; uint8_t N_PRB_oh = ((rnti_type==NFAPI_NR_RNTI_SI)||(rnti_type==NFAPI_NR_RNTI_RA)||(rnti_type==NFAPI_NR_RNTI_P))? 0 : \ - (config.pdsch_config.); + (config.pdsch_config.x_overhead.value); + uint8_t mcs_table = config.pdsch_config.mcs_table.value; + uint8_t N_sh_symb = dlsch_rel15->L; + uint8_t Imcs = dlsch_rel15->Imcs; uint16_t N_prime_RE = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS - N_PRB_oh; LOG_I(MAC, "N_prime_RE %d for %d symbols %d DMRS per PRB and %d overhead\n", N_prime_RE, N_sh_symb, N_PRB_DMRS, N_PRB_oh); - -}*/ + uint16_t N_RE, N_info, N_info_prime; + uint8_t table_idx, R, Qm, n; + float tmp, C; // temporary N_info_prime in float to avoid back and forth casting to int + + N_RE = min(156, N_RE)*dlsch_rel15->n_prb; + if ((mcs_table == NFAPI_NR_MCS_TABLE_QAM256) && (dci_format == NFAPI_NR_DL_DCI_FORMAT_1_1) && ((rnti_type==NFAPI_NR_RNTI_C)||(rnti_type==NFAPI_NR_RNTI_CS))) + table_idx = 2; + else if ((mcs_table == NFAPI_NR_MCS_TABLE_QAM64_LOW_SE) && (rnti_type!=NFAPI_NR_RNTI_new) && (rnti_type==NFAPI_NR_RNTI_C) && (ss_type==NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)) + table_idx = 3; + else if (rnti_type==NFAPI_NR_RNTI_new) + table_idx = 3; + else if ((mcs_table == NFAPI_NR_MCS_TABLE_QAM256) && (rnti_type==NFAPI_NR_RNTI_CS) && (dci_format == NFAPI_NR_DL_DCI_FORMAT_1_1)) + table_idx = 2; // Condition mcs_table not configured in sps_config necessary here but not yet implemented + /*else if((mcs_table == NFAPI_NR_MCS_TABLE_QAM64_LOW_SE) && (rnti_type==NFAPI_NR_RNTI_CS)) + * table_idx = 3; + * Note: the commented block refers to the case where the mcs_table is from sps_config*/ + else + table_idx = 1; + + R = nr_get_code_rate(Imcs, table_idx); + Qm = nr_get_Qm(Imcs, table_idx); + N_info = N_RE*R*Qm*harq->Nl; + + if (N_info <= 3824) { + n = max(3, (uint8_t)(floor(log2(N_info)-6))); + N_info_prime = max(24, (N_info>>n)<<n); + for (int i=0; i<93; i++) + if (nr_tbs_table[i] >= N_info_prime) { + harq->TBS = nr_tbs_table[i]; + break; + } + } + else { + n = (uint8_t)floor(log2(N_info)-24) - 5; + tmp = max(3840, ((uint16_t)round(((float)N_info-24)/(1<<n)))<<n); + + if (R<0.25) { + C = ceil((tmp+24)/3816); + harq->TBS = ((uint16_t)(C*ceil((tmp+24)/(8*C))))<<3; + } + else { + if (tmp>8424) { + C = ceil((tmp+24)/8424); + harq->TBS = ((uint16_t)(C*ceil((tmp+24)/(8*C))))<<3; + } + else + harq->TBS = ((uint16_t)ceil((tmp+24)/8) - 24)<<3; + } + } +} diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 05a6b267b7f1b1f5d3cce0ff4e5e289dd940c2f3..f62756bc684cfabb88b51d7ab76e8f67198f538f 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -51,6 +51,8 @@ typedef struct { uint16_t size; /// Aggregation level uint8_t L; + /// HARQ PID + uint8_t harq_pid; /// PDCCH parameters nfapi_nr_dl_config_pdcch_parameters_rel15_t pdcch_params; /// CCE list @@ -66,8 +68,8 @@ typedef struct { typedef struct { - /// Status Flag indicating for this DLSCH (idle,active,disabled) - //SCH_status_t status; + /// Nfapi DLSCH PDU + nfapi_nr_dl_config_dlsch_pdu dlsch_pdu; /// Transport block size uint32_t TBS; /// pointer to pdu from MAC interface (this is "a" in 36.212) @@ -133,7 +135,6 @@ typedef struct { /// codeword this transport block is mapped to uint8_t codeword; /// Number of codewords - uint8_t n_codewords; } NR_DL_gNB_HARQ_t; @@ -141,18 +142,6 @@ typedef struct { /// Pointers to 16 HARQ processes for the DLSCH NR_DL_gNB_HARQ_t *harq_processes[16]; - nfapi_nr_pdsch_time_domain_alloc_type_e time_alloc_type; - uint8_t time_alloc_list_flag; - uint8_t rbg_list[NR_MAX_NB_RBG]; - /// Time domain allocation - uint8_t S; - uint8_t L; - /// Freq domain allocation - uint16_t rb_start; - uint16_t n_rb; - /// BWP index - uint8_t bwp_idx; - /// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding) int32_t *txdataF[8]; /// beamforming weights for UE-spec transmission (antenna ports 5 or 7..14), for each codeword, maximum 4 layers? diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index b7fabb1a276a5a49ff77e4f8574437c29093160c..53e3a14d625f4af8d38431a9e3c8e92b9b88e711 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -86,6 +86,8 @@ #define NR_MAX_NB_RBG 18 #define NR_MAX_NB_LAYERS 8 +#define NR_MAX_NB_CODEWORDS 2 +#define NR_MAX_PDSCH_ENCODED_LENGTH 1000 //random typedef enum { NR_MU_0=0, @@ -116,6 +118,14 @@ typedef enum { nr_FR2 } nr_frequency_range_e; +typedef enum { + BPSK=0, + QPSK, + QAM16, + QAM64, + QAM256 +}nr_mod_t; + typedef struct { /// Size of first RBG uint8_t start_size; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index f2c9ee8661a841f88ea2ea8340bc6d97ca38622d..6758b4f019bdc83c192ea8037186ca6842376197 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -30,11 +30,13 @@ #include "nr_mac_gNB.h" #include "SCHED_NR/sched_nr.h" +#include "PHY/NR_TRANSPORT/nr_dlsch.h" +#include "PHY/NR_TRANSPORT/nr_dci.h" extern RAN_CONTEXT_t RC; /*Scheduling of DLSCH with associated DCI in common search space - * current version has only a DCI for type 1 PDCCH for RA-RNTI*/ + * current version has only a DCI for type 1 PDCCH for C_RNTI*/ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) @@ -63,6 +65,12 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, nfapi_nr_dl_config_dci_dl_pdu_rel15_t *pdu_rel15 = &dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel15; nfapi_nr_dl_config_pdcch_parameters_rel15_t *params_rel15 = &dl_config_pdu->dci_dl_pdu.pdcch_params_rel15; + nfapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_pdu_rel15 = &dl_config_pdu->dlsch_pdu.dlsch_pdu_rel15; + + dlsch_pdu_rel15->start_prb = 0; + dlsch_pdu_rel15->n_prb = 40; + dlsch_pdu_rel15->S = 8; + dlsch_pdu_rel15->L = 6; nr_configure_css_dci_from_mib(&gNB->pdcch_type0_params, kHz30, kHz30, nr_FR1, 0, 0, @@ -70,8 +78,8 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, cfg->rf_config.dl_channel_bandwidth.value); memcpy((void*)params_rel15, (void*)&gNB->pdcch_type0_params, sizeof(nfapi_nr_dl_config_pdcch_parameters_rel15_t)); - pdu_rel15->frequency_domain_assignment = get_RIV(0, 40, 106); - pdu_rel15->time_domain_assignment = get_SLIV(8, 14); + pdu_rel15->frequency_domain_assignment = get_RIV(dlsch_pdu_rel15->start_prb, dlsch_pdu_rel15->n_prb, cfg->rf_config.dl_channel_bandwidth.value); + pdu_rel15->time_domain_assignment = get_SLIV(dlsch_pdu_rel15->S, dlsch_pdu_rel15->L); pdu_rel15->vrb_to_prb_mapping = 1; pdu_rel15->mcs = 12; pdu_rel15->tb_scaling = 1; @@ -92,10 +100,6 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, pdu_rel15->tb_scaling = 1; - pdu_rel15->tb_scaling = 1; - pdu_rel15->tb_scaling = 1; - pdu_rel15->tb_scaling = 1; - LOG_I(MAC, "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d, time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d\n", pdu_rel15->frequency_domain_assignment,