Fix scheduler for long prach

Long PRACH extends beyond a slot. Changes necessary to mark future slots
that may contain prach in ru, phy and mac functions.

In RU, the PRACH IDFT is done only after receiving last slot and marks
for L1 to start processing. The L1 processes at the last prach slot and
reports to MAC with the first slot index.

In MAC scheduler, the VRB for future slots are also marked as used.
PRACH scheduler is called in advance one frame minus num prach slots.
This commit is contained in:
Sakthivel Velumani
2025-02-25 11:58:41 -05:00
parent 94c74f4a1d
commit cf0206e7c6
13 changed files with 132 additions and 59 deletions
+28 -25
View File
@@ -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,
@@ -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);
+1 -1
View File
@@ -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;
+2
View File
@@ -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;
+6 -5
View File
@@ -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);
}
+1 -1
View File
@@ -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];