reworking prach scheduler to use new rach occasion information

This commit is contained in:
francescomani
2025-03-12 10:15:49 +01:00
parent 8f1661c66c
commit 24fed617b5
4 changed files with 46 additions and 141 deletions
+1 -3
View File
@@ -320,7 +320,7 @@ typedef struct {
int Pc_max; int Pc_max;
} NR_PRACH_RESOURCES_t; } NR_PRACH_RESOURCES_t;
typedef struct{ typedef struct {
float ssb_per_ro; float ssb_per_ro;
int preambles_per_ssb; int preambles_per_ssb;
} ssb_ro_preambles_t; } ssb_ro_preambles_t;
@@ -362,8 +362,6 @@ typedef struct {
bool RA_active; bool RA_active;
/// Random-access preamble index /// Random-access preamble index
int ra_PreambleIndex; int ra_PreambleIndex;
// When multiple SSBs per RO is configured, this indicates which one is selected in this RO -> this is used to properly compute the PRACH preamble
uint8_t ssb_nb_in_ro;
int zeroCorrelationZoneConfig; int zeroCorrelationZoneConfig;
int restricted_set_config; int restricted_set_config;
// selected SSB for RACH (not the SSB-Index but the cumulative index, excluding not trasmitted SSBs) // selected SSB for RACH (not the SSB-Index but the cumulative index, excluding not trasmitted SSBs)
-1
View File
@@ -302,4 +302,3 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t ca
for (int i = mac->TAG_list.count; i > 0 ; i--) for (int i = mac->TAG_list.count; i > 0 ; i--)
asn_sequence_del(&mac->TAG_list, i - 1, 1); asn_sequence_del(&mac->TAG_list, i - 1, 1);
} }
+11 -11
View File
@@ -403,7 +403,7 @@ static void ra_resource_selection(NR_UE_MAC_INST_t *mac)
ssb = mac->mib_ssb; ssb = mac->mib_ssb;
// set the PREAMBLE_INDEX to a ra-PreambleIndex corresponding to the selected SSB // set the PREAMBLE_INDEX to a ra-PreambleIndex corresponding to the selected SSB
ra->ra_PreambleIndex = res->ra_PreambleIndex; ra->ra_PreambleIndex = res->ra_PreambleIndex;
ra->ro_mask_index = cfra->resourcesTwoStep_r16.ra_ssb_OccasionMaskIndex; ra->ro_mask_index = cfra->resourcesTwoStep_r16.ra_ssb_OccasionMaskIndex;
break; break;
} }
} }
@@ -454,7 +454,7 @@ static void select_prach_occasion(RA_config_t *ra,
int idx_ssb = 0; int idx_ssb = 0;
int temp_idx = 0; int temp_idx = 0;
if (ra->ssb_ro_config.ssb_per_ro < 1) { if (ra->ssb_ro_config.ssb_per_ro < 1) {
num_ros_per_ssb = (int) (1 / ra->ssb_ro_config.ssb_per_ro); num_ros_per_ssb = (int)(1 / ra->ssb_ro_config.ssb_per_ro);
idx_ssb = (rand_r(&seed) % num_ros_per_ssb); idx_ssb = (rand_r(&seed) % num_ros_per_ssb);
temp_idx = ra->ra_ssb * num_ros_per_ssb + idx_ssb; temp_idx = ra->ra_ssb * num_ros_per_ssb + idx_ssb;
} else { } else {
@@ -508,13 +508,13 @@ static void configure_prach_occasions(NR_UE_MAC_INST_t *mac, int prach_config_in
if (fs->frame_type == TDD && !check_mixed_slot_prach(fs, slot, start_symbol, end_symbol)) if (fs->frame_type == TDD && !check_mixed_slot_prach(fs, slot, start_symbol, end_symbol))
continue; continue;
for (int f = 0; f < num_fd_occasions; f++) { // fd occasions for (int f = 0; f < num_fd_occasions; f++) { // fd occasions
ra_occasions_period[num_ra_occasions_period] = (prach_occasion_info_t) { ra_occasions_period[num_ra_occasions_period] =
.slot = slot, (prach_occasion_info_t){.slot = slot,
.frame_info[0] = prach_info.x, .frame_info[0] = prach_info.x,
.frame_info[1] = n == 0 ? prach_info.y : prach_info.y2, .frame_info[1] = n == 0 ? prach_info.y : prach_info.y2,
.start_symbol = start_symbol, .start_symbol = start_symbol,
.fdm = f, .fdm = f,
.format = prach_info.format}; .format = prach_info.format};
LOG_D(NR_MAC, LOG_D(NR_MAC,
"RA occasion %d: slot %d start symbol %d fd occasion %d\n", "RA occasion %d: slot %d start symbol %d fd occasion %d\n",
num_ra_occasions_period, num_ra_occasions_period,
@@ -533,10 +533,10 @@ static void configure_prach_occasions(NR_UE_MAC_INST_t *mac, int prach_config_in
ra->association_periods = 1; ra->association_periods = 1;
int nb_eq_ssb = mac->ssb_list.nb_tx_ssb; int nb_eq_ssb = mac->ssb_list.nb_tx_ssb;
if (ra->ssb_ro_config.ssb_per_ro < 1) if (ra->ssb_ro_config.ssb_per_ro < 1)
nb_eq_ssb *= (int) (1 / ra->ssb_ro_config.ssb_per_ro); nb_eq_ssb *= (int)(1 / ra->ssb_ro_config.ssb_per_ro);
int nb_eq_ro = num_ra_occasions_period; int nb_eq_ro = num_ra_occasions_period;
if (ra->ssb_ro_config.ssb_per_ro > 1) if (ra->ssb_ro_config.ssb_per_ro > 1)
nb_eq_ro *= (int) ra->ssb_ro_config.ssb_per_ro; nb_eq_ro *= (int)ra->ssb_ro_config.ssb_per_ro;
while (nb_eq_ssb > nb_eq_ro) { while (nb_eq_ssb > nb_eq_ro) {
// not enough PRACH occasions -> need to increase association period // not enough PRACH occasions -> need to increase association period
ra->association_periods <<= 1; ra->association_periods <<= 1;
+34 -126
View File
@@ -1939,91 +1939,6 @@ static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac)
} }
} }
// Returns a RACH occasion if any matches the SSB idx, the frame and the slot
static int get_nr_prach_info_from_ssb_index(prach_association_pattern_t *prach_assoc_pattern,
int ssb_idx,
int frame,
int slot,
ssb_list_info_t *ssb_list,
prach_occasion_info_t **prach_occasion_info_pp)
{
prach_occasion_slot_t *prach_occasion_slot_p = NULL;
*prach_occasion_info_pp = NULL;
// Search for a matching RO slot in the SSB_to_RO map
// A valid RO slot will match:
// - ssb_idx mapped to one of the ROs in that RO slot
// - exact slot number
// - frame offset
int idx_list = ssb_list->nb_ssb_per_index[ssb_idx];
ssb_info_t *ssb_info_p = &ssb_list->tx_ssb[idx_list];
LOG_D(NR_MAC, "checking for prach : ssb_info_p->nb_mapped_ro %d\n", ssb_info_p->nb_mapped_ro);
for (int n_mapped_ro = 0; n_mapped_ro < ssb_info_p->nb_mapped_ro; n_mapped_ro++) {
LOG_D(NR_MAC,
"%d.%d: mapped_ro[%d]->frame.slot %d.%d, prach_assoc_pattern->nb_of_frame %d\n",
frame,
slot,
n_mapped_ro,
ssb_info_p->mapped_ro[n_mapped_ro]->frame,
ssb_info_p->mapped_ro[n_mapped_ro]->slot,
prach_assoc_pattern->nb_of_frame);
if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) && prach_assoc_pattern->prach_conf_period_list[0].nb_of_frame != 0 &&
(ssb_info_p->mapped_ro[n_mapped_ro]->frame == (frame % prach_assoc_pattern->nb_of_frame))) {
uint8_t prach_config_period_nb = ssb_info_p->mapped_ro[n_mapped_ro]->frame / prach_assoc_pattern->prach_conf_period_list[0].nb_of_frame;
uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ro[n_mapped_ro]->frame % prach_assoc_pattern->prach_conf_period_list[0].nb_of_frame;
prach_occasion_slot_p = &prach_assoc_pattern->prach_conf_period_list[prach_config_period_nb].prach_occasion_slot_map[frame_nb_in_prach_config_period][slot];
}
}
// If there is a matching RO slot in the SSB_to_RO map
if (NULL != prach_occasion_slot_p) {
// A random RO mapped to the SSB index should be selected in the slot
// First count the number of times the SSB index is found in that RO
uint8_t nb_mapped_ssb = 0;
for (int ro_in_time = 0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) {
for (int ro_in_freq = 0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) {
prach_occasion_info_t *ro_p =
prach_occasion_slot_p->prach_occasion + ro_in_time * prach_occasion_slot_p->nb_of_prach_occasion_in_freq + ro_in_freq;
for (uint8_t ssb_nb = 0; ssb_nb < ro_p->nb_mapped_ssb; ssb_nb++) {
if (ro_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
nb_mapped_ssb++;
}
}
}
}
// Choose a random SSB nb
uint8_t random_ssb_nb = 0;
random_ssb_nb = ((taus()) % nb_mapped_ssb);
// Select the RO according to the chosen random SSB nb
nb_mapped_ssb=0;
for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) {
for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) {
prach_occasion_info_t *ro_p =
prach_occasion_slot_p->prach_occasion + ro_in_time * prach_occasion_slot_p->nb_of_prach_occasion_in_freq + ro_in_freq;
for (uint8_t ssb_nb = 0; ssb_nb < ro_p->nb_mapped_ssb; ssb_nb++) {
if (ro_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
if (nb_mapped_ssb == random_ssb_nb) {
*prach_occasion_info_pp = ro_p;
return 1;
}
else {
nb_mapped_ssb++;
}
}
}
}
}
}
return 0;
}
// Build the SSB to RO mapping upon RRC configuration update // Build the SSB to RO mapping upon RRC configuration update
void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac) void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac)
{ {
@@ -2522,6 +2437,23 @@ void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot)
} }
} }
static bool is_prach_frame(frame_t frame, prach_occasion_info_t *prach_occasion_info, int association_periods)
{
int config_period = prach_occasion_info->frame_info[0];
int frame_period = config_period * association_periods;
int frame_in_period = frame % frame_period;
if (association_periods > 1) {
int current_assoc_period = frame_in_period / config_period;
if (current_assoc_period != prach_occasion_info->association_period_idx)
return false;
frame_in_period %= config_period;
}
if (frame_in_period == prach_occasion_info->frame_info[1]) // SFN % x == y (see Tables in Table 6.3.3.2 of 38.211)
return true;
else
return false;
}
// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x // This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x
// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
// - todo: // - todo:
@@ -2533,49 +2465,36 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
if (ra->ra_state != nrRA_GENERATE_PREAMBLE) if (ra->ra_state != nrRA_GENERATE_PREAMBLE)
return; return;
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; // Get any valid PRACH occasion in the current slot for the selected SSB index
fapi_nr_prach_config_t *prach_config = &cfg->prach_config; prach_occasion_info_t *prach_occasion_info = &ra->sched_ro_info;
const int bwp_id = mac->current_UL_BWP->bwp_id; if (!is_prach_frame(frameP, prach_occasion_info, ra->association_periods))
return;
if (is_ul_slot(slotP, &mac->frame_structure)) { if (is_ul_slot(slotP, &mac->frame_structure)) {
// WIP Need to get the proper selected ssb_idx if (slotP == prach_occasion_info->slot) {
// Initial beam selection functionality is not available yet
uint8_t selected_gnb_ssb_idx = mac->mib_ssb;
// Get any valid PRACH occasion in the current slot for the selected SSB index
prach_occasion_info_t *prach_occasion_info_p;
int is_nr_prach_slot = get_nr_prach_info_from_ssb_index(&mac->prach_assoc_pattern[bwp_id],
selected_gnb_ssb_idx,
(int)frameP,
(int)slotP,
&mac->ssb_list,
&prach_occasion_info_p);
if (is_nr_prach_slot) {
AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n");
nr_get_RA_window(mac); nr_get_RA_window(mac);
uint16_t format = prach_occasion_info_p->format;
uint16_t format0 = format & 0xff; // single PRACH format
uint16_t format1 = (format >> 8) & 0xff; // dual PRACH format
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH); fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH);
if (!pdu) { if (!pdu) {
LOG_E(NR_MAC, "Error in PRACH allocation\n"); LOG_E(NR_MAC, "Error in PRACH allocation\n");
return; return;
} }
uint16_t format = prach_occasion_info->format;
uint16_t format0 = format & 0xff; // single PRACH format
uint16_t format1 = (format >> 8) & 0xff; // dual PRACH format
fapi_nr_prach_config_t *prach_config = &mac->phy_config.config_req.prach_config;
pdu->prach_config_pdu = (fapi_nr_ul_config_prach_pdu){ pdu->prach_config_pdu = (fapi_nr_ul_config_prach_pdu){
.phys_cell_id = mac->physCellId, .phys_cell_id = mac->physCellId,
.num_prach_ocas = 1, .num_prach_ocas = 1,
.prach_slot = prach_occasion_info_p->slot, .prach_slot = prach_occasion_info->slot,
.prach_start_symbol = prach_occasion_info_p->start_symbol, .prach_start_symbol = prach_occasion_info->start_symbol,
.num_ra = prach_occasion_info_p->fdm, .num_ra = prach_occasion_info->fdm,
.num_cs = get_NCS(ra->zeroCorrelationZoneConfig, format0, ra->restricted_set_config), .num_cs = get_NCS(ra->zeroCorrelationZoneConfig, format0, ra->restricted_set_config),
.root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index, .root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].prach_root_sequence_index,
.restricted_set = prach_config->restricted_set_config, .restricted_set = prach_config->restricted_set_config,
.freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1}; .freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].k1};
LOG_I(NR_MAC, LOG_I(NR_MAC,
"PRACH scheduler: Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n", "PRACH scheduler: Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n",
@@ -2584,15 +2503,6 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
pdu->prach_config_pdu.prach_start_symbol, pdu->prach_config_pdu.prach_start_symbol,
pdu->prach_config_pdu.num_ra); pdu->prach_config_pdu.num_ra);
// Search which SSB is mapped in the RO (among all the SSBs mapped to this RO)
for (int ssb_nb_in_ro=0; ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb; ssb_nb_in_ro++) {
if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb_in_ro] == selected_gnb_ssb_idx) {
ra->ssb_nb_in_ro = ssb_nb_in_ro;
break;
}
}
AssertFatal(ra->ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx);
if (format1 != 0xff) { if (format1 != 0xff) {
switch (format0) { // dual PRACH format switch (format0) { // dual PRACH format
case 0xa1: case 0xa1:
@@ -2706,7 +2616,7 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
// Compute MsgB RNTI // Compute MsgB RNTI
ra->MsgB_rnti = ra->MsgB_rnti =
nr_get_MsgB_rnti(prach_occasion_info_p->start_symbol, slot_RA, prach_occasion_info_p->fdm, 0); nr_get_MsgB_rnti(prach_occasion_info->start_symbol, slot_RA, prach_occasion_info->fdm, 0);
LOG_D(NR_MAC, "ra->ra_state %s\n", nrra_ue_text[ra->ra_state]); LOG_D(NR_MAC, "ra->ra_state %s\n", nrra_ue_text[ra->ra_state]);
ra->ra_state = nrRA_WAIT_MSGB; ra->ra_state = nrRA_WAIT_MSGB;
ra->t_crnti = 0; ra->t_crnti = 0;
@@ -2715,8 +2625,6 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
} else { } else {
AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type); AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type);
} }
// rnti = ra->t_crnti;
} // is_nr_prach_slot } // is_nr_prach_slot
} // if is_nr_UL_slot } // if is_nr_UL_slot
} }