Commit cf0206e7 authored by Sakthivel Velumani's avatar Sakthivel Velumani

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.
parent 94c74f4a
...@@ -1287,6 +1287,17 @@ int get_scan_ssb_first_sc(const double fc, const int nbRB, const int nrBand, con ...@@ -1287,6 +1287,17 @@ int get_scan_ssb_first_sc(const double fc, const int nbRB, const int nrBand, con
return numGscn; 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 get_delay_idx(int delay, int max_delay_comp)
{ {
int delay_idx = max_delay_comp + delay; int delay_idx = max_delay_comp + delay;
......
...@@ -287,6 +287,7 @@ void check_ssb_raster(uint64_t freq, int band, int scs); ...@@ -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); 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_m_srs(int c_srs, int b_srs);
unsigned short get_N_b_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); int get_slot_idx_in_period(const int slot, const frame_structure_t *fs);
......
...@@ -1310,22 +1310,24 @@ void *ru_thread(void *param) ...@@ -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(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)); 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++) { for (int prach_oc = 0; prach_oc < p->num_prach_ocas; prach_oc++) {
int prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol + prach_oc * N_dur; 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}. //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, rx_nr_prach_ru(ru,
ru->prach_list[prach_id].fmt, //could also use format p->fmt, // could also use format
ru->prach_list[prach_id].numRA, p->numRA,
prachStartSymbol, prachStartSymbol,
p->slot,
prach_oc, prach_oc,
proc->frame_rx, proc->frame_rx,
proc->tti_rx); proc->tti_rx);
} }
free_nr_ru_prach_entry(ru,prach_id); free_nr_ru_prach_entry(ru,prach_id);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0); 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 (ru->feprx)
} // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { } // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
......
...@@ -43,6 +43,7 @@ void init_prach_list(PHY_VARS_gNB *gNB) ...@@ -43,6 +43,7 @@ void init_prach_list(PHY_VARS_gNB *gNB)
gNB->prach_vars.list[i].frame = -1; gNB->prach_vars.list[i].frame = -1;
gNB->prach_vars.list[i].slot = -1; gNB->prach_vars.list[i].slot = -1;
gNB->prach_vars.list[i].beam_nb = -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) ...@@ -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].frame = -1;
gNB->prach_vars.list[prach_id].slot = -1; gNB->prach_vars.list[prach_id].slot = -1;
gNB->prach_vars.list[prach_id].beam_nb = -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) { int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) {
AssertFatal(gNB!=NULL,"gNB is null\n"); AssertFatal(gNB!=NULL,"gNB is null\n");
for (uint16_t i=0; i<NUMBER_OF_NR_PRACH_MAX; i++) { 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_list_t *p = gNB->prach_vars.list + i;
gNB->prach_vars.list[i].frame,gNB->prach_vars.list[i].slot); 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) && if ((type == SEARCH_EXIST_OR_FREE) && (p->frame == -1) && (p->slot == -1)) {
(gNB->prach_vars.list[i].frame == -1) && return i;
(gNB->prach_vars.list[i].slot == -1)) { } else if ((type == SEARCH_EXIST) && (p->frame == frame) && (p->slot + p->num_slots - 1 == slot)) {
return i; return i;
} }
else if ((type == SEARCH_EXIST) &&
(gNB->prach_vars.list[i].frame == frame) &&
(gNB->prach_vars.list[i].slot == slot)) {
return i;
}
} }
return -1; return -1;
} }
...@@ -80,6 +77,8 @@ void nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *p ...@@ -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]; gNB_PRACH_list_t *prach = &gNB->prach_vars.list[prach_id];
prach->frame = SFN; prach->frame = SFN;
prach->slot = Slot; 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; prach->beam_nb = 0;
if (gNB->common_vars.beam_id) { if (gNB->common_vars.beam_id) {
int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; 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) ...@@ -98,6 +97,7 @@ void init_prach_ru_list(RU_t *ru)
for (int i = 0; i < NUMBER_OF_NR_RU_PRACH_MAX; i++) { for (int i = 0; i < NUMBER_OF_NR_RU_PRACH_MAX; i++) {
ru->prach_list[i].frame = -1; ru->prach_list[i].frame = -1;
ru->prach_list[i].slot = -1; ru->prach_list[i].slot = -1;
ru->prach_list[i].num_slots = -1;
} }
pthread_mutex_init(&ru->prach_list_mutex, NULL); 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) ...@@ -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"); AssertFatal(ru != NULL, "ru is null\n");
pthread_mutex_lock(&ru->prach_list_mutex); pthread_mutex_lock(&ru->prach_list_mutex);
for (int i = 0; i < NUMBER_OF_NR_RU_PRACH_MAX; i++) { 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", RU_PRACH_list_t *p = ru->prach_list + i;
frame, LOG_D(PHY, "searching for PRACH in %d.%d : prach_index %d=> %d.%d\n", frame, slot, i, p->frame, p->slot);
slot, if ((type == SEARCH_EXIST_OR_FREE) && (p->frame == -1) && (p->slot == -1)) {
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)) {
pthread_mutex_unlock(&ru->prach_list_mutex); pthread_mutex_unlock(&ru->prach_list_mutex);
return i; return i;
} } else if ((type == SEARCH_EXIST) && (p->frame == frame) && (p->slot + p->num_slots - 1 == slot)) {
else if ((type == SEARCH_EXIST) && (ru->prach_list[i].frame == frame) && (ru->prach_list[i].slot == slot)) {
pthread_mutex_unlock(&ru->prach_list_mutex); pthread_mutex_unlock(&ru->prach_list_mutex);
return i; 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 ...@@ -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); pthread_mutex_lock(&ru->prach_list_mutex);
ru->prach_list[prach_id].frame = SFN; ru->prach_list[prach_id].frame = SFN;
ru->prach_list[prach_id].slot = Slot; 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].numRA = prach_pdu->num_ra;
ru->prach_list[prach_id].prachStartSymbol = prach_pdu->prach_start_symbol; ru->prach_list[prach_id].prachStartSymbol = prach_pdu->prach_start_symbol;
ru->prach_list[prach_id].num_prach_ocas = prach_pdu->num_prach_ocas; 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) ...@@ -150,8 +148,14 @@ void free_nr_ru_prach_entry(RU_t *ru, int prach_id)
pthread_mutex_unlock(&ru->prach_list_mutex); pthread_mutex_unlock(&ru->prach_list_mutex);
} }
void rx_nr_prach_ru(RU_t *ru,
void rx_nr_prach_ru(RU_t *ru, int prachFormat, int numRA, int prachStartSymbol, int prachOccasion, int frame, int slot) int prachFormat,
int numRA,
int prachStartSymbol,
int prachStartSlot,
int prachOccasion,
int frame,
int slot)
{ {
AssertFatal(ru != NULL,"ru is null\n"); 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, ...@@ -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++){ for (int aa=0; aa<ru->nb_rx; aa++){
if (prach_sequence_length == 0) 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]; 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, ...@@ -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); memcpy((void*)rxsigF2,(void *)rxsigF_tmp,N_ZC<<2);
} }
} }
void rx_nr_prach(PHY_VARS_gNB *gNB, void rx_nr_prach(PHY_VARS_gNB *gNB,
......
...@@ -275,7 +275,8 @@ void rx_nr_prach_ru(RU_t *ru, ...@@ -275,7 +275,8 @@ void rx_nr_prach_ru(RU_t *ru,
int prach_fmt, int prach_fmt,
int numRA, int numRA,
int prachStartSymbol, int prachStartSymbol,
int prachOccasion, int prachStartSlot,
int prachOccasion,
int frame, int frame,
int subframe); int subframe);
......
...@@ -195,6 +195,7 @@ typedef struct { ...@@ -195,6 +195,7 @@ typedef struct {
int numRA; int numRA;
int prachStartSymbol; int prachStartSymbol;
int num_prach_ocas; int num_prach_ocas;
int num_slots;
} RU_PRACH_list_t; } RU_PRACH_list_t;
#define NUMBER_OF_NR_RU_PRACH_MAX 8 #define NUMBER_OF_NR_RU_PRACH_MAX 8
...@@ -426,7 +427,6 @@ typedef enum { ...@@ -426,7 +427,6 @@ typedef enum {
WAIT_RESYNCH = 3 WAIT_RESYNCH = 3
} rru_cmd_t; } rru_cmd_t;
typedef struct RU_t_s { typedef struct RU_t_s {
/// ThreadPool for RU /// ThreadPool for RU
tpool_t *threadPool; tpool_t *threadPool;
......
...@@ -141,6 +141,8 @@ typedef struct { ...@@ -141,6 +141,8 @@ typedef struct {
int slot; int slot;
// identifier for concurrent beams // identifier for concurrent beams
int beam_nb; int beam_nb;
// prach duration in slots
int num_slots;
nfapi_nr_prach_pdu_t pdu; nfapi_nr_prach_pdu_t pdu;
} gNB_PRACH_list_t; } gNB_PRACH_list_t;
......
...@@ -111,11 +111,11 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac ...@@ -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]; ru=gNB->RU_list[0];
int prach_id=find_nr_prach(gNB,frame,slot,SEARCH_EXIST); int prach_id = find_nr_prach(gNB, frame, slot, SEARCH_EXIST);
if (prach_id >= 0) {
if (prach_id>=0) {
LOG_D(NR_PHY,"%d.%d Got prach entry id %d\n",frame,slot,prach_id); 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; 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 prachStartSymbol;
uint8_t N_dur = get_nr_prach_duration(prach_pdu->prach_format); 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 ...@@ -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 " "[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", "%u freq index %u\n",
frame, frame,
slot, prach_start_slot,
max_preamble[0], max_preamble[0],
max_preamble_energy[0] / 10, max_preamble_energy[0] / 10,
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 ...@@ -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 (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 (gNB->prach_energy_counter < 100) gNB->prach_energy_counter++;
} //if prach_id>0 } //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); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
} }
...@@ -774,7 +774,7 @@ int main(int argc, char **argv){ ...@@ -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) for (int i = 0; i < ru->nb_rx; ++i)
gNB->prach_vars.rxsigF[i] = ru->prach_rxsigF[prachOccasion][i]; gNB->prach_vars.rxsigF[i] = ru->prach_rxsigF[prachOccasion][i];
......
...@@ -475,7 +475,8 @@ static void config_common(gNB_MAC_INST *nrmac, ...@@ -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; nrmac->common_channels[0].frame_type = frame_type;
// Cell configuration // Cell configuration
...@@ -511,18 +512,26 @@ static void config_common(gNB_MAC_INST *nrmac, ...@@ -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->prach_config.prach_sequence_length.tl.tag = NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG;
cfg->num_tlv++; 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) if (rach_ConfigCommon->msg1_SubcarrierSpacing)
cfg->prach_config.prach_sub_c_spacing.value = *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; // 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->prach_config.prach_sub_c_spacing.tl.tag = NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG;
cfg->num_tlv++; cfg->num_tlv++;
cfg->prach_config.restricted_set_config.value = rach_ConfigCommon->restrictedSetConfig; 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->prach_config.restricted_set_config.tl.tag = NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG;
cfg->num_tlv++; 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: case 0:
...@@ -543,10 +552,6 @@ static void config_common(gNB_MAC_INST *nrmac, ...@@ -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->prach_config.num_prach_fd_occasions.tl.tag = NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG;
cfg->num_tlv++; 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)); 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++) {
...@@ -588,6 +593,14 @@ static void config_common(gNB_MAC_INST *nrmac, ...@@ -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->prach_config.ssb_per_rach.tl.tag = NFAPI_NR_CONFIG_SSB_PER_RACH_TAG;
cfg->num_tlv++; 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 // SSB Table Configuration
cfg->ssb_table.ssb_offset_point_a.value = cfg->ssb_table.ssb_offset_point_a.value =
......
...@@ -223,11 +223,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_ ...@@ -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) { if (get_softmodem_params()->phy_test == 0) {
/* we need to make sure that resources for PRACH are free. To avoid that /* 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 e.g. PUSCH has already been scheduled, make sure we schedule before
anything else: below, we simply assume an advance one frame (minus one anything else: below, we simply assume an advance one frame (minus
slot, because otherwise we would allocate the current slot in 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 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). */ (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 frame_t f = (frame + (slot + n_slots_ahead) / slots_frame) % 1024;
const sub_frame_t s = (slot + n_slots_ahead) % slots_frame; const sub_frame_t s = (slot + n_slots_ahead) % slots_frame;
schedule_nr_prach(module_idP, f, s); schedule_nr_prach(module_idP, f, s);
......
...@@ -356,6 +356,27 @@ static void schedule_nr_MsgA_pusch(NR_UplinkConfigCommon_t *uplinkConfigCommon, ...@@ -356,6 +356,27 @@ static void schedule_nr_MsgA_pusch(NR_UplinkConfigCommon_t *uplinkConfigCommon,
UL_tti_req->n_pdus += 1; 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) void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
{ {
gNB_MAC_INST *gNB = RC.nrmac[module_idP]; 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 ...@@ -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 // block resources in vrb_map_UL
const int mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; const int mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch); 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); // mark PRBs as occupied for current and future slots if prach extends beyond current slot
uint16_t *vrb_map_UL = &cc->vrb_map_UL[beam.idx][index * MAX_BWP_SIZE]; int total_prach_slots;
for (int i = 0; i < n_ra_rb * fdm; ++i) { if (format0 < 4) {
AssertFatal( N_dur = 14; // number of PRACH symbols in PRACH slot
!(vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] & SL_to_bitmap(start_symbol, N_t_slot * N_dur)), total_prach_slots = get_long_prach_dur(format0, mu_pusch);
"PRACH resources are already occupied!\n"); AssertFatal(slotP + total_prach_slots - 1 < slots_frame, "PRACH cannot extend across frames\n");
vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] |= SL_to_bitmap(start_symbol, N_t_slot * N_dur); } 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);
} }
} }
} }
......
...@@ -301,6 +301,8 @@ typedef struct { ...@@ -301,6 +301,8 @@ typedef struct {
uint8_t ssb_index[MAX_NUM_OF_SSB]; uint8_t ssb_index[MAX_NUM_OF_SSB];
//CB preambles for each SSB //CB preambles for each SSB
int cb_preambles_per_ssb; int cb_preambles_per_ssb;
/// Max prach length in slots
int prach_len;
} NR_COMMON_channels_t; } NR_COMMON_channels_t;
// SP ZP CSI-RS Resource Set Activation/Deactivation MAC CE // SP ZP CSI-RS Resource Set Activation/Deactivation MAC CE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment