diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 1a2820f236b179397632a4f224f8b8c9598794f9..544b55094418c6eda620cee4074af642001503c1 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1287,6 +1287,17 @@ int get_scan_ssb_first_sc(const double fc, const int nbRB, const int nrBand, con return numGscn; } +// Table 38.211 6.3.3.1-1 +static uint8_t long_prach_dur[4] = {1, 3, 4, 1}; // 0.9, 2.28, 3.35, 0.9 ms + +uint8_t get_long_prach_dur(unsigned int format, unsigned int mu) +{ + AssertFatal(format < 4, "Invalid long PRACH format %d\n", format); + const int num_slots_subframe = (1 << mu); + const int prach_dur_subframes = long_prach_dur[format]; + return (prach_dur_subframes * num_slots_subframe); +} + int get_delay_idx(int delay, int max_delay_comp) { int delay_idx = max_delay_comp + delay; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 6d24f08d45423e2f94626cc839c06926376b7ae5..37fcd6e0102a75d4b62be9d1ba22d6b725ca2998 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -287,6 +287,7 @@ void check_ssb_raster(uint64_t freq, int band, int scs); int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_range, int n_rbs); unsigned short get_m_srs(int c_srs, int b_srs); unsigned short get_N_b_srs(int c_srs, int b_srs); +uint8_t get_long_prach_dur(unsigned int format, unsigned int num_slots_subframe); int get_slot_idx_in_period(const int slot, const frame_structure_t *fs); diff --git a/executables/nr-ru.c b/executables/nr-ru.c index f3311ecb655f1dc6dc225ff6f0cd597ce5598eab..8c458b88caf2a531c4dc49d99190bbdc845a92e8 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1310,22 +1310,24 @@ void *ru_thread(void *param) T(T_GNB_PHY_PRACH_INPUT_SIGNAL, T_INT(proc->frame_rx), T_INT(proc->tti_rx), T_INT(0), T_BUFFER(&ru->common.rxdata[0][fp->get_samples_slot_timestamp(proc->tti_rx-1,fp,0)]/*-ru->N_TA_offset*/, fp->get_samples_per_slot(proc->tti_rx,fp)*4*2)); - int N_dur = get_nr_prach_duration(ru->prach_list[prach_id].fmt); + RU_PRACH_list_t *p = ru->prach_list + prach_id; + int N_dur = get_nr_prach_duration(p->fmt); - for (int prach_oc = 0; prach_oc<ru->prach_list[prach_id].num_prach_ocas; prach_oc++) { - int prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol + prach_oc * N_dur; + for (int prach_oc = 0; prach_oc < p->num_prach_ocas; prach_oc++) { + int prachStartSymbol = p->prachStartSymbol + prach_oc * N_dur; //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. rx_nr_prach_ru(ru, - ru->prach_list[prach_id].fmt, //could also use format - ru->prach_list[prach_id].numRA, + p->fmt, // could also use format + p->numRA, prachStartSymbol, + p->slot, prach_oc, proc->frame_rx, proc->tti_rx); } free_nr_ru_prach_entry(ru,prach_id); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0); - } // end if (prach_id > 0) + } // end if (prach_id >= 0) } // end if (ru->feprx) } // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 9e3df3f2234e8553cd0c5a82469485db3d3d34cc..b4ab491ac08159e5d7c786b68dc17a24b0d78a7f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -43,6 +43,7 @@ void init_prach_list(PHY_VARS_gNB *gNB) gNB->prach_vars.list[i].frame = -1; gNB->prach_vars.list[i].slot = -1; gNB->prach_vars.list[i].beam_nb = -1; + gNB->prach_vars.list[i].num_slots = -1; } } @@ -51,24 +52,20 @@ void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id) gNB->prach_vars.list[prach_id].frame = -1; gNB->prach_vars.list[prach_id].slot = -1; gNB->prach_vars.list[prach_id].beam_nb = -1; + gNB->prach_vars.list[prach_id].num_slots = -1; } int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) { AssertFatal(gNB!=NULL,"gNB is null\n"); for (uint16_t i=0; i<NUMBER_OF_NR_PRACH_MAX; i++) { - LOG_D(PHY,"searching for PRACH in %d.%d prach_index %d=> %d.%d\n", frame,slot,i, - gNB->prach_vars.list[i].frame,gNB->prach_vars.list[i].slot); - if((type == SEARCH_EXIST_OR_FREE) && - (gNB->prach_vars.list[i].frame == -1) && - (gNB->prach_vars.list[i].slot == -1)) { - return i; - } - else if ((type == SEARCH_EXIST) && - (gNB->prach_vars.list[i].frame == frame) && - (gNB->prach_vars.list[i].slot == slot)) { - return i; - } + gNB_PRACH_list_t *p = gNB->prach_vars.list + i; + LOG_D(PHY, "searching for PRACH in %d.%d prach_index %d=> %d.%d\n", frame, slot, i, p->frame, p->slot); + if ((type == SEARCH_EXIST_OR_FREE) && (p->frame == -1) && (p->slot == -1)) { + return i; + } else if ((type == SEARCH_EXIST) && (p->frame == frame) && (p->slot + p->num_slots - 1 == slot)) { + return i; + } } return -1; } @@ -80,6 +77,8 @@ void nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *p gNB_PRACH_list_t *prach = &gNB->prach_vars.list[prach_id]; prach->frame = SFN; prach->slot = Slot; + const int format = prach_pdu->prach_format; + prach->num_slots = (format < 4) ? get_long_prach_dur(format, gNB->frame_parms.numerology_index) : 1; prach->beam_nb = 0; if (gNB->common_vars.beam_id) { int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; @@ -98,6 +97,7 @@ void init_prach_ru_list(RU_t *ru) for (int i = 0; i < NUMBER_OF_NR_RU_PRACH_MAX; i++) { ru->prach_list[i].frame = -1; ru->prach_list[i].slot = -1; + ru->prach_list[i].num_slots = -1; } pthread_mutex_init(&ru->prach_list_mutex, NULL); } @@ -107,16 +107,12 @@ int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type) AssertFatal(ru != NULL, "ru is null\n"); pthread_mutex_lock(&ru->prach_list_mutex); for (int i = 0; i < NUMBER_OF_NR_RU_PRACH_MAX; i++) { - LOG_D(PHY,"searching for PRACH in %d.%d : prach_index %d=> %d.%d\n", - frame, - slot, - i, - ru->prach_list[i].frame,ru->prach_list[i].slot); - if((type == SEARCH_EXIST_OR_FREE) && (ru->prach_list[i].frame == -1) && (ru->prach_list[i].slot == -1)) { + RU_PRACH_list_t *p = ru->prach_list + i; + LOG_D(PHY, "searching for PRACH in %d.%d : prach_index %d=> %d.%d\n", frame, slot, i, p->frame, p->slot); + if ((type == SEARCH_EXIST_OR_FREE) && (p->frame == -1) && (p->slot == -1)) { pthread_mutex_unlock(&ru->prach_list_mutex); return i; - } - else if ((type == SEARCH_EXIST) && (ru->prach_list[i].frame == frame) && (ru->prach_list[i].slot == slot)) { + } else if ((type == SEARCH_EXIST) && (p->frame == frame) && (p->slot + p->num_slots - 1 == slot)) { pthread_mutex_unlock(&ru->prach_list_mutex); return i; } @@ -135,7 +131,9 @@ void nr_fill_prach_ru(RU_t *ru, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_p pthread_mutex_lock(&ru->prach_list_mutex); ru->prach_list[prach_id].frame = SFN; ru->prach_list[prach_id].slot = Slot; - ru->prach_list[prach_id].fmt = prach_pdu->prach_format; + const int fmt = prach_pdu->prach_format; + ru->prach_list[prach_id].num_slots = (fmt < 4) ? get_long_prach_dur(fmt, ru->nr_frame_parms->numerology_index) : 1; + ru->prach_list[prach_id].fmt = fmt; ru->prach_list[prach_id].numRA = prach_pdu->num_ra; ru->prach_list[prach_id].prachStartSymbol = prach_pdu->prach_start_symbol; ru->prach_list[prach_id].num_prach_ocas = prach_pdu->num_prach_ocas; @@ -150,8 +148,14 @@ void free_nr_ru_prach_entry(RU_t *ru, int prach_id) pthread_mutex_unlock(&ru->prach_list_mutex); } - -void rx_nr_prach_ru(RU_t *ru, int prachFormat, int numRA, int prachStartSymbol, int prachOccasion, int frame, int slot) +void rx_nr_prach_ru(RU_t *ru, + int prachFormat, + int numRA, + int prachStartSymbol, + int prachStartSlot, + int prachOccasion, + int frame, + int slot) { AssertFatal(ru != NULL,"ru is null\n"); @@ -193,7 +197,7 @@ void rx_nr_prach_ru(RU_t *ru, int prachFormat, int numRA, int prachStartSymbol, for (int aa=0; aa<ru->nb_rx; aa++){ if (prach_sequence_length == 0) - slot2 = (slot / fp->slots_per_subframe) * fp->slots_per_subframe; + slot2 = prachStartSlot; prach[aa] = (int16_t*)&ru->common.rxdata[aa][fp->get_samples_slot_timestamp(slot2, fp, 0) + sample_offset_slot - ru->N_TA_offset]; } @@ -433,7 +437,6 @@ void rx_nr_prach_ru(RU_t *ru, int prachFormat, int numRA, int prachStartSymbol, } memcpy((void*)rxsigF2,(void *)rxsigF_tmp,N_ZC<<2); } - } void rx_nr_prach(PHY_VARS_gNB *gNB, diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 6dbf6e565d9826f41dc9fa00448bdc72f3a534b8..c1f769b34c260ee8819cd99d8590c408cf60af89 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -275,7 +275,8 @@ void rx_nr_prach_ru(RU_t *ru, int prach_fmt, int numRA, int prachStartSymbol, - int prachOccasion, + int prachStartSlot, + int prachOccasion, int frame, int subframe); diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index 167326e8116c4cb600722c782c48850c439f6565..1417180cb389b4ffc2c725a803702da91b46a6e5 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -195,6 +195,7 @@ typedef struct { int numRA; int prachStartSymbol; int num_prach_ocas; + int num_slots; } RU_PRACH_list_t; #define NUMBER_OF_NR_RU_PRACH_MAX 8 @@ -426,7 +427,6 @@ typedef enum { WAIT_RESYNCH = 3 } rru_cmd_t; - typedef struct RU_t_s { /// ThreadPool for RU tpool_t *threadPool; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 7f3e4f12e173634a86a167be5f85e85ad01e3099..eb0a1acc0e92ef4e038acf7145f2ca27075b280e 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -141,6 +141,8 @@ typedef struct { int slot; // identifier for concurrent beams int beam_nb; + // prach duration in slots + int num_slots; nfapi_nr_prach_pdu_t pdu; } gNB_PRACH_list_t; diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index 12ec6a0b422a39468880f43280162997daeebde9..ad4204bdee441e48859a017587969a5e916f8309 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -111,11 +111,11 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac ru=gNB->RU_list[0]; - int prach_id=find_nr_prach(gNB,frame,slot,SEARCH_EXIST); - - if (prach_id>=0) { + int prach_id = find_nr_prach(gNB, frame, slot, SEARCH_EXIST); + if (prach_id >= 0) { LOG_D(NR_PHY,"%d.%d Got prach entry id %d\n",frame,slot,prach_id); nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_vars.list[prach_id].pdu; + const int prach_start_slot = gNB->prach_vars.list[prach_id].slot; uint8_t prachStartSymbol; uint8_t N_dur = get_nr_prach_duration(prach_pdu->prach_format); @@ -151,7 +151,7 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac "[RAPROC] %d.%d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol " "%u freq index %u\n", frame, - slot, + prach_start_slot, max_preamble[0], max_preamble_energy[0] / 10, max_preamble_energy[0] % 10, @@ -187,6 +187,7 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac if (frame==0) LOG_I(PHY,"prach_I0 = %d.%d dB\n",gNB->measurements.prach_I0/10,gNB->measurements.prach_I0%10); if (gNB->prach_energy_counter < 100) gNB->prach_energy_counter++; } //if prach_id>0 - } //for NUMBER_OF_NR_PRACH_OCCASION_MAX + rach_ind->slot = prach_start_slot; + } // for NUMBER_OF_NR_PRACH_OCCASION_MAX VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); } diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index fd2c1bcf773374cc5e5d976973c1e9517979cb0c..0205c339df7174e89dbe1fc920e9079d38e8d026 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -774,7 +774,7 @@ int main(int argc, char **argv){ } } - rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, prachOccasion, frame, slot); + rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, slot, prachOccasion, frame, slot); for (int i = 0; i < ru->nb_rx; ++i) gNB->prach_vars.rxsigF[i] = ru->prach_rxsigF[prachOccasion][i]; diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 862bf563df433271576784df15656b68aef4d6c1..218226eb2cbeb32063c68e578ed0fa06d955566c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -475,7 +475,8 @@ static void config_common(gNB_MAC_INST *nrmac, } } - frame_type_t frame_type = get_frame_type(*frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); + NR_FreqBandIndicatorNR_t band = *frequencyInfoDL->frequencyBandList.list.array[0]; + frame_type_t frame_type = get_frame_type(band, *scc->ssbSubcarrierSpacing); nrmac->common_channels[0].frame_type = frame_type; // Cell configuration @@ -511,18 +512,26 @@ static void config_common(gNB_MAC_INST *nrmac, cfg->prach_config.prach_sequence_length.tl.tag = NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_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++; + if (rach_ConfigCommon->msg1_SubcarrierSpacing) cfg->prach_config.prach_sub_c_spacing.value = *rach_ConfigCommon->msg1_SubcarrierSpacing; - else - cfg->prach_config.prach_sub_c_spacing.value = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + else { + // If absent, use SCS as derived from the prach-ConfigurationIndex (for 839) + int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; + int frame_type = get_frame_type(band, frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing); + const int64_t *prach_config_info_p = get_prach_config_info(frequency_range, config_index, frame_type); + int format = prach_config_info_p[0]; + cfg->prach_config.prach_sub_c_spacing.value = get_delta_f_RA_long(format); + } + 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) { case 0: @@ -543,10 +552,6 @@ static void config_common(gNB_MAC_INST *nrmac, 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.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++) { @@ -588,6 +593,14 @@ static void config_common(gNB_MAC_INST *nrmac, cfg->prach_config.ssb_per_rach.tl.tag = NFAPI_NR_CONFIG_SSB_PER_RACH_TAG; cfg->num_tlv++; + // compute and store prach duration in slots from rach_ConfigCommon + NR_RACH_ConfigGeneric_t *rachConfig = + &scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric; + NR_COMMON_channels_t *cc = nrmac->common_channels; + const uint32_t pointA = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA; + const int prach_fmt = (get_nr_prach_format_from_index(rachConfig->prach_ConfigurationIndex, pointA, cc->frame_type) & 0xff); + cc->prach_len = (prach_fmt < 4) ? get_long_prach_dur(prach_fmt, *scc->ssbSubcarrierSpacing) : 1; + // SSB Table Configuration cfg->ssb_table.ssb_offset_point_a.value = diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 49f88373dfb94ad08c832b18b2e58e7d25b184f5..d3455ad8e8b39a694c7d153223a619098705f875 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -223,11 +223,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_ if (get_softmodem_params()->phy_test == 0) { /* we need to make sure that resources for PRACH are free. To avoid that e.g. PUSCH has already been scheduled, make sure we schedule before - anything else: below, we simply assume an advance one frame (minus one - slot, because otherwise we would allocate the current slot in + anything else: below, we simply assume an advance one frame (minus + prach duration, because otherwise we would allocate the current slot in UL_tti_req_ahead), but be aware that, e.g., K2 is allowed to be larger (schedule_nr_prach will assert if resources are not free). */ - const sub_frame_t n_slots_ahead = slots_frame - 1 + get_NTN_Koffset(scc); + const int n_slots_ahead = slots_frame - cc->prach_len + get_NTN_Koffset(scc); const frame_t f = (frame + (slot + n_slots_ahead) / slots_frame) % 1024; const sub_frame_t s = (slot + n_slots_ahead) % slots_frame; schedule_nr_prach(module_idP, f, s); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 4fe45742091f6585c0137b9bbadd32760fbbec12..c6f64e21090d8ab50fde691f08010a98f90cc108 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -356,6 +356,27 @@ static void schedule_nr_MsgA_pusch(NR_UplinkConfigCommon_t *uplinkConfigCommon, UL_tti_req->n_pdus += 1; } +static void fill_vrb(const frame_t frame, + const sub_frame_t slot, + int nb_rb, + int beam_idx, + int vrb_size, + int slots_frame, + int rb_start, + int start_symb, + int num_symb, + NR_COMMON_channels_t *cc) +{ + const int index = ul_buffer_index(frame, slot, slots_frame, vrb_size); + uint16_t *vrb_map_UL = &cc->vrb_map_UL[beam_idx][index * MAX_BWP_SIZE]; + for (int i = 0; i < nb_rb; ++i) { + AssertFatal( + !(vrb_map_UL[rb_start + i] & SL_to_bitmap(start_symb, num_symb)), + "PRACH resources are already occupied!\n"); + vrb_map_UL[rb_start + i] |= SL_to_bitmap(start_symb, num_symb); + } +} + void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { gNB_MAC_INST *gNB = RC.nrmac[module_idP]; @@ -557,13 +578,29 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP // block resources in vrb_map_UL const int mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch); - index = ul_buffer_index(frameP, slotP, slots_frame, gNB->vrb_map_UL_size); - uint16_t *vrb_map_UL = &cc->vrb_map_UL[beam.idx][index * MAX_BWP_SIZE]; - for (int i = 0; i < n_ra_rb * fdm; ++i) { - AssertFatal( - !(vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] & SL_to_bitmap(start_symbol, N_t_slot * N_dur)), - "PRACH resources are already occupied!\n"); - vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] |= SL_to_bitmap(start_symbol, N_t_slot * N_dur); + // mark PRBs as occupied for current and future slots if prach extends beyond current slot + int total_prach_slots; + if (format0 < 4) { + N_dur = 14; // number of PRACH symbols in PRACH slot + total_prach_slots = get_long_prach_dur(format0, mu_pusch); + AssertFatal(slotP + total_prach_slots - 1 < slots_frame, "PRACH cannot extend across frames\n"); + } else { + // TODO: to be revisited for format B4 (also extends beyond current slot for FR1 30kHz SCS and FR2) + AssertFatal((format != 0xb4) || (mu_pusch < 1), "Format B4 not supported for this PUSCH SCS\n"); + total_prach_slots = 1; + } + // reserve PRBs occupied by PRACH in all PRACH slot. + for (int i = 0; i < total_prach_slots; i++) { + fill_vrb(frameP, + slotP + i, + n_ra_rb * fdm, + beam.idx, + gNB->vrb_map_UL_size, + slots_frame, + bwp_start + rach_ConfigGeneric->msg1_FrequencyStart, + start_symbol, + N_t_slot * N_dur, + cc); } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index a464611ec856a3d187e553464e51f97dd7d6d02b..13083169d061a4a53d8605e28b3d41eb8c5fb7db 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -301,6 +301,8 @@ typedef struct { uint8_t ssb_index[MAX_NUM_OF_SSB]; //CB preambles for each SSB int cb_preambles_per_ssb; + /// Max prach length in slots + int prach_len; } NR_COMMON_channels_t; // SP ZP CSI-RS Resource Set Activation/Deactivation MAC CE