From 7ecba96f424f29a162055316d5917987c0790692 Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Thu, 23 Jul 2020 09:52:38 -0400 Subject: [PATCH 01/31] Fixed compilation errors and warnings --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 469 ++++++++++++++++++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 40 ++ openair2/LAYER2/NR_MAC_UE/config_ue.c | 2 + openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 249 ++++++---- 4 files changed, 651 insertions(+), 109 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 074908022c..78d07aaac3 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -954,6 +954,475 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, } } + +// The PRACH Config period is a series of selected slots in one or multiple frames +typedef struct prach_conf_period { + prach_occasion_slot_t prach_occasion_slots_map[MAX_NB_FRAMES_IN_PRACH_CONF_PERIOD][MAX_NB_SLOTS_IN_FRAME]; + uint16_t nb_of_prach_occasions; // Total number of PRACH occasions in the PRACH Config period + uint8_t nb_of_frames; // Size of the PRACH Config period in number of 10ms frames + uint8_t nb_of_slots; // Nb of slots in each frame +} prach_conf_period_t; + +// The association period is a series of PRACH Config periods +typedef struct prach_association_period { + prach_conf_period_t *prach_conf_periods_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; + uint8_t nb_of_prach_conf_periods; // Nb of PRACH configuration periods within the association period + uint8_t nb_of_frames; // Total number of frames included in the association period +} prach_association_period_t; + +// The association pattern is a series of Association periods +typedef struct prach_association_pattern { + prach_association_period_t prach_association_periods_list[MAX_NB_PRACH_ASSOC_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + prach_conf_period_t prach_conf_periods_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + uint8_t nb_of_assoc_periods; // Nb of association periods within the association pattern + uint8_t nb_of_prach_conf_periods_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH + uint8_t nb_of_frames; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) +} prach_association_pattern_t; + +// SSB details +typedef struct ssb_info { + boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration + prach_occasion_info_t *mapped_ros[MAX_NB_SSBS_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions + uint8_t nb_mapped_ros; +} ssb_info_t; + +// List of all the possible SSBs and their details +typedef struct ssb_list_info { + ssb_info_t tx_ssb[MAX_NB_SSBS]; + uint8_t nb_tx_ssbs; +} ssb_list_info_t; + +static prach_association_pattern_t prach_assoc_pattern; +static ssb_list_info_t ssb_list; + +static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { + + int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers + int64_t s_map; + uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot + uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot + uint8_t N_dur; // Duration of a PRACH occasion (nb of symbols) + uint8_t frame; // Maximum is NB_FRAMES_IN_MAX_ASSOCIATION_PATTERN_PERIOD + uint8_t slot; // Maximum is the number of slots in a frame @ SCS 240kHz + uint16_t format = 0xffff; + uint8_t format2 = 0xff; + int fdm; + + uint8_t config_index, mu; + uint32_t pointa; + int msg1_FDM; + + NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; + + config_index = rach_ConfigGeneric->prach_ConfigurationIndex; + + if (setup->msg1_SubcarrierSpacing) + mu = *setup->msg1_SubcarrierSpacing; + else + mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + + pointa = frequencyInfoDL->absoluteFrequencyPointA; + msg1_FDM = rach_ConfigGeneric->msg1_FDM; + + switch (msg1_FDM){ + case 0: + case 1: + case 2: + case 3: + fdm = 1 << msg1_FDM; + break; + default: + AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM); + } + + // Create the PRACH occasions map + // ============================== + // WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule + // WIP: Only FR2 is implemented + + // Identify the proper PRACH Configuration Index table according to the operating frequency + if (pointa > 2016666) { //FR2 + int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers + uint8_t slot_60khz; + + uint8_t prach_conf_period_idx; + uint8_t nb_of_frames_per_prach_conf_period; + uint8_t prach_conf_period_frame_idx; + + x = table_6_3_3_2_4_prachConfig_Index[config_index][2]; + y = table_6_3_3_2_4_prachConfig_Index[config_index][3]; + y2 = table_6_3_3_2_4_prachConfig_Index[config_index][4]; + + prach_assoc_pattern.nb_of_prach_conf_periods_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; + nb_of_frames_per_prach_conf_period = x; + + // Fill in the PRACH occasions table for every slot in every frame in a maximum association pattern period + for (prach_conf_period_idx=0; prach_conf_period_idx> (mu-2); // in PRACH configuration index table slots are numbered wrt 60kHz + s_map = table_6_3_3_2_4_prachConfig_Index[config_index][5]; + if ( (s_map>>slot_60khz)&0x01 ) { + // Valid slot according to the 60kHz table + // Additionally, for 120kHz, we must check for the n_RA_Slot param also + if (mu == 3) { + if ( (table_6_3_3_2_4_prachConfig_Index[config_index][7] == 1) && (slot%2 == 0) ) + continue; // no prach in even slots @ 120kHz for 1 prach per 60khz slot + } + + // We're good: valid frame and valid slot + // Compute all the PRACH occasions in the slot + prach_conf_start_symbol = table_6_3_3_2_4_prachConfig_Index[config_index][6]; + N_t_slot = table_6_3_3_2_4_prachConfig_Index[config_index][8]; + N_dur = table_6_3_3_2_4_prachConfig_Index[config_index][9]; + if (table_6_3_3_2_4_prachConfig_Index[config_index][1] != -1) + format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][1]; + format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][0]) | (format2<<8); + + uint8_t n_prach_occ_in_time; + uint8_t n_prach_occ_in_freq; + + for (n_prach_occ_in_time=0; n_prach_occ_in_timestart_symbol = start_symbol; + prach_occasion_p->fdm = n_prach_occ_in_freq; + prach_occasion_p->frame = frame; + prach_occasion_p->slot = slot; + prach_occasion_p->format = format; + prach_assoc_pattern.prach_conf_periods_list[prach_conf_period_idx].nb_of_prach_occasions++; + prach_assoc_pattern.prach_conf_periods_list[prach_conf_period_idx].prach_occasion_slots_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasions_in_freq++; + } // For every freq in the slot + } // For every time occasions in the slot + } // Valid slot? + } // For every slots in a frame + } // Valid frame? + } // For every frames in a prach configuration period + } // For every prach configuration periods in the maximum association pattern period (160ms) + } // FR2? + +} + +static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { + + // Create the list of transmitted SSBs + // =================================== + // WIP: Assumption: the optional ssb_PositionsInBurst is provided + BIT_STRING_t *ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; + + // Fill in the Tx SSBs list by going through all the bits set in the SSB bitmask + uint8_t nb_of_bytes = ssb_bitmap->size; + uint8_t last_bit = 0; + uint8_t *byte_p = ssb_bitmap->buf; + uint8_t ssb_idx = 0; + + // Loop through the SSB idx bitmask starting with bit 0 up to the max of the bitmask + for (uint8_t byte_nb=nb_of_bytes; byte_nb>=1; byte_nb--) { + if (byte_nb == nb_of_bytes) { + last_bit = ssb_bitmap->bits_unused; + } + + for (uint8_t bit_nb=last_bit; bit_nb<=sizeof(uint8_t)-1; bit_nb++) { + if (*byte_p>>bit_nb & 0x01) { + ssb_list.nb_tx_ssbs++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + } + ssb_idx++; + } + byte_p++; + } +} + +static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { + + // Map SSBs to PRACH occasions + // =========================== + // WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule + NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; + + boolean_t multiple_ssbs_per_ro; // true if more than one or exactly one SSB per RACH, false if more than one RACH per SSB + uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB + uint16_t required_nb_of_prach_occasions; // Nb of RACH occasions required to map all the SSBs + uint8_t required_nb_of_prach_conf_periods; // Nb of PRACH configuration periods required to map all the SSBs + + // Determine the SSB to RACH mapping ratio + switch (ssb_perRACH_config){ + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: + multiple_ssbs_per_ro = false; + ssb_rach_ratio = 8; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: + multiple_ssbs_per_ro = false; + ssb_rach_ratio = 4; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: + multiple_ssbs_per_ro = false; + ssb_rach_ratio = 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: + multiple_ssbs_per_ro = true; + ssb_rach_ratio = 1; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: + multiple_ssbs_per_ro = true; + ssb_rach_ratio = 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: + multiple_ssbs_per_ro = true; + ssb_rach_ratio = 4; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: + multiple_ssbs_per_ro = true; + ssb_rach_ratio = 8; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: + multiple_ssbs_per_ro = true; + ssb_rach_ratio = 16; + break; + default: + multiple_ssbs_per_ro = false; + ssb_rach_ratio = 1; // WIP: handle properly the case where the SSB per RACH is not defined + break; + } + + // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period + if (true == multiple_ssbs_per_ro) { + required_nb_of_prach_occasions = ((ssb_list.nb_tx_ssbs-1) + ssb_rach_ratio) / ssb_rach_ratio; + } + else { + required_nb_of_prach_occasions = ssb_list.nb_tx_ssbs * ssb_rach_ratio; + } + + // WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions + // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) + // There is only one possible association period + required_nb_of_prach_conf_periods = ((required_nb_of_prach_occasions-1) + prach_assoc_pattern.prach_conf_periods_list[0].nb_of_prach_occasions) / prach_assoc_pattern.prach_conf_periods_list[0].nb_of_prach_occasions; + + if (required_nb_of_prach_conf_periods == 1) { + prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 1; + } + else if (required_nb_of_prach_conf_periods == 2) { + prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 2; + } + else if (required_nb_of_prach_conf_periods <= 4) { + prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 4; + } + else if (required_nb_of_prach_conf_periods <= 8) { + prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 8; + } + else { + // WIP: make sure that the calculated required_nb_of_prach_conf_periods ratio is <= 16 + prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 16; + } + + // WIP: Make sure that the association period size fits with the number of prach configuration periods within an association pattern max size + // association_period <= prach_assoc_pattern.nb_of_prach_conf_periods + + // WIP: for now we assume that all PRACH occasions within the PRACH Configuration periods are identical throughout the maximum association pattern period (160ms) + // It means that only one association period will be necessary to create an association pattern + prach_assoc_pattern.nb_of_assoc_periods = 1; + prach_assoc_pattern.prach_association_periods_list[0].nb_of_frames = prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods * prach_assoc_pattern.prach_conf_periods_list[0].nb_of_frames; + prach_assoc_pattern.nb_of_frames = prach_assoc_pattern.prach_association_periods_list[0].nb_of_frames; + + // Proceed to the SSB to RO mapping + // ================================ + uint8_t association_period_idx; // Association period index within the association pattern + uint8_t ssb_idx = MAX_NB_SSBS; + uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern + prach_conf_period_t *prach_conf_period_p; + + // Map all the association periods within the association pattern period + for (association_period_idx=0; association_period_idxnb_of_frames; frame++) { + for (slot=0; slotnb_of_slots; slot++) { + for (ro_in_time=0; ro_in_timeprach_occasion_slots_map[frame][slot].nb_of_prach_occasions_in_time; ro_in_time++) { + for (ro_in_freq=0; ro_in_freqprach_occasion_slots_map[frame][slot].nb_of_prach_occasions_in_freq; ro_in_freq++) { + prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slots_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; + + // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO + for (ssb_idx=0; ssb_idxmapped_ssb_idx[ro_p->nb_mapped_ssbs] = ssb_idx; + ro_p->nb_mapped_ssbs++; + ssb_list.tx_ssb[ssb_idx].mapped_ros[ssb_list.tx_ssb[ssb_idx].nb_mapped_ros] = ro_p; + ssb_list.tx_ssb[ssb_idx].nb_mapped_ros++; + + if (ro_p->nb_mapped_ssbs == ssb_rach_ratio) { + ssb_idx++; + break; + } + } // if ssb_idx is transmitted + } // for ssb_idx + + // Exit the loop if there is no more SSBs to map + if (MAX_NB_SSBS == ssb_idx) break; + } // for ro_in_freq + + // Exit the loop if there is no more SSBs to map + if (MAX_NB_SSBS == ssb_idx) break; + } // for ro_in_time + + // Exit the loop if there is no more SSBs to map + if (MAX_NB_SSBS == ssb_idx) break; + } // for slot + + // Exit the loop if there is no more SSBs to map + if (MAX_NB_SSBS == ssb_idx) break; + } // for frame + + // Exit the loop if there is no more SSBs to map + if (MAX_NB_SSBS == ssb_idx) break; + } // for n_prach_conf + + // WIP: If association_period is ever reached in this loop, the mapping should be completed: all SSB_idx are mapped to the required number of ROs + + } // if multiple_ssbs_per_ro + + else { + // Multiple ROs per SSB + // -------------------- + // Go through the list of transmitted SSBs + for (ssb_idx=0; ssb_idxnb_of_frames; frame++) { + for (; slotnb_of_slots; slot++) { + for (; ro_in_timeprach_occasion_slots_map[frame][slot].nb_of_prach_occasions_in_time; ro_in_time++) { + for (; ro_in_freqprach_occasion_slots_map[frame][slot].nb_of_prach_occasions_in_freq; ro_in_freq++) { + prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slots_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; + + ro_p->mapped_ssb_idx[0] = ssb_idx; + ro_p->nb_mapped_ssbs = 1; + ssb_list.tx_ssb[ssb_idx].mapped_ros[ssb_list.tx_ssb[ssb_idx].nb_mapped_ros] = ro_p; + ssb_list.tx_ssb[ssb_idx].nb_mapped_ros++; + nb_mapped_ros_in_association_period++; + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ros_in_association_period == ssb_rach_ratio) { + ro_in_freq++; + break; + } + } // for ro_in_freq + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; + else ro_in_freq = 0; + } // for ro_in_time + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; + else ro_in_time = 0; + } // for slot + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; + else slot = 0; + } // for frame + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; + else frame = 0; + } // for n_prach_conf + + // WIP: If association_period is ever reached in this loop, the mapping should be completed: all SSB_idx have their required number of ROs assigned + + } // if ssb_idx is transmitted + } // for ssb_idx + } // else if multiple_ssbs_per_ro + + } // for association_period_index +} + +void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc) { + + // Clear all the lists and maps + memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t)); + memset(&ssb_list, 0, sizeof(ssb_list_info_t)); + + build_ro_list(scc); + build_ssb_list(scc); + map_ssb_to_ro(scc); +} + +int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, + int frame, + int slot, + prach_occasion_slot_t *prach_occasion_slot_p) { + + ssb_info_t *ssb_info_p; + + prach_occasion_slot_p = 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 + ssb_info_p = &ssb_list.tx_ssb[ssb_idx]; + for (uint8_t n_mapped_ro=0; n_mapped_ronb_mapped_ros; n_mapped_ro++) { + if ((slot == ssb_info_p->mapped_ros[n_mapped_ro]->slot) && + (ssb_info_p->mapped_ros[n_mapped_ro]->frame == (frame % prach_assoc_pattern.nb_of_frames))) { + + uint8_t prach_config_period_nb = ssb_info_p->mapped_ros[n_mapped_ro]->frame / prach_assoc_pattern.prach_conf_periods_list[0].nb_of_frames; + uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ros[n_mapped_ro]->frame % prach_assoc_pattern.prach_conf_periods_list[0].nb_of_frames; + prach_occasion_slot_p = &prach_assoc_pattern.prach_conf_periods_list[prach_config_period_nb].prach_occasion_slots_map[frame_nb_in_prach_config_period][slot]; + return 1; + } + } + + return 0; +} + int get_nr_prach_info_from_index(uint8_t index, int frame, int slot, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 2f7f144983..291a70ec94 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -36,6 +36,43 @@ #include "NR_CellGroupConfig.h" #include "nr_mac.h" +#define MAX_NB_PRACH_ASSOC_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of association periods in max association pattern period (160ms) +#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16 +#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms +#define MAX_NB_FRAMES_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms +#define MAX_NB_SLOTS_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) +#define MAX_NB_PRACH_OCCASIONS_IN_TIME (7) // Max number of PRACH occasions in time per slot +#define MAX_NB_PRACH_OCCASIONS_IN_FREQ (8) // Max number of PRACH occasions in frequency per slot +#define MAX_NB_FRAMES_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period +#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms +#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot +#define MAX_NB_SSBS (64) +#define MAX_RO_PER_SSB_RATIO (8) +#define MAX_SSB_PER_RO_RATIO (16) + +// Maximum number of SSBs that can be mapped in an association pattern +// Here we chose an arbitrary maximum number - maximum number of slots in an association pattern * maximum number of ROs in a slot +#define MAX_NB_SSBS_IN_ASSOCIATION_PATTERN (MAX_NB_PRACH_OCCASIONS_IN_TIME*MAX_NB_PRACH_OCCASIONS_IN_FREQ*MAX_NB_SLOTS_IN_FRAME*MAX_NB_FRAMES_IN_ASSOCIATION_PATTERN_PERIOD) + +// PRACH occasion details +typedef struct prach_occasion_info { + uint8_t start_symbol; // 0 - 13 (14 symbols in a slot) + uint8_t fdm; // 1, 2, 4 or 8 (possible values of msg1-FDM) + uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz) + uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern) + uint8_t mapped_ssb_idx[MAX_SSB_PER_RO_RATIO]; // List of mapped SSBs + uint8_t nb_mapped_ssbs; + uint16_t format; // RO preamble format +} prach_occasion_info_t; + +// PRACH occasions details in a slot +// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency +typedef struct prach_occasion_slot { + prach_occasion_info_t prach_occasion[MAX_NB_PRACH_OCCASIONS_IN_TIME][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot - 0Xff when no more valid PRACH occasion in that slot + uint8_t nb_of_prach_occasions_in_time; + uint8_t nb_of_prach_occasions_in_freq; +} prach_occasion_slot_t; + typedef enum { NR_DL_DCI_FORMAT_1_0 = 0, NR_DL_DCI_FORMAT_1_1, @@ -88,6 +125,9 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, uint16_t *slot_period, uint16_t *offset); +void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc); +int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, int frame, int slot, prach_occasion_slot_t *prach_occasion_slot_p); + int get_nr_prach_info_from_index(uint8_t index, int frame, int slot, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 5a9620ed01..b4020ec6cd 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -357,6 +357,8 @@ int nr_rrc_mac_config_req_ue( } mac->scg = cell_group_config; + build_ssb_to_ro_map(mac->scc); + /* if(mac_cell_group_configP != NULL){ if(mac_cell_group_configP->drx_Config != NULL ){ diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 109d4570f4..c8e7f27d4b 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -945,15 +945,16 @@ void nr_ue_msg2_scheduler(module_id_t mod_id, } // This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x -// It fills the PRACH PDU per each FD occasion. // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. // - todo: // - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - uint8_t config_index, mu, N_dur, N_t_slot, start_symbol; +// uint8_t config_index, mu, N_dur, N_t_slot, start_symbol; + prach_occasion_slot_t prach_occasion_slot; uint16_t format, format0, format1, ncs; - int msg1_FDM, is_nr_prach_slot, fdm; +// int msg1_FDM, is_nr_prach_slot, fdm; + int is_nr_prach_slot; NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); @@ -964,134 +965,164 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s NR_ServingCellConfigCommon_t *scc = mac->scc; NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; +// NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - config_index = rach_ConfigGeneric->prach_ConfigurationIndex; + +// config_index = rach_ConfigGeneric->prach_ConfigurationIndex; mac->RA_offset = 2; // to compensate the rx frame offset at the gNB if (is_nr_UL_slot(scc, slotP)) { - if (setup->msg1_SubcarrierSpacing) - mu = *setup->msg1_SubcarrierSpacing; - else - mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; +// if (setup->msg1_SubcarrierSpacing) +// mu = *setup->msg1_SubcarrierSpacing; +// else +// mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - is_nr_prach_slot = get_nr_prach_info_from_index(config_index, - (int)frameP, - (int)slotP, - frequencyInfoDL->absoluteFrequencyPointA, - mu, - cfg->cell_config.frame_duplex_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur); +// is_nr_prach_slot = get_nr_prach_info_from_index(config_index, +// (int)frameP, +// (int)slotP, +// frequencyInfoDL->absoluteFrequencyPointA, +// mu, +// cfg->cell_config.frame_duplex_type, +// &format, +// &start_symbol, +// &N_t_slot, +// &N_dur); + + uint8_t selected_gnb_ssb_idx = 0; // WIP Need to get the proper selected ssb_idx + mac->generate_nr_prach = 0; + is_nr_prach_slot = get_nr_prach_info_from_ssb_index(selected_gnb_ssb_idx, + (int)frameP, + (int)slotP, + &prach_occasion_slot); if (is_nr_prach_slot && mac->ra_state == RA_UE_IDLE) { - mac->generate_nr_prach = 1; - - fdm = rach_ConfigGeneric->msg1_FDM; - - switch (fdm){ - case 0: - case 1: - case 2: - case 3: - msg1_FDM = 1 << fdm; - break; - default: - AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", fdm); - } +// fdm = rach_ConfigGeneric->msg1_FDM; +// +// switch (fdm){ +// case 0: +// case 1: +// case 2: +// case 3: +// msg1_FDM = 1 << fdm; +// break; +// default: +// AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", fdm); +// } + format = prach_occasion_slot.prach_occasion[0][0].format; format0 = format & 0xff; // single PRACH format format1 = (format >> 8) & 0xff; // dual PRACH format ul_config->sfn = frameP; ul_config->slot = slotP; - for (int n = 0; n < msg1_FDM; n++) { // one structure per frequency domain occasion +// for (int n = 0; n < msg1_FDM; n++) { // one structure per frequency domain occasion - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; - prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; - memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); - ul_config->number_pdus += 1; + // Go through all the ROs in the slot and find the first that is mapped to the selected SSB index + for (int ro_in_time=0; ro_in_time < prach_occasion_slot.nb_of_prach_occasions_in_time; ro_in_time++) { + for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot.nb_of_prach_occasions_in_freq; ro_in_freq++) { + prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot.prach_occasion[ro_in_time][ro_in_freq]; + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssbs; ssb_nb++) { + if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == selected_gnb_ssb_idx) { - ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); + ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; + prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; + memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); + ul_config->number_pdus += 1; - // filling PRACH PDU for FAPI config request - prach_config_pdu->phys_cell_id = *scc->physCellId; - prach_config_pdu->num_prach_ocas = N_t_slot; - prach_config_pdu->prach_start_symbol = start_symbol; - prach_config_pdu->num_ra = n; - prach_config_pdu->num_cs = ncs; - prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[n].prach_root_sequence_index; - prach_config_pdu->restricted_set = prach_config->restricted_set_config; - prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1; + ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); - if (format1 != 0xff) { - switch(format0) { // dual PRACH format - case 0xa1: - prach_config_pdu->prach_format = 9; + // filling PRACH PDU for FAPI config request + prach_config_pdu->phys_cell_id = *scc->physCellId; +// prach_config_pdu->num_prach_ocas = N_t_slot; + prach_config_pdu->num_prach_ocas = 1; +// prach_config_pdu->prach_start_symbol = start_symbol; + prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol; +// prach_config_pdu->num_ra = n; + prach_config_pdu->num_ra = prach_occasion_info_p->fdm; + prach_config_pdu->num_cs = ncs; +// prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[n].prach_root_sequence_index; + prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index; + prach_config_pdu->restricted_set = prach_config->restricted_set_config; +// prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1; + prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1; + + if (format1 != 0xff) { + switch(format0) { // dual PRACH format + case 0xa1: + prach_config_pdu->prach_format = 9; + break; + case 0xa2: + prach_config_pdu->prach_format = 10; + break; + case 0xa3: + prach_config_pdu->prach_format = 11; + break; + default: + AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); + } + } else { + switch(format0) { // single PRACH format + case 0xa1: + prach_config_pdu->prach_format = 0; + break; + case 0xa2: + prach_config_pdu->prach_format = 1; + break; + case 0xa3: + prach_config_pdu->prach_format = 2; + break; + case 0xb1: + prach_config_pdu->prach_format = 3; + break; + case 0xb2: + prach_config_pdu->prach_format = 4; + break; + case 0xb3: + prach_config_pdu->prach_format = 5; + break; + case 0xb4: + prach_config_pdu->prach_format = 6; + break; + case 0xc0: + prach_config_pdu->prach_format = 7; + break; + case 0xc2: + prach_config_pdu->prach_format = 8; + break; + case 0: + // long formats are handled @ PHY + break; + case 1: + // long formats are handled @ PHY + break; + case 2: + // long formats are handled @ PHY + break; + case 3: + // long formats are handled @ PHY + break; + default: + AssertFatal(1 == 0, "Invalid PRACH format"); + } + } // if format1 + + // RO matching the SSB is found -> get out of mapping loop + mac->generate_nr_prach = 1; break; - case 0xa2: - prach_config_pdu->prach_format = 10; - break; - case 0xa3: - prach_config_pdu->prach_format = 11; - break; - default: - AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); - } - } else { - switch(format0) { // single PRACH format - case 0xa1: - prach_config_pdu->prach_format = 0; - break; - case 0xa2: - prach_config_pdu->prach_format = 1; - break; - case 0xa3: - prach_config_pdu->prach_format = 2; - break; - case 0xb1: - prach_config_pdu->prach_format = 3; - break; - case 0xb2: - prach_config_pdu->prach_format = 4; - break; - case 0xb3: - prach_config_pdu->prach_format = 5; - break; - case 0xb4: - prach_config_pdu->prach_format = 6; - break; - case 0xc0: - prach_config_pdu->prach_format = 7; - break; - case 0xc2: - prach_config_pdu->prach_format = 8; - break; - case 0: - // long formats are handled @ PHY - break; - case 1: - // long formats are handled @ PHY - break; - case 2: - // long formats are handled @ PHY - break; - case 3: - // long formats are handled @ PHY - break; - default: - AssertFatal(1 == 0, "Invalid PRACH format"); - } - } - } - } else { - mac->generate_nr_prach = 0; + } // if selected_gnb_ssb_idx + } // for ssb_nb + + // RO matching the SSB is found -> get out of mapping loop + if (1 == mac->generate_nr_prach) break; + } // for ro_in_freq + + // RO matching the SSB is found -> get out of mapping loop + if (1 == mac->generate_nr_prach) break; + } // for ro_in_time } mac->scheduled_response.ul_config = ul_config; } From f967ba1756f37a31713ab3e5023142da0a6ae5bb Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Thu, 23 Jul 2020 17:14:46 -0400 Subject: [PATCH 02/31] Added some comments and cleaned up code --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 235 +++++++++++------- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 33 +-- openair2/LAYER2/NR_MAC_UE/config_ue.c | 1 + openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 198 +++++++-------- 4 files changed, 261 insertions(+), 206 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 78d07aaac3..eb96b0eb3e 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -32,6 +32,68 @@ #include "LAYER2/NR_MAC_gNB/mac_proto.h" +// ================================================ +// SSB to RO mapping private defines and structures +// ================================================ + +#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16 +#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms +#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms +#define MAX_NB_FRAMES_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms +#define MAX_NB_SLOTS_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) +#define MAX_NB_FRAMES_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period +#define MAX_NB_SSBS (64) // Maximum number of possible SSB indexes +#define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config + +// Maximum number of ROs that can be mapped to an SSB in an association pattern +// This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB +// An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot +#define MAX_NB_ROS_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOTS_IN_FRAME*MAX_NB_FRAMES_IN_ASSOCIATION_PATTERN_PERIOD) + +// The PRACH Config period is a series of selected slots in one or multiple frames +typedef struct prach_conf_period { + prach_occasion_slot_t prach_occasion_slots_map[MAX_NB_FRAMES_IN_PRACH_CONF_PERIOD][MAX_NB_SLOTS_IN_FRAME]; + uint16_t nb_of_prach_occasions; // Total number of PRACH occasions in the PRACH Config period + uint8_t nb_of_frames; // Size of the PRACH Config period in number of 10ms frames + uint8_t nb_of_slots; // Nb of slots in each frame +} prach_conf_period_t; + +// The association period is a series of PRACH Config periods +typedef struct prach_association_period { + prach_conf_period_t *prach_conf_periods_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; + uint8_t nb_of_prach_conf_periods; // Nb of PRACH configuration periods within the association period + uint8_t nb_of_frames; // Total number of frames included in the association period +} prach_association_period_t; + +// The association pattern is a series of Association periods +typedef struct prach_association_pattern { + prach_association_period_t prach_association_periods_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + prach_conf_period_t prach_conf_periods_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + uint8_t nb_of_assoc_periods; // Nb of association periods within the association pattern + uint8_t nb_of_prach_conf_periods_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH + uint8_t nb_of_frames; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) +} prach_association_pattern_t; + +// SSB details +typedef struct ssb_info { + boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration + prach_occasion_info_t *mapped_ros[MAX_NB_ROS_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index + uint16_t nb_mapped_ros; // Total number of mapped ROs to this SSB index +} ssb_info_t; + +// List of all the possible SSBs and their details +typedef struct ssb_list_info { + ssb_info_t tx_ssb[MAX_NB_SSBS]; + uint8_t nb_tx_ssbs; +} ssb_list_info_t; + +static prach_association_pattern_t prach_assoc_pattern; +static ssb_list_info_t ssb_list; + +// =============================================== +// =============================================== + + const uint8_t nr_slots_per_frame[5] = {10, 20, 40, 80, 160}; // Table 6.3.3.1-5 (38.211) NCS for preamble formats with delta_f_RA = 1.25 KHz @@ -954,47 +1016,7 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, } } - -// The PRACH Config period is a series of selected slots in one or multiple frames -typedef struct prach_conf_period { - prach_occasion_slot_t prach_occasion_slots_map[MAX_NB_FRAMES_IN_PRACH_CONF_PERIOD][MAX_NB_SLOTS_IN_FRAME]; - uint16_t nb_of_prach_occasions; // Total number of PRACH occasions in the PRACH Config period - uint8_t nb_of_frames; // Size of the PRACH Config period in number of 10ms frames - uint8_t nb_of_slots; // Nb of slots in each frame -} prach_conf_period_t; - -// The association period is a series of PRACH Config periods -typedef struct prach_association_period { - prach_conf_period_t *prach_conf_periods_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; - uint8_t nb_of_prach_conf_periods; // Nb of PRACH configuration periods within the association period - uint8_t nb_of_frames; // Total number of frames included in the association period -} prach_association_period_t; - -// The association pattern is a series of Association periods -typedef struct prach_association_pattern { - prach_association_period_t prach_association_periods_list[MAX_NB_PRACH_ASSOC_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; - prach_conf_period_t prach_conf_periods_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; - uint8_t nb_of_assoc_periods; // Nb of association periods within the association pattern - uint8_t nb_of_prach_conf_periods_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH - uint8_t nb_of_frames; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) -} prach_association_pattern_t; - -// SSB details -typedef struct ssb_info { - boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration - prach_occasion_info_t *mapped_ros[MAX_NB_SSBS_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions - uint8_t nb_mapped_ros; -} ssb_info_t; - -// List of all the possible SSBs and their details -typedef struct ssb_list_info { - ssb_info_t tx_ssb[MAX_NB_SSBS]; - uint8_t nb_tx_ssbs; -} ssb_list_info_t; - -static prach_association_pattern_t prach_assoc_pattern; -static ssb_list_info_t ssb_list; - +// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers @@ -1039,8 +1061,9 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { // Create the PRACH occasions map // ============================== - // WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule - // WIP: Only FR2 is implemented + // WIP-IDCC: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule + // WIP-IDCC: Only FR2 is implemented + // WIP-IDCC: RACH preambles are not mapped yet (assumptions: ssb_per_rach is <= 1, totalNumberOfRA = CB-preamblesPerSSB = 64) // Identify the proper PRACH Configuration Index table according to the operating frequency if (pointa > 2016666) { //FR2 @@ -1058,17 +1081,27 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { prach_assoc_pattern.nb_of_prach_conf_periods_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; nb_of_frames_per_prach_conf_period = x; - // Fill in the PRACH occasions table for every slot in every frame in a maximum association pattern period + // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period + // ---------------------------------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------------------------------- + + // For every PRACH configuration periods + // ------------------------------------- for (prach_conf_period_idx=0; prach_conf_period_idx> (mu-2); // in PRACH configuration index table slots are numbered wrt 60kHz @@ -1118,11 +1151,12 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { } +// Build the list of all the valid/transmitted SSBs according to the config static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { // Create the list of transmitted SSBs // =================================== - // WIP: Assumption: the optional ssb_PositionsInBurst is provided + // WIP-IDCC: Assumption: the optional ssb_PositionsInBurst is provided BIT_STRING_t *ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; // Fill in the Tx SSBs list by going through all the bits set in the SSB bitmask @@ -1138,6 +1172,7 @@ static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { } for (uint8_t bit_nb=last_bit; bit_nb<=sizeof(uint8_t)-1; bit_nb++) { + // If SSB is transmitted if (*byte_p>>bit_nb & 0x01) { ssb_list.nb_tx_ssbs++; ssb_list.tx_ssb[ssb_idx].transmitted = true; @@ -1148,20 +1183,22 @@ static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { } } +// Map the transmitted SSBs to the ROs and create the association pattern according to the config static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // Map SSBs to PRACH occasions // =========================== - // WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule + // WIP-IDCC: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; - boolean_t multiple_ssbs_per_ro; // true if more than one or exactly one SSB per RACH, false if more than one RACH per SSB + boolean_t multiple_ssbs_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB uint16_t required_nb_of_prach_occasions; // Nb of RACH occasions required to map all the SSBs uint8_t required_nb_of_prach_conf_periods; // Nb of PRACH configuration periods required to map all the SSBs // Determine the SSB to RACH mapping ratio + // ======================================= switch (ssb_perRACH_config){ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: multiple_ssbs_per_ro = false; @@ -1196,12 +1233,15 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ssb_rach_ratio = 16; break; default: - multiple_ssbs_per_ro = false; - ssb_rach_ratio = 1; // WIP: handle properly the case where the SSB per RACH is not defined + AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); break; } // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period + // ============================================================================================================== + // WIP-IDCC: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions + // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) + // There is only one possible association period if (true == multiple_ssbs_per_ro) { required_nb_of_prach_occasions = ((ssb_list.nb_tx_ssbs-1) + ssb_rach_ratio) / ssb_rach_ratio; } @@ -1209,9 +1249,6 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { required_nb_of_prach_occasions = ssb_list.nb_tx_ssbs * ssb_rach_ratio; } - // WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions - // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) - // There is only one possible association period required_nb_of_prach_conf_periods = ((required_nb_of_prach_occasions-1) + prach_assoc_pattern.prach_conf_periods_list[0].nb_of_prach_occasions) / prach_assoc_pattern.prach_conf_periods_list[0].nb_of_prach_occasions; if (required_nb_of_prach_conf_periods == 1) { @@ -1227,16 +1264,12 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 8; } else { - // WIP: make sure that the calculated required_nb_of_prach_conf_periods ratio is <= 16 + AssertFatal(16 >= required_nb_of_prach_conf_periods, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_periods); + prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 16; } - // WIP: Make sure that the association period size fits with the number of prach configuration periods within an association pattern max size - // association_period <= prach_assoc_pattern.nb_of_prach_conf_periods - - // WIP: for now we assume that all PRACH occasions within the PRACH Configuration periods are identical throughout the maximum association pattern period (160ms) - // It means that only one association period will be necessary to create an association pattern - prach_assoc_pattern.nb_of_assoc_periods = 1; + prach_assoc_pattern.nb_of_assoc_periods = 1; // WIP-IDCC: only one possible association period prach_assoc_pattern.prach_association_periods_list[0].nb_of_frames = prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods * prach_assoc_pattern.prach_conf_periods_list[0].nb_of_frames; prach_assoc_pattern.nb_of_frames = prach_assoc_pattern.prach_association_periods_list[0].nb_of_frames; @@ -1256,20 +1289,24 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { uint8_t ro_in_freq=0; // Set the starting PRACH Configuration period index in the association_pattern map for this particular association period - // WIP: For now, only a single association period is supported - prach_configuration_period_idx = 0; + prach_configuration_period_idx = 0; // WIP-IDCC: only one possible association period // Check if we need to map multiple SSBs per RO or multiple ROs per SSB if (true == multiple_ssbs_per_ro) { + // -------------------- + // -------------------- // Multiple SSBs per RO // -------------------- - // Go through the list of ROs - for (n_prach_conf=0; n_prach_confnb_of_frames; frame++) { for (slot=0; slotnb_of_slots; slot++) { for (ro_in_time=0; ro_in_timeprach_occasion_slots_map[frame][slot].nb_of_prach_occasions_in_time; ro_in_time++) { @@ -1281,12 +1318,13 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // Map only the transmitted ssb_idx if (true == ssb_list.tx_ssb[ssb_idx].transmitted) { - // Map all the required ROs to this SSB ro_p->mapped_ssb_idx[ro_p->nb_mapped_ssbs] = ssb_idx; ro_p->nb_mapped_ssbs++; ssb_list.tx_ssb[ssb_idx].mapped_ros[ssb_list.tx_ssb[ssb_idx].nb_mapped_ros] = ro_p; ssb_list.tx_ssb[ssb_idx].nb_mapped_ros++; + AssertFatal(MAX_NB_ROS_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ros,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ros); + // If all the required SSBs are mapped to this RO, exit the loop of SSBs if (ro_p->nb_mapped_ssbs == ssb_rach_ratio) { ssb_idx++; break; @@ -1294,45 +1332,52 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { } // if ssb_idx is transmitted } // for ssb_idx - // Exit the loop if there is no more SSBs to map + // Exit the loop of ROs if there is no more SSB to map if (MAX_NB_SSBS == ssb_idx) break; } // for ro_in_freq - // Exit the loop if there is no more SSBs to map + // Exit the loop of ROs if there is no more SSB to map if (MAX_NB_SSBS == ssb_idx) break; } // for ro_in_time - // Exit the loop if there is no more SSBs to map + // Exit the loop of slots if there is no more SSB to map if (MAX_NB_SSBS == ssb_idx) break; } // for slot - // Exit the loop if there is no more SSBs to map + // Exit the loop frames if there is no more SSB to map if (MAX_NB_SSBS == ssb_idx) break; } // for frame - // Exit the loop if there is no more SSBs to map + // Exit the loop of PRACH configurations if there is no more SSB to map if (MAX_NB_SSBS == ssb_idx) break; } // for n_prach_conf - // WIP: If association_period is ever reached in this loop, the mapping should be completed: all SSB_idx are mapped to the required number of ROs + // WIP-IDCC: note that there is no re-mapping of the SSBs within the association period since there is no invalid ROs in the PRACH config periods that would create this situation } // if multiple_ssbs_per_ro else { + // -------------------- + // -------------------- // Multiple ROs per SSB // -------------------- + // -------------------- + + n_prach_conf = 0; + // Go through the list of transmitted SSBs for (ssb_idx=0; ssb_idxnb_of_frames; frame++) { @@ -1345,6 +1390,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ro_p->nb_mapped_ssbs = 1; ssb_list.tx_ssb[ssb_idx].mapped_ros[ssb_list.tx_ssb[ssb_idx].nb_mapped_ros] = ro_p; ssb_list.tx_ssb[ssb_idx].nb_mapped_ros++; + AssertFatal(MAX_NB_ROS_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ros,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ros); nb_mapped_ros_in_association_period++; // Exit the loop if this SSB has been mapped to all the required ROs @@ -1356,26 +1402,24 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // Exit the loop if this SSB has been mapped to all the required ROs if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; - else ro_in_freq = 0; + else ro_in_freq = 0; // else go to the next time symbol in that slot } // for ro_in_time // Exit the loop if this SSB has been mapped to all the required ROs if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; - else ro_in_time = 0; + else ro_in_time = 0; // else go to the next slot in that PRACH config period } // for slot // Exit the loop if this SSB has been mapped to all the required ROs if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; - else slot = 0; + else slot = 0; // else go to the next frame in that PRACH config period } // for frame // Exit the loop if this SSB has been mapped to all the required ROs if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; - else frame = 0; + else frame = 0; // else go to the next PRACH config period in that association period } // for n_prach_conf - // WIP: If association_period is ever reached in this loop, the mapping should be completed: all SSB_idx have their required number of ROs assigned - } // if ssb_idx is transmitted } // for ssb_idx } // else if multiple_ssbs_per_ro @@ -1383,25 +1427,33 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { } // for association_period_index } +// Build the SSB to RO mapping upon RRC configuration update void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc) { // Clear all the lists and maps memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t)); memset(&ssb_list, 0, sizeof(ssb_list_info_t)); + // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config build_ro_list(scc); + + // Build the list of all the valid/transmitted SSBs according to the config build_ssb_list(scc); + + // Map the transmitted SSBs to the ROs and create the association pattern according to the config map_ssb_to_ro(scc); } +// Returns a RACH occasion if any matches the SSB idx, the frame and the slot int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, int frame, int slot, - prach_occasion_slot_t *prach_occasion_slot_p) { + prach_occasion_info_t **prach_occasion_info_pp) { ssb_info_t *ssb_info_p; + prach_occasion_slot_t *prach_occasion_slot_p = NULL; - 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: @@ -1416,7 +1468,24 @@ int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, uint8_t prach_config_period_nb = ssb_info_p->mapped_ros[n_mapped_ro]->frame / prach_assoc_pattern.prach_conf_periods_list[0].nb_of_frames; uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ros[n_mapped_ro]->frame % prach_assoc_pattern.prach_conf_periods_list[0].nb_of_frames; prach_occasion_slot_p = &prach_assoc_pattern.prach_conf_periods_list[prach_config_period_nb].prach_occasion_slots_map[frame_nb_in_prach_config_period][slot]; - return 1; + } + } + + // If there is a matching RO slot in the SSB_to_RO map + if (NULL != prach_occasion_slot_p) + { + // Go through all the ROs in the slot and find the first that is mapped to the selected SSB index + // WIP-IDCC: A random RO mapped to the SSB index should be selected in the slot instead + for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasions_in_time; ro_in_time++) { + for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasions_in_freq; ro_in_freq++) { + prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssbs; ssb_nb++) { + if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { + *prach_occasion_info_pp = prach_occasion_info_p; + return 1; + } + } + } } } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 291a70ec94..23924ca44e 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -36,23 +36,13 @@ #include "NR_CellGroupConfig.h" #include "nr_mac.h" -#define MAX_NB_PRACH_ASSOC_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of association periods in max association pattern period (160ms) -#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16 -#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms -#define MAX_NB_FRAMES_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms -#define MAX_NB_SLOTS_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) -#define MAX_NB_PRACH_OCCASIONS_IN_TIME (7) // Max number of PRACH occasions in time per slot -#define MAX_NB_PRACH_OCCASIONS_IN_FREQ (8) // Max number of PRACH occasions in frequency per slot -#define MAX_NB_FRAMES_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period -#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms -#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot -#define MAX_NB_SSBS (64) -#define MAX_RO_PER_SSB_RATIO (8) -#define MAX_SSB_PER_RO_RATIO (16) -// Maximum number of SSBs that can be mapped in an association pattern -// Here we chose an arbitrary maximum number - maximum number of slots in an association pattern * maximum number of ROs in a slot -#define MAX_NB_SSBS_IN_ASSOCIATION_PATTERN (MAX_NB_PRACH_OCCASIONS_IN_TIME*MAX_NB_PRACH_OCCASIONS_IN_FREQ*MAX_NB_SLOTS_IN_FRAME*MAX_NB_FRAMES_IN_ASSOCIATION_PATTERN_PERIOD) +// =============================================== +// SSB to RO mapping public defines and structures +// =============================================== +#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO +#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot +#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot // PRACH occasion details typedef struct prach_occasion_info { @@ -60,19 +50,22 @@ typedef struct prach_occasion_info { uint8_t fdm; // 1, 2, 4 or 8 (possible values of msg1-FDM) uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz) uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern) - uint8_t mapped_ssb_idx[MAX_SSB_PER_RO_RATIO]; // List of mapped SSBs + uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs uint8_t nb_mapped_ssbs; uint16_t format; // RO preamble format } prach_occasion_info_t; -// PRACH occasions details in a slot +// PRACH occasion slot details // A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency typedef struct prach_occasion_slot { - prach_occasion_info_t prach_occasion[MAX_NB_PRACH_OCCASIONS_IN_TIME][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot - 0Xff when no more valid PRACH occasion in that slot + prach_occasion_info_t prach_occasion[MAX_TDM][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot uint8_t nb_of_prach_occasions_in_time; uint8_t nb_of_prach_occasions_in_freq; } prach_occasion_slot_t; +// ======================================== + + typedef enum { NR_DL_DCI_FORMAT_1_0 = 0, NR_DL_DCI_FORMAT_1_1, @@ -126,7 +119,7 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, uint16_t *offset); void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc); -int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, int frame, int slot, prach_occasion_slot_t *prach_occasion_slot_p); +int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, int frame, int slot, prach_occasion_info_t **prach_occasion_info_pp); int get_nr_prach_info_from_index(uint8_t index, int frame, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index b4020ec6cd..1dcbeafc1f 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -357,6 +357,7 @@ int nr_rrc_mac_config_req_ue( } mac->scg = cell_group_config; + // Setup the SSB to Rach Occasions mapping according to the config build_ssb_to_ro_map(mac->scc); /* diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index c8e7f27d4b..7ff4ce838e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -951,10 +951,10 @@ void nr_ue_msg2_scheduler(module_id_t mod_id, void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { // uint8_t config_index, mu, N_dur, N_t_slot, start_symbol; - prach_occasion_slot_t prach_occasion_slot; uint16_t format, format0, format1, ncs; // int msg1_FDM, is_nr_prach_slot, fdm; int is_nr_prach_slot; + prach_occasion_info_t *prach_occasion_info_p; NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); @@ -967,7 +967,6 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; // NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - // config_index = rach_ConfigGeneric->prach_ConfigurationIndex; mac->RA_offset = 2; // to compensate the rx frame offset at the gNB @@ -990,15 +989,21 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s // &N_t_slot, // &N_dur); - uint8_t selected_gnb_ssb_idx = 0; // WIP Need to get the proper selected ssb_idx - mac->generate_nr_prach = 0; + // WIP-IDCC Need to get the proper selected ssb_idx + uint8_t selected_gnb_ssb_idx = 0; + + // Get any valid PRACH occasion in the current slot for the selected SSB index is_nr_prach_slot = get_nr_prach_info_from_ssb_index(selected_gnb_ssb_idx, (int)frameP, (int)slotP, - &prach_occasion_slot); + &prach_occasion_info_p); if (is_nr_prach_slot && mac->ra_state == RA_UE_IDLE) { + AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n"); + + mac->generate_nr_prach = 1; + // fdm = rach_ConfigGeneric->msg1_FDM; // // switch (fdm){ @@ -1012,7 +1017,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s // AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", fdm); // } - format = prach_occasion_slot.prach_occasion[0][0].format; + format = prach_occasion_info_p->format; format0 = format & 0xff; // single PRACH format format1 = (format >> 8) & 0xff; // dual PRACH format @@ -1021,111 +1026,98 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s // for (int n = 0; n < msg1_FDM; n++) { // one structure per frequency domain occasion - // Go through all the ROs in the slot and find the first that is mapped to the selected SSB index - for (int ro_in_time=0; ro_in_time < prach_occasion_slot.nb_of_prach_occasions_in_time; ro_in_time++) { - for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot.nb_of_prach_occasions_in_freq; ro_in_freq++) { - prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot.prach_occasion[ro_in_time][ro_in_freq]; - for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssbs; ssb_nb++) { - if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == selected_gnb_ssb_idx) { + ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; + prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; + memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); + ul_config->number_pdus += 1; - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; - prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; - memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); - ul_config->number_pdus += 1; + ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); - ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); + // filling PRACH PDU for FAPI config request +// prach_config_pdu->phys_cell_id = *scc->physCellId; +// prach_config_pdu->num_prach_ocas = N_t_slot; +// prach_config_pdu->prach_start_symbol = start_symbol; +// prach_config_pdu->num_ra = n; - // filling PRACH PDU for FAPI config request - prach_config_pdu->phys_cell_id = *scc->physCellId; -// prach_config_pdu->num_prach_ocas = N_t_slot; - prach_config_pdu->num_prach_ocas = 1; -// prach_config_pdu->prach_start_symbol = start_symbol; - prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol; -// prach_config_pdu->num_ra = n; - prach_config_pdu->num_ra = prach_occasion_info_p->fdm; - prach_config_pdu->num_cs = ncs; -// prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[n].prach_root_sequence_index; - prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index; - prach_config_pdu->restricted_set = prach_config->restricted_set_config; -// prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1; - prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1; + prach_config_pdu->phys_cell_id = *scc->physCellId; + prach_config_pdu->num_prach_ocas = 1; + prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol; + prach_config_pdu->num_ra = prach_occasion_info_p->fdm; - if (format1 != 0xff) { - switch(format0) { // dual PRACH format - case 0xa1: - prach_config_pdu->prach_format = 9; - break; - case 0xa2: - prach_config_pdu->prach_format = 10; - break; - case 0xa3: - prach_config_pdu->prach_format = 11; - break; - default: - AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); - } - } else { - switch(format0) { // single PRACH format - case 0xa1: - prach_config_pdu->prach_format = 0; - break; - case 0xa2: - prach_config_pdu->prach_format = 1; - break; - case 0xa3: - prach_config_pdu->prach_format = 2; - break; - case 0xb1: - prach_config_pdu->prach_format = 3; - break; - case 0xb2: - prach_config_pdu->prach_format = 4; - break; - case 0xb3: - prach_config_pdu->prach_format = 5; - break; - case 0xb4: - prach_config_pdu->prach_format = 6; - break; - case 0xc0: - prach_config_pdu->prach_format = 7; - break; - case 0xc2: - prach_config_pdu->prach_format = 8; - break; - case 0: - // long formats are handled @ PHY - break; - case 1: - // long formats are handled @ PHY - break; - case 2: - // long formats are handled @ PHY - break; - case 3: - // long formats are handled @ PHY - break; - default: - AssertFatal(1 == 0, "Invalid PRACH format"); - } - } // if format1 + prach_config_pdu->num_cs = ncs; +// prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[n].prach_root_sequence_index; + prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index; - // RO matching the SSB is found -> get out of mapping loop - mac->generate_nr_prach = 1; + prach_config_pdu->restricted_set = prach_config->restricted_set_config; +// prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1; + prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1; + + if (format1 != 0xff) { + switch(format0) { // dual PRACH format + case 0xa1: + prach_config_pdu->prach_format = 9; break; - } // if selected_gnb_ssb_idx - } // for ssb_nb + case 0xa2: + prach_config_pdu->prach_format = 10; + break; + case 0xa3: + prach_config_pdu->prach_format = 11; + break; + default: + AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); + } + } else { + switch(format0) { // single PRACH format + case 0xa1: + prach_config_pdu->prach_format = 0; + break; + case 0xa2: + prach_config_pdu->prach_format = 1; + break; + case 0xa3: + prach_config_pdu->prach_format = 2; + break; + case 0xb1: + prach_config_pdu->prach_format = 3; + break; + case 0xb2: + prach_config_pdu->prach_format = 4; + break; + case 0xb3: + prach_config_pdu->prach_format = 5; + break; + case 0xb4: + prach_config_pdu->prach_format = 6; + break; + case 0xc0: + prach_config_pdu->prach_format = 7; + break; + case 0xc2: + prach_config_pdu->prach_format = 8; + break; + case 0: + // long formats are handled @ PHY + break; + case 1: + // long formats are handled @ PHY + break; + case 2: + // long formats are handled @ PHY + break; + case 3: + // long formats are handled @ PHY + break; + default: + AssertFatal(1 == 0, "Invalid PRACH format"); + } + } // if format1 +// } for n + } else { + mac->generate_nr_prach = 0; + } // if-else is_nr_prach_slot - // RO matching the SSB is found -> get out of mapping loop - if (1 == mac->generate_nr_prach) break; - } // for ro_in_freq - - // RO matching the SSB is found -> get out of mapping loop - if (1 == mac->generate_nr_prach) break; - } // for ro_in_time - } mac->scheduled_response.ul_config = ul_config; - } + } // if is_nr_UL_slot } //////////////////////////////////////////////////////////////////////////// From 8735920b5a398845f64e5863f3468f37aef551da Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Fri, 24 Jul 2020 08:17:59 -0400 Subject: [PATCH 03/31] Modified a comment --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index eb96b0eb3e..42b2ad8196 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1063,7 +1063,7 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { // ============================== // WIP-IDCC: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule // WIP-IDCC: Only FR2 is implemented - // WIP-IDCC: RACH preambles are not mapped yet (assumptions: ssb_per_rach is <= 1, totalNumberOfRA = CB-preamblesPerSSB = 64) + // WIP-IDCC: RACH preambles are not mapped yet (assumptions: ssb_per_rach is <= 1, totalNumberOfRA = CB-preamblesPerSSB - see NR_MAC_UE/nr_ra_procedures.c->nr_get_prach_resources) // Identify the proper PRACH Configuration Index table according to the operating frequency if (pointa > 2016666) { //FR2 From 8ea4897ff9988bba85e96b73784dd7659c1cfb25 Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Fri, 24 Jul 2020 15:22:01 -0400 Subject: [PATCH 04/31] Renaming of variables after code review --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 231 +++++++++--------- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 6 +- 2 files changed, 119 insertions(+), 118 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 42b2ad8196..0b2e6747fd 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -39,52 +39,52 @@ #define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16 #define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms #define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms -#define MAX_NB_FRAMES_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms -#define MAX_NB_SLOTS_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) -#define MAX_NB_FRAMES_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period -#define MAX_NB_SSBS (64) // Maximum number of possible SSB indexes +#define MAX_NB_FRAME_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms +#define MAX_NB_SLOT_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) +#define MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period +#define MAX_NB_SSB (64) // Maximum number of possible SSB indexes #define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config // Maximum number of ROs that can be mapped to an SSB in an association pattern // This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB // An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot -#define MAX_NB_ROS_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOTS_IN_FRAME*MAX_NB_FRAMES_IN_ASSOCIATION_PATTERN_PERIOD) +#define MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOT_IN_FRAME*MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD) // The PRACH Config period is a series of selected slots in one or multiple frames typedef struct prach_conf_period { - prach_occasion_slot_t prach_occasion_slots_map[MAX_NB_FRAMES_IN_PRACH_CONF_PERIOD][MAX_NB_SLOTS_IN_FRAME]; - uint16_t nb_of_prach_occasions; // Total number of PRACH occasions in the PRACH Config period - uint8_t nb_of_frames; // Size of the PRACH Config period in number of 10ms frames - uint8_t nb_of_slots; // Nb of slots in each frame + prach_occasion_slot_t prach_occasion_slot_map[MAX_NB_FRAME_IN_PRACH_CONF_PERIOD][MAX_NB_SLOT_IN_FRAME]; + uint16_t nb_of_prach_occasion; // Total number of PRACH occasions in the PRACH Config period + uint8_t nb_of_frame; // Size of the PRACH Config period in number of 10ms frames + uint8_t nb_of_slot; // Nb of slots in each frame } prach_conf_period_t; // The association period is a series of PRACH Config periods typedef struct prach_association_period { - prach_conf_period_t *prach_conf_periods_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; - uint8_t nb_of_prach_conf_periods; // Nb of PRACH configuration periods within the association period - uint8_t nb_of_frames; // Total number of frames included in the association period + prach_conf_period_t *prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; + uint8_t nb_of_prach_conf_period; // Nb of PRACH configuration periods within the association period + uint8_t nb_of_frame; // Total number of frames included in the association period } prach_association_period_t; // The association pattern is a series of Association periods typedef struct prach_association_pattern { - prach_association_period_t prach_association_periods_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; - prach_conf_period_t prach_conf_periods_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; - uint8_t nb_of_assoc_periods; // Nb of association periods within the association pattern - uint8_t nb_of_prach_conf_periods_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH - uint8_t nb_of_frames; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) + prach_association_period_t prach_association_period_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + prach_conf_period_t prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + uint8_t nb_of_assoc_period; // Nb of association periods within the association pattern + uint8_t nb_of_prach_conf_period_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH + uint8_t nb_of_frame; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) } prach_association_pattern_t; // SSB details typedef struct ssb_info { boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration - prach_occasion_info_t *mapped_ros[MAX_NB_ROS_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index - uint16_t nb_mapped_ros; // Total number of mapped ROs to this SSB index + prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index + uint16_t nb_mapped_ro; // Total number of mapped ROs to this SSB index } ssb_info_t; // List of all the possible SSBs and their details typedef struct ssb_list_info { - ssb_info_t tx_ssb[MAX_NB_SSBS]; - uint8_t nb_tx_ssbs; + ssb_info_t tx_ssb[MAX_NB_SSB]; + uint8_t nb_tx_ssb; } ssb_list_info_t; static prach_association_pattern_t prach_assoc_pattern; @@ -1028,7 +1028,7 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { uint8_t slot; // Maximum is the number of slots in a frame @ SCS 240kHz uint16_t format = 0xffff; uint8_t format2 = 0xff; - int fdm; + int nb_fdm; uint8_t config_index, mu; uint32_t pointa; @@ -1053,7 +1053,7 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { case 1: case 2: case 3: - fdm = 1 << msg1_FDM; + nb_fdm = 1 << msg1_FDM; break; default: AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM); @@ -1078,7 +1078,7 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { y = table_6_3_3_2_4_prachConfig_Index[config_index][3]; y2 = table_6_3_3_2_4_prachConfig_Index[config_index][4]; - prach_assoc_pattern.nb_of_prach_conf_periods_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; + prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; nb_of_frames_per_prach_conf_period = x; // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period @@ -1087,10 +1087,10 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { // For every PRACH configuration periods // ------------------------------------- - for (prach_conf_period_idx=0; prach_conf_period_idxstart_symbol = start_symbol; prach_occasion_p->fdm = n_prach_occ_in_freq; prach_occasion_p->frame = frame; prach_occasion_p->slot = slot; prach_occasion_p->format = format; - prach_assoc_pattern.prach_conf_periods_list[prach_conf_period_idx].nb_of_prach_occasions++; - prach_assoc_pattern.prach_conf_periods_list[prach_conf_period_idx].prach_occasion_slots_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasions_in_freq++; + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++; + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq++; } // For every freq in the slot } // For every time occasions in the slot } // Valid slot? @@ -1174,7 +1174,7 @@ static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { for (uint8_t bit_nb=last_bit; bit_nb<=sizeof(uint8_t)-1; bit_nb++) { // If SSB is transmitted if (*byte_p>>bit_nb & 0x01) { - ssb_list.nb_tx_ssbs++; + ssb_list.nb_tx_ssb++; ssb_list.tx_ssb[ssb_idx].transmitted = true; } ssb_idx++; @@ -1192,44 +1192,44 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; - boolean_t multiple_ssbs_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB + boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB - uint16_t required_nb_of_prach_occasions; // Nb of RACH occasions required to map all the SSBs - uint8_t required_nb_of_prach_conf_periods; // Nb of PRACH configuration periods required to map all the SSBs + uint16_t required_nb_of_prach_occasion; // Nb of RACH occasions required to map all the SSBs + uint8_t required_nb_of_prach_conf_period; // Nb of PRACH configuration periods required to map all the SSBs // Determine the SSB to RACH mapping ratio // ======================================= switch (ssb_perRACH_config){ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: - multiple_ssbs_per_ro = false; + multiple_ssb_per_ro = false; ssb_rach_ratio = 8; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: - multiple_ssbs_per_ro = false; + multiple_ssb_per_ro = false; ssb_rach_ratio = 4; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: - multiple_ssbs_per_ro = false; + multiple_ssb_per_ro = false; ssb_rach_ratio = 2; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: - multiple_ssbs_per_ro = true; + multiple_ssb_per_ro = true; ssb_rach_ratio = 1; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: - multiple_ssbs_per_ro = true; + multiple_ssb_per_ro = true; ssb_rach_ratio = 2; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: - multiple_ssbs_per_ro = true; + multiple_ssb_per_ro = true; ssb_rach_ratio = 4; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: - multiple_ssbs_per_ro = true; + multiple_ssb_per_ro = true; ssb_rach_ratio = 8; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: - multiple_ssbs_per_ro = true; + multiple_ssb_per_ro = true; ssb_rach_ratio = 16; break; default: @@ -1242,46 +1242,47 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // WIP-IDCC: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) // There is only one possible association period - if (true == multiple_ssbs_per_ro) { - required_nb_of_prach_occasions = ((ssb_list.nb_tx_ssbs-1) + ssb_rach_ratio) / ssb_rach_ratio; + if (true == multiple_ssb_per_ro) { + required_nb_of_prach_occasion = ((ssb_list.nb_tx_ssb-1) + ssb_rach_ratio) / ssb_rach_ratio; } else { - required_nb_of_prach_occasions = ssb_list.nb_tx_ssbs * ssb_rach_ratio; + required_nb_of_prach_occasion = ssb_list.nb_tx_ssb * ssb_rach_ratio; } - required_nb_of_prach_conf_periods = ((required_nb_of_prach_occasions-1) + prach_assoc_pattern.prach_conf_periods_list[0].nb_of_prach_occasions) / prach_assoc_pattern.prach_conf_periods_list[0].nb_of_prach_occasions; + required_nb_of_prach_conf_period = ((required_nb_of_prach_occasion-1) + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion) / prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion; - if (required_nb_of_prach_conf_periods == 1) { - prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 1; + if (required_nb_of_prach_conf_period == 1) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 1; } - else if (required_nb_of_prach_conf_periods == 2) { - prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 2; + else if (required_nb_of_prach_conf_period == 2) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 2; } - else if (required_nb_of_prach_conf_periods <= 4) { - prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 4; + else if (required_nb_of_prach_conf_period <= 4) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 4; } - else if (required_nb_of_prach_conf_periods <= 8) { - prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 8; + else if (required_nb_of_prach_conf_period <= 8) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 8; + } + else if (required_nb_of_prach_conf_period <= 16) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 16; } else { - AssertFatal(16 >= required_nb_of_prach_conf_periods, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_periods); - - prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods = 16; + AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period); } - prach_assoc_pattern.nb_of_assoc_periods = 1; // WIP-IDCC: only one possible association period - prach_assoc_pattern.prach_association_periods_list[0].nb_of_frames = prach_assoc_pattern.prach_association_periods_list[0].nb_of_prach_conf_periods * prach_assoc_pattern.prach_conf_periods_list[0].nb_of_frames; - prach_assoc_pattern.nb_of_frames = prach_assoc_pattern.prach_association_periods_list[0].nb_of_frames; + prach_assoc_pattern.nb_of_assoc_period = 1; // WIP-IDCC: only one possible association period + prach_assoc_pattern.prach_association_period_list[0].nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period * prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; + prach_assoc_pattern.nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_frame; // Proceed to the SSB to RO mapping // ================================ uint8_t association_period_idx; // Association period index within the association pattern - uint8_t ssb_idx = MAX_NB_SSBS; + uint8_t ssb_idx = MAX_NB_SSB; uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern prach_conf_period_t *prach_conf_period_p; // Map all the association periods within the association pattern period - for (association_period_idx=0; association_period_idxnb_of_frames; frame++) { - for (slot=0; slotnb_of_slots; slot++) { - for (ro_in_time=0; ro_in_timeprach_occasion_slots_map[frame][slot].nb_of_prach_occasions_in_time; ro_in_time++) { - for (ro_in_freq=0; ro_in_freqprach_occasion_slots_map[frame][slot].nb_of_prach_occasions_in_freq; ro_in_freq++) { - prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slots_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; + for (frame=0; framenb_of_frame; frame++) { + for (slot=0; slotnb_of_slot; slot++) { + for (ro_in_time=0; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { + for (ro_in_freq=0; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO - for (ssb_idx=0; ssb_idxmapped_ssb_idx[ro_p->nb_mapped_ssbs] = ssb_idx; - ro_p->nb_mapped_ssbs++; - ssb_list.tx_ssb[ssb_idx].mapped_ros[ssb_list.tx_ssb[ssb_idx].nb_mapped_ros] = ro_p; - ssb_list.tx_ssb[ssb_idx].nb_mapped_ros++; - AssertFatal(MAX_NB_ROS_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ros,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ros); + ro_p->mapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx; + ro_p->nb_mapped_ssb++; + ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; + AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); // If all the required SSBs are mapped to this RO, exit the loop of SSBs - if (ro_p->nb_mapped_ssbs == ssb_rach_ratio) { + if (ro_p->nb_mapped_ssb == ssb_rach_ratio) { ssb_idx++; break; } @@ -1333,23 +1334,23 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { } // for ssb_idx // Exit the loop of ROs if there is no more SSB to map - if (MAX_NB_SSBS == ssb_idx) break; + if (MAX_NB_SSB == ssb_idx) break; } // for ro_in_freq // Exit the loop of ROs if there is no more SSB to map - if (MAX_NB_SSBS == ssb_idx) break; + if (MAX_NB_SSB == ssb_idx) break; } // for ro_in_time // Exit the loop of slots if there is no more SSB to map - if (MAX_NB_SSBS == ssb_idx) break; + if (MAX_NB_SSB == ssb_idx) break; } // for slot // Exit the loop frames if there is no more SSB to map - if (MAX_NB_SSBS == ssb_idx) break; + if (MAX_NB_SSB == ssb_idx) break; } // for frame // Exit the loop of PRACH configurations if there is no more SSB to map - if (MAX_NB_SSBS == ssb_idx) break; + if (MAX_NB_SSB == ssb_idx) break; } // for n_prach_conf // WIP-IDCC: note that there is no re-mapping of the SSBs within the association period since there is no invalid ROs in the PRACH config periods that would create this situation @@ -1366,57 +1367,57 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { n_prach_conf = 0; // Go through the list of transmitted SSBs - for (ssb_idx=0; ssb_idxnb_of_frames; frame++) { - for (; slotnb_of_slots; slot++) { - for (; ro_in_timeprach_occasion_slots_map[frame][slot].nb_of_prach_occasions_in_time; ro_in_time++) { - for (; ro_in_freqprach_occasion_slots_map[frame][slot].nb_of_prach_occasions_in_freq; ro_in_freq++) { - prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slots_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; + for (; framenb_of_frame; frame++) { + for (; slotnb_of_slot; slot++) { + for (; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { + for (; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; ro_p->mapped_ssb_idx[0] = ssb_idx; - ro_p->nb_mapped_ssbs = 1; - ssb_list.tx_ssb[ssb_idx].mapped_ros[ssb_list.tx_ssb[ssb_idx].nb_mapped_ros] = ro_p; - ssb_list.tx_ssb[ssb_idx].nb_mapped_ros++; - AssertFatal(MAX_NB_ROS_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ros,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ros); - nb_mapped_ros_in_association_period++; + ro_p->nb_mapped_ssb = 1; + ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; + AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + nb_mapped_ro_in_association_period++; // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ros_in_association_period == ssb_rach_ratio) { + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { ro_in_freq++; break; } } // for ro_in_freq // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) break; else ro_in_freq = 0; // else go to the next time symbol in that slot } // for ro_in_time // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) break; else ro_in_time = 0; // else go to the next slot in that PRACH config period } // for slot // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) break; else slot = 0; // else go to the next frame in that PRACH config period } // for frame // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ros_in_association_period == ssb_rach_ratio) break; + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) break; else frame = 0; // else go to the next PRACH config period in that association period } // for n_prach_conf @@ -1461,13 +1462,13 @@ int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, // - exact slot number // - frame offset ssb_info_p = &ssb_list.tx_ssb[ssb_idx]; - for (uint8_t n_mapped_ro=0; n_mapped_ronb_mapped_ros; n_mapped_ro++) { - if ((slot == ssb_info_p->mapped_ros[n_mapped_ro]->slot) && - (ssb_info_p->mapped_ros[n_mapped_ro]->frame == (frame % prach_assoc_pattern.nb_of_frames))) { + for (uint8_t n_mapped_ro=0; n_mapped_ronb_mapped_ro; n_mapped_ro++) { + if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) && + (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_ros[n_mapped_ro]->frame / prach_assoc_pattern.prach_conf_periods_list[0].nb_of_frames; - uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ros[n_mapped_ro]->frame % prach_assoc_pattern.prach_conf_periods_list[0].nb_of_frames; - prach_occasion_slot_p = &prach_assoc_pattern.prach_conf_periods_list[prach_config_period_nb].prach_occasion_slots_map[frame_nb_in_prach_config_period][slot]; + 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]; } } @@ -1476,10 +1477,10 @@ int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, { // Go through all the ROs in the slot and find the first that is mapped to the selected SSB index // WIP-IDCC: A random RO mapped to the SSB index should be selected in the slot instead - for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasions_in_time; ro_in_time++) { - for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasions_in_freq; ro_in_freq++) { + 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 *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; - for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssbs; ssb_nb++) { + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { *prach_occasion_info_pp = prach_occasion_info_p; return 1; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 23924ca44e..3cb0c52281 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -51,7 +51,7 @@ typedef struct prach_occasion_info { uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz) uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern) uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs - uint8_t nb_mapped_ssbs; + uint8_t nb_mapped_ssb; uint16_t format; // RO preamble format } prach_occasion_info_t; @@ -59,8 +59,8 @@ typedef struct prach_occasion_info { // A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency typedef struct prach_occasion_slot { prach_occasion_info_t prach_occasion[MAX_TDM][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot - uint8_t nb_of_prach_occasions_in_time; - uint8_t nb_of_prach_occasions_in_freq; + uint8_t nb_of_prach_occasion_in_time; + uint8_t nb_of_prach_occasion_in_freq; } prach_occasion_slot_t; // ======================================== From 638d8f8d0dc06f3f0d0be3894ac7849736a83166 Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Wed, 26 Aug 2020 13:14:50 -0400 Subject: [PATCH 05/31] Fix endianness handling of the ssb_PositionsInBurst --- common/utils/asn1_conversions.h | 4 ++-- openair1/PHY/INIT/nr_parms.c | 2 +- openair2/GNB_APP/gnb_config.c | 15 +++------------ openair2/LAYER2/NR_MAC_UE/config_ue.c | 4 ++-- 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/common/utils/asn1_conversions.h b/common/utils/asn1_conversions.h index 050c065d9d..82dca54c08 100644 --- a/common/utils/asn1_conversions.h +++ b/common/utils/asn1_conversions.h @@ -101,11 +101,11 @@ static inline uint64_t BIT_STRING_to_uint64(BIT_STRING_t *asn) { shift = ((asn->size - 1) * 8) - asn->bits_unused; for (index = 0; index < (asn->size - 1); index++) { - result |= asn->buf[index] << shift; + result |= ((uint64_t)asn->buf[index]) << shift; shift -= 8; } - result |= asn->buf[index] >> asn->bits_unused; + result |= ((uint64_t)asn->buf[index]) >> asn->bits_unused; return result; } diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index c3fe9c54b1..7153b048e2 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -385,7 +385,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->Lmax = 64; } - fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[1].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask; + fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask; fp->N_ssb = 0; for (int p=0; pLmax; p++) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 61aa10e47b..9cb88c42a4 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -223,20 +223,12 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { scc->ssb_PositionsInBurst->choice.shortBitmap.bits_unused = 4; scc->ssb_PositionsInBurst->choice.shortBitmap.buf = CALLOC(1,1); scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] = 0; - for (int i=0; i<8; i++) { - if (issb_PositionsInBurst->choice.shortBitmap.bits_unused) - curr_bit = 0; - else - curr_bit = (ssbmap>>(7-i))&0x01; - scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] |= curr_bit<ssb_PositionsInBurst->choice.shortBitmap.buf[0] = ssbmap & 0xF0; }else if(ssbmaplen==NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap){ scc->ssb_PositionsInBurst->choice.mediumBitmap.size = 1; scc->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0; scc->ssb_PositionsInBurst->choice.mediumBitmap.buf = CALLOC(1,1); - scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] = 0; - for (int i=0; i<8; i++) - scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] |= (((ssbmap>>(7-i))&0x01)<ssb_PositionsInBurst->choice.mediumBitmap.buf[0] = ssbmap; }else { scc->ssb_PositionsInBurst->choice.longBitmap.size = 8; scc->ssb_PositionsInBurst->choice.longBitmap.bits_unused = 0; @@ -244,8 +236,7 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { for (int j=0; j<8; j++) { scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-j] = 0; curr_bit = (ssbmap>>(j<<3))&(0xff); - for (int i=0; i<8; i++) - scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-j] |= (((curr_bit>>(7-i))&0x01)<ssb_PositionsInBurst->choice.longBitmap.buf[7-j] = curr_bit; } } diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 1dcbeafc1f..91fffbc06c 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -244,8 +244,8 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, cfg->ssb_table.ssb_mask_list[0].ssb_mask = 0; cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; for (i=0; i<4; i++) { - cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]< Date: Wed, 26 Aug 2020 13:24:04 -0400 Subject: [PATCH 06/31] Fixed initialization of SSB to RO mapping tables --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 86 ++++++++++++++----- 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 0b2e6747fd..c5c17fa2af 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -31,6 +31,7 @@ */ #include "LAYER2/NR_MAC_gNB/mac_proto.h" +#include "asn1_conversions.h" // ================================================ // SSB to RO mapping private defines and structures @@ -1040,6 +1041,10 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { config_index = rach_ConfigGeneric->prach_ConfigurationIndex; + // WIP-IDCC Force config index to 44 for debug +// LOG_D(MAC,"Change PRACH config index from %d to 44 for debug\n", config_index); +// config_index = 44; + if (setup->msg1_SubcarrierSpacing) mu = *setup->msg1_SubcarrierSpacing; else @@ -1066,6 +1071,7 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { // WIP-IDCC: RACH preambles are not mapped yet (assumptions: ssb_per_rach is <= 1, totalNumberOfRA = CB-preamblesPerSSB - see NR_MAC_UE/nr_ra_procedures.c->nr_get_prach_resources) // Identify the proper PRACH Configuration Index table according to the operating frequency + LOG_D(MAC,"Pointa %d, mu = %d\n", pointa, mu); if (pointa > 2016666) { //FR2 int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers uint8_t slot_60khz; @@ -1080,6 +1086,7 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; nb_of_frames_per_prach_conf_period = x; + LOG_D(MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period); // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period // ---------------------------------------------------------------------------------------------------------------------------------------------- @@ -1092,11 +1099,14 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_frame = nb_of_frames_per_prach_conf_period; prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_slot = nr_slots_per_frame[mu]; + LOG_D(MAC,"PRACH Conf Period Idx %d\n", prach_conf_period_idx); + // For every frames in a PRACH configuration period // ------------------------------------------------ for (prach_conf_period_frame_idx=0; prach_conf_period_frame_idxslot = slot; prach_occasion_p->format = format; prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++; - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq++; + + LOG_D(MAC,"Adding a PRACH occasion: fdm %d, frame %d, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n", + frame, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion, + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time, + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq); } // For every freq in the slot } // For every time occasions in the slot } // Valid slot? @@ -1157,29 +1174,26 @@ static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { // Create the list of transmitted SSBs // =================================== // WIP-IDCC: Assumption: the optional ssb_PositionsInBurst is provided - BIT_STRING_t *ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; - - // Fill in the Tx SSBs list by going through all the bits set in the SSB bitmask + BIT_STRING_t *ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; + uint64_t ssb_positionsInBurst; uint8_t nb_of_bytes = ssb_bitmap->size; - uint8_t last_bit = 0; - uint8_t *byte_p = ssb_bitmap->buf; uint8_t ssb_idx = 0; - // Loop through the SSB idx bitmask starting with bit 0 up to the max of the bitmask - for (uint8_t byte_nb=nb_of_bytes; byte_nb>=1; byte_nb--) { - if (byte_nb == nb_of_bytes) { - last_bit = ssb_bitmap->bits_unused; - } + // WIP-IDCC: Support only long SSB bitmap for now + if (8 == nb_of_bytes) { + ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); - for (uint8_t bit_nb=last_bit; bit_nb<=sizeof(uint8_t)-1; bit_nb++) { + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%llx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { // If SSB is transmitted - if (*byte_p>>bit_nb & 0x01) { + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { ssb_list.nb_tx_ssb++; ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); } ssb_idx++; } - byte_p++; } } @@ -1199,6 +1213,8 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // Determine the SSB to RACH mapping ratio // ======================================= + LOG_D(MAC,"SSB per RACH config %u\n", ssb_perRACH_config); + switch (ssb_perRACH_config){ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: multiple_ssb_per_ro = false; @@ -1236,12 +1252,14 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); break; } + LOG_D(MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro); // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period // ============================================================================================================== // WIP-IDCC: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) // There is only one possible association period + LOG_D(MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n"); if (true == multiple_ssb_per_ro) { required_nb_of_prach_occasion = ((ssb_list.nb_tx_ssb-1) + ssb_rach_ratio) / ssb_rach_ratio; } @@ -1274,6 +1292,10 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { prach_assoc_pattern.prach_association_period_list[0].nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period * prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; prach_assoc_pattern.nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_frame; + LOG_D(MAC,"Assoc period %d, Nb of frames in assoc period %d\n", + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period, + prach_assoc_pattern.prach_association_period_list[0].nb_of_frame); + // Proceed to the SSB to RO mapping // ================================ uint8_t association_period_idx; // Association period index within the association pattern @@ -1282,6 +1304,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { prach_conf_period_t *prach_conf_period_p; // Map all the association periods within the association pattern period + LOG_D(MAC,"Proceed to the SSB to RO mapping\n"); for (association_period_idx=0; association_period_idx ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); nb_mapped_ro_in_association_period++; + LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); + LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period); + // Exit the loop if this SSB has been mapped to all the required ROs + // WIP: Assuming that ssb_rach_ratio equals the maximum nb of a given ssb_idx mapped within an assocation period: this is true if + // no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { ro_in_freq++; break; @@ -1402,23 +1430,31 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { } // for ro_in_freq // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) break; - else ro_in_freq = 0; // else go to the next time symbol in that slot + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else ro_in_freq = 0; // else go to the next time symbol in that slot and reset the freq index } // for ro_in_time // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) break; - else ro_in_time = 0; // else go to the next slot in that PRACH config period + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else ro_in_time = 0; // else go to the next slot in that PRACH config period and reset the symbol index } // for slot // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) break; - else slot = 0; // else go to the next frame in that PRACH config period + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else slot = 0; // else go to the next frame in that PRACH config period and reset the slot index } // for frame // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) break; - else frame = 0; // else go to the next PRACH config period in that association period + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else frame = 0; // else go to the next PRACH config period in that association period and reset the frame index } // for n_prach_conf } // if ssb_idx is transmitted @@ -1436,13 +1472,17 @@ void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc) { memset(&ssb_list, 0, sizeof(ssb_list_info_t)); // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config + LOG_D(MAC,"Build RO list\n"); build_ro_list(scc); // Build the list of all the valid/transmitted SSBs according to the config + LOG_D(MAC,"Build SSB list\n"); build_ssb_list(scc); // Map the transmitted SSBs to the ROs and create the association pattern according to the config + LOG_D(MAC,"Map SSB to RO\n"); map_ssb_to_ro(scc); + LOG_D(MAC,"Map SSB to RO done\n"); } // Returns a RACH occasion if any matches the SSB idx, the frame and the slot From 597ddf75742dc92586cd58b646690758d12d579d Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Thu, 27 Aug 2020 15:23:59 -0400 Subject: [PATCH 07/31] Merged in some FR2 fixes from Rakesh --- executables/nr-uesoftmodem.c | 15 +++++++++++---- openair1/PHY/MODULATION/slot_fep_nr.c | 10 ++++++++-- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 1 + openair2/LAYER2/NR_MAC_UE/config_ue.c | 2 +- openair2/LAYER2/NR_MAC_gNB/config.c | 2 +- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 6d3bbc9038..9e3ed3eedf 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -691,9 +691,9 @@ int main( int argc, char **argv ) { nr_init_frame_parms_ue(frame_parms[CC_id],nrUE_config,NORMAL); // Overwrite DL frequency (for FR2 testing) - if (downlink_frequency[0][0]!=0) - frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0]; - + //if (downlink_frequency[0][0]!=0) + // frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0]; + init_nr_ue_vars(UE[CC_id],frame_parms[CC_id],0,abstraction_flag); UE[CC_id]->mac_enabled = 1; @@ -752,7 +752,14 @@ int main( int argc, char **argv ) { UE[CC_id]->N_TA_offset = (int)(N_TA_offset * factor); LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d)\n", UE[CC_id]->Mod_id, UE[CC_id]->N_TA_offset, factor, UE[CC_id]->frame_parms.ul_CarrierFreq, N_RB); } - } + + // Overwrite DL frequency (for FR2 testing) + if (downlink_frequency[0][0]!=0){ + frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0]; + if (frame_parms[CC_id]->frame_type == TDD) + frame_parms[CC_id]->ul_CarrierFreq = downlink_frequency[0][0]; + } +} // printf("tx_max_power = %d -> amp %d\n",tx_max_power[0],get_tx_amp(tx_max_poHwer,tx_max_power)); init_openair0(); diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index cf0a50a018..8b9cdd268a 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -461,9 +461,15 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, dft(dftsize,(int16_t *)&tmp_dft_in, (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); } - else - dft(dftsize,(int16_t *)&rxdata[rxdata_offset-sample_offset], + else{ + //dft(dftsize,(int16_t *)&rxdata[rxdata_offset-sample_offset], + // (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); + memcpy((void *)tmp_dft_in, + (void *) &rxdata[rxdata_offset-sample_offset], + (frame_parms->ofdm_symbol_size)*sizeof(int)); + dft(dftsize,(int16_t *)&tmp_dft_in, (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); + } // clear DC carrier from OFDM symbols rxdataF[symbol * frame_parms->ofdm_symbol_size] = 0; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index c5c17fa2af..c3a7002d26 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1151,6 +1151,7 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { prach_occasion_p->frame = frame; prach_occasion_p->slot = slot; prach_occasion_p->format = format; + printf("\nprach_conf_period_idx : %d, .nb_of_prach_occasion : %d\n",prach_conf_period_idx,prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion); prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++; LOG_D(MAC,"Adding a PRACH occasion: fdm %d, frame %d, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n", diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 91fffbc06c..4db1aeaf81 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -205,7 +205,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, uint16_t band; int32_t offset; - get_band((cfg->carrier_config.dl_frequency)*1000, + get_band((uint64_t)(cfg->carrier_config.dl_frequency)*1000, &band, &offset, &frame_type); diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 36b81927f8..3e4b65e9bf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -125,7 +125,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm uint16_t band; int32_t offset; - get_band((cfg->carrier_config.dl_frequency.value)*1000, + get_band((uint64_t)(cfg->carrier_config.dl_frequency.value)*1000, &band, &offset, &frame_type); From c48e96e93a0a89adb84e0bf868b9c153e6dd6347 Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Tue, 8 Sep 2020 11:18:42 -0400 Subject: [PATCH 08/31] -UE RACH updates - Added support for FR1 in RO selection -RACH preamble selected according to the chosen RO --- .../nfapi/public_inc/fapi_nr_ue_interface.h | 3 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 285 +++++++++++------- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 4 +- openair2/LAYER2/NR_MAC_UE/config_ue.c | 2 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 3 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 112 +++++-- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 8 + 8 files changed, 286 insertions(+), 133 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 246ab13e86..c262ac9adb 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -170,6 +170,7 @@ typedef struct { uint8_t prach_format; /// Num RA uint8_t num_ra; + uint8_t prach_slot; uint8_t prach_start_symbol; /// 38.211 (NCS 38.211 6.3.3.1). uint16_t num_cs; @@ -179,6 +180,8 @@ typedef struct { uint8_t restricted_set; /// see TS 38.211 (6.3.3.2). uint16_t freq_msg1; + // 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; // nfapi_nr_ul_beamforming_t beamforming; } fapi_nr_ul_config_prach_pdu; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index e902977721..0928b68abf 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -4526,7 +4526,7 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t ue->ulsch_Msg3_active[i] = 0; } } - nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx); + nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], ue->prach_vars[0], mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx); } } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index c3a7002d26..6e21c76197 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1018,9 +1018,13 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, } // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config -static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { +static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers + int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers + uint8_t slot_shift_for_map; + uint8_t map_shift; + boolean_t even_slot_invalid; int64_t s_map; uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot @@ -1035,6 +1039,10 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { uint32_t pointa; int msg1_FDM; + uint8_t prach_conf_period_idx; + uint8_t nb_of_frames_per_prach_conf_period; + uint8_t prach_conf_period_frame_idx; + NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; @@ -1071,102 +1079,137 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc) { // WIP-IDCC: RACH preambles are not mapped yet (assumptions: ssb_per_rach is <= 1, totalNumberOfRA = CB-preamblesPerSSB - see NR_MAC_UE/nr_ra_procedures.c->nr_get_prach_resources) // Identify the proper PRACH Configuration Index table according to the operating frequency - LOG_D(MAC,"Pointa %d, mu = %d\n", pointa, mu); - if (pointa > 2016666) { //FR2 - int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers - uint8_t slot_60khz; + LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index = %u, unpaired = %u\n", pointa, mu, config_index, unpaired); - uint8_t prach_conf_period_idx; - uint8_t nb_of_frames_per_prach_conf_period; - uint8_t prach_conf_period_frame_idx; + if (pointa > 2016666) { //FR2 x = table_6_3_3_2_4_prachConfig_Index[config_index][2]; y = table_6_3_3_2_4_prachConfig_Index[config_index][3]; y2 = table_6_3_3_2_4_prachConfig_Index[config_index][4]; - prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; - nb_of_frames_per_prach_conf_period = x; - LOG_D(MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period); + s_map = table_6_3_3_2_4_prachConfig_Index[config_index][5]; - // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period - // ---------------------------------------------------------------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------------------------------------------------------------- + prach_conf_start_symbol = table_6_3_3_2_4_prachConfig_Index[config_index][6]; + N_t_slot = table_6_3_3_2_4_prachConfig_Index[config_index][8]; + N_dur = table_6_3_3_2_4_prachConfig_Index[config_index][9]; + if (table_6_3_3_2_4_prachConfig_Index[config_index][1] != -1) + format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][1]; + format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][0]) | (format2<<8); - // For every PRACH configuration periods - // ------------------------------------- - for (prach_conf_period_idx=0; prach_conf_period_idx> (mu-2); // in PRACH configuration index table slots are numbered wrt 60kHz - s_map = table_6_3_3_2_4_prachConfig_Index[config_index][5]; - if ( (s_map>>slot_60khz)&0x01 ) { - // Valid slot according to the 60kHz table - // Additionally, for 120kHz, we must check for the n_RA_Slot param also - if (mu == 3) { - if ( (table_6_3_3_2_4_prachConfig_Index[config_index][7] == 1) && (slot%2 == 0) ) - continue; // no prach in even slots @ 120kHz for 1 prach per 60khz slot - } + prach_conf_start_symbol = table_6_3_3_2_2_prachConfig_Index[config_index][5]; + N_t_slot = table_6_3_3_2_2_prachConfig_Index[config_index][7]; + N_dur = table_6_3_3_2_2_prachConfig_Index[config_index][8]; + if (table_6_3_3_2_2_prachConfig_Index[config_index][1] != -1) + format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[config_index][1]; + format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[config_index][0]) | (format2<<8); + } - // We're good: valid frame and valid slot - // Compute all the PRACH occasions in the slot - prach_conf_start_symbol = table_6_3_3_2_4_prachConfig_Index[config_index][6]; - N_t_slot = table_6_3_3_2_4_prachConfig_Index[config_index][8]; - N_dur = table_6_3_3_2_4_prachConfig_Index[config_index][9]; - if (table_6_3_3_2_4_prachConfig_Index[config_index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][1]; - format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][0]) | (format2<<8); + y2 = y; + slot_shift_for_map = mu; + if ( (mu == 1) && (table_6_3_3_2_3_prachConfig_Index[config_index][6] <= 1) ) + even_slot_invalid = true; + else + even_slot_invalid = false; + } // FR2 / FR1 - uint8_t n_prach_occ_in_time; - uint8_t n_prach_occ_in_freq; + prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; + nb_of_frames_per_prach_conf_period = x; - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot; - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm; + LOG_D(MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period); - for (n_prach_occ_in_time=0; n_prach_occ_in_timestart_symbol = start_symbol; - prach_occasion_p->fdm = n_prach_occ_in_freq; - prach_occasion_p->frame = frame; - prach_occasion_p->slot = slot; - prach_occasion_p->format = format; - printf("\nprach_conf_period_idx : %d, .nb_of_prach_occasion : %d\n",prach_conf_period_idx,prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion); - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++; + // For every frames in a PRACH configuration period + // ------------------------------------------------ + for (prach_conf_period_frame_idx=0; prach_conf_period_frame_idx> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz + if ( (s_map>>map_shift)&0x01 ) { + // Valid slot + + // Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also + if ( even_slot_invalid && (slot%2 == 0) ) + continue; // no prach in even slots @ 30kHz/120kHz for 1 prach per 60khz slot/subframe + + // We're good: valid frame and valid slot + // Compute all the PRACH occasions in the slot + + uint8_t n_prach_occ_in_time; + uint8_t n_prach_occ_in_freq; + + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot; + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm; + + for (n_prach_occ_in_time=0; n_prach_occ_in_timestart_symbol = start_symbol; + prach_occasion_p->fdm = n_prach_occ_in_freq; + prach_occasion_p->frame = frame; + prach_occasion_p->slot = slot; + prach_occasion_p->format = format; + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++; + + LOG_D(MAC,"Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n", + frame, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion, + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time, + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq); + } // For every freq in the slot + } // For every time occasions in the slot + } // Valid slot? + } // For every slots in a frame + } // Valid frame? + } // For every frames in a prach configuration period + } // For every prach configuration periods in the maximum association pattern period (160ms) } // Build the list of all the valid/transmitted SSBs according to the config @@ -1174,27 +1217,62 @@ static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { // Create the list of transmitted SSBs // =================================== - // WIP-IDCC: Assumption: the optional ssb_PositionsInBurst is provided - BIT_STRING_t *ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; + BIT_STRING_t *ssb_bitmap; uint64_t ssb_positionsInBurst; - uint8_t nb_of_bytes = ssb_bitmap->size; uint8_t ssb_idx = 0; - // WIP-IDCC: Support only long SSB bitmap for now - if (8 == nb_of_bytes) { - ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); + switch (scc->ssb_PositionsInBurst->present) { + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; - LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%llx\n", ssb_positionsInBurst); + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list.nb_tx_ssb++; - ssb_list.tx_ssb[ssb_idx].transmitted = true; - LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; } - ssb_idx++; - } + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + default: + AssertFatal(false,"ssb_PositionsInBurst not present\n"); + break; } } @@ -1214,8 +1292,6 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // Determine the SSB to RACH mapping ratio // ======================================= - LOG_D(MAC,"SSB per RACH config %u\n", ssb_perRACH_config); - switch (ssb_perRACH_config){ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: multiple_ssb_per_ro = false; @@ -1300,7 +1376,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // Proceed to the SSB to RO mapping // ================================ uint8_t association_period_idx; // Association period index within the association pattern - uint8_t ssb_idx = MAX_NB_SSB; + uint8_t ssb_idx = 0; uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern prach_conf_period_t *prach_conf_period_p; @@ -1324,9 +1400,11 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // -------------------- // -------------------- + // WIP-IDCC: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO + ssb_idx = 0; + // Go through the list of PRACH config periods within this association period for (n_prach_conf=0; n_prach_confprach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO - for (ssb_idx=0; ssb_idxmapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx; @@ -1349,6 +1427,9 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); + LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + // If all the required SSBs are mapped to this RO, exit the loop of SSBs if (ro_p->nb_mapped_ssb == ssb_rach_ratio) { ssb_idx++; @@ -1422,8 +1503,8 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period); // Exit the loop if this SSB has been mapped to all the required ROs - // WIP: Assuming that ssb_rach_ratio equals the maximum nb of a given ssb_idx mapped within an assocation period: this is true if - // no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule + // WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period: + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { ro_in_freq++; break; @@ -1466,7 +1547,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { } // Build the SSB to RO mapping upon RRC configuration update -void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc) { +void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){ // Clear all the lists and maps memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t)); @@ -1474,7 +1555,7 @@ void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc) { // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config LOG_D(MAC,"Build RO list\n"); - build_ro_list(scc); + build_ro_list(scc, unpaired); // Build the list of all the valid/transmitted SSBs according to the config LOG_D(MAC,"Build SSB list\n"); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 3cb0c52281..7f027f28cc 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -47,7 +47,7 @@ // PRACH occasion details typedef struct prach_occasion_info { uint8_t start_symbol; // 0 - 13 (14 symbols in a slot) - uint8_t fdm; // 1, 2, 4 or 8 (possible values of msg1-FDM) + uint8_t fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8) uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz) uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern) uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs @@ -118,7 +118,7 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, uint16_t *slot_period, uint16_t *offset); -void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc); +void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired); int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, int frame, int slot, prach_occasion_info_t **prach_occasion_info_pp); int get_nr_prach_info_from_index(uint8_t index, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 4db1aeaf81..0686360bd7 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -358,7 +358,7 @@ int nr_rrc_mac_config_req_ue( mac->scg = cell_group_config; // Setup the SSB to Rach Occasions mapping according to the config - build_ssb_to_ro_map(mac->scc); + build_ssb_to_ro_map(mac->scc, mac->phy_config.config_req.cell_config.frame_duplex_type); /* if(mac_cell_group_configP != NULL){ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index e9d7a97a5d..8b8f3eca2a 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -237,6 +237,7 @@ andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 @param nr_tti_tx slot for PRACH transmission @returns indication to generate PRACH to phy */ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, + NR_UE_PRACH *prach_vars, module_id_t mod_id, int CC_id, UE_MODE_t UE_mode, @@ -254,9 +255,9 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, void nr_get_prach_resources(module_id_t mod_id, int CC_id, uint8_t gNB_id, - uint8_t t_id, uint8_t first_Msg3, NR_PRACH_RESOURCES_t *prach_resources, + NR_UE_PRACH *prach_vars, NR_RACH_ConfigDedicated_t * rach_ConfigDedicated); void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 56ae14f98b..6028ddfe31 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -76,9 +76,9 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac); void nr_get_prach_resources(module_id_t mod_id, int CC_id, uint8_t gNB_id, - uint8_t t_id, uint8_t first_Msg3, NR_PRACH_RESOURCES_t *prach_resources, + NR_UE_PRACH *prach_vars, NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); @@ -88,8 +88,8 @@ void nr_get_prach_resources(module_id_t mod_id, // NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo - int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, i, deltaPreamble_Msg3 = 0; - uint8_t noGroupB = 0, s_id, f_id, ul_carrier_id, prach_ConfigIndex, SFN_nbr, Msg3_size; + int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, deltaPreamble_Msg3 = 0; + uint8_t noGroupB = 0, s_id, t_id, f_id, ul_carrier_id, Msg3_size; AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id); nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; @@ -101,6 +101,7 @@ void nr_get_prach_resources(module_id_t mod_id, //////////* UE Random Access Resource Selection *////////// /////////////////////////////////////////////////////////// + // todo: // - switch initialisation cases // -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321) @@ -130,12 +131,81 @@ void nr_get_prach_resources(module_id_t mod_id, // rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB; + // Determine the SSB to RACH mapping ratio + // ======================================= + NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; + boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB + uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB + long cb_preambles_per_ssb; // Nb of preambles per SSB + int total_preambles_per_ssb; + int starting_preamble_nb = 0; + uint8_t ssb_nb_in_ro; + + switch (ssb_perRACH_config){ + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 8; + cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 4; + cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 2; + cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 1; + cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 2; + cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 4; + cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 8; + cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 16; + cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen; + break; + default: + AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); + break; + } + Msg3_size = mac->RA_Msg3_size; numberOfRA_Preambles = 64; if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL) numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles); + // Compute the proper Preamble selection params according to the selected SSB and the ssb_perRACH_OccasionAndCB_PreamblesPerSSB configuration + if ((true == multiple_ssb_per_ro) && + (ssb_rach_ratio > 1)) { + total_preambles_per_ssb = numberOfRA_Preambles / ssb_rach_ratio; + + ssb_nb_in_ro = prach_vars->prach_pdu.ssb_nb_in_ro; + starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro; + } + else { + total_preambles_per_ssb = numberOfRA_Preambles; + starting_preamble_nb = 0; + } + if (!nr_rach_ConfigCommon->groupBconfigured) { noGroupB = 1; } else { @@ -221,27 +291,27 @@ void nr_get_prach_resources(module_id_t mod_id, if (first_Msg3 == 1) { if (noGroupB == 1) { // use Group A preamble - prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles; + prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb); mac->RA_usedGroupA = 1; } else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) { // Group B is configured and RA preamble Group A is used // - todo add condition on CCCH_sdu_size for initiation by CCCH - prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA; + prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA); mac->RA_usedGroupA = 1; } else { // Group B preamble is configured and used // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A // the remaining belong to RA Preambles Group B - prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); + prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); mac->RA_usedGroupA = 0; } } else { // Msg3 is being retransmitted if (mac->RA_usedGroupA == 1 && noGroupB == 1) { - prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles; + prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb); } else if (mac->RA_usedGroupA == 1 && noGroupB == 0){ - prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA; + prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA); } else { - prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); + prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); } } LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex); @@ -269,27 +339,16 @@ void nr_get_prach_resources(module_id_t mod_id, // 1) this does not apply to contention-free RA Preamble for beam failure recovery request // 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario) - prach_ConfigIndex = rach_ConfigGeneric->prach_ConfigurationIndex; - // ra_RNTI computation - // - todo: this is for TDD FR1 only // - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier // - f_id: index of the PRACH occasion in the frequency domain // - s_id is starting symbol of the PRACH occasion [0...14] // - t_id is the first slot of the PRACH occasion in a system frame [0...80] - ul_carrier_id = 0; // NUL - f_id = rach_ConfigGeneric->msg1_FrequencyStart; - SFN_nbr = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][4]; - s_id = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][5]; + f_id = prach_vars->prach_pdu.num_ra; + t_id = prach_vars->prach_pdu.prach_slot; + s_id = prach_vars->prach_pdu.prach_start_symbol; - // Pick the first slot of the PRACH occasion in a system frame - for (i = 0; i < 10; i++){ - if (((SFN_nbr & (1 << i)) >> i) == 1){ - t_id = 2*i; - break; - } - } prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id; mac->ra_rnti = prach_resources->ra_RNTI; @@ -336,6 +395,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint // - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, + NR_UE_PRACH *prach_vars, module_id_t mod_id, int CC_id, UE_MODE_t UE_mode, @@ -450,7 +510,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, // Fill in preamble and PRACH resources if (mac->generate_nr_prach) - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated); + nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated); offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer (uint8_t *) payload, // UL MAC pdu pointer @@ -573,7 +633,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, // Fill in preamble and PRACH resources if (mac->generate_nr_prach) - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); + nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated); } else { @@ -587,7 +647,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, // Fill in preamble and PRACH resources if (mac->generate_nr_prach) - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); + nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated); } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 7ff4ce838e..3101c428fb 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1041,6 +1041,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s prach_config_pdu->phys_cell_id = *scc->physCellId; prach_config_pdu->num_prach_ocas = 1; + prach_config_pdu->prach_slot = prach_occasion_info_p->slot; prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol; prach_config_pdu->num_ra = prach_occasion_info_p->fdm; @@ -1052,6 +1053,13 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s // prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1; prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1; + // Search which SSB is mapped in the RO (among all the SSBs mapped to this RO) + for (prach_config_pdu->ssb_nb_in_ro=0; prach_config_pdu->ssb_nb_in_ronb_mapped_ssb; prach_config_pdu->ssb_nb_in_ro++) { + if (prach_occasion_info_p->mapped_ssb_idx[prach_config_pdu->ssb_nb_in_ro] == selected_gnb_ssb_idx) + break; + } + AssertFatal(prach_config_pdu->ssb_nb_in_ronb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx); + if (format1 != 0xff) { switch(format0) { // dual PRACH format case 0xa1: From 7996582729fbe63b792c612018584726239ccfc4 Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Fri, 18 Sep 2020 15:00:59 -0400 Subject: [PATCH 09/31] - Added support for random RO selection for a given SSB index in a slot (as per 38.321) - Fixed random preamble selection in contention-based RA - Cleaned-up comments and commented code --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 180 ++++------------ openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 11 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 199 +++++++----------- 3 files changed, 121 insertions(+), 269 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 89f265678c..ac08155e2f 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1048,10 +1048,6 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { config_index = rach_ConfigGeneric->prach_ConfigurationIndex; - // WIP-IDCC Force config index to 44 for debug -// LOG_D(MAC,"Change PRACH config index from %d to 44 for debug\n", config_index); -// config_index = 44; - if (setup->msg1_SubcarrierSpacing) mu = *setup->msg1_SubcarrierSpacing; else @@ -1074,8 +1070,6 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { // Create the PRACH occasions map // ============================== // WIP-IDCC: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule - // WIP-IDCC: Only FR2 is implemented - // WIP-IDCC: RACH preambles are not mapped yet (assumptions: ssb_per_rach is <= 1, totalNumberOfRA = CB-preamblesPerSSB - see NR_MAC_UE/nr_ra_procedures.c->nr_get_prach_resources) // Identify the proper PRACH Configuration Index table according to the operating frequency LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index = %u, unpaired = %u\n", pointa, mu, config_index, unpaired); @@ -1334,7 +1328,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // ============================================================================================================== // WIP-IDCC: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) - // There is only one possible association period + // There is only one possible association period which can contain up to 16 PRACH configuration periods LOG_D(MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n"); if (true == multiple_ssb_per_ro) { required_nb_of_prach_occasion = ((ssb_list.nb_tx_ssb-1) + ssb_rach_ratio) / ssb_rach_ratio; @@ -1389,7 +1383,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { uint8_t ro_in_freq=0; // Set the starting PRACH Configuration period index in the association_pattern map for this particular association period - prach_configuration_period_idx = 0; // WIP-IDCC: only one possible association period + prach_configuration_period_idx = 0; // WIP-IDCC: only one possible association period so the starting PRACH configuration period is automatically 0 // Check if we need to map multiple SSBs per RO or multiple ROs per SSB if (true == multiple_ssb_per_ro) { @@ -1400,6 +1394,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // -------------------- // WIP-IDCC: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule ssb_idx = 0; // Go through the list of PRACH config periods within this association period @@ -1417,6 +1412,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO // WIP-IDCC: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule for (; ssb_idxnb_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 *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { - *prach_occasion_info_pp = prach_occasion_info_p; - return 1; + 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 *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; + + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { + if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { + if (nb_mapped_ssb == random_ssb_nb) { + *prach_occasion_info_pp = prach_occasion_info_p; + return 1; + } + else { + nb_mapped_ssb++; + } } } } @@ -1614,138 +1638,6 @@ int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, return 0; } -int get_nr_prach_info_from_index(uint8_t index, - int frame, - int slot, - uint32_t pointa, - uint8_t mu, - uint8_t unpaired, - uint16_t *format, - uint8_t *start_symbol, - uint8_t *N_t_slot, - uint8_t *N_dur) { - - int x,y; - int64_t s_map; - uint8_t format2 = 0xff; - - if (pointa > 2016666) { //FR2 - int y2; - uint8_t slot_60khz; - x = table_6_3_3_2_4_prachConfig_Index[index][2]; - y = table_6_3_3_2_4_prachConfig_Index[index][3]; - y2 = table_6_3_3_2_4_prachConfig_Index[index][4]; - // checking n_sfn mod x = y - if ( (frame%x)==y || (frame%x)==y2 ) { - slot_60khz = slot >> (mu-2); // in table slots are numbered wrt 60kHz - s_map = table_6_3_3_2_4_prachConfig_Index[index][5]; - if ( ((s_map>>slot_60khz)&0x01) ) { - if (mu == 3) { - if ( (table_6_3_3_2_4_prachConfig_Index[index][7] == 1) && (slot%2 == 0) ) - return 0; // no prach in even slots @ 120kHz for 1 prach per 60khz slot - } - if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ - *start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6]; - *N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8]; - *N_dur = table_6_3_3_2_4_prachConfig_Index[index][9]; - if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1]; - *format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, - slot, - index, - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur); - } - return 1; - } - else - return 0; // no prach in current slot - } - else - return 0; // no prach in current frame - } - else { - uint8_t subframe; - if (unpaired) { - x = table_6_3_3_2_3_prachConfig_Index[index][2]; - y = table_6_3_3_2_3_prachConfig_Index[index][3]; - if ( (frame%x)==y ) { - subframe = slot >> mu; - s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; - if ( (s_map>>subframe)&0x01 ) { - if (mu == 1) { - if ( (table_6_3_3_2_3_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) - return 0; // no prach in even slots @ 30kHz for 1 prach per subframe - } - if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ - *start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5]; - *N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7]; - *N_dur = table_6_3_3_2_3_prachConfig_Index[index][8]; - if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; - *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %ld) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, - slot, - index, table_6_3_3_2_3_prachConfig_Index[index][6], - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur); - } - return 1; - } - else - return 0; // no prach in current slot - } - else - return 0; // no prach in current frame - } - else { // FDD - x = table_6_3_3_2_2_prachConfig_Index[index][2]; - y = table_6_3_3_2_2_prachConfig_Index[index][3]; - if ( (frame%x)==y ) { - subframe = slot >> mu; - s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; - if ( (s_map>>subframe)&0x01 ) { - if (mu == 1) { - if ( (table_6_3_3_2_2_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) - return 0; // no prach in even slots @ 30kHz for 1 prach per subframe - } - if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ - *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; - *N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7]; - *N_dur = table_6_3_3_2_2_prachConfig_Index[index][8]; - if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1]; - *format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, - slot, - index, - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur); - } - return 1; - } - else - return 0; // no prach in current slot - } - else - return 0; // no prach in current frame - } - } -} - //Table 6.3.3.1-3: Mapping from logical index i to sequence number u for preamble formats with L_RA = 839 uint16_t table_63313[838] = { 129, 710, 140, 699, 120, 719, 210, 629, 168, 671, 84 , 755, 105, 734, 93 , 746, 70 , 769, 60 , 779, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 5a4cd7881d..803acdc572 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -144,27 +144,27 @@ void nr_get_prach_resources(module_id_t mod_id, case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: multiple_ssb_per_ro = false; ssb_rach_ratio = 8; - cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth; + cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1); break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: multiple_ssb_per_ro = false; ssb_rach_ratio = 4; - cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth; + cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1); break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: multiple_ssb_per_ro = false; ssb_rach_ratio = 2; - cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf; + cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1); break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: multiple_ssb_per_ro = true; ssb_rach_ratio = 1; - cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one; + cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1); break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: multiple_ssb_per_ro = true; ssb_rach_ratio = 2; - cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two; + cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1); break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: multiple_ssb_per_ro = true; @@ -313,6 +313,7 @@ void nr_get_prach_resources(module_id_t mod_id, prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); } } + LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex); } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 32d991ab4c..41852d748c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -940,9 +940,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in // - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { -// uint8_t config_index, mu, N_dur, N_t_slot, start_symbol; uint16_t format, format0, format1, ncs; -// int msg1_FDM, is_nr_prach_slot, fdm; int is_nr_prach_slot; prach_occasion_info_t *prach_occasion_info_p; @@ -955,32 +953,15 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s NR_ServingCellConfigCommon_t *scc = mac->scc; NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; -// NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; -// config_index = rach_ConfigGeneric->prach_ConfigurationIndex; mac->RA_offset = 2; // to compensate the rx frame offset at the gNB mac->generate_nr_prach = 0; // Reset flag for PRACH generation if (is_nr_UL_slot(scc, slotP)) { -// if (setup->msg1_SubcarrierSpacing) -// mu = *setup->msg1_SubcarrierSpacing; -// else -// mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - -// is_nr_prach_slot = get_nr_prach_info_from_index(config_index, -// (int)frameP, -// (int)slotP, -// frequencyInfoDL->absoluteFrequencyPointA, -// mu, -// cfg->cell_config.frame_duplex_type, -// &format, -// &start_symbol, -// &N_t_slot, -// &N_dur); - // WIP-IDCC Need to get the proper selected ssb_idx + // Initial beam selection functionality is not available yet uint8_t selected_gnb_ssb_idx = 0; // Get any valid PRACH occasion in the current slot for the selected SSB index @@ -990,24 +971,10 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s &prach_occasion_info_p); if (is_nr_prach_slot && mac->ra_state == RA_UE_IDLE) { - AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n"); mac->generate_nr_prach = 1; -// fdm = rach_ConfigGeneric->msg1_FDM; -// -// switch (fdm){ -// case 0: -// case 1: -// case 2: -// case 3: -// msg1_FDM = 1 << fdm; -// break; -// default: -// AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", fdm); -// } - format = prach_occasion_info_p->format; format0 = format & 0xff; // single PRACH format format1 = (format >> 8) & 0xff; // dual PRACH format @@ -1015,102 +982,94 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s ul_config->sfn = frameP; ul_config->slot = slotP; -// for (int n = 0; n < msg1_FDM; n++) { // one structure per frequency domain occasion + ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; + prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; + memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); + ul_config->number_pdus += 1; - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; - prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; - memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); - ul_config->number_pdus += 1; + ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); - ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); + prach_config_pdu->phys_cell_id = *scc->physCellId; + prach_config_pdu->num_prach_ocas = 1; + prach_config_pdu->prach_slot = prach_occasion_info_p->slot; + prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol; + prach_config_pdu->num_ra = prach_occasion_info_p->fdm; - // filling PRACH PDU for FAPI config request -// prach_config_pdu->phys_cell_id = *scc->physCellId; -// prach_config_pdu->num_prach_ocas = N_t_slot; -// prach_config_pdu->prach_start_symbol = start_symbol; -// prach_config_pdu->num_ra = n; + prach_config_pdu->num_cs = ncs; + prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index; - prach_config_pdu->phys_cell_id = *scc->physCellId; - prach_config_pdu->num_prach_ocas = 1; - prach_config_pdu->prach_slot = prach_occasion_info_p->slot; - prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol; - prach_config_pdu->num_ra = prach_occasion_info_p->fdm; + prach_config_pdu->restricted_set = prach_config->restricted_set_config; + prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1; - prach_config_pdu->num_cs = ncs; -// prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[n].prach_root_sequence_index; - prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index; + LOG_D(MAC,"Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n", frameP, prach_config_pdu->prach_slot, prach_config_pdu->prach_start_symbol, prach_config_pdu->num_ra); - prach_config_pdu->restricted_set = prach_config->restricted_set_config; -// prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1; - prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1; + // Search which SSB is mapped in the RO (among all the SSBs mapped to this RO) + for (prach_config_pdu->ssb_nb_in_ro=0; prach_config_pdu->ssb_nb_in_ronb_mapped_ssb; prach_config_pdu->ssb_nb_in_ro++) { + if (prach_occasion_info_p->mapped_ssb_idx[prach_config_pdu->ssb_nb_in_ro] == selected_gnb_ssb_idx) + break; + } + AssertFatal(prach_config_pdu->ssb_nb_in_ronb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx); - // Search which SSB is mapped in the RO (among all the SSBs mapped to this RO) - for (prach_config_pdu->ssb_nb_in_ro=0; prach_config_pdu->ssb_nb_in_ronb_mapped_ssb; prach_config_pdu->ssb_nb_in_ro++) { - if (prach_occasion_info_p->mapped_ssb_idx[prach_config_pdu->ssb_nb_in_ro] == selected_gnb_ssb_idx) + if (format1 != 0xff) { + switch(format0) { // dual PRACH format + case 0xa1: + prach_config_pdu->prach_format = 9; break; + case 0xa2: + prach_config_pdu->prach_format = 10; + break; + case 0xa3: + prach_config_pdu->prach_format = 11; + break; + default: + AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); } - AssertFatal(prach_config_pdu->ssb_nb_in_ronb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx); - - if (format1 != 0xff) { - switch(format0) { // dual PRACH format - case 0xa1: - prach_config_pdu->prach_format = 9; - break; - case 0xa2: - prach_config_pdu->prach_format = 10; - break; - case 0xa3: - prach_config_pdu->prach_format = 11; - break; + } else { + switch(format0) { // single PRACH format + case 0xa1: + prach_config_pdu->prach_format = 0; + break; + case 0xa2: + prach_config_pdu->prach_format = 1; + break; + case 0xa3: + prach_config_pdu->prach_format = 2; + break; + case 0xb1: + prach_config_pdu->prach_format = 3; + break; + case 0xb2: + prach_config_pdu->prach_format = 4; + break; + case 0xb3: + prach_config_pdu->prach_format = 5; + break; + case 0xb4: + prach_config_pdu->prach_format = 6; + break; + case 0xc0: + prach_config_pdu->prach_format = 7; + break; + case 0xc2: + prach_config_pdu->prach_format = 8; + break; + case 0: + // long formats are handled @ PHY + break; + case 1: + // long formats are handled @ PHY + break; + case 2: + // long formats are handled @ PHY + break; + case 3: + // long formats are handled @ PHY + break; default: - AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); - } - } else { - switch(format0) { // single PRACH format - case 0xa1: - prach_config_pdu->prach_format = 0; - break; - case 0xa2: - prach_config_pdu->prach_format = 1; - break; - case 0xa3: - prach_config_pdu->prach_format = 2; - break; - case 0xb1: - prach_config_pdu->prach_format = 3; - break; - case 0xb2: - prach_config_pdu->prach_format = 4; - break; - case 0xb3: - prach_config_pdu->prach_format = 5; - break; - case 0xb4: - prach_config_pdu->prach_format = 6; - break; - case 0xc0: - prach_config_pdu->prach_format = 7; - break; - case 0xc2: - prach_config_pdu->prach_format = 8; - break; - case 0: - // long formats are handled @ PHY - break; - case 1: - // long formats are handled @ PHY - break; - case 2: - // long formats are handled @ PHY - break; - case 3: - // long formats are handled @ PHY - break; - default: - AssertFatal(1 == 0, "Invalid PRACH format"); - } - } // if format1 -// } for n + AssertFatal(1 == 0, "Invalid PRACH format"); + } + } // if format1 + } else if (mac->ra_state == RA_SUCCEEDED){ mac->generate_nr_prach = 2; } // if-else is_nr_prach_slot From b0b5825c6a3d12cc4f0d3d866499c62bf6cc85bd Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Mon, 21 Sep 2020 16:53:03 -0400 Subject: [PATCH 10/31] -Re-added a missing function for the gNB build --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 712e0e9772..2a57a96074 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -34,6 +34,9 @@ #include "asn1_conversions.h" #include +/* Tools */ +#include "SIMULATION/TOOLS/sim.h" // for taus + // ================================================ // SSB to RO mapping private defines and structures // ================================================ @@ -1638,6 +1641,138 @@ int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, return 0; } +int get_nr_prach_info_from_index(uint8_t index, + int frame, + int slot, + uint32_t pointa, + uint8_t mu, + uint8_t unpaired, + uint16_t *format, + uint8_t *start_symbol, + uint8_t *N_t_slot, + uint8_t *N_dur) { + + int x,y; + int64_t s_map; + uint8_t format2 = 0xff; + + if (pointa > 2016666) { //FR2 + int y2; + uint8_t slot_60khz; + x = table_6_3_3_2_4_prachConfig_Index[index][2]; + y = table_6_3_3_2_4_prachConfig_Index[index][3]; + y2 = table_6_3_3_2_4_prachConfig_Index[index][4]; + // checking n_sfn mod x = y + if ( (frame%x)==y || (frame%x)==y2 ) { + slot_60khz = slot >> (mu-2); // in table slots are numbered wrt 60kHz + s_map = table_6_3_3_2_4_prachConfig_Index[index][5]; + if ( ((s_map>>slot_60khz)&0x01) ) { + if (mu == 3) { + if ( (table_6_3_3_2_4_prachConfig_Index[index][7] == 1) && (slot%2 == 0) ) + return 0; // no prach in even slots @ 120kHz for 1 prach per 60khz slot + } + if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ + *start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6]; + *N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8]; + *N_dur = table_6_3_3_2_4_prachConfig_Index[index][9]; + if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1) + format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1]; + *format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8); + LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, + slot, + index, + pointa, + mu, + unpaired, + *start_symbol, + *N_t_slot, + *N_dur); + } + return 1; + } + else + return 0; // no prach in current slot + } + else + return 0; // no prach in current frame + } + else { + uint8_t subframe; + if (unpaired) { + x = table_6_3_3_2_3_prachConfig_Index[index][2]; + y = table_6_3_3_2_3_prachConfig_Index[index][3]; + if ( (frame%x)==y ) { + subframe = slot >> mu; + s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; + if ( (s_map>>subframe)&0x01 ) { + if (mu == 1) { + if ( (table_6_3_3_2_3_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) + return 0; // no prach in even slots @ 30kHz for 1 prach per subframe + } + if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ + *start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5]; + *N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7]; + *N_dur = table_6_3_3_2_3_prachConfig_Index[index][8]; + if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) + format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; + *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); + LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %ld) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, + slot, + index, table_6_3_3_2_3_prachConfig_Index[index][6], + pointa, + mu, + unpaired, + *start_symbol, + *N_t_slot, + *N_dur); + } + return 1; + } + else + return 0; // no prach in current slot + } + else + return 0; // no prach in current frame + } + else { // FDD + x = table_6_3_3_2_2_prachConfig_Index[index][2]; + y = table_6_3_3_2_2_prachConfig_Index[index][3]; + if ( (frame%x)==y ) { + subframe = slot >> mu; + s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; + if ( (s_map>>subframe)&0x01 ) { + if (mu == 1) { + if ( (table_6_3_3_2_2_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) + return 0; // no prach in even slots @ 30kHz for 1 prach per subframe + } + if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ + *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; + *N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7]; + *N_dur = table_6_3_3_2_2_prachConfig_Index[index][8]; + if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1) + format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1]; + *format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8); + LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, + slot, + index, + pointa, + mu, + unpaired, + *start_symbol, + *N_t_slot, + *N_dur); + } + return 1; + } + else + return 0; // no prach in current slot + } + else + return 0; // no prach in current frame + } + } +} + //Table 6.3.3.1-3: Mapping from logical index i to sequence number u for preamble formats with L_RA = 839 uint16_t table_63313[838] = { 129, 710, 140, 699, 120, 719, 210, 629, 168, 671, 84 , 755, 105, 734, 93 , 746, 70 , 769, 60 , 779, From 7428723c87b976af13df6674aeefc297c592ac69 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 9 Oct 2020 17:23:48 +0200 Subject: [PATCH 11/31] Synchronize gnb.band78.tm1.106PRB.usrpn300.conf files in ci-scripts and targets directory --- .../gnb.band78.tm1.106PRB.usrpn300.conf | 18 +++++++++--------- .../CONF/gnb.band78.tm1.106PRB.usrpn300.conf | 15 +++++++-------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf index aa03e91fd0..884ab771e6 100644 --- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf @@ -45,8 +45,8 @@ gNBs = dl_carrierBandwidth = 106; #initialDownlinkBWP #genericParameters - # this is RBstart=0,L=50 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 13475; + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; @@ -59,7 +59,7 @@ gNBs = #initialULBWPmappingType #0=typeA,1=typeB initialDLBWPmappingType_0 = 0; - #this is SS=2,L=3 + #this is SS=1,L=13 initialDLBWPstartSymbolAndLength_0 = 40; initialDLBWPk0_1 = 0; @@ -74,7 +74,7 @@ gNBs = initialDLBWPk0_3 = 0; initialDLBWPmappingType_3 = 0; - #this is SS=1,L=4 + #this is SS=1,L=5 initialDLBWPstartSymbolAndLength_3 = 57; #uplinkConfigCommon @@ -89,7 +89,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 13475; + initialULBWPlocationAndBandwidth = 6366; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -135,8 +135,8 @@ gNBs = initialULBWPmappingType_0 = 1 # this is SS=0 L=11 initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 6; + + initialULBWPk2_1 = 6; initialULBWPmappingType_1 = 1; # this is SS=0 L=12 initialULBWPstartSymbolAndLength_1 = 69; @@ -145,7 +145,7 @@ gNBs = initialULBWPmappingType_2 = 1; # this is SS=10 L=4 initialULBWPstartSymbolAndLength_2 = 52; - + msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -249,7 +249,7 @@ RUs = ( eNB_instances = [0]; #beamforming 1x4 matrix: bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; - sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf index aeb9e2be88..884ab771e6 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf @@ -45,7 +45,7 @@ gNBs = dl_carrierBandwidth = 106; #initialDownlinkBWP #genericParameters - # this is RBstart=0,L=50 (275*(L-1))+RBstart + # this is RBstart=41,L=24 (275*(L-1))+RBstart initialDLBWPlocationAndBandwidth = 6366; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 @@ -74,7 +74,7 @@ gNBs = initialDLBWPk0_3 = 0; initialDLBWPmappingType_3 = 0; - #this is SS=1,L=4 + #this is SS=1,L=5 initialDLBWPstartSymbolAndLength_3 = 57; #uplinkConfigCommon @@ -126,27 +126,26 @@ gNBs = # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex # msg1_SubcarrierSpacing = 1, + # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; + initialULBWPk2_0 = 6; initialULBWPmappingType_0 = 1 # this is SS=0 L=11 initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; + + initialULBWPk2_1 = 6; initialULBWPmappingType_1 = 1; # this is SS=0 L=12 initialULBWPstartSymbolAndLength_1 = 69; - initialULBWPk2_2 = 7; + initialULBWPk2_2 = 7; initialULBWPmappingType_2 = 1; # this is SS=10 L=4 initialULBWPstartSymbolAndLength_2 = 52; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; From d9a3009f10ded11fee995b52802a8c4295e4a61d Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 9 Oct 2020 17:45:48 +0200 Subject: [PATCH 12/31] fix some cppcheck warnings --- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 12 ++++++------ openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 42f88d16f4..a528eb734c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -478,7 +478,12 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[UE_id][0]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; - + + if (!harq_process) { + LOG_E(PHY,"ulsch_decoding.c: NULL harq_process pointer\n"); + return 1; + } + t_nrLDPC_dec_params decParams; t_nrLDPC_dec_params* p_decParams = &decParams; @@ -488,11 +493,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, phy_vars_gNB->nbDecode = 0; harq_process->processedSegments = 0; - if (!harq_process) { - LOG_E(PHY,"ulsch_decoding.c: NULL harq_process pointer\n"); - return 1; - } - double Coderate = 0.0; // ------------------------------------------------------------------ diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index d24c88fd1f..65afb46a01 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -894,6 +894,9 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, int *dlsch_errors, runmode_t mode) { + if (dlsch0==NULL) + AssertFatal(0,"dlsch0 should be defined at this level \n"); + int harq_pid = dlsch0->current_harq_pid; int frame_rx = proc->frame_rx; int nr_tti_rx = proc->nr_tti_rx; @@ -921,9 +924,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, uint16_t bw_scaling, start_symbol; float tc_factor; - if (dlsch0==NULL) - AssertFatal(0,"dlsch0 should be defined at this level \n"); - is_cw0_active = dlsch0->harq_processes[harq_pid]->status; nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol; @@ -1352,9 +1352,9 @@ void *UE_thread_slot1_dl_processing(void *arg) { CPU_ZERO(&cpuset); if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.slot1_proc_one != -1 ) CPU_SET(threads.slot1_proc_one, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 ) + if ( RX_NB_TH > 1 && (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 ) CPU_SET(threads.slot1_proc_two, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 ) + if ( RX_NB_TH > 2 && (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 ) CPU_SET(threads.slot1_proc_three, &cpuset); init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, From 65962b4881c8a5c628dbe72d61c6878b70f44868 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 9 Oct 2020 18:18:23 +0200 Subject: [PATCH 13/31] fix compilation of telnetsrv_proccmd.c with deadline scheduler disabled --- common/utils/telnetsrv/telnetsrv_proccmd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/utils/telnetsrv/telnetsrv_proccmd.c b/common/utils/telnetsrv/telnetsrv_proccmd.c index 9dd512091d..6a0da678e2 100644 --- a/common/utils/telnetsrv/telnetsrv_proccmd.c +++ b/common/utils/telnetsrv/telnetsrv_proccmd.c @@ -121,9 +121,11 @@ char toksep[2]; case SCHED_RR: lptr+=sprintf(lptr,"%s ","rt: rr"); break; +#ifdef SCHED_DEADLINE case SCHED_DEADLINE: lptr+=sprintf(lptr,"%s ","rt: deadline"); break; +#endif default: lptr+=sprintf(lptr,"%s ","????"); break; From 4589d86018be040595c8e28d677e85893412b0b2 Mon Sep 17 00:00:00 2001 From: cig Date: Tue, 20 Oct 2020 18:07:17 +0200 Subject: [PATCH 14/31] Set init_msg1 at the start of the nr_ue_prach_procedures --- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 65afb46a01..3fe81fe4c2 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -2128,6 +2128,11 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN); + if (!prach_resources->init_msg1 && (frame_tx > ue->prach_resources[gNB_id]->sync_frame + 150)){ + ue->prach_cnt = 0; + prach_resources->init_msg1 = 1; + } + if (ue->mac_enabled == 0){ // prach_resources->ra_PreambleIndex = preamble_tx; prach_resources->ra_TDD_map_index = 0; @@ -2148,11 +2153,6 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t } } - if (!prach_resources->init_msg1 && (frame_tx > ue->prach_resources[gNB_id]->sync_frame + 150)){ - ue->prach_cnt = 0; - prach_resources->init_msg1 = 1; - } - if (ue->prach_resources[gNB_id] != NULL && nr_prach == 1 && prach_resources->init_msg1) { pathloss = get_nr_PL(mod_id, ue->CC_id, gNB_id); From fb7a098a47944a5015c4acfd992ebbc2e21ec9ae Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 21 Oct 2020 14:56:44 +0200 Subject: [PATCH 15/31] fix execution of nr_ue_pdsch_procedures() only once per slot for SI_PDSCH, P_PDSCH and RA_PDSCH --- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 139 +++++++------------- 1 file changed, 44 insertions(+), 95 deletions(-) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 3fe81fe4c2..2ab3bac6e0 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1813,24 +1813,48 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN); nr_ue_pdsch_procedures(ue, - proc, - gNB_id, - SI_PDSCH, - ue->dlsch_SI[gNB_id], - NULL); + proc, + gNB_id, + SI_PDSCH, + ue->dlsch_SI[gNB_id], + NULL); + nr_ue_dlsch_procedures(ue, + proc, + gNB_id, + SI_PDSCH, + ue->dlsch_SI[gNB_id], + NULL, + &ue->dlsch_SI_errors[gNB_id], + mode); + + // deactivate dlsch once dlsch proc is done + ue->dlsch_SI[gNB_id]->active = 0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT); } - // do procedures for SI-RNTI + // do procedures for P-RNTI if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN); nr_ue_pdsch_procedures(ue, - proc, - gNB_id, - P_PDSCH, - ue->dlsch_p[gNB_id], - NULL); + proc, + gNB_id, + P_PDSCH, + ue->dlsch_p[gNB_id], + NULL); + + nr_ue_dlsch_procedures(ue, + proc, + gNB_id, + P_PDSCH, + ue->dlsch_p[gNB_id], + NULL, + &ue->dlsch_p_errors[gNB_id], + mode); + + // deactivate dlsch once dlsch proc is done + ue->dlsch_p[gNB_id]->active = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT); } @@ -1839,15 +1863,11 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN); nr_ue_pdsch_procedures(ue, - proc, - gNB_id, - RA_PDSCH, - ue->dlsch_ra[gNB_id], - NULL); - - // #if UE_TIMING_TRACE - // start_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); - // #endif + proc, + gNB_id, + RA_PDSCH, + ue->dlsch_ra[gNB_id], + NULL); nr_ue_dlsch_procedures(ue, proc, @@ -1858,18 +1878,10 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, &ue->dlsch_ra_errors[gNB_id], mode); - // #if UE_TIMING_TRACE - // stop_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); - #if DISABLE_LOG_X - printf("[SFN %d] Slot1: Pdsch Proc %5.2f\n", nr_tti_rx, ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); - printf("[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n", nr_tti_rx, ue->dlsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0)); - #else - LOG_D(PHY, "[SFN %d] Slot1: Pdsch Proc %5.2f\n", nr_tti_rx, ue->pdsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0)); - LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n", nr_tti_rx, ue->dlsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0)); - #endif - // #endif + // deactivate dlsch once dlsch proc is done + ue->dlsch_ra[gNB_id]->active = 0; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); } // do procedures for C-RNTI @@ -1936,71 +1948,8 @@ start_meas(&ue->generic_stat); } #endif - // do procedures for SI-RNTI - if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) { - nr_ue_pdsch_procedures(ue, - proc, - gNB_id, - SI_PDSCH, - ue->dlsch_SI[gNB_id], - NULL); - - /*ue_dlsch_procedures(ue, - proc, - gNB_id, - SI_PDSCH, - ue->dlsch_SI[gNB_id], - NULL, - &ue->dlsch_SI_errors[gNB_id], - mode, - abstraction_flag); - ue->dlsch_SI[gNB_id]->active = 0;*/ - } - - // do procedures for P-RNTI - if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) { - nr_ue_pdsch_procedures(ue, - proc, - gNB_id, - P_PDSCH, - ue->dlsch_p[gNB_id], - NULL); - - - /*ue_dlsch_procedures(ue, - proc, - gNB_id, - P_PDSCH, - ue->dlsch_p[gNB_id], - NULL, - &ue->dlsch_p_errors[gNB_id], - mode, - abstraction_flag);*/ - ue->dlsch_p[gNB_id]->active = 0; - } - // do procedures for RA-RNTI - if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1)) { - nr_ue_pdsch_procedures(ue, - proc, - gNB_id, - RA_PDSCH, - ue->dlsch_ra[gNB_id], - NULL); - - /*ue_dlsch_procedures(ue, - proc, - gNB_id, - RA_PDSCH, - ue->dlsch_ra[gNB_id], - NULL, - &ue->dlsch_ra_errors[gNB_id], - mode, - abstraction_flag);*/ - ue->dlsch_ra[gNB_id]->active = 0; - } - // duplicate harq structure - /* +/* uint8_t current_harq_pid = ue->dlsch[ue->current_thread_id[nr_tti_rx]][gNB_id][0]->current_harq_pid; NR_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[ue->current_thread_id[nr_tti_rx]][gNB_id][0]->harq_processes[current_harq_pid]; NR_DL_UE_HARQ_t *harq_processes_dest = ue->dlsch[next1_thread_id][gNB_id][0]->harq_processes[current_harq_pid]; From 1ef9a7ceb622a59b27cac9372a10167d225142ab Mon Sep 17 00:00:00 2001 From: cig Date: Wed, 21 Oct 2020 16:02:47 +0200 Subject: [PATCH 16/31] Enter PRACH procedures only after UE sync --- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 2ab3bac6e0..c5baebf13a 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -216,7 +216,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, /* RACH */ if (get_softmodem_params()->do_ra==1) { - if ((ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) { + if ((ue->UE_mode[gNB_id] > NOT_SYNCHED && ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) { nr_ue_prach_procedures(ue, proc, gNB_id, mode); } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 117e5d2970..4d250ec95d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -363,7 +363,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n"); - if (UE_mode < PUSCH && prach_resources->init_msg1) { + if (prach_resources->init_msg1) { LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active); From ae8c0ef448d63cc1610e4cecda5fbe4579e448ab Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Wed, 21 Oct 2020 18:07:35 +0200 Subject: [PATCH 17/31] nr: add MAC PDU traces for wireshark The T tracer macpdu2wireshark has been modified to handle the new traces. The usage is the same as for LTE. In NR the RACH is logged as an LTE RACH. Maybe we'll change that in the future. Looking at the source code of wireshark, I could not find any way to report NR RACH. Maybe they forgot it. Or I did not search correctly... --- common/utils/T/T_messages.txt | 16 + common/utils/T/tracer/macpdu2wireshark.c | 319 +++++++++++++++--- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 10 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 4 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 3 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 6 + 6 files changed, 317 insertions(+), 41 deletions(-) diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index d036b40560..a4c92f9e3c 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -85,6 +85,10 @@ ID = ENB_PHY_MIB DESC = MIB data GROUP = ALL:PHY:ENB:WIRESHARK FORMAT = int,eNB_ID : int,frame : int,subframe : buffer,data +ID = GNB_PHY_MIB + DESC = NR MIB data + GROUP = ALL:PHY:GNB:WIRESHARK + FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data #MAC logs ID = ENB_MAC_UE_DL_SDU @@ -131,6 +135,18 @@ ID = ENB_MAC_UE_DL_RAR_PDU_WITH_DATA DESC = MAC downlink PDU for an UE GROUP = ALL:MAC:ENB:WIRESHARK FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : buffer,data +ID = GNB_MAC_DL_PDU_WITH_DATA + DESC = NR MAC downlink PDU for an UE + GROUP = ALL:MAC:GNB:WIRESHARK + FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data +ID = GNB_MAC_UL_PDU_WITH_DATA + DESC = NR MAC uplink PDU for an UE + GROUP = ALL:MAC:GNB:WIRESHARK + FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data +ID = GNB_MAC_DL_RAR_PDU_WITH_DATA + DESC = NR MAC downlink PDU for RAR + GROUP = ALL:MAC:GNB:WIRESHARK + FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data #RLC logs ID = ENB_RLC_DL diff --git a/common/utils/T/tracer/macpdu2wireshark.c b/common/utils/T/tracer/macpdu2wireshark.c index c391a99786..d262f09e4a 100644 --- a/common/utils/T/tracer/macpdu2wireshark.c +++ b/common/utils/T/tracer/macpdu2wireshark.c @@ -23,6 +23,8 @@ typedef struct { int socket; struct sockaddr_in to; OBUF buf; + + /* LTE traces */ /* ul */ int ul_rnti; int ul_frame; @@ -46,6 +48,28 @@ typedef struct { int rar_frame; int rar_subframe; int rar_data; + + /* NR traces */ + /* NR ul */ + int nr_ul_rnti; + int nr_ul_frame; + int nr_ul_slot; + int nr_ul_data; + /* NR dl */ + int nr_dl_rnti; + int nr_dl_frame; + int nr_dl_slot; + int nr_dl_data; + /* NR mib */ + int nr_mib_frame; + int nr_mib_slot; + int nr_mib_data; + /* NR RAR */ + int nr_rar_rnti; + int nr_rar_frame; + int nr_rar_slot; + int nr_rar_data; + /* config */ int no_mib; int no_sib; @@ -58,8 +82,13 @@ typedef struct { int cur_sib; } ev_data; -void trace(ev_data *d, int direction, int rnti_type, int rnti, - int frame, int subframe, void *buf, int bufsize, int preamble) { +/****************************************************************************/ +/* LTE */ +/****************************************************************************/ + +void trace_lte(ev_data *d, int direction, int rnti_type, int rnti, + int frame, int subframe, void *buf, int bufsize, int preamble) +{ ssize_t ret; int fsf; int i; @@ -100,15 +129,17 @@ void trace(ev_data *d, int direction, int rnti_type, int rnti, if (ret != d->buf.osize) abort(); } -void ul(void *_d, event e) { +void ul(void *_d, event e) +{ ev_data *d = _d; - trace(d, DIRECTION_UPLINK, C_RNTI, e.e[d->ul_rnti].i, - e.e[d->ul_frame].i, e.e[d->ul_subframe].i, - e.e[d->ul_data].b, e.e[d->ul_data].bsize, - NO_PREAMBLE); + trace_lte(d, DIRECTION_UPLINK, C_RNTI, e.e[d->ul_rnti].i, + e.e[d->ul_frame].i, e.e[d->ul_subframe].i, + e.e[d->ul_data].b, e.e[d->ul_data].bsize, + NO_PREAMBLE); } -void dl(void *_d, event e) { +void dl(void *_d, event e) +{ ev_data *d = _d; if (e.e[d->dl_rnti].i == 0xffff) { @@ -119,14 +150,15 @@ void dl(void *_d, event e) { d->cur_sib++; } - trace(d, DIRECTION_DOWNLINK, - e.e[d->dl_rnti].i != 0xffff ? C_RNTI : SI_RNTI, e.e[d->dl_rnti].i, - e.e[d->dl_frame].i, e.e[d->dl_subframe].i, - e.e[d->dl_data].b, e.e[d->dl_data].bsize, - NO_PREAMBLE); + trace_lte(d, DIRECTION_DOWNLINK, + e.e[d->dl_rnti].i != 0xffff ? C_RNTI : SI_RNTI, e.e[d->dl_rnti].i, + e.e[d->dl_frame].i, e.e[d->dl_subframe].i, + e.e[d->dl_data].b, e.e[d->dl_data].bsize, + NO_PREAMBLE); } -void mib(void *_d, event e) { +void mib(void *_d, event e) +{ ev_data *d = _d; if (d->no_mib) return; @@ -134,30 +166,141 @@ void mib(void *_d, event e) { if (d->max_mib && d->cur_mib == d->max_mib) return; d->cur_mib++; - trace(d, DIRECTION_DOWNLINK, NO_RNTI, 0, - e.e[d->mib_frame].i, e.e[d->mib_subframe].i, - e.e[d->mib_data].b, e.e[d->mib_data].bsize, - NO_PREAMBLE); + trace_lte(d, DIRECTION_DOWNLINK, NO_RNTI, 0, + e.e[d->mib_frame].i, e.e[d->mib_subframe].i, + e.e[d->mib_data].b, e.e[d->mib_data].bsize, + NO_PREAMBLE); } -void preamble(void *_d, event e) { +void preamble(void *_d, event e) +{ ev_data *d = _d; - trace(d, DIRECTION_UPLINK, NO_RNTI, 0, - e.e[d->preamble_frame].i, e.e[d->preamble_subframe].i, - NULL, 0, - e.e[d->preamble_preamble].i); + trace_lte(d, DIRECTION_UPLINK, NO_RNTI, 0, + e.e[d->preamble_frame].i, e.e[d->preamble_subframe].i, + NULL, 0, + e.e[d->preamble_preamble].i); } -void rar(void *_d, event e) { +void rar(void *_d, event e) +{ ev_data *d = _d; - trace(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->rar_rnti].i, - e.e[d->rar_frame].i, e.e[d->rar_subframe].i, - e.e[d->rar_data].b, e.e[d->rar_data].bsize, - NO_PREAMBLE); + trace_lte(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->rar_rnti].i, + e.e[d->rar_frame].i, e.e[d->rar_subframe].i, + e.e[d->rar_data].b, e.e[d->rar_data].bsize, + NO_PREAMBLE); } +/****************************************************************************/ +/* NR */ +/****************************************************************************/ + +#define MAC_NR_START_STRING "mac-nr" + +#define MAC_NR_PAYLOAD_TAG 0x01 +#define MAC_NR_RNTI_TAG 0x02 +#define MAC_NR_FRAME_SLOT_TAG 0x07 + +#define NR_FDD_RADIO 1 +#define NR_TDD_RADIO 2 + +#define NR_DIRECTION_UPLINK 0 +#define NR_DIRECTION_DOWNLINK 1 + +#define NR_NO_RNTI 0 +#define NR_RA_RNTI 2 +#define NR_C_RNTI 3 + +void trace_nr(ev_data *d, int direction, int rnti_type, int rnti, + int frame, int slot, void *buf, int bufsize, int preamble) +{ + ssize_t ret; + int i; + d->buf.osize = 0; + PUTS(&d->buf, MAC_NR_START_STRING); + PUTC(&d->buf, NR_TDD_RADIO); + PUTC(&d->buf, direction); + PUTC(&d->buf, rnti_type); + + if (rnti_type == NR_C_RNTI || rnti_type == NR_RA_RNTI) { + PUTC(&d->buf, MAC_NR_RNTI_TAG); + PUTC(&d->buf, (rnti>>8) & 255); + PUTC(&d->buf, rnti & 255); + } + +#if 0 + /* for old versions of wireshark; not sure if correct */ + int fsf = (frame << 4) + slot; + PUTC(&d->buf, 4 /* MAC_NR_FRAME_SUBFRAME_TAG */); + PUTC(&d->buf, (fsf>>8) & 255); + PUTC(&d->buf, fsf & 255); +#else + PUTC(&d->buf, MAC_NR_FRAME_SLOT_TAG); + PUTC(&d->buf, (frame>>8) & 255); + PUTC(&d->buf, frame & 255); + PUTC(&d->buf, (slot>>8) & 255); + PUTC(&d->buf, slot & 255); +#endif + + PUTC(&d->buf, MAC_NR_PAYLOAD_TAG); + + for (i = 0; i < bufsize; i++) + PUTC(&d->buf, ((char *)buf)[i]); + + ret = sendto(d->socket, d->buf.obuf, d->buf.osize, 0, + (struct sockaddr *)&d->to, sizeof(struct sockaddr_in)); + + if (ret != d->buf.osize) abort(); +} + +void nr_ul(void *_d, event e) +{ + ev_data *d = _d; + + trace_nr(d, NR_DIRECTION_UPLINK, NR_C_RNTI, e.e[d->nr_ul_rnti].i, + e.e[d->nr_ul_frame].i, e.e[d->nr_ul_slot].i, + e.e[d->nr_ul_data].b, e.e[d->nr_ul_data].bsize, NO_PREAMBLE); +} + +void nr_dl(void *_d, event e) +{ + ev_data *d = _d; + + trace_nr(d, NR_DIRECTION_DOWNLINK, NR_C_RNTI, e.e[d->nr_dl_rnti].i, + e.e[d->nr_dl_frame].i, e.e[d->nr_dl_slot].i, + e.e[d->nr_dl_data].b, e.e[d->nr_dl_data].bsize, NO_PREAMBLE); +} + +void nr_mib(void *_d, event e) +{ + ev_data *d = _d; + + if (d->no_mib) return; + + if (d->max_mib && d->cur_mib == d->max_mib) return; + + d->cur_mib++; + + trace_nr(d, NR_DIRECTION_DOWNLINK, NR_NO_RNTI, 0, + e.e[d->nr_mib_frame].i, e.e[d->nr_mib_slot].i, + e.e[d->nr_mib_data].b, e.e[d->nr_mib_data].bsize, NO_PREAMBLE); +} + +void nr_rar(void *_d, event e) +{ + ev_data *d = _d; + + trace_nr(d, NR_DIRECTION_DOWNLINK, NR_RA_RNTI, e.e[d->nr_rar_rnti].i, + e.e[d->nr_rar_frame].i, e.e[d->nr_rar_slot].i, + e.e[d->nr_rar_data].b, e.e[d->nr_rar_data].bsize, NO_PREAMBLE); +} + +/****************************************************************************/ +/****************************************************************************/ + void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, - int preamble_id, int rar_id) { + int preamble_id, int rar_id, + int nr_ul_id, int nr_dl_id, int nr_mib_id, int nr_rar_id) +{ database_event_format f; int i; d->ul_rnti = -1; @@ -174,10 +317,27 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, d->preamble_frame = -1; d->preamble_subframe = -1; d->preamble_preamble = -1; - d->rar_rnti = -1; - d->rar_frame = -1; - d->rar_subframe = -1; - d->rar_data = -1; + d->rar_rnti = -1; + d->rar_frame = -1; + d->rar_subframe = -1; + d->rar_data = -1; + + d->nr_ul_rnti = -1; + d->nr_ul_frame = -1; + d->nr_ul_slot = -1; + d->nr_ul_data = -1; + d->nr_dl_rnti = -1; + d->nr_dl_frame = -1; + d->nr_dl_slot = -1; + d->nr_dl_data = -1; + d->nr_mib_frame = -1; + d->nr_mib_slot = -1; + d->nr_mib_data = -1; + d->nr_rar_rnti = -1; + d->nr_rar_frame = -1; + d->nr_rar_slot = -1; + d->nr_rar_data = -1; + #define G(var_name, var_type, var) \ if (!strcmp(f.name[i], var_name)) { \ if (strcmp(f.type[i], var_type)) goto error; \ @@ -247,6 +407,60 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, if (d->rar_rnti == -1 || d->rar_frame == -1 || d->rar_subframe == -1 || d->rar_data == -1) goto error; + /* NR ul: rnti, frame, slot, data */ + f = get_format(database, nr_ul_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->nr_ul_rnti); + G("frame", "int", d->nr_ul_frame); + G("slot", "int", d->nr_ul_slot); + G("data", "buffer", d->nr_ul_data); + } + + if (d->nr_ul_rnti == -1 || d->nr_ul_frame == -1 || d->nr_ul_slot == -1 || + d->nr_ul_data == -1) + goto error; + + /* NR dl: rnti, frame, slot, data */ + f = get_format(database, nr_dl_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->nr_dl_rnti); + G("frame", "int", d->nr_dl_frame); + G("slot", "int", d->nr_dl_slot); + G("data", "buffer", d->nr_dl_data); + } + + if (d->nr_dl_rnti == -1 || d->nr_dl_frame == -1 || d->nr_dl_slot == -1 || + d->nr_dl_data == -1) + goto error; + + /* NR MIB: frame, slot, data */ + f = get_format(database, nr_mib_id); + + for (i = 0; i < f.count; i++) { + G("frame", "int", d->nr_mib_frame); + G("slot", "int", d->nr_mib_slot); + G("data", "buffer", d->nr_mib_data); + } + + if (d->nr_mib_frame == -1 || d->nr_mib_slot== -1 || d->nr_mib_data == -1) + goto error; + + /* NR RAR: rnti, frame, slot, data */ + f = get_format(database, nr_rar_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->nr_rar_rnti); + G("frame", "int", d->nr_rar_frame); + G("slot", "int", d->nr_rar_slot); + G("data", "buffer", d->nr_rar_data); + } + + if (d->nr_rar_rnti == -1 || d->nr_rar_frame == -1 || d->nr_rar_slot == -1 || + d->nr_rar_data == -1) + goto error; + #undef G return; error: @@ -254,7 +468,8 @@ error: abort(); } -void *receiver(void *_d) { +void *receiver(void *_d) +{ ev_data *d = _d; int s; char buf[100000]; @@ -279,7 +494,8 @@ void *receiver(void *_d) { return 0; } -void usage(void) { +void usage(void) +{ printf( "options:\n" " -d this option is mandatory\n" @@ -304,14 +520,16 @@ void usage(void) { exit(1); } -int main(int n, char **v) { +int main(int n, char **v) +{ char *database_filename = NULL; char *input_filename = NULL; void *database; event_handler *h; int in; int i; - int ul_id, dl_id, mib_id = -1, preamble_id, rar_id; + int ul_id, dl_id, mib_id, preamble_id, rar_id; + int nr_ul_id, nr_dl_id, nr_mib_id, nr_rar_id; ev_data d; char *ip = DEFAULT_IP; int port = DEFAULT_PORT; @@ -382,6 +600,11 @@ int main(int n, char **v) { on_off(database, "ENB_PHY_INITIATE_RA_PROCEDURE", is_on, 1); on_off(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA", is_on, 1); + on_off(database, "GNB_MAC_UL_PDU_WITH_DATA", is_on, 1); + on_off(database, "GNB_MAC_DL_PDU_WITH_DATA", is_on, 1); + on_off(database, "GNB_PHY_MIB", is_on, 1); + on_off(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA", is_on, 1); + /* activate selected traces */ if (socket_send(in, &mt, 1) == -1 || socket_send(in, &number_of_events, sizeof(int)) == -1 || @@ -398,12 +621,26 @@ int main(int n, char **v) { mib_id = event_id_from_name(database, "ENB_PHY_MIB"); preamble_id = event_id_from_name(database, "ENB_PHY_INITIATE_RA_PROCEDURE"); rar_id = event_id_from_name(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA"); - setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id); + + nr_ul_id = event_id_from_name(database, "GNB_MAC_UL_PDU_WITH_DATA"); + nr_dl_id = event_id_from_name(database, "GNB_MAC_DL_PDU_WITH_DATA"); + nr_mib_id = event_id_from_name(database, "GNB_PHY_MIB"); + nr_rar_id = event_id_from_name(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA"); + + setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id, + nr_ul_id, nr_dl_id, nr_mib_id, nr_rar_id); + register_handler_function(h, ul_id, ul, &d); register_handler_function(h, dl_id, dl, &d); register_handler_function(h, mib_id, mib, &d); register_handler_function(h, preamble_id, preamble, &d); register_handler_function(h, rar_id, rar, &d); + + register_handler_function(h, nr_ul_id, nr_ul, &d); + register_handler_function(h, nr_dl_id, nr_dl, &d); + register_handler_function(h, nr_mib_id, nr_mib, &d); + register_handler_function(h, nr_rar_id, nr_rar, &d); + d.socket = socket(AF_INET, SOCK_DGRAM, 0); if (d.socket == -1) { @@ -424,8 +661,10 @@ int main(int n, char **v) { if (e.type == -1) break; - if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id || - e.type == preamble_id || e.type == rar_id)) continue; + if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id || + e.type == preamble_id || e.type == rar_id || + e.type == nr_ul_id || e.type == nr_dl_id || + e.type == nr_mib_id || e.type == nr_rar_id)) continue; handle_event(h, e); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 2d246101a6..8b365dc078 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -113,7 +113,15 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) { nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); else nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); - + + if (T_ACTIVE(T_GNB_PHY_MIB)) { + unsigned char bch[3]; + bch[0] = gNB->ssb_pdu.ssb_pdu_rel15.bchPayload & 0xff; + bch[1] = (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload >> 8) & 0xff; + bch[2] = (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload >> 16) & 0xff; + T(T_GNB_PHY_MIB, T_INT(0) /* module ID */, T_INT(frame), T_INT(slot), T_BUFFER(bch, 3)); + } + nr_generate_pbch(&gNB->pbch, &gNB->ssb_pdu, gNB->nr_pbch_interleaver, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index af40c9ccd8..03e0ffa6fd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -921,6 +921,10 @@ void nr_generate_Msg2(module_id_t module_idP, nr_mac->TX_req[CC_id].Slot = slotP; memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length); + T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), + T_INT(RA_rnti), T_INT(frameP), T_INT(slotP), T_INT(0) /* harq pid, meaningful? */, + T_BUFFER(&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length)); + /* mark the corresponding RBs as used */ uint8_t *vrb_map = cc[CC_id].vrb_map; for (int rb = 0; rb < pdsch_pdu_rel15->rbSize; rb++) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 4c6558d4f6..02d62d76d7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -804,6 +804,9 @@ void nr_schedule_ue_spec(module_id_t module_id, retInfo->mcs = sched_ctrl->mcs; retInfo->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData; + T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), + T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(buf, TBS)); + #if defined(ENABLE_MAC_PAYLOAD_DEBUG) if (frame%100 == 0) { LOG_I(MAC, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 0479c4da30..a76ad31f81 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -324,6 +324,12 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[0]; + if (sduP != NULL) { + T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), + T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */, + T_BUFFER(sduP, sdu_lenP)); + } + // random access pusch with TC-RNTI if (ra->state == WAIT_Msg3) { if (sduP != NULL) { // if the CRC passed From 3874e934d8b77a8a1b8db3a771fb58cea1eb8733 Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Wed, 21 Oct 2020 15:45:08 -0400 Subject: [PATCH 18/31] Added support of PRACH on start symbol != 0 on the UE --- openair1/PHY/NR_UE_TRANSPORT/nr_prach.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 29841c3186..885a24494e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -72,7 +72,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ int16_t Ncp = 0, amp, *prach, *prach2, *prachF, *Xu; int32_t Xu_re, Xu_im; - int prach_start, prach_sequence_length, i, prach_len, dftlen, mu, kbar, K, n_ra_prb, k; + int prach_start, prach_sequence_length, i, prach_len, dftlen, mu, kbar, K, n_ra_prb, k, prachStartSymbol, sample_offset_slot; //int restricted_Type; prach = prach_tmp; @@ -95,7 +95,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ kbar = 1; K = 24; k = 12*n_ra_prb - 6*fp->N_RB_UL; - //prachStartSymbol = prach_config_pdu->prach_start_symbol + prachStartSymbol = prach_pdu->prach_start_symbol; //restricted_Type = 0; compute_nr_prach_seq(nrUE_config->prach_config.prach_sequence_length, @@ -103,7 +103,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index, ue->X_u); - prach_start = fp->get_samples_slot_timestamp(slot, fp, 0); + sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1)); + prach_start = fp->get_samples_slot_timestamp(slot, fp, 0) + sample_offset_slot; // First compute physical root sequence /************************************************************************ From 7c5677fd1f91eeb06402aef7f28a3a331e5f4d8e Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 22 Oct 2020 10:25:48 +0200 Subject: [PATCH 19/31] fix message 1 frame number calculation on NR UE UE initiates the RA procedure with sending message 1 via PRACH 150 frames after synchronizing with the gNB. As the frame numbers wrap at 1024, we have to calculate the frame number for message 1 using modulo calculation. --- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index c5baebf13a..1d688f5cdc 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -2077,7 +2077,7 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN); - if (!prach_resources->init_msg1 && (frame_tx > ue->prach_resources[gNB_id]->sync_frame + 150)){ + if (!prach_resources->init_msg1 && (frame_tx == (ue->prach_resources[gNB_id]->sync_frame + 150) % MAX_FRAME_NUMBER)){ ue->prach_cnt = 0; prach_resources->init_msg1 = 1; } From 8d65628052feaad8a60f84dc69ac4efb274164f7 Mon Sep 17 00:00:00 2001 From: hardy Date: Thu, 22 Oct 2020 17:58:00 +0200 Subject: [PATCH 20/31] re-enabling RA test --- ci-scripts/reportTestLocally.sh | 90 +++++++++++++++------------------ ci-scripts/runTestOnVM.sh | 66 +++--------------------- 2 files changed, 49 insertions(+), 107 deletions(-) diff --git a/ci-scripts/reportTestLocally.sh b/ci-scripts/reportTestLocally.sh index 03cda20542..64c5d74975 100755 --- a/ci-scripts/reportTestLocally.sh +++ b/ci-scripts/reportTestLocally.sh @@ -768,55 +768,47 @@ function report_test { #RA test (--do-ra option) -# Currently disabled -# #build log files names -# RA_ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb_ra_test.log -# RA_UE_LOG=$ARCHIVES_LOC/ra_check_${TMODE}_${BW}prb_${CN_CONFIG}_ue_ra_test.log -# if [ -f $RA_ENB_LOG ] && [ -f $RA_UE_LOG ] -# then -# #get rid of full path -# NAME_ENB=`echo $RA_ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"` -# NAME_UE=`echo $RA_UE_LOG | sed -e "s#$ARCHIVES_LOC/##"` -# echo " " >> ./test_simulator_results.html -# echo " $NAME_ENB --- $NAME_UE" >> ./test_simulator_results.html -# echo " Check if RA proc succeeded" >> ./test_simulator_results.html -# -# #gNB RA check -# GNB_RECEIVED=`egrep -c "received correctly" $RA_ENB_LOG` -# GNB_CONNECTED=`egrep -c "now 5G connected" $RA_ENB_LOG` -# #UE RA check -# UE_RA_PROC_OK=`egrep -c "RA procedure succeeded" $RA_UE_LOG` -# -# -# if [ $GNB_RECEIVED -gt 0 ] && [ $GNB_CONNECTED -gt 0 ] && [ $UE_RA_PROC_OK -gt 0 ] -# then -# echo " OK" >> ./test_simulator_results.html -# else -# echo " KO" >> ./test_simulator_results.html -# fi -# -# echo "
" >> ./test_simulator_results.html
-#                    if [ $GNB_RECEIVED -gt 0 ]
-#                    then
-#                        echo "- gNB --> RA received" >> ./test_simulator_results.html
-#                    else
-#                        echo "- gNB RA NOT RECEIVED" >> ./test_simulator_results.html
-#                    fi
-#                    if [ $GNB_CONNECTED -gt 0 ]
-#                    then
-#                        echo "- gNB --> 5G connected" >> ./test_simulator_results.html
-#                    else
-#                        echo "- gNB NOT 5G CONNECTED" >> ./test_simulator_results.html
-#                    fi
-#                    if [ $UE_RA_PROC_OK -gt 0 ]
-#                    then
-#                        echo "- NR UE  --> RA procedure succeded" >> ./test_simulator_results.html
-#                    else
-#                        echo "- NR UE RA procedure failed" >> ./test_simulator_results.html
-#                    fi
-#                    echo "        
" >> ./test_simulator_results.html -# echo " " >> ./test_simulator_results.html -# fi + #build log files names + RA_ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb_ra_test.log + RA_UE_LOG=$ARCHIVES_LOC/ra_check_${TMODE}_${BW}prb_${CN_CONFIG}_ue_ra_test.log + if [ -f $RA_ENB_LOG ] && [ -f $RA_UE_LOG ] + then + #get rid of full path + NAME_ENB=`echo $RA_ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"` + NAME_UE=`echo $RA_UE_LOG | sed -e "s#$ARCHIVES_LOC/##"` + echo " " >> ./test_simulator_results.html + echo " $NAME_ENB --- $NAME_UE" >> ./test_simulator_results.html + echo " Check if RA proc succeeded" >> ./test_simulator_results.html + + #gNB RA check + GNB_RECEIVED=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly and UE_id (.+) is now 5G connected" $RA_ENB_LOG` + #UE RA check + UE_RA_PROC_OK=`egrep -c "RA procedure succeeded" $RA_UE_LOG` + + + if [ $GNB_RECEIVED -gt 0 ] && [ $UE_RA_PROC_OK -gt 0 ] + then + echo " OK" >> ./test_simulator_results.html + else + echo " KO" >> ./test_simulator_results.html + fi + + echo "
" >> ./test_simulator_results.html
+                    if [ $GNB_RECEIVED -gt 0 ]
+                    then
+                        echo "- gNB --> RA received" >> ./test_simulator_results.html
+                    else
+                        echo "- gNB RA NOT RECEIVED" >> ./test_simulator_results.html
+                    fi
+                    if [ $UE_RA_PROC_OK -gt 0 ]
+                    then
+                        echo "- NR UE  --> RA procedure succeded" >> ./test_simulator_results.html
+                    else
+                        echo "- NR UE RA procedure failed" >> ./test_simulator_results.html
+                    fi
+                    echo "        
" >> ./test_simulator_results.html + echo " " >> ./test_simulator_results.html + fi #SYNC test ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb.log diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 734001040c..f1f4945b9b 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -283,8 +283,8 @@ function check_ra_result { #gNB RA test echo "Checking gNB Log for RA success" - egrep "received correctly" $1 - egrep "now 5G connected" $1 + egrep "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly and UE_id (.+) is now 5G connected" $1 + #UE RA test echo 'Checking UE Log for RA success' @@ -2241,71 +2241,21 @@ function run_test_on_vm { echo "############################################################" # Proper check to be done when RA test is working! - #check_ra_result $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE + check_ra_result $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE try_cnt=$[$try_cnt+1] - ########### end RA test done - sleep 10 - try_cnt="0" + ########### end RA test + + sleep 30 + ######### start of PHY TEST loop + try_cnt="0" while [ $try_cnt -lt 4 ] do - #start RA test - SYNC_STATUS=0 - PING_STATUS=0 - IPERF_STATUS=0 - - echo "############################################################" - echo "${CN_CONFIG} : Starting the gNB" - echo "############################################################" - CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log - #last argument = 1 is to enable --do-ra for RA test - start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1 - - echo "############################################################" - echo "${CN_CONFIG} : Starting the NR-UE" - echo "############################################################" - CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log - #last argument = 1 is to enable --do-ra for RA test - start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1 - if [ $NR_UE_SYNC -eq 0 ] - then - echo "Problem w/ gNB and NR-UE not syncing" - terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 - terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 - scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC - scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC - SYNC_STATUS=-1 - try_cnt=$[$try_cnt+1] - continue - fi - - echo "############################################################" - echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators" - echo "############################################################" - sleep 20 - terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 - terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 - scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC - scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC - - #check RA markers in gNB and NR UE log files - echo "############################################################" - echo "${CN_CONFIG} : Checking RA on gNB / NR-UE" - echo "############################################################" - - mv $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_GNB_LOG_FILE - mv $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_NR_UE_LOG_FILE - # Proper check to be done when RA test is working! - #check_ra_result $ARCHIVES_LOC/ra_check_$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_NR_UE_LOG_FILE - - - #end RA test - sleep 30 SYNC_STATUS=0 PING_STATUS=0 From 31fb92b802c357ddb0f893234162c9e79c30bccb Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Thu, 22 Oct 2020 13:45:33 -0400 Subject: [PATCH 21/31] Moved UE SSB/RO handling code from nr_mac_common to nr_ue_procedures --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 704 +--------------- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 7 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 3 + openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 796 ++++++++++++++++-- openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c | 9 +- 5 files changed, 769 insertions(+), 750 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 4f2b7b4bb3..7e39b28697 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -31,72 +31,8 @@ */ #include "LAYER2/NR_MAC_gNB/mac_proto.h" -#include "asn1_conversions.h" #include -/* Tools */ -#include "SIMULATION/TOOLS/sim.h" // for taus - -// ================================================ -// SSB to RO mapping private defines and structures -// ================================================ - -#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16 -#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms -#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms -#define MAX_NB_FRAME_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms -#define MAX_NB_SLOT_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) -#define MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period -#define MAX_NB_SSB (64) // Maximum number of possible SSB indexes -#define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config - -// Maximum number of ROs that can be mapped to an SSB in an association pattern -// This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB -// An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot -#define MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOT_IN_FRAME*MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD) - -// The PRACH Config period is a series of selected slots in one or multiple frames -typedef struct prach_conf_period { - prach_occasion_slot_t prach_occasion_slot_map[MAX_NB_FRAME_IN_PRACH_CONF_PERIOD][MAX_NB_SLOT_IN_FRAME]; - uint16_t nb_of_prach_occasion; // Total number of PRACH occasions in the PRACH Config period - uint8_t nb_of_frame; // Size of the PRACH Config period in number of 10ms frames - uint8_t nb_of_slot; // Nb of slots in each frame -} prach_conf_period_t; - -// The association period is a series of PRACH Config periods -typedef struct prach_association_period { - prach_conf_period_t *prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; - uint8_t nb_of_prach_conf_period; // Nb of PRACH configuration periods within the association period - uint8_t nb_of_frame; // Total number of frames included in the association period -} prach_association_period_t; - -// The association pattern is a series of Association periods -typedef struct prach_association_pattern { - prach_association_period_t prach_association_period_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; - prach_conf_period_t prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; - uint8_t nb_of_assoc_period; // Nb of association periods within the association pattern - uint8_t nb_of_prach_conf_period_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH - uint8_t nb_of_frame; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) -} prach_association_pattern_t; - -// SSB details -typedef struct ssb_info { - boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration - prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index - uint16_t nb_mapped_ro; // Total number of mapped ROs to this SSB index -} ssb_info_t; - -// List of all the possible SSBs and their details -typedef struct ssb_list_info { - ssb_info_t tx_ssb[MAX_NB_SSB]; - uint8_t nb_tx_ssb; -} ssb_list_info_t; - -static prach_association_pattern_t prach_assoc_pattern; -static ssb_list_info_t ssb_list; - -// =============================================== -// =============================================== const uint8_t nr_slots_per_frame[5] = {10, 20, 40, 80, 160}; // Table 6.3.3.1-5 (38.211) NCS for preamble formats with delta_f_RA = 1.25 KHz @@ -1011,6 +947,24 @@ int get_format0(uint8_t index, return format; } +int64_t *get_prach_config_info(uint32_t pointa, + uint8_t index, + uint8_t unpaired) { + int64_t *prach_config_info_p; + + if (pointa > 2016666) { //FR2 + prach_config_info_p = table_6_3_3_2_4_prachConfig_Index[index]; + } + else { // FR1 + if (unpaired) + prach_config_info_p = table_6_3_3_2_3_prachConfig_Index[index]; + else + prach_config_info_p = table_6_3_3_2_2_prachConfig_Index[index]; + } // FR2 / FR1 + + return prach_config_info_p; +} + void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, uint16_t *slot_period, uint16_t *offset) { @@ -1082,628 +1036,6 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, } } -// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config -static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { - - int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers - int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers - uint8_t slot_shift_for_map; - uint8_t map_shift; - boolean_t even_slot_invalid; - int64_t s_map; - uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot - uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot - uint8_t N_dur; // Duration of a PRACH occasion (nb of symbols) - uint8_t frame; // Maximum is NB_FRAMES_IN_MAX_ASSOCIATION_PATTERN_PERIOD - uint8_t slot; // Maximum is the number of slots in a frame @ SCS 240kHz - uint16_t format = 0xffff; - uint8_t format2 = 0xff; - int nb_fdm; - - uint8_t config_index, mu; - uint32_t pointa; - int msg1_FDM; - - uint8_t prach_conf_period_idx; - uint8_t nb_of_frames_per_prach_conf_period; - uint8_t prach_conf_period_frame_idx; - - NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - - config_index = rach_ConfigGeneric->prach_ConfigurationIndex; - - if (setup->msg1_SubcarrierSpacing) - mu = *setup->msg1_SubcarrierSpacing; - else - mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - - pointa = frequencyInfoDL->absoluteFrequencyPointA; - msg1_FDM = rach_ConfigGeneric->msg1_FDM; - - switch (msg1_FDM){ - case 0: - case 1: - case 2: - case 3: - nb_fdm = 1 << msg1_FDM; - break; - default: - AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM); - } - - // Create the PRACH occasions map - // ============================== - // WIP-IDCC: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule - - // Identify the proper PRACH Configuration Index table according to the operating frequency - LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index = %u, unpaired = %u\n", pointa, mu, config_index, unpaired); - - if (pointa > 2016666) { //FR2 - - x = table_6_3_3_2_4_prachConfig_Index[config_index][2]; - y = table_6_3_3_2_4_prachConfig_Index[config_index][3]; - y2 = table_6_3_3_2_4_prachConfig_Index[config_index][4]; - - s_map = table_6_3_3_2_4_prachConfig_Index[config_index][5]; - - prach_conf_start_symbol = table_6_3_3_2_4_prachConfig_Index[config_index][6]; - N_t_slot = table_6_3_3_2_4_prachConfig_Index[config_index][8]; - N_dur = table_6_3_3_2_4_prachConfig_Index[config_index][9]; - if (table_6_3_3_2_4_prachConfig_Index[config_index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][1]; - format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[config_index][0]) | (format2<<8); - - slot_shift_for_map = mu-2; - if ( (mu == 3) && (table_6_3_3_2_4_prachConfig_Index[config_index][7] == 1) ) - even_slot_invalid = true; - else - even_slot_invalid = false; - } - else { // FR1 - if (unpaired) { - x = table_6_3_3_2_3_prachConfig_Index[config_index][2]; - y = table_6_3_3_2_3_prachConfig_Index[config_index][3]; - - s_map = table_6_3_3_2_3_prachConfig_Index[config_index][4]; - - prach_conf_start_symbol = table_6_3_3_2_3_prachConfig_Index[config_index][5]; - N_t_slot = table_6_3_3_2_3_prachConfig_Index[config_index][7]; - N_dur = table_6_3_3_2_3_prachConfig_Index[config_index][8]; - if (table_6_3_3_2_3_prachConfig_Index[config_index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[config_index][1]; - format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[config_index][0]) | (format2<<8); - } - else { // FDD - x = table_6_3_3_2_2_prachConfig_Index[config_index][2]; - y = table_6_3_3_2_2_prachConfig_Index[config_index][3]; - - s_map = table_6_3_3_2_2_prachConfig_Index[config_index][4]; - - prach_conf_start_symbol = table_6_3_3_2_2_prachConfig_Index[config_index][5]; - N_t_slot = table_6_3_3_2_2_prachConfig_Index[config_index][7]; - N_dur = table_6_3_3_2_2_prachConfig_Index[config_index][8]; - if (table_6_3_3_2_2_prachConfig_Index[config_index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[config_index][1]; - format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[config_index][0]) | (format2<<8); - } - - y2 = y; - slot_shift_for_map = mu; - if ( (mu == 1) && (table_6_3_3_2_3_prachConfig_Index[config_index][6] <= 1) ) - even_slot_invalid = true; - else - even_slot_invalid = false; - } // FR2 / FR1 - - prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; - nb_of_frames_per_prach_conf_period = x; - - LOG_D(MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period); - - // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period - // ---------------------------------------------------------------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------------------------------------------------------------- - // For every PRACH configuration periods - // ------------------------------------- - for (prach_conf_period_idx=0; prach_conf_period_idx> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz - if ( (s_map>>map_shift)&0x01 ) { - // Valid slot - - // Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also - if ( even_slot_invalid && (slot%2 == 0) ) - continue; // no prach in even slots @ 30kHz/120kHz for 1 prach per 60khz slot/subframe - - // We're good: valid frame and valid slot - // Compute all the PRACH occasions in the slot - - uint8_t n_prach_occ_in_time; - uint8_t n_prach_occ_in_freq; - - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot; - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm; - - for (n_prach_occ_in_time=0; n_prach_occ_in_timestart_symbol = start_symbol; - prach_occasion_p->fdm = n_prach_occ_in_freq; - prach_occasion_p->frame = frame; - prach_occasion_p->slot = slot; - prach_occasion_p->format = format; - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++; - - LOG_D(MAC,"Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n", - frame, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion, - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time, - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq); - } // For every freq in the slot - } // For every time occasions in the slot - } // Valid slot? - } // For every slots in a frame - } // Valid frame? - } // For every frames in a prach configuration period - } // For every prach configuration periods in the maximum association pattern period (160ms) -} - -// Build the list of all the valid/transmitted SSBs according to the config -static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { - - // Create the list of transmitted SSBs - // =================================== - BIT_STRING_t *ssb_bitmap; - uint64_t ssb_positionsInBurst; - uint8_t ssb_idx = 0; - - switch (scc->ssb_PositionsInBurst->present) { - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; - - ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); - LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - - for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list.nb_tx_ssb++; - ssb_list.tx_ssb[ssb_idx].transmitted = true; - LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); - } - ssb_idx++; - } - break; - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; - - ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); - LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - - for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list.nb_tx_ssb++; - ssb_list.tx_ssb[ssb_idx].transmitted = true; - LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); - } - ssb_idx++; - } - break; - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; - - ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); - LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - - for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list.nb_tx_ssb++; - ssb_list.tx_ssb[ssb_idx].transmitted = true; - LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); - } - ssb_idx++; - } - break; - default: - AssertFatal(false,"ssb_PositionsInBurst not present\n"); - break; - } -} - -// Map the transmitted SSBs to the ROs and create the association pattern according to the config -static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { - - // Map SSBs to PRACH occasions - // =========================== - // WIP-IDCC: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule - NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; - - boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB - uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB - uint16_t required_nb_of_prach_occasion; // Nb of RACH occasions required to map all the SSBs - uint8_t required_nb_of_prach_conf_period; // Nb of PRACH configuration periods required to map all the SSBs - - // Determine the SSB to RACH mapping ratio - // ======================================= - switch (ssb_perRACH_config){ - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: - multiple_ssb_per_ro = false; - ssb_rach_ratio = 8; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: - multiple_ssb_per_ro = false; - ssb_rach_ratio = 4; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: - multiple_ssb_per_ro = false; - ssb_rach_ratio = 2; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 1; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 2; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 4; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 8; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 16; - break; - default: - AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); - break; - } - LOG_D(MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro); - - // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period - // ============================================================================================================== - // WIP-IDCC: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions - // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) - // There is only one possible association period which can contain up to 16 PRACH configuration periods - LOG_D(MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n"); - if (true == multiple_ssb_per_ro) { - required_nb_of_prach_occasion = ((ssb_list.nb_tx_ssb-1) + ssb_rach_ratio) / ssb_rach_ratio; - } - else { - required_nb_of_prach_occasion = ssb_list.nb_tx_ssb * ssb_rach_ratio; - } - - required_nb_of_prach_conf_period = ((required_nb_of_prach_occasion-1) + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion) / prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion; - - if (required_nb_of_prach_conf_period == 1) { - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 1; - } - else if (required_nb_of_prach_conf_period == 2) { - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 2; - } - else if (required_nb_of_prach_conf_period <= 4) { - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 4; - } - else if (required_nb_of_prach_conf_period <= 8) { - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 8; - } - else if (required_nb_of_prach_conf_period <= 16) { - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 16; - } - else { - AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period); - } - - prach_assoc_pattern.nb_of_assoc_period = 1; // WIP-IDCC: only one possible association period - prach_assoc_pattern.prach_association_period_list[0].nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period * prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; - prach_assoc_pattern.nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_frame; - - LOG_D(MAC,"Assoc period %d, Nb of frames in assoc period %d\n", - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period, - prach_assoc_pattern.prach_association_period_list[0].nb_of_frame); - - // Proceed to the SSB to RO mapping - // ================================ - uint8_t association_period_idx; // Association period index within the association pattern - uint8_t ssb_idx = 0; - uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern - prach_conf_period_t *prach_conf_period_p; - - // Map all the association periods within the association pattern period - LOG_D(MAC,"Proceed to the SSB to RO mapping\n"); - for (association_period_idx=0; association_period_idxnb_of_frame; frame++) { - for (slot=0; slotnb_of_slot; slot++) { - for (ro_in_time=0; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { - for (ro_in_freq=0; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { - prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; - - // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO - // WIP-IDCC: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO - // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule - for (; ssb_idxmapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx; - ro_p->nb_mapped_ssb++; - ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; - ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; - AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); - - LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); - LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); - - // If all the required SSBs are mapped to this RO, exit the loop of SSBs - if (ro_p->nb_mapped_ssb == ssb_rach_ratio) { - ssb_idx++; - break; - } - } // if ssb_idx is transmitted - } // for ssb_idx - - // Exit the loop of ROs if there is no more SSB to map - if (MAX_NB_SSB == ssb_idx) break; - } // for ro_in_freq - - // Exit the loop of ROs if there is no more SSB to map - if (MAX_NB_SSB == ssb_idx) break; - } // for ro_in_time - - // Exit the loop of slots if there is no more SSB to map - if (MAX_NB_SSB == ssb_idx) break; - } // for slot - - // Exit the loop frames if there is no more SSB to map - if (MAX_NB_SSB == ssb_idx) break; - } // for frame - - // Exit the loop of PRACH configurations if there is no more SSB to map - if (MAX_NB_SSB == ssb_idx) break; - } // for n_prach_conf - - // WIP-IDCC: note that there is no re-mapping of the SSBs within the association period since there is no invalid ROs in the PRACH config periods that would create this situation - - } // if multiple_ssbs_per_ro - - else { - // -------------------- - // -------------------- - // Multiple ROs per SSB - // -------------------- - // -------------------- - - n_prach_conf = 0; - - // Go through the list of transmitted SSBs - for (ssb_idx=0; ssb_idxnb_of_frame; frame++) { - for (; slotnb_of_slot; slot++) { - for (; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { - for (; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { - prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; - - ro_p->mapped_ssb_idx[0] = ssb_idx; - ro_p->nb_mapped_ssb = 1; - ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; - ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; - AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); - nb_mapped_ro_in_association_period++; - - LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); - LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period); - - // Exit the loop if this SSB has been mapped to all the required ROs - // WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period: - // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - ro_in_freq++; - break; - } - } // for ro_in_freq - - // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - break; - } - else ro_in_freq = 0; // else go to the next time symbol in that slot and reset the freq index - } // for ro_in_time - - // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - break; - } - else ro_in_time = 0; // else go to the next slot in that PRACH config period and reset the symbol index - } // for slot - - // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - break; - } - else slot = 0; // else go to the next frame in that PRACH config period and reset the slot index - } // for frame - - // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - break; - } - else frame = 0; // else go to the next PRACH config period in that association period and reset the frame index - } // for n_prach_conf - - } // if ssb_idx is transmitted - } // for ssb_idx - } // else if multiple_ssbs_per_ro - - } // for association_period_index -} - -// Build the SSB to RO mapping upon RRC configuration update -void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){ - - // Clear all the lists and maps - memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t)); - memset(&ssb_list, 0, sizeof(ssb_list_info_t)); - - // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config - LOG_D(MAC,"Build RO list\n"); - build_ro_list(scc, unpaired); - - // Build the list of all the valid/transmitted SSBs according to the config - LOG_D(MAC,"Build SSB list\n"); - build_ssb_list(scc); - - // Map the transmitted SSBs to the ROs and create the association pattern according to the config - LOG_D(MAC,"Map SSB to RO\n"); - map_ssb_to_ro(scc); - LOG_D(MAC,"Map SSB to RO done\n"); -} - -// Returns a RACH occasion if any matches the SSB idx, the frame and the slot -int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, - int frame, - int slot, - prach_occasion_info_t **prach_occasion_info_pp) { - - ssb_info_t *ssb_info_p; - 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 - ssb_info_p = &ssb_list.tx_ssb[ssb_idx]; - for (uint8_t n_mapped_ro=0; n_mapped_ronb_mapped_ro; n_mapped_ro++) { - if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) && - (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 *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; - - for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { - if (prach_occasion_info_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 *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; - - for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { - if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { - if (nb_mapped_ssb == random_ssb_nb) { - *prach_occasion_info_pp = prach_occasion_info_p; - return 1; - } - else { - nb_mapped_ssb++; - } - } - } - } - } - } - - return 0; -} - int get_nr_prach_occasion_info_from_index(uint8_t index, uint32_t pointa, uint8_t mu, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index a644864473..f65e68a26f 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -120,9 +120,6 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, uint16_t *slot_period, uint16_t *offset); -void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired); -int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, int frame, int slot, prach_occasion_info_t **prach_occasion_info_pp); - int get_nr_prach_info_from_index(uint8_t index, int frame, int slot, @@ -166,6 +163,10 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPreco int get_format0(uint8_t index, uint8_t unpaired); +int64_t *get_prach_config_info(uint32_t pointa, + uint8_t index, + uint8_t unpaired); + uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config); int get_num_dmrs(uint16_t dmrs_mask ); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 9e18180b91..84e331091e 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -306,5 +306,8 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu, uint8_t *nb_dmrs_re_per_rb, uint16_t *number_dmrs_symbols); +void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired); + + #endif /** @}*/ diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index d8765c1055..257fcc4c7d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -64,6 +64,10 @@ /* utils */ #include "assertions.h" +/* Tools */ +#include "asn1_conversions.h" +#include "SIMULATION/TOOLS/sim.h" // for taus + #include "common/utils/LOG/log.h" #include "SIMULATION/TOOLS/sim.h" // for taus #include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h" @@ -72,12 +76,73 @@ #include #include +// ================================================ +// SSB to RO mapping private defines and structures +// ================================================ + +#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16 +#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms +#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms +#define MAX_NB_FRAME_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms +#define MAX_NB_SLOT_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) +#define MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period +#define MAX_NB_SSB (64) // Maximum number of possible SSB indexes +#define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config + +// Maximum number of ROs that can be mapped to an SSB in an association pattern +// This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB +// An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot +#define MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOT_IN_FRAME*MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD) + +// The PRACH Config period is a series of selected slots in one or multiple frames +typedef struct prach_conf_period { + prach_occasion_slot_t prach_occasion_slot_map[MAX_NB_FRAME_IN_PRACH_CONF_PERIOD][MAX_NB_SLOT_IN_FRAME]; + uint16_t nb_of_prach_occasion; // Total number of PRACH occasions in the PRACH Config period + uint8_t nb_of_frame; // Size of the PRACH Config period in number of 10ms frames + uint8_t nb_of_slot; // Nb of slots in each frame +} prach_conf_period_t; + +// The association period is a series of PRACH Config periods +typedef struct prach_association_period { + prach_conf_period_t *prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; + uint8_t nb_of_prach_conf_period; // Nb of PRACH configuration periods within the association period + uint8_t nb_of_frame; // Total number of frames included in the association period +} prach_association_period_t; + +// The association pattern is a series of Association periods +typedef struct prach_association_pattern { + prach_association_period_t prach_association_period_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + prach_conf_period_t prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + uint8_t nb_of_assoc_period; // Nb of association periods within the association pattern + uint8_t nb_of_prach_conf_period_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH + uint8_t nb_of_frame; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) +} prach_association_pattern_t; + +// SSB details +typedef struct ssb_info { + boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration + prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index + uint16_t nb_mapped_ro; // Total number of mapped ROs to this SSB index +} ssb_info_t; + +// List of all the possible SSBs and their details +typedef struct ssb_list_info { + ssb_info_t tx_ssb[MAX_NB_SSB]; + uint8_t nb_tx_ssb; +} ssb_list_info_t; + +static prach_association_pattern_t prach_assoc_pattern; +static ssb_list_info_t ssb_list; + +// =============================================== +// =============================================== + //#define ENABLE_MAC_PAYLOAD_DEBUG 1 #define DEBUG_EXTRACT_DCI 1 extern int bwp_id; extern dci_pdu_rel15_t *def_dci_pdu_rel15; -extern const uint16_t nr_slots_per_frame[5]; +extern const uint8_t nr_slots_per_frame[5]; extern void mac_rlc_data_ind ( const module_id_t module_idP, @@ -92,6 +157,617 @@ extern void mac_rlc_data_ind ( num_tb_t num_tbP, crc_t *crcs_pP); +// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config +static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { + + int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers + int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers + uint8_t slot_shift_for_map; + uint8_t map_shift; + boolean_t even_slot_invalid; + int64_t s_map; + uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot + uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot + uint8_t N_dur; // Duration of a PRACH occasion (nb of symbols) + uint8_t frame; // Maximum is NB_FRAMES_IN_MAX_ASSOCIATION_PATTERN_PERIOD + uint8_t slot; // Maximum is the number of slots in a frame @ SCS 240kHz + uint16_t format = 0xffff; + uint8_t format2 = 0xff; + int nb_fdm; + + uint8_t config_index, mu; + uint32_t pointa; + int msg1_FDM; + + uint8_t prach_conf_period_idx; + uint8_t nb_of_frames_per_prach_conf_period; + uint8_t prach_conf_period_frame_idx; + int64_t *prach_config_info_p; + + NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; + + config_index = rach_ConfigGeneric->prach_ConfigurationIndex; + + if (setup->msg1_SubcarrierSpacing) + mu = *setup->msg1_SubcarrierSpacing; + else + mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + + pointa = frequencyInfoDL->absoluteFrequencyPointA; + msg1_FDM = rach_ConfigGeneric->msg1_FDM; + + switch (msg1_FDM){ + case 0: + case 1: + case 2: + case 3: + nb_fdm = 1 << msg1_FDM; + break; + default: + AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM); + } + + // Create the PRACH occasions map + // ============================== + // WIP-IDCC: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule + + // Identify the proper PRACH Configuration Index table according to the operating frequency + LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index = %u, unpaired = %u\n", pointa, mu, config_index, unpaired); + + prach_config_info_p = get_prach_config_info(pointa, config_index, unpaired); + + if (pointa > 2016666) { //FR2 + + x = prach_config_info_p[2]; + y = prach_config_info_p[3]; + y2 = prach_config_info_p[4]; + + s_map = prach_config_info_p[5]; + + prach_conf_start_symbol = prach_config_info_p[6]; + N_t_slot = prach_config_info_p[8]; + N_dur = prach_config_info_p[9]; + if (prach_config_info_p[1] != -1) + format2 = (uint8_t) prach_config_info_p[1]; + format = ((uint8_t) prach_config_info_p[0]) | (format2<<8); + + slot_shift_for_map = mu-2; + if ( (mu == 3) && (prach_config_info_p[7] == 1) ) + even_slot_invalid = true; + else + even_slot_invalid = false; + } + else { // FR1 + x = prach_config_info_p[2]; + y = prach_config_info_p[3]; + y2 = y; + + s_map = prach_config_info_p[4]; + + prach_conf_start_symbol = prach_config_info_p[5]; + N_t_slot = prach_config_info_p[7]; + N_dur = prach_config_info_p[8]; + if (prach_config_info_p[1] != -1) + format2 = (uint8_t) prach_config_info_p[1]; + format = ((uint8_t) prach_config_info_p[0]) | (format2<<8); + + slot_shift_for_map = mu; + if ( (mu == 1) && (prach_config_info_p[6] <= 1) ) + // no prach in even slots @ 30kHz for 1 prach per subframe + even_slot_invalid = true; + else + even_slot_invalid = false; + } // FR2 / FR1 + + prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; + nb_of_frames_per_prach_conf_period = x; + + LOG_D(MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period); + + // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period + // ---------------------------------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------------------------------- + // For every PRACH configuration periods + // ------------------------------------- + for (prach_conf_period_idx=0; prach_conf_period_idx> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz + if ( (s_map>>map_shift)&0x01 ) { + // Valid slot + + // Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also + if ( even_slot_invalid && (slot%2 == 0) ) + continue; // no prach in even slots @ 30kHz/120kHz for 1 prach per 60khz slot/subframe + + // We're good: valid frame and valid slot + // Compute all the PRACH occasions in the slot + + uint8_t n_prach_occ_in_time; + uint8_t n_prach_occ_in_freq; + + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot; + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm; + + for (n_prach_occ_in_time=0; n_prach_occ_in_timestart_symbol = start_symbol; + prach_occasion_p->fdm = n_prach_occ_in_freq; + prach_occasion_p->frame = frame; + prach_occasion_p->slot = slot; + prach_occasion_p->format = format; + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++; + + LOG_D(MAC,"Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n", + frame, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion, + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time, + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq); + } // For every freq in the slot + } // For every time occasions in the slot + } // Valid slot? + } // For every slots in a frame + } // Valid frame? + } // For every frames in a prach configuration period + } // For every prach configuration periods in the maximum association pattern period (160ms) +} + +// Build the list of all the valid/transmitted SSBs according to the config +static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { + + // Create the list of transmitted SSBs + // =================================== + BIT_STRING_t *ssb_bitmap; + uint64_t ssb_positionsInBurst; + uint8_t ssb_idx = 0; + + switch (scc->ssb_PositionsInBurst->present) { + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + default: + AssertFatal(false,"ssb_PositionsInBurst not present\n"); + break; + } +} + +// Map the transmitted SSBs to the ROs and create the association pattern according to the config +static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { + + // Map SSBs to PRACH occasions + // =========================== + // WIP-IDCC: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule + NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; + + boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB + uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB + uint16_t required_nb_of_prach_occasion; // Nb of RACH occasions required to map all the SSBs + uint8_t required_nb_of_prach_conf_period; // Nb of PRACH configuration periods required to map all the SSBs + + // Determine the SSB to RACH mapping ratio + // ======================================= + switch (ssb_perRACH_config){ + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 8; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 4; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 1; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 4; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 8; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 16; + break; + default: + AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); + break; + } + LOG_D(MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro); + + // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period + // ============================================================================================================== + // WIP-IDCC: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions + // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) + // There is only one possible association period which can contain up to 16 PRACH configuration periods + LOG_D(MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n"); + if (true == multiple_ssb_per_ro) { + required_nb_of_prach_occasion = ((ssb_list.nb_tx_ssb-1) + ssb_rach_ratio) / ssb_rach_ratio; + } + else { + required_nb_of_prach_occasion = ssb_list.nb_tx_ssb * ssb_rach_ratio; + } + + required_nb_of_prach_conf_period = ((required_nb_of_prach_occasion-1) + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion) / prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion; + + if (required_nb_of_prach_conf_period == 1) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 1; + } + else if (required_nb_of_prach_conf_period == 2) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 2; + } + else if (required_nb_of_prach_conf_period <= 4) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 4; + } + else if (required_nb_of_prach_conf_period <= 8) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 8; + } + else if (required_nb_of_prach_conf_period <= 16) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 16; + } + else { + AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period); + } + + prach_assoc_pattern.nb_of_assoc_period = 1; // WIP-IDCC: only one possible association period + prach_assoc_pattern.prach_association_period_list[0].nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period * prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; + prach_assoc_pattern.nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_frame; + + LOG_D(MAC,"Assoc period %d, Nb of frames in assoc period %d\n", + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period, + prach_assoc_pattern.prach_association_period_list[0].nb_of_frame); + + // Proceed to the SSB to RO mapping + // ================================ + uint8_t association_period_idx; // Association period index within the association pattern + uint8_t ssb_idx = 0; + uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern + prach_conf_period_t *prach_conf_period_p; + + // Map all the association periods within the association pattern period + LOG_D(MAC,"Proceed to the SSB to RO mapping\n"); + for (association_period_idx=0; association_period_idxnb_of_frame; frame++) { + for (slot=0; slotnb_of_slot; slot++) { + for (ro_in_time=0; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { + for (ro_in_freq=0; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; + + // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO + // WIP-IDCC: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule + for (; ssb_idxmapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx; + ro_p->nb_mapped_ssb++; + ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; + AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + + LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); + LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + + // If all the required SSBs are mapped to this RO, exit the loop of SSBs + if (ro_p->nb_mapped_ssb == ssb_rach_ratio) { + ssb_idx++; + break; + } + } // if ssb_idx is transmitted + } // for ssb_idx + + // Exit the loop of ROs if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for ro_in_freq + + // Exit the loop of ROs if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for ro_in_time + + // Exit the loop of slots if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for slot + + // Exit the loop frames if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for frame + + // Exit the loop of PRACH configurations if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for n_prach_conf + + // WIP-IDCC: note that there is no re-mapping of the SSBs within the association period since there is no invalid ROs in the PRACH config periods that would create this situation + + } // if multiple_ssbs_per_ro + + else { + // -------------------- + // -------------------- + // Multiple ROs per SSB + // -------------------- + // -------------------- + + n_prach_conf = 0; + + // Go through the list of transmitted SSBs + for (ssb_idx=0; ssb_idxnb_of_frame; frame++) { + for (; slotnb_of_slot; slot++) { + for (; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { + for (; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; + + ro_p->mapped_ssb_idx[0] = ssb_idx; + ro_p->nb_mapped_ssb = 1; + ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; + AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + nb_mapped_ro_in_association_period++; + + LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); + LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period); + + // Exit the loop if this SSB has been mapped to all the required ROs + // WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period: + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + ro_in_freq++; + break; + } + } // for ro_in_freq + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else ro_in_freq = 0; // else go to the next time symbol in that slot and reset the freq index + } // for ro_in_time + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else ro_in_time = 0; // else go to the next slot in that PRACH config period and reset the symbol index + } // for slot + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else slot = 0; // else go to the next frame in that PRACH config period and reset the slot index + } // for frame + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else frame = 0; // else go to the next PRACH config period in that association period and reset the frame index + } // for n_prach_conf + + } // if ssb_idx is transmitted + } // for ssb_idx + } // else if multiple_ssbs_per_ro + + } // for association_period_index +} + +// Returns a RACH occasion if any matches the SSB idx, the frame and the slot +static int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, + int frame, + int slot, + prach_occasion_info_t **prach_occasion_info_pp) { + + ssb_info_t *ssb_info_p; + 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 + ssb_info_p = &ssb_list.tx_ssb[ssb_idx]; + for (uint8_t n_mapped_ro=0; n_mapped_ronb_mapped_ro; n_mapped_ro++) { + if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) && + (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 *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; + + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { + if (prach_occasion_info_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 *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; + + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { + if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { + if (nb_mapped_ssb == random_ssb_nb) { + *prach_occasion_info_pp = prach_occasion_info_p; + return 1; + } + else { + nb_mapped_ssb++; + } + } + } + } + } + } + + return 0; +} + +// Build the SSB to RO mapping upon RRC configuration update +void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){ + + // Clear all the lists and maps + memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t)); + memset(&ssb_list, 0, sizeof(ssb_list_info_t)); + + // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config + LOG_D(MAC,"Build RO list\n"); + build_ro_list(scc, unpaired); + + // Build the list of all the valid/transmitted SSBs according to the config + LOG_D(MAC,"Build SSB list\n"); + build_ssb_list(scc); + + // Map the transmitted SSBs to the ROs and create the association pattern according to the config + LOG_D(MAC,"Map SSB to RO\n"); + map_ssb_to_ro(scc); + LOG_D(MAC,"Map SSB to RO done\n"); +} + void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, fapi_nr_dl_config_request_t *dl_config, fapi_nr_ul_config_request_t *ul_config, @@ -498,8 +1174,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id, SFN_C_TYPE sfn_c=SFN_C_IMPOSSIBLE; // only valid for mux=1 uint32_t n_c=UINT_MAX; uint32_t number_of_search_space_per_slot=UINT_MAX; - uint32_t first_symbol_index=UINT_MAX; - uint32_t search_space_duration; // element of search space +// uint32_t first_symbol_index=UINT_MAX; +// uint32_t search_space_duration; // element of search space // 38.213 table 10.1-1 /// MUX PATTERN 1 @@ -516,13 +1192,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id, sfn_c = SFN_C_MOD_2_EQ_0; } - if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (ssb_index&1)){ - first_symbol_index = num_symbols; - }else{ - first_symbol_index = table_38213_13_11_c4[index_4lsb]; - } +// if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (ssb_index&1)){ +// first_symbol_index = num_symbols; +// }else{ +// first_symbol_index = table_38213_13_11_c4[index_4lsb]; +// } // 38.213 chapter 13: over two consecutive slots - search_space_duration = 2; +// search_space_duration = 2; } if(mac->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){ @@ -530,15 +1206,15 @@ int8_t nr_ue_decode_mib(module_id_t module_id, number_of_search_space_per_slot = table_38213_13_11_c2[index_4lsb]; big_m = table_38213_13_12_c3[index_4lsb]; - if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (ssb_index&1)){ - first_symbol_index = 7; - }else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (ssb_index&1)){ - first_symbol_index = num_symbols; - }else{ - first_symbol_index = 0; - } +// if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (ssb_index&1)){ +// first_symbol_index = 7; +// }else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (ssb_index&1)){ +// first_symbol_index = num_symbols; +// }else{ +// first_symbol_index = 0; +// } // 38.213 chapter 13: over two consecutive slots - search_space_duration = 2; +// search_space_duration = 2; } /// MUX PATTERN 2 @@ -550,21 +1226,21 @@ int8_t nr_ue_decode_mib(module_id_t module_id, // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot // sfn_c = SFN_C_EQ_SFN_SSB; n_c = get_ssb_slot(ssb_index); - switch(ssb_index & 0x3){ // ssb_index(i) mod 4 - case 0: - first_symbol_index = 0; - break; - case 1: - first_symbol_index = 1; - break; - case 2: - first_symbol_index = 6; - break; - case 3: - first_symbol_index = 7; - break; - default: break; - } +// switch(ssb_index & 0x3){ // ssb_index(i) mod 4 +// case 0: +// first_symbol_index = 0; +// break; +// case 1: +// first_symbol_index = 1; +// break; +// case 2: +// first_symbol_index = 6; +// break; +// case 3: +// first_symbol_index = 7; +// break; +// default: break; +// } }else if((scs_ssb == scs_240kHz) && (scs_pdcch == scs_120kHz)){ // 38.213 Table 13-14 @@ -574,36 +1250,36 @@ int8_t nr_ue_decode_mib(module_id_t module_id, n_c = get_ssb_slot(ssb_index); switch(ssb_index & 0x7){ // ssb_index(i) mod 8 case 0: - first_symbol_index = 0; +// first_symbol_index = 0; break; case 1: - first_symbol_index = 1; +// first_symbol_index = 1; break; case 2: - first_symbol_index = 2; +// first_symbol_index = 2; break; case 3: - first_symbol_index = 3; +// first_symbol_index = 3; break; case 4: - first_symbol_index = 12; +// first_symbol_index = 12; n_c = get_ssb_slot(ssb_index) - 1; break; case 5: - first_symbol_index = 13; +// first_symbol_index = 13; n_c = get_ssb_slot(ssb_index) - 1; break; case 6: - first_symbol_index = 0; +// first_symbol_index = 0; break; case 7: - first_symbol_index = 1; +// first_symbol_index = 1; break; default: break; } }else{ ; } // 38.213 chapter 13: over one slot - search_space_duration = 1; +// search_space_duration = 1; } /// MUX PATTERN 3 @@ -614,24 +1290,24 @@ int8_t nr_ue_decode_mib(module_id_t module_id, // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot // sfn_c = SFN_C_EQ_SFN_SSB; n_c = get_ssb_slot(ssb_index); - switch(ssb_index & 0x3){ // ssb_index(i) mod 4 - case 0: - first_symbol_index = 4; - break; - case 1: - first_symbol_index = 8; - break; - case 2: - first_symbol_index = 2; - break; - case 3: - first_symbol_index = 6; - break; - default: break; - } +// switch(ssb_index & 0x3){ // ssb_index(i) mod 4 +// case 0: +// first_symbol_index = 4; +// break; +// case 1: +// first_symbol_index = 8; +// break; +// case 2: +// first_symbol_index = 2; +// break; +// case 3: +// first_symbol_index = 6; +// break; +// default: break; +// } }else{ ; } // 38.213 chapter 13: over one slot - search_space_duration = 1; +// search_space_duration = 1; } AssertFatal(number_of_search_space_per_slot!=UINT_MAX,""); @@ -2214,7 +2890,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, uint8_t time_domain_ind ){ int dmrs_typeA_pos = mac->scc->dmrs_TypeA_Position; - uint8_t k_offset=0; +// uint8_t k_offset=0; uint8_t sliv_S=0; uint8_t sliv_L=0; uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 @@ -2355,7 +3031,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, dlsch_config_pdu->number_symbols=L; } else {// Default configuration from tables - k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; +// k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; sliv_S = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1]; sliv_L = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2]; // k_offset = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0]; @@ -2398,7 +3074,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, pusch_config_pdu->nr_of_symbols=L; } else { - k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; +// k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; sliv_S = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1]; sliv_L = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2]; // k_offset = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0]; diff --git a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c index 06db41df9c..c81a1f7911 100644 --- a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c +++ b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c @@ -274,15 +274,22 @@ uint16_t nr_ue_process_rar(module_id_t mod_id, if (ue_mac->RA_RAPID_found) { uint8_t freq_hopping, mcs, Msg3_t_alloc, Msg3_f_alloc; - unsigned char tpc_command, csi_req; + unsigned char tpc_command; +#ifdef DEBUG_RAR + unsigned char csi_req; +#endif // TC-RNTI *t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); ue_mac->t_crnti = *t_crnti; // TA command ta_command = rar->TA2 + (rar->TA1 << 5); + +#ifdef DEBUG_RAR // CSI csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); +#endif + // TPC tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); switch (tpc_command){ From a9169c0234ce27895af6d7cc99d46d90f284045f Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Thu, 22 Oct 2020 17:55:23 -0400 Subject: [PATCH 22/31] -Updated for a clean merge --- executables/nr-uesoftmodem.c | 3 +-- openair1/PHY/MODULATION/slot_fep_nr.c | 10 ++------ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 1 + openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 24 +++++++++---------- 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index f7268938ea..e6d644453c 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -693,7 +693,6 @@ int main( int argc, char **argv ) { } init_symbol_rotation(frame_parms[CC_id],frame_parms[CC_id]->dl_CarrierFreq); - init_nr_ue_vars(UE[CC_id],frame_parms[CC_id],0,abstraction_flag); UE[CC_id]->mac_enabled = 1; @@ -752,7 +751,7 @@ int main( int argc, char **argv ) { UE[CC_id]->N_TA_offset = (int)(N_TA_offset * factor); LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d)\n", UE[CC_id]->Mod_id, UE[CC_id]->N_TA_offset, factor, UE[CC_id]->frame_parms.ul_CarrierFreq, N_RB); } -} + } // printf("tx_max_power = %d -> amp %d\n",tx_max_power[0],get_tx_amp(tx_max_poHwer,tx_max_power)); init_openair0(); diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 06087a6467..2ffdb013a5 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -483,15 +483,9 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, dft(dftsize,(int16_t *)&tmp_dft_in, (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); } - else{ - //dft(dftsize,(int16_t *)&rxdata[rxdata_offset-sample_offset], - // (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); - memcpy((void *)tmp_dft_in, - (void *) &rxdata[rxdata_offset-sample_offset], - (frame_parms->ofdm_symbol_size)*sizeof(int)); - dft(dftsize,(int16_t *)&tmp_dft_in, + else + dft(dftsize,(int16_t *)&rxdata[rxdata_offset-sample_offset], (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); - } // clear DC carrier from OFDM symbols rxdataF[symbol * frame_parms->ofdm_symbol_size] = 0; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 7e39b28697..c377dd3207 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1189,6 +1189,7 @@ uint8_t get_nr_prach_duration(uint8_t prach_format){ break; } + } int get_nr_prach_info_from_index(uint8_t index, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 257fcc4c7d..803c80c9e1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -211,7 +211,7 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { // Create the PRACH occasions map // ============================== - // WIP-IDCC: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule + // WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule // Identify the proper PRACH Configuration Index table according to the operating frequency LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index = %u, unpaired = %u\n", pointa, mu, config_index, unpaired); @@ -404,7 +404,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // Map SSBs to PRACH occasions // =========================== - // WIP-IDCC: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule + // WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; @@ -456,7 +456,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period // ============================================================================================================== - // WIP-IDCC: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions + // WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) // There is only one possible association period which can contain up to 16 PRACH configuration periods LOG_D(MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n"); @@ -488,7 +488,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period); } - prach_assoc_pattern.nb_of_assoc_period = 1; // WIP-IDCC: only one possible association period + prach_assoc_pattern.nb_of_assoc_period = 1; // WIP: only one possible association period prach_assoc_pattern.prach_association_period_list[0].nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period * prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; prach_assoc_pattern.nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_frame; @@ -513,7 +513,7 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { uint8_t ro_in_freq=0; // Set the starting PRACH Configuration period index in the association_pattern map for this particular association period - prach_configuration_period_idx = 0; // WIP-IDCC: only one possible association period so the starting PRACH configuration period is automatically 0 + prach_configuration_period_idx = 0; // WIP: only one possible association period so the starting PRACH configuration period is automatically 0 // Check if we need to map multiple SSBs per RO or multiple ROs per SSB if (true == multiple_ssb_per_ro) { @@ -523,8 +523,8 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { // -------------------- // -------------------- - // WIP-IDCC: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO - // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule + // WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule ssb_idx = 0; // Go through the list of PRACH config periods within this association period @@ -541,8 +541,8 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO - // WIP-IDCC: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO - // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule + // WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule for (; ssb_idx Date: Thu, 22 Oct 2020 18:39:25 -0400 Subject: [PATCH 23/31] Removed changes in fix_scc to avoid impact on the actual value of ssb_PositionsInBurst_Bitmap in the archived configuration files --- openair2/GNB_APP/gnb_config.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 6ee8bc1b6b..49af793e03 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -223,12 +223,20 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { scc->ssb_PositionsInBurst->choice.shortBitmap.bits_unused = 4; scc->ssb_PositionsInBurst->choice.shortBitmap.buf = CALLOC(1,1); scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] = 0; - scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] = ssbmap & 0xF0; + for (int i=0; i<8; i++) { + if (issb_PositionsInBurst->choice.shortBitmap.bits_unused) + curr_bit = 0; + else + curr_bit = (ssbmap>>(7-i))&0x01; + scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] |= curr_bit<ssb_PositionsInBurst->choice.mediumBitmap.size = 1; - scc->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0; + scc->ssb_PositionsInBurst->choice.mediumBitmap.size = 1; + scc->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0; scc->ssb_PositionsInBurst->choice.mediumBitmap.buf = CALLOC(1,1); - scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] = ssbmap; + scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] = 0; + for (int i=0; i<8; i++) + scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] |= (((ssbmap>>(7-i))&0x01)<ssb_PositionsInBurst->choice.longBitmap.size = 8; scc->ssb_PositionsInBurst->choice.longBitmap.bits_unused = 0; @@ -236,7 +244,8 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { for (int j=0; j<8; j++) { scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-j] = 0; curr_bit = (ssbmap>>(j<<3))&(0xff); - scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-j] = curr_bit; + for (int i=0; i<8; i++) + scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-j] |= (((curr_bit>>(7-i))&0x01)< Date: Thu, 22 Oct 2020 18:55:05 -0400 Subject: [PATCH 24/31] Changed for the original file in develop --- openair2/GNB_APP/gnb_config.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 49af793e03..977807d150 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -228,15 +228,15 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { curr_bit = 0; else curr_bit = (ssbmap>>(7-i))&0x01; - scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] |= curr_bit<ssb_PositionsInBurst->choice.shortBitmap.buf[0] |= curr_bit<ssb_PositionsInBurst->choice.mediumBitmap.size = 1; - scc->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0; + scc->ssb_PositionsInBurst->choice.mediumBitmap.size = 1; + scc->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0; scc->ssb_PositionsInBurst->choice.mediumBitmap.buf = CALLOC(1,1); scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] = 0; for (int i=0; i<8; i++) - scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] |= (((ssbmap>>(7-i))&0x01)<ssb_PositionsInBurst->choice.mediumBitmap.buf[0] |= (((ssbmap>>(7-i))&0x01)<ssb_PositionsInBurst->choice.longBitmap.size = 8; scc->ssb_PositionsInBurst->choice.longBitmap.bits_unused = 0; From 3826ea13acb51cdf28d5786e26d556b447ebc8da Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 23 Oct 2020 16:31:06 +0200 Subject: [PATCH 25/31] nr rlc: bugfix - ret.next was not set in a particular case The function next_missing needs a rewrite... --- openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 78a49e4604..e1ae1df077 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -922,6 +922,7 @@ static missing_data_t next_missing(nr_rlc_entity_am_t *entity, */ ret.sn_start = entity->rx_next; ret.so_start = 0; + ret.next = cur; goto set_end_different_sdu; } } From 818694acaabec0dd2158019cfc7fe014d6c5f500 Mon Sep 17 00:00:00 2001 From: Mario Hudon Date: Tue, 27 Oct 2020 11:26:16 -0400 Subject: [PATCH 26/31] -Code review: Use FAPI PRACH PDU instead of PRACH vars in nr_ue_get_rach/nr_get_prach_resources --- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 5 ++--- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 18 +++++++++--------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 41b200f328..2d75c48ef3 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -2144,7 +2144,7 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t ue->ulsch_Msg3_active[i] = 0; } } - nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], ue->prach_vars[0], mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx); + nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], &ue->prach_vars[0]->prach_pdu, mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx); } } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 84e331091e..3844695222 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -267,7 +267,7 @@ andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 @param nr_tti_tx slot for PRACH transmission @returns indication to generate PRACH to phy */ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, - NR_UE_PRACH *prach_vars, + fapi_nr_ul_config_prach_pdu *prach_pdu, module_id_t mod_id, int CC_id, UE_MODE_t UE_mode, @@ -279,7 +279,6 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, @param module_idP Index of UE instance @param CC_id Component Carrier Index @param gNB_index gNB index -@param t_id @param rach_ConfigDedicated @returns void */ void nr_get_prach_resources(module_id_t mod_id, @@ -287,7 +286,7 @@ void nr_get_prach_resources(module_id_t mod_id, uint8_t gNB_id, uint8_t first_Msg3, NR_PRACH_RESOURCES_t *prach_resources, - NR_UE_PRACH *prach_vars, + fapi_nr_ul_config_prach_pdu *prach_pdu, NR_RACH_ConfigDedicated_t * rach_ConfigDedicated); void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 123eb372f0..bc7e03324a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -77,7 +77,7 @@ void nr_get_prach_resources(module_id_t mod_id, uint8_t gNB_id, uint8_t first_Msg3, NR_PRACH_RESOURCES_t *prach_resources, - NR_UE_PRACH *prach_vars, + fapi_nr_ul_config_prach_pdu *prach_pdu, NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); @@ -197,7 +197,7 @@ void nr_get_prach_resources(module_id_t mod_id, (ssb_rach_ratio > 1)) { total_preambles_per_ssb = numberOfRA_Preambles / ssb_rach_ratio; - ssb_nb_in_ro = prach_vars->prach_pdu.ssb_nb_in_ro; + ssb_nb_in_ro = prach_pdu->ssb_nb_in_ro; starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro; } else { @@ -345,9 +345,9 @@ void nr_get_prach_resources(module_id_t mod_id, // - s_id is starting symbol of the PRACH occasion [0...14] // - t_id is the first slot of the PRACH occasion in a system frame [0...80] ul_carrier_id = 0; // NUL - f_id = prach_vars->prach_pdu.num_ra; - t_id = prach_vars->prach_pdu.prach_slot; - s_id = prach_vars->prach_pdu.prach_start_symbol; + f_id = prach_pdu->num_ra; + t_id = prach_pdu->prach_slot; + s_id = prach_pdu->prach_start_symbol; prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id; mac->ra_rnti = prach_resources->ra_RNTI; @@ -395,7 +395,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint // - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, - NR_UE_PRACH *prach_vars, + fapi_nr_ul_config_prach_pdu *prach_pdu, module_id_t mod_id, int CC_id, UE_MODE_t UE_mode, @@ -510,7 +510,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, // Fill in preamble and PRACH resources if (mac->generate_nr_prach == 1) - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated); + nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated); offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer (uint8_t *) payload, // UL MAC pdu pointer @@ -637,7 +637,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, // Fill in preamble and PRACH resources if (mac->generate_nr_prach == 1) - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated); + nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated); } else { @@ -651,7 +651,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, // Fill in preamble and PRACH resources if (mac->generate_nr_prach == 1) - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated); + nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated); } } From 31f1a4b13717f94bfc195126af900dc207f93437 Mon Sep 17 00:00:00 2001 From: Eurecom Date: Tue, 27 Oct 2020 18:23:14 +0100 Subject: [PATCH 27/31] fixed RA check marker --- ci-scripts/reportTestLocally.sh | 4 ++-- ci-scripts/runTestOnVM.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ci-scripts/reportTestLocally.sh b/ci-scripts/reportTestLocally.sh index 64c5d74975..a51494b4ce 100755 --- a/ci-scripts/reportTestLocally.sh +++ b/ci-scripts/reportTestLocally.sh @@ -781,9 +781,9 @@ function report_test { echo " Check if RA proc succeeded" >> ./test_simulator_results.html #gNB RA check - GNB_RECEIVED=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly and UE_id (.+) is now 5G connected" $RA_ENB_LOG` + GNB_RECEIVED=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $RA_ENB_LOG` #UE RA check - UE_RA_PROC_OK=`egrep -c "RA procedure succeeded" $RA_UE_LOG` + UE_RA_PROC_OK=`egrep -c "\[RAPROC\] RA procedure succeeded" $RA_UE_LOG` if [ $GNB_RECEIVED -gt 0 ] && [ $UE_RA_PROC_OK -gt 0 ] diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index f1f4945b9b..a3cf79e7ac 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -283,12 +283,12 @@ function check_ra_result { #gNB RA test echo "Checking gNB Log for RA success" - egrep "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly and UE_id (.+) is now 5G connected" $1 + egrep "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $1 #UE RA test echo 'Checking UE Log for RA success' - egrep "RA procedure succeeded" $2 + egrep "\[RAPROC\] RA procedure succeeded" $2 } From 3578426082d2b0f55087d6f9286ebb18e106acb2 Mon Sep 17 00:00:00 2001 From: hardy Date: Wed, 28 Oct 2020 10:07:25 +0100 Subject: [PATCH 28/31] fixed UE log file name --- ci-scripts/reportTestLocally.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/reportTestLocally.sh b/ci-scripts/reportTestLocally.sh index a51494b4ce..7c3c79777e 100755 --- a/ci-scripts/reportTestLocally.sh +++ b/ci-scripts/reportTestLocally.sh @@ -770,7 +770,7 @@ function report_test { #build log files names RA_ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb_ra_test.log - RA_UE_LOG=$ARCHIVES_LOC/ra_check_${TMODE}_${BW}prb_${CN_CONFIG}_ue_ra_test.log + RA_UE_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_ue_ra_test.log if [ -f $RA_ENB_LOG ] && [ -f $RA_UE_LOG ] then #get rid of full path From b18c36112560d97620b316167e5bd7dd8a3f8904 Mon Sep 17 00:00:00 2001 From: hardy Date: Wed, 28 Oct 2020 17:07:19 +0100 Subject: [PATCH 29/31] improved CI RA checks --- ci-scripts/runTestOnVM.sh | 51 ++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index a3cf79e7ac..b2cf9cd2fd 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -281,14 +281,35 @@ function check_ra_result { local LOC_GNB_LOG=$1 local LOC_UE_LOG=$2 - #gNB RA test - echo "Checking gNB Log for RA success" - egrep "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $1 - - - #UE RA test - echo 'Checking UE Log for RA success' - egrep "\[RAPROC\] RA procedure succeeded" $2 + #if log files exist + if [ -f $LOC_GNB_LOG ] && [ -f $LOC_UE_LOG ] + then + + #gNB RA test + #console check + echo "Checking gNB Log for RA success" + egrep "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $1 + #script check + local GNB_COMPLETE=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $1` + + #UE RA test + #console check + echo 'Checking UE Log for RA success' + egrep "\[RAPROC\] RA procedure succeeded" $2 + #script check + local UE_COMPLETE=`egrep -c "\[RAPROC\] RA procedure succeeded" $2` + + #generate status + if [ $GNB_COMPLETE -eq 0 ] || [ $UE_COMPLETE -eq 0 ] + then + RA_STATUS=-1 + echo "RA test FAILED, could not find the markers" + fi + #case where log files do not exist + else + echo "RA test log files not present" + RA_STATUS=-1 + fi } @@ -2196,10 +2217,11 @@ function run_test_on_vm { NR_STATUS=0 ######### start of RA TEST loop - while [ $try_cnt -lt 1 ] + while [ $try_cnt -lt 4 ] do SYNC_STATUS=0 + RA_STATUS=0 echo "############################################################" echo "${CN_CONFIG} : Starting the gNB" @@ -2242,9 +2264,13 @@ function run_test_on_vm { # Proper check to be done when RA test is working! check_ra_result $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE - - try_cnt=$[$try_cnt+1] - + if [ $RA_STATUS -ne 0 ] + then + echo "RA test NOT OK" + try_cnt=$[$try_cnt+1] + else + try_cnt=$[$try_cnt+10] + fi done ########### end RA test @@ -2359,6 +2385,7 @@ function run_test_on_vm { echo "Checking run status" echo "############################################################" + if [ $RA_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $SYNC_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $PING_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $IPERF_STATUS -ne 0 ]; then NR_STATUS=-1; fi From 9d2651d080ec704586f6ea2ca5713d1aef30d2d0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 28 Oct 2020 17:10:21 +0100 Subject: [PATCH 30/31] CI: Parse UE TUN interface correctly in S1 mode See also commit 8c5976e27907147fba629e822704d724336f5200 Above commit changed the TUN interface configuration to use program "ip" only. This commit changes the CI script parsing correspondingly: the pipeline will recognize the attempt to bring up the interface of the first UE. --- ci-scripts/reportTestLocally.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/reportTestLocally.sh b/ci-scripts/reportTestLocally.sh index 03cda20542..1ba69e4742 100755 --- a/ci-scripts/reportTestLocally.sh +++ b/ci-scripts/reportTestLocally.sh @@ -470,7 +470,7 @@ function report_test { then NB_UE_TUNNEL_UP=`egrep -c "Interface oaitun_ue1 successfully configured" $UE_LOG` else - NB_UE_TUNNEL_UP=`egrep -c "executing ifconfig oaitun_ue1" $UE_LOG` + NB_UE_TUNNEL_UP=`egrep -c "ip link set oaitun_ue1 up" $UE_LOG` fi if [ $NB_ENB_GOT_SYNC -gt 0 ] && [ $NB_UE_GOT_SYNC -gt 0 ] && [ $NB_ENB_SYNCED_WITH_UE -gt 0 ] then From c355a26aa69ae58d4fae552cb0b2c120137eb38a Mon Sep 17 00:00:00 2001 From: Eurecom Date: Fri, 30 Oct 2020 15:26:57 +0100 Subject: [PATCH 31/31] fixing RA test iteration to 10 times to have a chance (unstable in CI env) --- ci-scripts/runTestOnVM.sh | 59 +++++++++++++++------------------------ 1 file changed, 22 insertions(+), 37 deletions(-) diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index b2cf9cd2fd..9f44e0ae91 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -1246,16 +1246,6 @@ function start_rf_sim_gnb { ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR < $1 rm $1 - # For the moment, in RA test, no check and no copy of generated raw files - if [ $LOC_RA_TEST -eq 1 ] # RA test - then - sleep 30 - echo "echo \"free -m\"" > $1 - echo "free -m" >> $1 - ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR < $1 - rm $1 - return 0 - fi local i="0" echo "egrep -c \"got sync\" /home/ubuntu/tmp/cmake_targets/log/$LOC_LOG_FILE" > $1 @@ -1279,7 +1269,9 @@ function start_rf_sim_gnb { GNB_SYNC=1 echo "RF-SIM gNB is sync'ed: waiting for UE(s) to connect" fi - if [ $LOC_S1_CONFIGURATION -eq 0 ] + + # check noS1 config only outside RA test (as it does not support noS1) + if [ $LOC_S1_CONFIGURATION -eq 0 ] && [ $LOC_RA_TEST -eq 0 ] then echo "ifconfig oaitun_enb1 | egrep -c \"inet addr\"" > $1 # Checking oaitun_enb1 interface has now an IP address @@ -1362,14 +1354,6 @@ function start_rf_sim_nr_ue { ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1 rm $1 - # In case of RA test mode, no UE sync check for the moment. - # To be removed later? - if [ $LOC_RA_TEST -eq 1 ] # RA test - then - sleep 30 - NR_UE_SYNC=1 - return 0 - fi local i="0" echo "egrep -c \"Initial sync: pbch decoded sucessfully\" /home/ubuntu/tmp/cmake_targets/log/$LOC_LOG_FILE" > $1 while [ $i -lt 10 ] @@ -1393,11 +1377,13 @@ function start_rf_sim_nr_ue { else echo "RF-SIM NR-UE is sync'ed w/ gNB" fi - # Checking oaitun_ue1 interface has now an IP address - i="0" - echo "ifconfig oaitun_ue1 | egrep -c \"inet addr\"" > $1 - while [ $i -lt 10 ] - do + # Checking oaitun_ue1 interface has now an IP address (only outside RA test) + if [ $LOC_RA_TEST -eq 0 ] + then + i="0" + echo "ifconfig oaitun_ue1 | egrep -c \"inet addr\"" > $1 + while [ $i -lt 10 ] + do sleep 5 CONNECTED=`ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1` if [ $CONNECTED -eq 1 ] @@ -1406,21 +1392,20 @@ function start_rf_sim_nr_ue { else i=$[$i+1] fi - done - echo "echo \"free -m\"" > $1 - echo "free -m" >> $1 - ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1 - rm $1 - if [ $i -lt 50 ] - then + done + echo "echo \"free -m\"" > $1 + echo "free -m" >> $1 + ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1 + rm $1 + if [ $i -lt 50 ] + then NR_UE_SYNC=0 echo "RF-SIM NR-UE oaitun_ue1 is DOWN or NOT CONFIGURED" - else + else echo "RF-SIM NR-UE oaitun_ue1 is UP and CONFIGURED" - fi - sleep 10 - - + fi + sleep 10 + fi } @@ -2217,7 +2202,7 @@ function run_test_on_vm { NR_STATUS=0 ######### start of RA TEST loop - while [ $try_cnt -lt 4 ] + while [ $try_cnt -lt 10 ] #10 because it hardly succeed within CI do SYNC_STATUS=0