Compare commits

...

15 Commits

Author SHA1 Message Date
Francesco Mani
82ea17c0a3 use aperiodic SRS for Aerial CI tests 2026-05-30 09:06:21 +02:00
Francesco Mani
57b646b433 reverse HARQ bits in PUCCH2 handling at gNB
Signed-off-by: Francesco Mani <email@francescomani.it>
2026-05-30 08:49:48 +02:00
francescomani
ef22e593ed add documentation on scheduling ACK/NACK
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:49:48 +02:00
francescomani
c90f972131 remove double definition of MAX_NUM_NR_UCI_PDUS
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:49:48 +02:00
francescomani
bf813153a3 use functions to determine scheduled slot and frame according to feedback time
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:49:48 +02:00
francescomani
934695c09d procedures to keep track of allocated UL RRC periodic resources to support multiple BWPs in a multi-UE scenario
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:49:47 +02:00
francescomani
a737f70f10 code refactoring with common functions to compute PUCCH allocation parameters in RRC
also fixing a bug in computation of number of pucch available taking into account BWP start

Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:47:07 +02:00
francescomani
5833b04197 handle SR reception in PUCCH2
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:47:07 +02:00
francescomani
afcc914983 fix for PUCCH2 transmission buffer overflow
code is simplified to adhere to computation of RE and symbol offsets as in other channels

Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:47:07 +02:00
francescomani
a69bb4b8e8 multiple PUCCH resources per UE
this commit reworks the PUCCH RRC configuration by allowing shared PUCCH occasions between UEs and a maximum of 8 resources per resource set

Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:47:07 +02:00
francescomani
ad828037d3 allow transition from P0 to P2 in case we need to send more than 2 ACK/NACK per instance
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:37:24 +02:00
francescomani
604af5a5ac scheduling SR in advance (in a similar way to CSI measurement reports) to allow shared PUCCH resources
this is now necessary because we have shared PUCCH occasions between UEs and periodic channels as SR need to reserve a given occasion and prevent it to be used by other UEs

Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:35:07 +02:00
francescomani
6084d84147 improvement in pucch allocation functions foreseeing multple PUCCH resources per type
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:33:45 +02:00
francescomani
068aed1403 common function to find pucch res index
(to avoid code repetition)

Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:15:13 +02:00
francescomani
51f364ea13 minor: formatting improvement
Signed-off-by: francescomani <email@francescomani.it>
2026-05-30 08:15:12 +02:00
23 changed files with 793 additions and 490 deletions

View File

@@ -25,7 +25,7 @@ gNBs =
pdsch_AntennaPorts_N1 = 2;
pusch_AntennaPorts = 2;
do_CSIRS = 1;
do_SRS = "periodic";
do_SRS = "aperiodic";
min_rxtxtime = 2;
uess_agg_levels = [0, 4, 2, 1, 0];

View File

@@ -26,7 +26,7 @@ gNBs =
pdsch_AntennaPorts_N1 = 2;
pusch_AntennaPorts = 2;
do_CSIRS = 1;
do_SRS = "periodic";
do_SRS = "aperiodic";
min_rxtxtime = 2;
force_UL256qam_off = 1;
servingCellConfigCommon = (

View File

@@ -63,6 +63,20 @@ in aggregation level 2 which translates to `uess_agg_levels` set to `[0, 2, 0,
0, 0]`. For example, to enable one candidate on aggregation levels 2 and 4 set
`uess_agg_levels` to `[0, 1, 1, 0, 0]`.
## Feedback time for ACK/NACK on PUCCH
Feedback time for DLSCH ACK/NACK on PUCCH is selected by looping among the values on a list
(either default one or defined by upper layers). If the given element of the list provides
a feedback slot compatible with the frame configuration and the configured minimum feedback time,
the scheduler checks if there is an already active PUCCH in the given slot.
If there is no active PUCCH, it activates one and it increases by one the DAI counter to signal
the presence of one HARQ process feedback in the given PUCCH occasion.
If there is an already active PUCCH, it tries to allocate the feedback on that instance
pending multiple checks including
* the possibility to schedule HARQ and CSI feedback simultaneously
* the possibility to transition from a format with 2 bits limit to one without in case the limit is surpassed
* resource availability in terms of beam, PRBs and PUCCH coderate
### Examples:
#### Example 1:
Say we have 90% PDCCH success rate at aggregation level 1, `pdcch_cl_adjust` will stay at 0

View File

@@ -812,7 +812,7 @@ void nr_generate_pucch2(c16_t **txdataF,
uint8_t startingSymbolIndex = pucch_pdu->start_symbol_index;
uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
for (int l = 0; l < pucch_pdu->nr_of_symbols; l++) {
// c_init calculation according to TS38.211 subclause
uint64_t temp_x2 = 1ll << 17;
temp_x2 *= 14UL * nr_slot_tx + l + startingSymbolIndex + 1;
@@ -822,40 +822,19 @@ void nr_generate_pucch2(c16_t **txdataF,
uint32_t m = (startingPRB * NR_PUCCH_DMRS_RB * DMRS_MOD_ORDER) % 32;
const int seq_sz = ((startingPRB + pucch_pdu->prb_size) * NR_PUCCH_DMRS_RB * DMRS_MOD_ORDER + 31) / 32;
uint32_t *seq = gold_cache(temp_x2, seq_sz);
for (int rb=0; rb<pucch_pdu->prb_size; rb++) {
//startingPRB = startingPRB + rb;
const bool nb_rb_is_even = frame_parms->N_RB_DL & 1;
const int halfRBs = frame_parms->N_RB_DL / 2;
int symbol_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size;
for (int rb = 0; rb < pucch_pdu->prb_size; rb++) {
const int baseRB = rb + startingPRB;
int re_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size + 12 * baseRB;
if (nb_rb_is_even) {
if (baseRB < halfRBs) // if number RBs in bandwidth is even and current PRB is lower band
re_offset += frame_parms->first_carrier_offset;
else
re_offset -= halfRBs;
} else {
if (baseRB < halfRBs) // if number RBs in bandwidth is odd and current PRB is lower band
re_offset += frame_parms->first_carrier_offset;
else if (baseRB > halfRBs) // if number RBs in bandwidth is odd and current PRB is upper band
re_offset += -halfRBs + 6;
else
re_offset += frame_parms->first_carrier_offset;
}
//txptr = &txdataF[0][re_offset];
int re_offset = (frame_parms->first_carrier_offset + 12 * baseRB) % frame_parms->ofdm_symbol_size;
int k=0;
#ifdef DEBUG_NR_PUCCH_TX
int kk=0;
#endif
for (int n=0; n<12; n++) {
if (n == 6 && baseRB == halfRBs && !nb_rb_is_even) {
// if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB)
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size);
}
for (int n = 0; n < 12; n++) {
if (n%3 != 1) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3
txdataF[0][re_offset] = d[outSample + k];
if (n % 3 != 1) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3
txdataF[0][re_offset + symbol_offset] = d[outSample + k];
#ifdef DEBUG_NR_PUCCH_TX
printf(
"\t [nr_generate_pucch2] (n=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
@@ -869,15 +848,15 @@ void nr_generate_pucch2(c16_t **txdataF,
re_offset,
l,
n,
txdataF[0][re_offset].r,
txdataF[0][re_offset].i);
txdataF[0][re_offset + symbol_offset].r,
txdataF[0][re_offset + symbol_offset].i);
#endif
k++;
}
if (n%3 == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2
txdataF[0][re_offset].r = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (m)) & 1)))));
txdataF[0][re_offset].i = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (m + 1)) & 1)))));
if (n % 3 == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2
txdataF[0][re_offset + symbol_offset].r = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (m)) & 1)))));
txdataF[0][re_offset + symbol_offset].i = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (m + 1)) & 1)))));
m += 2;
#ifdef DEBUG_NR_PUCCH_TX
printf(
@@ -892,13 +871,14 @@ void nr_generate_pucch2(c16_t **txdataF,
re_offset,
l,
n,
txdataF[0][re_offset].r,
txdataF[0][re_offset].i);
txdataF[0][re_offset + symbol_offset].r,
txdataF[0][re_offset + symbol_offset].i);
kk++;
#endif
}
re_offset++;
if (re_offset >= frame_parms->ofdm_symbol_size)
re_offset -= frame_parms->ofdm_symbol_size;
}
outSample += 8;

View File

@@ -332,11 +332,6 @@ typedef struct {
int prach_I0;
} PHY_MEASUREMENTS_gNB;
// the current RRC resource allocation is that each UE gets its
// "own" PUCCH resource (for F0) in a dedicated PRB in each slot
// therefore, we can have up to "number of UE" UCI PDUs
#define MAX_NUM_NR_UCI_PDUS MAX_MOBILES_PER_GNB
/// Top-level PHY Data Structure for gNB
typedef struct PHY_VARS_gNB_s {
/// Module ID indicator for this instance

View File

@@ -828,7 +828,20 @@ int main(int argc, char **argv)
rnti_t rnti = 0x1234;
int uid = 0;
int ssb_index = 0;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid, ssb_index);
NR_UE_UL_RRC_info_t sr_info = {.allocated = true,
.resource = 0,
.offset = get_ul_slot_offset(&frame_structure, 0, true),
.period = frame_structure.numb_slots_period};
NR_UE_UL_RRC_info_t csimeas_info = sr_info;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc,
UE_Capability_nr,
sr_info,
csimeas_info,
0,
1,
&conf,
uid,
ssb_index);
secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc, frame);
/* -U option modify DMRS */
@@ -851,7 +864,6 @@ int main(int argc, char **argv)
phy_init_nr_gNB(gNB);
N_RB_DL = gNB->frame_parms.N_RB_DL;
NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.connected_ue_list[0];
configure_UE_BWP(RC.nrmac[0], scc, UE_info, false, NR_SearchSpace__searchSpaceType_PR_ue_Specific, -1, -1);
// stub to configure frame_parms

View File

@@ -837,7 +837,20 @@ int main(int argc, char *argv[])
rnti_t rnti = 0x1234;
int uid = 0;
int ssb_index = 0;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid, ssb_index);
NR_UE_UL_RRC_info_t sr_info = {.allocated = true,
.resource = 0,
.offset = get_ul_slot_offset(&frame_structure, 0, true),
.period = frame_structure.numb_slots_period};
NR_UE_UL_RRC_info_t csimeas_info = sr_info;
NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc,
UE_Capability_nr,
sr_info,
csimeas_info,
0,
1,
&conf,
uid,
ssb_index);
secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc, frame);
NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc);

View File

@@ -27,6 +27,7 @@
#include "asn_internal.h"
#include "NR_MAC_gNB/nr_mac_gNB.h"
#include "NR_MAC_gNB/mac_proto.h"
#include "NR_MAC_gNB/nr_radio_config.h"
#include "common/5g_platform_types.h"
#include "common/config/config_paramdesc.h"
#include "common/config/config_userapi.h"

View File

@@ -15,6 +15,7 @@
#include "BIT_STRING.h"
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "LAYER2/NR_MAC_gNB/nr_radio_config.h"
#include "GNB_APP/gnb_config.h"
#include "NR_MIB.h"
#include "NR_MAC_gNB/nr_mac_gNB.h"
@@ -962,6 +963,9 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
LOG_D(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n");
config_common(nrmac, config, scc);
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
int bw = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
config_ul_rrc_info(nrmac, config, *scc->ssbSubcarrierSpacing, bw);
fill_beam_index_list(scc, config, nrmac);
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
@@ -1257,7 +1261,7 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t
bool res = add_connected_nr_ue(nrmac, UE);
if (!res) {
LOG_E(NR_MAC, "Error adding UE %04x\n", rnti);
delete_nr_ue_data(UE, &nrmac->UE_info.uid_allocator);
delete_nr_ue_data(UE, nrmac, &nrmac->UE_info.uid_allocator);
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return false;
}

View File

@@ -216,13 +216,13 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo
nr_schedule_ulsch(module_idP, frame, slot, &sched_info->UL_dci_req);
stop_meas(&gNB->schedule_ulsch);
nr_sr_reporting(gNB, frame, slot);
// This schedules the DCI for Downlink and PDSCH
start_meas(&gNB->schedule_dlsch);
nr_schedule_ue_spec(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req);
stop_meas(&gNB->schedule_dlsch);
nr_sr_reporting(gNB, frame, slot);
nr_schedule_pucch(gNB, frame, slot);
/* TODO: we copy from gNB->UL_tti_req_ahead[0][current_index], ie. CC_id == 0,

View File

@@ -707,7 +707,7 @@ void nr_initiate_ra_proc(module_id_t module_idP,
UE = get_new_nr_ue_inst(&nr_mac->UE_info.uid_allocator, rnti, NULL, &nr_mac->radio_config);
if (!add_new_UE_RA(nr_mac, UE)) {
LOG_E(NR_MAC, "FAILURE: %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", frame, slot, preamble_index);
delete_nr_ue_data(UE, &nr_mac->UE_info.uid_allocator);
delete_nr_ue_data(UE, nr_mac, &nr_mac->UE_info.uid_allocator);
NR_SCHED_UNLOCK(&nr_mac->sched_lock);
return;
}
@@ -793,9 +793,9 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
ra->Msg3_tda_id);
int slots_frame = nr_mac->frame_structure.numb_slots_frame;
uint16_t K2 = tda_info.k2 + get_NTN_Koffset(scc);
const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER;
const int sched_slot = (slot + K2) % slots_frame;
int NTN_gNB_Koffset = get_NTN_Koffset(scc);
const int sched_frame = get_fb_frame(frame, slot, tda_info.k2, slots_frame, NTN_gNB_Koffset);
const int sched_slot = get_fb_slot(slot, tda_info.k2, slots_frame, NTN_gNB_Koffset);
uint16_t slot_bitmap = get_ul_bitmap(&nr_mac->frame_structure, sched_slot);
uint16_t msg3_mask = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
@@ -985,7 +985,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
start_ra_contention_resolution_timer(
ra,
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer,
K2,
NTN_gNB_Koffset + tda_info.k2,
ul_bwp->scs);
// reset state to wait msg3
@@ -1011,10 +1011,9 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc,
int slots_per_frame = fs->numb_slots_frame;
for (int i = 0; i < tda_list->list.count; i++) {
// check if it is UL
long k2 = *tda_list->list.array[i]->k2 + NTN_gNB_Koffset;
int abs_slot = slot + k2 + mu_delta;
int temp_frame = (frame + (abs_slot / slots_per_frame)) & 1023;
int temp_slot = abs_slot % slots_per_frame; // msg3 slot according to 8.3 in 38.213
// msg3 slot according to 8.3 in 38.213
int temp_frame = get_fb_frame(frame, slot, *tda_list->list.array[i]->k2 + mu_delta, slots_per_frame, NTN_gNB_Koffset);
int temp_slot = get_fb_slot(slot, *tda_list->list.array[i]->k2 + mu_delta, slots_per_frame, NTN_gNB_Koffset);
if (fs->frame_type == TDD && !is_ul_slot(temp_slot, fs))
continue;
@@ -1026,7 +1025,7 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc,
int start, nr;
SLIV2SL(startSymbolAndLength, &start, &nr);
uint16_t msg3_mask = SL_to_bitmap(start, nr);
LOG_D(NR_MAC, "Check Msg3 TDA %d for slot %d: k2 %ld, S %d L %d\n", i, temp_slot, k2, start, nr);
LOG_D(NR_MAC, "Check Msg3 TDA %d for slot %d: k2 %ld, S %d L %d\n", i, temp_slot, *tda_list->list.array[i]->k2, start, nr);
/* if this start and length of this TDA cannot be fulfilled, skip */
if ((slot_mask & msg3_mask) != msg3_mask)
continue;
@@ -2133,7 +2132,7 @@ void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti)
NR_UEs_t *UE_info = &mac->UE_info;
NR_UE_info_t *UE = remove_UE_from_list(NR_NB_RA_PROC_MAX, UE_info->access_ue_list, rnti);
if (UE) {
delete_nr_ue_data(UE, &UE_info->uid_allocator);
delete_nr_ue_data(UE, mac, &UE_info->uid_allocator);
} else {
LOG_W(NR_MAC,"Call to release RA UE with rnti %04x, but not existing\n", rnti);
}

View File

@@ -9,6 +9,7 @@
#include "assertions.h"
#include "NR_MAC_gNB/nr_mac_gNB.h"
#include "NR_MAC_gNB/mac_proto.h"
#include "NR_MAC_gNB/nr_radio_config.h"
#include "common/utils/LOG/log.h"
#include "UTIL/OPT/opt.h"
#include "common/utils/nr/nr_common.h"

View File

@@ -11,6 +11,7 @@
#include "NR_MAC_COMMON/nr_mac.h"
#include "NR_MAC_gNB/nr_mac_gNB.h"
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "NR_MAC_gNB/nr_radio_config.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
/*TAG*/

View File

@@ -250,10 +250,10 @@ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_p
tda);
DevAssert(tda_info.valid_tda);
int K2 = tda_info.k2 + get_NTN_Koffset(scc);
int slots_frame = nr_mac->frame_structure.numb_slots_frame;
const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER;
const int sched_slot = (slot + K2) % slots_frame;
int NTN_gNB_Koffset = get_NTN_Koffset(scc);
const int sched_frame = get_fb_frame(frame, slot, tda_info.k2, slots_frame, NTN_gNB_Koffset);
const int sched_slot = get_fb_slot(slot, tda_info.k2, slots_frame, NTN_gNB_Koffset);
/* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE
* limitations). Note that if K2 or the TDD configuration is changed, below

View File

@@ -11,6 +11,7 @@
#include "NR_MAC_gNB/nr_mac_gNB.h"
#include "NR_MAC_gNB/mac_proto.h"
#include "NR_MAC_gNB/nr_radio_config.h"
#include "common/utils/bits.h"
#include "common/utils/LOG/log.h"
#include "UTIL/OPT/opt.h"
@@ -92,6 +93,18 @@ static const uint16_t cqi_table3[16][2] = {{0, 0},
{6, 6660},
{6, 7720}};
int get_fb_frame(int frame, int slot, int K, int n_slots_frame, int NTN_gNB_Koffset)
{
// K is the feedback time in slot
return (frame + ((slot + K + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER;
}
int get_fb_slot(int slot, int K, int n_slots_frame, int NTN_gNB_Koffset)
{
// K is the feedback time in slot
return (slot + K + NTN_gNB_Koffset) % n_slots_frame;
}
int get_ssbidx_from_beam(gNB_MAC_INST *mac, int beam_idx)
{
for (int i = 0; i < MAX_NUM_OF_SSB; i++)
@@ -2544,8 +2557,14 @@ NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP)
return NULL;
}
void delete_nr_ue_data(NR_UE_info_t *UE, uid_allocator_t *uia)
void delete_nr_ue_data(NR_UE_info_t *UE, gNB_MAC_INST *nrmac, uid_allocator_t *uia)
{
if (UE->sr_info.allocated)
nrmac->ul_rrc_info.sr_resources[UE->sr_info.resource][UE->sr_info.offset] = -1;
if (UE->csimeas_info.allocated) {
nrmac->ul_rrc_info.csimeas_resources[UE->csimeas_info.resource][UE->csimeas_info.offset] = -1;
nrmac->ul_rrc_info.csimeas_resources[UE->csimeas_info.resource][UE->csimeas_info.offset2] = -1;
}
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup);
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
@@ -3110,7 +3129,7 @@ bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
bool success = add_UE_to_list(MAX_MOBILES_PER_GNB, UE_info->connected_ue_list, UE);
if (!success) {
LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", UE->rnti);
delete_nr_ue_data(UE, &UE_info->uid_allocator);
delete_nr_ue_data(UE, nr_mac, &UE_info->uid_allocator);
return false;
}
@@ -3181,7 +3200,7 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti)
NR_UEs_t *UE_info = &nr_mac->UE_info;
NR_UE_info_t *UE = remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, UE_info->connected_ue_list, rnti);
if (UE)
delete_nr_ue_data(UE, &UE_info->uid_allocator);
delete_nr_ue_data(UE, nr_mac, &UE_info->uid_allocator);
else
nr_release_ra_UE(nr_mac, rnti);
}
@@ -3913,6 +3932,51 @@ void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_le
mac->mac_rrc.initial_ul_rrc_message_transfer(0, &ul_rrc_msg);
}
bool mac_ul_rrc_periodic_resources(gNB_MAC_INST *mac, NR_UE_info_t *UE, const NR_ServingCellConfigCommon_t *scc, int active_bwp)
{
int bwp_size = 0;
int bwp_start = 0;
const nr_mac_config_t *configuration = &mac->radio_config;
if(configuration->num_additional_bwps > 0 && active_bwp != 0) {
bwp_size = NRRIV2BW(configuration->bwp_config[active_bwp - 1].location_and_bw, MAX_BWP_SIZE);
bwp_start = NRRIV2PRBOFFSET(configuration->bwp_config[active_bwp - 1].location_and_bw, MAX_BWP_SIZE);
} else {
bwp_size = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
bwp_start = NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
}
bool sr_allocated = UE->sr_info.allocated; // allocation information of SR resource
bool sr = set_ul_periodic_resources(mac->ul_rrc_info.sr_resources,
configuration,
&UE->sr_info,
&mac->frame_structure,
false,
UE->uid,
bwp_start,
bwp_size,
mac->ul_rrc_info.sr_period);
if (sr) {
bool csi = set_ul_periodic_resources(mac->ul_rrc_info.csimeas_resources,
configuration,
&UE->csimeas_info,
&mac->frame_structure,
true,
UE->uid,
bwp_start,
bwp_size,
mac->ul_rrc_info.csimeas_period);
if (csi)
return true;
else if (!sr_allocated) {
// if it was a new allocation for SR but we can't allocate CSI we need to revert SR allocation
UE->sr_info.allocated = false;
mac->ul_rrc_info.sr_resources[UE->sr_info.resource][UE->sr_info.offset] = -1;
}
}
return false;
}
bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
{
NR_SCHED_ENSURE_LOCKED(&mac->sched_lock);
@@ -3939,13 +4003,24 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
int srb_id = 1;
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
int ssb_index = get_ssbidx_from_beam(mac, UE->UE_beam_index);
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config, ssb_index);
bool alloc = mac_ul_rrc_periodic_resources(mac, UE, scc, mac->radio_config.first_active_bwp);
NR_CellGroupConfig_t *cellGroupConfig = NULL;
if (alloc)
cellGroupConfig = get_initial_cellGroupConfig(UE->uid,
UE->sr_info,
UE->csimeas_info,
scc,
&mac->radio_config,
&mac->rlc_config,
ssb_index);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
UE->CellGroup = cellGroupConfig;
UE->local_bwp_id = mac->radio_config.first_active_bwp;
if (!cellGroupConfig)
if (!cellGroupConfig) {
LOG_W(NR_MAC, "Couldn't allocate RRC resources to the UE %04x, to be rejected\n", UE->rnti);
return true;
}
/* the cellGroup sent to CU specifies there is SRB1, so create it */
DevAssert(cellGroupConfig->rlc_BearerToAddModList->list.count == 1);
@@ -4065,20 +4140,21 @@ static bool verify_bwp_switch(const NR_UE_info_t *UE, const nr_mac_config_t *con
return false;
}
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id, bool new_beam)
void nr_mac_trigger_reconfiguration(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id, bool new_beam)
{
DevAssert(UE->CellGroup != NULL);
NR_CellGroupConfig_t *cellGroup_for_UE = NULL;
if (new_beam) {
UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
current_BWP->srs_Config = NULL;
int ssb_index = nrmac->common_channels[0].ssb_index[UE->UE_beam_index];
cellGroup_for_UE = update_cellGroupConfig_for_beam_switch(UE->CellGroup,
&nrmac->radio_config,
UE->capability,
nrmac->common_channels[0].ServingCellConfigCommon,
UE->uid,
current_BWP->pucch_Config,
UE->csimeas_info,
UE->current_DL_BWP.bwp_id,
ssb_index);
} else {
@@ -4089,11 +4165,19 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE,
else {
UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated
UE->local_bwp_id = new_bwp_id;
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[0].ServingCellConfigCommon;
bool alloc = mac_ul_rrc_periodic_resources(nrmac, UE, scc, new_bwp_id);
if (!alloc) {
LOG_E(NR_MAC, "Cannot switch to BWP %d. Couldn't allocate resources\n", new_bwp_id);
return;
}
int ssb_index = nrmac->common_channels[0].ssb_index[UE->UE_beam_index];
cellGroup_for_UE = update_cellGroupConfig_for_BWP_switch(UE->CellGroup,
&nrmac->radio_config,
UE->capability,
nrmac->common_channels[0].ServingCellConfigCommon,
UE->sr_info,
UE->csimeas_info,
UE->uid,
UE->current_DL_BWP.bwp_id,
new_bwp_id,

View File

@@ -187,6 +187,80 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frame, slot_t slot)
}
}
static int find_pucch_resource_index(const NR_PUCCH_Config_t *pucch_Config, int resset_idx, int pucch_idx)
{
// resset_idx 0 for f0 and f1, resset_idx 1 for f2 and f3
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[resset_idx];
const int n = pucchresset->resourceList.list.count;
int res_index = 0;
for (; res_index < n; res_index++)
if (*pucchresset->resourceList.list.array[res_index] == pucch_idx)
break;
AssertFatal(res_index < n, "PUCCH resource with index %d not found among PUCCH resources\n", pucch_idx);
return res_index;
}
static bool pucch23_vrb_occupation(gNB_MAC_INST *nrmac,
NR_PUCCH_Config_t *pucch_Config,
NR_sched_pucch_t *curr_pucch,
NR_beam_alloc_t beam,
int res_id,
int bwp_start,
int sched_frame,
int sched_slot)
{
const int n_slots_frame = nrmac->frame_structure.numb_slots_frame;
const int index = ul_buffer_index(sched_frame, sched_slot, n_slots_frame, nrmac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &nrmac->common_channels[0].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
const int m = pucch_Config->resourceToAddModList->list.count;
for (int j = 0; j < m; j++) {
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j];
if (pucchres->pucch_ResourceId != res_id)
continue;
int start = pucchres->startingPRB;
int len = 1;
uint64_t mask = 0;
switch(pucchres->format.present) {
case NR_PUCCH_Resource__format_PR_format2 :
len = pucchres->format.choice.format2->nrofPRBs;
mask = SL_to_bitmap(pucchres->format.choice.format2->startingSymbolIndex, pucchres->format.choice.format2->nrofSymbols);
curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI;
LOG_D(NR_MAC,
"%d.%d Allocating PUCCH format 2, startPRB %d, nPRB %d, simulHARQ %d, num_bits %d\n",
sched_frame,
sched_slot,
start,
len,
curr_pucch->simultaneous_harqcsi,
curr_pucch->csi_bits);
break;
case NR_PUCCH_Resource__format_PR_format3 :
len = pucchres->format.choice.format3->nrofPRBs;
mask = SL_to_bitmap(pucchres->format.choice.format3->startingSymbolIndex, pucchres->format.choice.format3->nrofSymbols);
curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI;
break;
case NR_PUCCH_Resource__format_PR_format4:
mask = SL_to_bitmap(pucchres->format.choice.format4->startingSymbolIndex, pucchres->format.choice.format4->nrofSymbols);
curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI;
break;
default:
AssertFatal(false, "Invalid PUCCH format type\n");
}
// verify resources are free
for (int i = start; i < start + len; ++i) {
if((vrb_map_UL[i + bwp_start] & mask) != 0) {
LOG_E(NR_MAC, "VRB MAP in %4d.%2d not free. Can't schedule CSI reporting on PUCCH.\n", sched_frame, sched_slot);
return false;
}
}
// reserve resources
for (int i = start; i < start + len; ++i)
vrb_map_UL[i + bwp_start] |= mask;
return true;
}
return false;
}
void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot)
{
const int CC_id = 0;
@@ -225,94 +299,43 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot)
// we schedule CSI reporting max_fb_time slots in advance
int period, offset;
csi_period_offset(csirep, NULL, &period, &offset);
const int sched_slot = (slot + ul_bwp->max_fb_time + NTN_gNB_Koffset) % n_slots_frame;
const int sched_frame = (frame + ((slot + ul_bwp->max_fb_time + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER;
const int sched_slot = get_fb_slot(slot, ul_bwp->max_fb_time, n_slots_frame, NTN_gNB_Koffset);
const int sched_frame = get_fb_frame(frame, slot, ul_bwp->max_fb_time, n_slots_frame, NTN_gNB_Koffset);
// prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0)
continue;
AssertFatal(is_ul_slot(sched_slot, &nrmac->frame_structure), "CSI reporting slot %d is not set for an uplink slot\n", sched_slot);
AssertFatal(is_ul_slot(sched_slot, &nrmac->frame_structure), "CSI reporting slot %d is not an uplink slot\n", sched_slot);
LOG_D(NR_MAC, "CSI reporting in frame %d slot %d CSI report ID %ld\n", sched_frame, sched_slot, csirep->reportConfigId);
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
const int n = pucchresset->resourceList.list.count;
int res_index = 0;
for (; res_index < n; res_index++)
if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource)
break;
AssertFatal(res_index < n,
"CSI pucch resource %ld not found among PUCCH resources\n", pucchcsires->pucch_Resource);
int res_index = find_pucch_resource_index(pucch_Config, 1, pucchcsires->pucch_Resource); // index 1 for F2
const int pucch_index = get_pucch_index(sched_frame, sched_slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
if (curr_pucch->active) {
LOG_E(NR_MAC, "CSI structure is scheduled in advance. It should be free!\n");
memset(curr_pucch, 0, sizeof(*curr_pucch));
}
// going through the list of PUCCH resources to find the one indexed by resource_id
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate CSI measurements on PUCCH in any available beam\n");
curr_pucch->beam_idx = beam.idx;
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
bool ret = pucch23_vrb_occupation(nrmac,
pucch_Config,
curr_pucch,
beam,
*pucchresset->resourceList.list.array[res_index],
ul_bwp->BWPStart,
sched_frame,
sched_slot);
AssertFatal(ret, "Resources not free to schedule CSI report\n");
curr_pucch->r_pucch = -1;
curr_pucch->frame = sched_frame;
curr_pucch->ul_slot = sched_slot;
curr_pucch->resource_indicator = res_index;
curr_pucch->csi_bits += nr_get_csi_bitlen(&UE->csi_report_template[csi_report_id]);
curr_pucch->active = true;
int bwp_start = ul_bwp->BWPStart;
// going through the list of PUCCH resources to find the one indexed by resource_id
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate CSI measurements on PUCCH in any available beam\n");
curr_pucch->beam_idx = beam.idx;
const int index = ul_buffer_index(sched_frame, sched_slot, n_slots_frame, nrmac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &nrmac->common_channels[0].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
const int m = pucch_Config->resourceToAddModList->list.count;
for (int j = 0; j < m; j++) {
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j];
if (pucchres->pucch_ResourceId != *pucchresset->resourceList.list.array[res_index])
continue;
int start = pucchres->startingPRB;
int len = 1;
uint64_t mask = 0;
switch(pucchres->format.present){
case NR_PUCCH_Resource__format_PR_format2:
len = pucchres->format.choice.format2->nrofPRBs;
mask = SL_to_bitmap(pucchres->format.choice.format2->startingSymbolIndex, pucchres->format.choice.format2->nrofSymbols);
curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI;
LOG_D(NR_MAC,
"%d.%d Allocating PUCCH format 2, startPRB %d, nPRB %d, simulHARQ %d, num_bits %d\n",
sched_frame,
sched_slot,
start,
len,
curr_pucch->simultaneous_harqcsi,
curr_pucch->csi_bits);
break;
case NR_PUCCH_Resource__format_PR_format3:
len = pucchres->format.choice.format3->nrofPRBs;
mask = SL_to_bitmap(pucchres->format.choice.format3->startingSymbolIndex, pucchres->format.choice.format3->nrofSymbols);
curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI;
break;
case NR_PUCCH_Resource__format_PR_format4:
mask = SL_to_bitmap(pucchres->format.choice.format4->startingSymbolIndex, pucchres->format.choice.format4->nrofSymbols);
curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI;
break;
default:
AssertFatal(0, "Invalid PUCCH format type\n");
}
// verify resources are free
for (int i = start; i < start + len; ++i) {
if((vrb_map_UL[i+bwp_start] & mask) != 0) {
LOG_E(NR_MAC,
"%4d.%2d VRB MAP in %4d.%2d not free. Can't schedule CSI reporting on PUCCH.\n",
frame,
slot,
sched_frame,
sched_slot);
memset(curr_pucch, 0, sizeof(*curr_pucch));
}
else
vrb_map_UL[i+bwp_start] |= mask;
}
}
}
}
}
@@ -1009,15 +1032,17 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, slot_t slot, c
T_INT(uci_234->rssi));
}
// TODO: handle SR
if (uci_234->pduBitmap & 0x1) {
if (uci_234->sr.sr_payload && uci_234->sr.sr_payload[0])
sched_ctrl->SR = true;
free(uci_234->sr.sr_payload);
}
if ((uci_234->pduBitmap >> 1) & 0x01) {
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01;
int rev_bit = uci_234->harq.harq_bit_len - 1 - harq_bit;
const int acknack = ((uci_234->harq.harq_payload[rev_bit >> 3]) >> (rev_bit & 7)) & 0x01;
NR_UE_harq_t *harq = find_harq(frame, slot, UE, RC.nrmac[mod_id]->dl_bler.harq_round_max);
if (!harq) {
LOG_E(NR_MAC, "UE %04x: Could not find a HARQ process at %4d.%2d!\n", UE->rnti, frame, slot);
@@ -1057,17 +1082,72 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, slot_t slot, c
NR_SCHED_UNLOCK(&nrmac->sched_lock);
}
static void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch, const int bwp_size, NR_sched_pucch_t *pucch)
static bool test_pucch0_vrb_occupation(const NR_PUCCH_Resource_t *resource,
uint16_t *vrb_map_UL,
const int bwp_start,
const int bwp_size)
{
if(r_pucch<0){
const NR_PUCCH_Resource_t *resource = ul_bwp->pucch_Config->resourceToAddModList->list.array[0];
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
pucch->second_hop_prb = resource->secondHopPRB!= NULL ? *resource->secondHopPRB : 0;
pucch->nr_of_symb = resource->format.choice.format0->nrofSymbols;
pucch->start_symb = resource->format.choice.format0->startingSymbolIndex;
pucch->prb_start = resource->startingPRB;
if (!resource)
return false;
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
// We assume initial cyclic shift is always 0 so different pucch resources can't overlap
// verifying occupation of PRBs for ACK/NACK on dedicated pucch
for (int l = 0; l < resource->format.choice.format0->nrofSymbols; l++) {
uint16_t symb = SL_to_bitmap(resource->format.choice.format0->startingSymbolIndex + l, 1);
int prb = (l == 1 && resource->secondHopPRB) ? *resource->secondHopPRB : resource->startingPRB;
AssertFatal(prb < bwp_size, "PUCCH0 PRB %d\n exceeds BWP size %d\n", prb, bwp_size);
if ((vrb_map_UL[bwp_start + prb] & symb) != 0) {
return false;
break;
}
}
else{
return true;
}
static NR_PUCCH_Resource_t *get_pucch_resource(const NR_PUCCH_Config_t *pucch_Config, const NR_PUCCH_ResourceId_t *resource_id)
{
DevAssert(resource_id);
DevAssert(pucch_Config->resourceSetToAddModList);
for (int n = 0; n < pucch_Config->resourceToAddModList->list.count; n++) {
NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[n];
if (resource->pucch_ResourceId == *resource_id)
return resource;
}
LOG_E(NR_MAC, "Couldn't find PUCCH resource with ID %ld\n", *resource_id);
return NULL;
}
static void set_pucch_allocation(const NR_PUCCH_Resource_t *resource, NR_sched_pucch_t *pucch, int resource_ind)
{
pucch->second_hop_prb = resource->secondHopPRB != NULL ? *resource->secondHopPRB : 0;
pucch->nr_of_symb = resource->format.choice.format0->nrofSymbols;
pucch->start_symb = resource->format.choice.format0->startingSymbolIndex;
pucch->prb_start = resource->startingPRB;
pucch->resource_indicator = resource_ind;
}
static bool find_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp,
uint16_t *vrb_map_UL,
const int r_pucch,
const int bwp_start,
const int bwp_size,
NR_sched_pucch_t *pucch)
{
if (r_pucch < 0) {
NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config;
// PUCCH resource set for F0 or 1 is the one with index 0
DevAssert(pucch_Config->resourceSetToAddModList);
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0];
for (int i = 0; i < pucchresset->resourceList.list.count; i++) {
NR_PUCCH_ResourceId_t *resource_id = pucchresset->resourceList.list.array[i];
NR_PUCCH_Resource_t *resource = get_pucch_resource(pucch_Config, resource_id);
if (test_pucch0_vrb_occupation(resource, vrb_map_UL, bwp_start, bwp_size)) {
set_pucch_allocation(resource, pucch, i);
return true; // we found a valid occasion (otherwise we try with the following one)
}
}
return false; // we couldn't find any valid occasion
} else {
int rsetindex = *ul_bwp->pucch_ConfigCommon->pucch_ResourceCommon;
set_r_pucch_parms(rsetindex,
r_pucch,
@@ -1076,43 +1156,27 @@ static void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch
&pucch->second_hop_prb,
&pucch->nr_of_symb,
&pucch->start_symb);
return true;
}
}
static bool test_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *vrb_map_UL, const int bwp_start)
static void set_reset_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *vrb_map_UL, const int bwp_start, bool set)
{
// We assume initial cyclic shift is always 0 so different pucch resources can't overlap
// verifying occupation of PRBs for ACK/NACK on dedicated pucch
for (int l=0; l<pucch->nr_of_symb; l++) {
uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1);
for (int l = 0; l < pucch->nr_of_symb; l++) {
uint16_t symb = SL_to_bitmap(pucch->start_symb + l, 1);
int prb;
if (l==1 && pucch->second_hop_prb != 0)
if (l == 1 && pucch->second_hop_prb != 0)
prb = pucch->second_hop_prb;
else
prb = pucch->prb_start;
if ((vrb_map_UL[bwp_start+prb] & symb) != 0) {
return false;
break;
}
}
return true;
}
static void set_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *vrb_map_UL, const int bwp_start)
{
for (int l=0; l<pucch->nr_of_symb; l++) {
uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1);
int prb;
if (l==1 && pucch->second_hop_prb != 0)
prb = pucch->second_hop_prb;
if (set)
vrb_map_UL[bwp_start + prb] |= symb;
else
prb = pucch->prb_start;
vrb_map_UL[bwp_start+prb] |= symb;
vrb_map_UL[bwp_start + prb] &= ~symb;
}
}
bool check_bits_vs_coderate_limit(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_resource)
static bool check_bits_vs_coderate_limit(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_resource)
{
int resource_id = get_pucch_resourceid(pucch_Config, O_uci, pucch_resource);
AssertFatal(pucch_Config->resourceToAddModList != NULL, "PUCCH resourceToAddModList is null\n");
@@ -1159,44 +1223,32 @@ bool check_bits_vs_coderate_limit(NR_PUCCH_Config_t *pucch_Config, int O_uci, in
// this function returns an index to NR_sched_pucch structure
// if the function returns -1 it was not possible to schedule acknack
int nr_acknack_scheduling(gNB_MAC_INST *mac,
NR_UE_info_t *UE,
frame_t frame,
slot_t slot,
int ue_beam,
int r_pucch,
int is_common)
int nr_acknack_scheduling(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frame, slot_t slot, int ue_beam, int r_pucch, int is_common)
{
/* we assume that this function is mutex-protected from outside. Since it is
* called often, don't try to lock every time */
const int CC_id = 0;
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
const int minfbtime = mac->radio_config.minRXTXTIME + NTN_gNB_Koffset;
const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
const frame_structure_t *fs = &mac->frame_structure;
const int n_slots_frame = fs->numb_slots_frame;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config;
const int bwp_start = ul_bwp->BWPStart;
const int bwp_size = ul_bwp->BWPSize;
nr_dci_format_t dci_format = NR_DL_DCI_FORMAT_1_0;
if(is_common == 0)
dci_format = UE->current_DL_BWP.dci_format;
uint8_t pdsch_to_harq_feedback[8];
int fb_size = get_pdsch_to_harq_feedback(pucch_Config, dci_format, pdsch_to_harq_feedback);
for (int f = 0; f < fb_size; f++) {
// can't schedule ACKNACK before minimum feedback time
if((pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) < minfbtime)
continue;
const int pucch_slot = (slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) % n_slots_frame;
const int pucch_slot = get_fb_slot(slot, pdsch_to_harq_feedback[f], n_slots_frame, NTN_gNB_Koffset);
// check if the slot is UL
if (fs->frame_type == TDD) {
int mod_slot = get_slot_idx_in_period(pucch_slot, fs);
@@ -1206,19 +1258,22 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
if (r_pucch >= 0 && is_mixed_slot(mod_slot, fs) && pc->tdd_slot_bitmap[mod_slot].num_ul_symbols < 2)
continue;
}
const int pucch_frame = (frame + ((slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER;
const int pucch_frame = get_fb_frame(frame, slot, pdsch_to_harq_feedback[f], n_slots_frame, NTN_gNB_Koffset);
// we store PUCCH resources according to slot, TDD configuration and size of the vector containing PUCCH structures
const int pucch_index = get_pucch_index(pucch_frame, pucch_slot, &mac->frame_structure, sched_ctrl->sched_pucch_size);
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
if (curr_pucch->active &&
curr_pucch->frame == pucch_frame &&
curr_pucch->ul_slot == pucch_slot) { // if there is already a PUCCH in given frame and slot
LOG_D(NR_MAC, "pucch_acknack DL %4d.%2d, UL_ACK %4d.%2d Bits already in current PUCCH: DAI_C %d CSI %d\n",
frame, slot, pucch_frame, pucch_slot, curr_pucch->dai_c, curr_pucch->csi_bits);
// we can't schedule if short pucch is already full
if (curr_pucch->csi_bits == 0 &&
curr_pucch->dai_c == 2)
continue;
// if there is already a PUCCH in given frame and slot
if (curr_pucch->active && curr_pucch->frame == pucch_frame && curr_pucch->ul_slot == pucch_slot) {
LOG_D(NR_MAC,
"pucch_acknack DL %4d.%2d, UL_ACK %4d.%2d Bits already in current PUCCH: SR %d DAI_C %d CSI %d\n",
frame,
slot,
pucch_frame,
pucch_slot,
curr_pucch->sr_flag,
curr_pucch->dai_c,
curr_pucch->csi_bits);
// if there is CSI but simultaneous HARQ+CSI is disable we can't schedule
if (curr_pucch->csi_bits > 0 && !curr_pucch->simultaneous_harqcsi)
continue;
@@ -1226,11 +1281,10 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
// according to PUCCH code rate (if not we search for another allocation)
// the number of bits in the check need to include possible SR (1 bit)
// and the ack/nack bit to be scheduled (1 bit)
// so the number of bits already scheduled in current pucch + 2
if (curr_pucch->csi_bits > 0
&& !check_bits_vs_coderate_limit(pucch_Config,
curr_pucch->csi_bits + curr_pucch->dai_c + 2,
curr_pucch->resource_indicator))
// so the number of bits already scheduled in current pucch + SR flag + 1
int tot_bits = curr_pucch->csi_bits + curr_pucch->dai_c + curr_pucch->sr_flag + 1;
if (curr_pucch->csi_bits + curr_pucch->dai_c > 2
&& !check_bits_vs_coderate_limit(pucch_Config, tot_bits, curr_pucch->resource_indicator))
continue;
// TODO temporarily limit ack/nak to 3 bits because of performances of polar for PUCCH (required for > 11 bits)
if (curr_pucch->csi_bits > 0 && curr_pucch->dai_c >= 3)
@@ -1239,12 +1293,43 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
// otherwise we can schedule in this active PUCCH
// no need to check VRB occupation because already done when PUCCH has been activated
curr_pucch->timing_indicator = f;
// if we already reached the limit for PUCCH F0 or 1, we need to switch to another format
if (curr_pucch->dai_c == 2 && curr_pucch->csi_bits == 0) {
if (!pucch_Config) // in common PUCCH we can transmit at most 2 bits
continue;
const int index = ul_buffer_index(pucch_frame, pucch_slot, n_slots_frame, mac->vrb_map_UL_size);
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, pucch_frame, pucch_slot, ue_beam, n_slots_frame);
AssertFatal(beam.idx >= 0, "Beam should have been already allocated when setting PUCCH0, so it should be available\n");
uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
// resetting PUCCH0 occupation
set_reset_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start, false);
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1];
bool ret = pucch23_vrb_occupation(mac,
pucch_Config,
curr_pucch,
beam,
*pucchresset->resourceList.list.array[curr_pucch->resource_indicator],
bwp_start,
pucch_frame,
pucch_slot);
if (!ret) { // if we can't allocate a PUCCH able to carry more than 2 bits we need to keep looking
set_reset_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start, true);
continue;
}
}
curr_pucch->dai_c++;
LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d CSI %d\n",
frame,slot,curr_pucch->frame,curr_pucch->ul_slot,pucch_index,f,curr_pucch->dai_c,curr_pucch->csi_bits);
LOG_D(NR_MAC,
"DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d CSI %d\n",
frame,
slot,
curr_pucch->frame,
curr_pucch->ul_slot,
pucch_index,
f,
curr_pucch->dai_c,
curr_pucch->csi_bits);
return pucch_index; // index of current PUCCH structure
}
else if (curr_pucch->active) {
} else if (curr_pucch->active) {
LOG_E(NR_MAC,
"current PUCCH inactive: curr_pucch frame.slot %d.%d not matching with computed frame.slot %d.%d\n",
curr_pucch->frame,
@@ -1252,10 +1337,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
pucch_frame,
pucch_slot);
memset(curr_pucch, 0, sizeof(*curr_pucch));
}
else { // unoccupied occasion
// checking if in ul_slot the resources potentially to be assigned to this PUCCH are available
set_pucch_allocation(ul_bwp, r_pucch, bwp_size, curr_pucch);
} else { // unoccupied occasion
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, pucch_frame, pucch_slot, ue_beam, n_slots_frame);
if (beam.idx < 0) {
LOG_D(NR_MAC,
@@ -1267,10 +1349,11 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
continue;
}
curr_pucch->beam_idx = beam.idx;
// checking if in ul_slot the resources potentially to be assigned to this PUCCH are available
const int index = ul_buffer_index(pucch_frame, pucch_slot, n_slots_frame, mac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
bool ret = test_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start);
if(!ret) {
bool valid = find_pucch_allocation(ul_bwp, vrb_map_UL, r_pucch, bwp_start, bwp_size, curr_pucch);
if(!valid) {
LOG_D(NR_MAC,
"DL %4d.%2d, UL_ACK %4d.%2d PRB resources for this occasion are already occupied, move to the following occasion\n",
frame,
@@ -1286,15 +1369,19 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
curr_pucch->ul_slot = pucch_slot;
curr_pucch->timing_indicator = f; // index in the list of timing indicators
curr_pucch->dai_c++;
curr_pucch->resource_indicator = 0; // each UE has dedicated PUCCH resources
curr_pucch->r_pucch=r_pucch;
LOG_D(NR_MAC, "DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d\n",
frame, slot, curr_pucch->frame, curr_pucch->ul_slot, pucch_index, f, curr_pucch->dai_c);
LOG_D(NR_MAC,
"DL %4d.%2d, UL_ACK %4d.%2d Scheduling ACK/NACK in PUCCH %d with timing indicator %d DAI %d\n",
frame,
slot,
curr_pucch->frame,
curr_pucch->ul_slot,
pucch_index,
f,
curr_pucch->dai_c);
// blocking resources for current PUCCH in VRB map
set_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start);
set_reset_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start, true);
return pucch_index; // index of current PUCCH structure
}
}
@@ -1302,15 +1389,13 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
return -1;
}
void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, slot_t slot)
{
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
if (!is_ul_slot(slot, &nrmac->frame_structure))
return;
const int CC_id = 0;
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
UE_iterator(nrmac->UE_info.connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
@@ -1322,67 +1407,66 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, slot_t slot)
if (!pucch_Config || !pucch_Config->schedulingRequestResourceToAddModList)
continue;
AssertFatal(pucch_Config->schedulingRequestResourceToAddModList->list.count>0,"NO SR configuration available");
for (int SR_resource_id = 0; SR_resource_id < pucch_Config->schedulingRequestResourceToAddModList->list.count;SR_resource_id++) {
NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id];
struct NR_PUCCH_Config__schedulingRequestResourceToAddModList *sr_list = pucch_Config->schedulingRequestResourceToAddModList;
AssertFatal(sr_list->list.count > 0, "NO SR configuration available");
for (int id = 0; id < sr_list->list.count; id++) {
NR_SchedulingRequestResourceConfig_t *srConf = sr_list->list.array[id];
int SR_period; int SR_offset;
find_period_offset_SR(SchedulingRequestResourceConfig, &SR_period, &SR_offset);
// convert to int to avoid underflow of uint
int sfn_sf = SFN * n_slots_frame + slot;
LOG_D(NR_MAC,"SR_resource_id %d: SR_period %d, SR_offset %d\n", SR_resource_id, SR_period, SR_offset);
find_period_offset_SR(srConf, &SR_period, &SR_offset);
// we schedule SR max_fb_time slots in advance
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
const int sched_slot = get_fb_slot(slot, ul_bwp->max_fb_time, n_slots_frame, NTN_gNB_Koffset);
const int sched_frame = get_fb_frame(SFN, slot, ul_bwp->max_fb_time, n_slots_frame, NTN_gNB_Koffset);
// convert to int to avoid underflow of uint
int sfn_sf = sched_frame * n_slots_frame + sched_slot;
LOG_D(NR_MAC, "SR_resource_id %d: SR_period %d, SR_offset %d\n", id, SR_period, SR_offset);
if ((sfn_sf - SR_offset) % SR_period != 0)
continue;
LOG_D(NR_MAC, "%4d.%2d Scheduling Request UE %04x identified\n", SFN, slot, UE->rnti);
NR_PUCCH_ResourceId_t *PucchResourceId = SchedulingRequestResourceConfig->resource;
int idx = -1;
NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0]; // set with formats 0,1
int n_list = pucchresset->resourceList.list.count;
for (int i=0; i<n_list; i++) {
if (*pucchresset->resourceList.list.array[i] == *PucchResourceId )
idx = i;
}
AssertFatal(idx > -1, "SR resource not found among PUCCH resources");
const int pucch_index = get_pucch_index(SFN, slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
AssertFatal(is_ul_slot(sched_slot, &nrmac->frame_structure), "SR slot %d is not set for an uplink slot\n", sched_slot);
LOG_D(NR_MAC, "%4d.%2d Scheduling Request UE %04x identified\n", sched_frame, sched_slot, UE->rnti);
NR_PUCCH_ResourceId_t *PucchResourceId = srConf->resource;
int idx = find_pucch_resource_index(pucch_Config, 0, *PucchResourceId); // index 0 for F0
const int pucch_index = get_pucch_index(sched_frame, sched_slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
if (curr_pucch->active && curr_pucch->frame == SFN && curr_pucch->ul_slot == slot && curr_pucch->resource_indicator == idx)
if (curr_pucch->active
&& curr_pucch->frame == sched_frame
&& curr_pucch->ul_slot == sched_slot
&& curr_pucch->resource_indicator == idx)
curr_pucch->sr_flag = true;
else if (curr_pucch->active) {
LOG_E(NR_MAC,
"current PUCCH inactive: curr_pucch frame.slot %d.%d not matching with computed frame.slot %d.%d\n",
curr_pucch->frame,
curr_pucch->ul_slot,
SFN,
slot);
sched_frame,
sched_slot);
memset(curr_pucch, 0, sizeof(*curr_pucch));
continue;
}
else {
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, SFN, slot, UE->UE_beam_index, n_slots_frame);
} else {
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info,
sched_frame,
sched_slot,
UE->UE_beam_index,
n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SR in any available beam\n");
const int index = ul_buffer_index(SFN, slot, n_slots_frame, nrmac->vrb_map_UL_size);
const int index = ul_buffer_index(sched_frame, sched_slot, n_slots_frame, nrmac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
const int bwp_start = ul_bwp->BWPStart;
const int bwp_size = ul_bwp->BWPSize;
set_pucch_allocation(ul_bwp, -1, bwp_size, curr_pucch);
bool ret = test_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start);
NR_PUCCH_Resource_t *resource = get_pucch_resource(pucch_Config, PucchResourceId);
bool ret = test_pucch0_vrb_occupation(resource, vrb_map_UL, bwp_start, bwp_size);
if (!ret) {
LOG_E(NR_MAC,"Cannot schedule SR. PRBs not available\n");
LOG_E(NR_MAC, "Cannot schedule SR. PRBs not available\n");
continue;
}
set_pucch_allocation(resource, curr_pucch, idx);
curr_pucch->beam_idx = beam.idx;
curr_pucch->frame = SFN;
curr_pucch->ul_slot = slot;
curr_pucch->frame = sched_frame;
curr_pucch->ul_slot = sched_slot;
curr_pucch->sr_flag = true;
curr_pucch->resource_indicator = idx;
curr_pucch->r_pucch = -1;
curr_pucch->active = true;
set_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start);
set_reset_pucch0_vrb_occupation(curr_pucch, vrb_map_UL, bwp_start, true);
}
}
}

View File

@@ -8,6 +8,7 @@
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "NR_MAC_gNB/nr_radio_config.h"
#include "executables/softmodem-common.h"
#include "common/utils/nr/nr_common.h"
#include "utils.h"
@@ -757,7 +758,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
UE->UE_sched_ctrl.ta_frame = (frame + 100) % MAX_FRAME_NUMBER;
if (!transition_ra_connected_nr_ue(mac, UE)) {
LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti);
delete_nr_ue_data(UE, &mac->UE_info.uid_allocator);
delete_nr_ue_data(UE, mac, &mac->UE_info.uid_allocator);
} else {
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti);
}
@@ -2541,8 +2542,8 @@ void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch)
int k2 = fsn_get_diff(*next, current) - koffset;
DevAssert(k2 > 0);
int slots_per_frame = nr_mac->frame_structure.numb_slots_frame;
int sched_frame = (frame + (slot + k2 + koffset) / slots_per_frame) % MAX_FRAME_NUMBER;
int sched_slot = (slot + k2 + koffset) % slots_per_frame;
int sched_frame = get_fb_frame(frame, slot, k2, slots_per_frame, koffset);
int sched_slot = get_fb_slot(slot, k2, slots_per_frame, koffset);
/* Check that at least one TDA can reach this slot, if not, no future slot is reachable either */
{

View File

@@ -28,7 +28,7 @@ int get_dl_slots_per_period(const frame_structure_t *fs);
int get_full_ul_slots_per_period(const frame_structure_t *fs);
int get_full_dl_slots_per_period(const frame_structure_t *fs);
int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed);
void delete_nr_ue_data(NR_UE_info_t *UE, uid_allocator_t *uia);
void delete_nr_ue_data(NR_UE_info_t *UE, gNB_MAC_INST *nrmac, uid_allocator_t *uia);
void mac_top_init_gNB(ngran_node_t node_type,
NR_ServingCellConfigCommon_t *scc,
@@ -179,13 +179,7 @@ void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, slot_t slotP);
void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot);
int nr_acknack_scheduling(gNB_MAC_INST *mac,
NR_UE_info_t *UE,
frame_t frameP,
slot_t slotP,
int beam_index,
int r_pucch,
int do_common);
int nr_acknack_scheduling(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frame, slot_t slot, int ue_beam, int r_pucch, int is_common);
int get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config,
nr_dci_format_t dci_format,
@@ -517,8 +511,9 @@ bool nr_mac_ue_is_active(const NR_UE_info_t *ue);
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing);
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl);
bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl);
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id, bool new_beam);
void config_ul_rrc_info(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, int scs, int bw);
void nr_mac_trigger_reconfiguration(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id, bool new_beam);
bool mac_ul_rrc_periodic_resources(gNB_MAC_INST *mac, NR_UE_info_t *UE, const NR_ServingCellConfigCommon_t *scc, int active_bwp);
bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c);
nr_lc_config_t *nr_mac_get_lc_config(NR_UE_sched_ctrl_t* sched_ctrl, int lcid);
@@ -584,4 +579,6 @@ bool nr_ul_check_phr(const nr_ul_sched_params_t *params,
uint16_t rbSize,
uint8_t mcs,
nr_ul_phr_advice_t *advice);
int get_fb_frame(int frame, int slot, int K, int n_slots_frame, int NTN_gNB_Koffset);
int get_fb_slot(int slot, int K, int n_slots_frame, int NTN_gNB_Koffset);
#endif /*__LAYER2_NR_MAC_PROTO_H__*/

View File

@@ -543,12 +543,29 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
const NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
const nr_mac_config_t *configuration = &mac->radio_config;
int ssb_index = get_ssbidx_from_beam(mac, UE->UE_beam_index);
bool alloc = mac_ul_rrc_periodic_resources(mac, UE, scc, mac->radio_config.first_active_bwp);
if (is_SA) {
cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config, ssb_index);
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame);
} else {
if (alloc) {
cellGroupConfig = get_initial_cellGroupConfig(UE->uid,
UE->sr_info,
UE->csimeas_info,
scc,
&mac->radio_config,
&mac->rlc_config,
ssb_index);
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame);
}
} else if (alloc) {
NR_UE_NR_Capability_t *cap = get_ue_nr_cap_from_cg_config_info(cgci);
cellGroupConfig = get_default_secondaryCellGroup(scc, cap, 1, 1, configuration, UE->uid, ssb_index);
cellGroupConfig = get_default_secondaryCellGroup(scc,
cap,
UE->sr_info,
UE->csimeas_info,
1,
1,
configuration,
UE->uid,
ssb_index);
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame);
// TODO: in NSA we assign capabilities here, otherwise outside => not logic
UE->capability = cap;
@@ -569,7 +586,7 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
DevAssert(res);
} else {
if (!add_new_UE_RA(mac, UE)) {
delete_nr_ue_data(UE, &mac->UE_info.uid_allocator);
delete_nr_ue_data(UE, mac, &mac->UE_info.uid_allocator);
LOG_E(NR_MAC, "UE list full while creating new UE\n");
return NULL;
}

View File

@@ -19,6 +19,7 @@
#include "NR_MAC_gNB/mac_proto.h"
#include "NR_MAC_gNB/mac_rrc_ul.h"
#include "NR_MAC_gNB/nr_mac_gNB.h"
#include "NR_MAC_gNB/nr_radio_config.h"
#include "NR_PHY_INTERFACE/NR_IF_Module.h"
#include "NR_RLC-BearerConfig.h"
#include "NR_RadioBearerConfig.h"
@@ -358,13 +359,19 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac)
NR_UEs_t *UE_info = &mac->UE_info;
for (int i = 0; i < sizeofArray(UE_info->connected_ue_list); ++i)
if (UE_info->connected_ue_list[i])
delete_nr_ue_data(UE_info->connected_ue_list[i], &UE_info->uid_allocator);
delete_nr_ue_data(UE_info->connected_ue_list[i], mac, &UE_info->uid_allocator);
for (int i = 0; i < sizeofArray(UE_info->access_ue_list); ++i)
if (UE_info->access_ue_list[i])
delete_nr_ue_data(UE_info->access_ue_list[i], &UE_info->uid_allocator);
delete_nr_ue_data(UE_info->access_ue_list[i], mac, &UE_info->uid_allocator);
if (mac->f1_config.setup_resp)
free_f1ap_setup_response(mac->f1_config.setup_resp);
free(mac->f1_config.setup_resp);
for (int i = 0; i < mac->ul_rrc_info.max_num_res; i++) {
free(mac->ul_rrc_info.csimeas_resources[i]);
free(mac->ul_rrc_info.sr_resources[i]);
}
free(mac->ul_rrc_info.csimeas_resources);
free(mac->ul_rrc_info.sr_resources);
}
void nr_mac_send_f1_setup_req(void)

View File

@@ -50,7 +50,6 @@
#include "NR_BCCH-BCH-Message.h"
#include "NR_CellGroupConfig.h"
#include "NR_BCCH-DL-SCH-Message.h"
#include "nr_radio_config.h"
/* PHY */
#include "time_meas.h"
@@ -785,6 +784,14 @@ typedef struct measgap_config {
int mgl_slots;
} measgap_config_t;
typedef struct NR_UE_UL_RRC_info {
bool allocated;
int resource;
int offset;
int offset2;
int period;
} NR_UE_UL_RRC_info_t;
/*! \brief UE list used by gNB to order UEs/CC for scheduling*/
typedef struct NR_UE_info {
rnti_t rnti;
@@ -816,6 +823,8 @@ typedef struct NR_UE_info {
long pdsch_HARQ_ACK_Codebook;
bool is_redcap;
bool reestablish_rlc;
NR_UE_UL_RRC_info_t sr_info;
NR_UE_UL_RRC_info_t csimeas_info;
NR_RA_t *ra;
// 3GPP mandates that BWPs are enumerated consecutively, but we only send one (dedicated)
// BWP to the UE (and modify that BWP on reconfiguration); consequently, the BWP ID for a
@@ -1153,6 +1162,14 @@ typedef struct NR_du_stats {
uint32_t pusch_mcs_dist[8][2][32];
} NR_du_stats_t;
typedef struct {
int **sr_resources;
int **csimeas_resources;
int sr_period;
int csimeas_period;
int max_num_res;
} NR_UL_RRC_res_list_t;
/*! \brief top level eNB MAC structure */
typedef struct gNB_MAC_INST_s {
/// Ethernet parameters for northbound midhaul interface
@@ -1211,6 +1228,7 @@ typedef struct gNB_MAC_INST_s {
time_stats_t rx_ulsch_sdu; // include rlc_data_ind
NR_beam_info_t beam_info;
NR_UL_RRC_res_list_t ul_rrc_info;
/// maximum number of slots before a UE will be scheduled ULSCH automatically
uint32_t ulsch_max_frame_inactivity;

View File

@@ -16,7 +16,6 @@
#include "assertions.h"
#include "common/openairinterface5g_limits.h"
#include "common/utils/T/T.h"
#include "common/utils/nr/nr_common.h"
#include "constr_TYPE.h"
#include "executables/softmodem-common.h"
#include "oai_asn1.h"
@@ -32,7 +31,8 @@
#include "xer_encoder.h"
#define NR_MAX_SUPPORTED_DL_LAYERS 4
#define MAX_PUCCH_PER_SET 8
#define MAX_PUCCH_RESOURCES 128
/* Default values for measurement gap configuration */
#define DEFAULT_MGRP NR_GapConfig__mgrp_ms160
#define DEFAULT_MGTA NR_GapConfig__mgta_ms0dot5
@@ -204,27 +204,6 @@ static int get_pucch2_size(const int num_ant_ports)
return (num_ant_ports <= 4 ? 8 : 12);
}
static int get_nb_pucch2_per_slot(const NR_ServingCellConfigCommon_t *scc, int bwp_size, const nr_pdsch_AntennaPorts_t *ap)
{
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing];
int ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0) : n_slots_frame;
int n_slots_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame;
int max_meas_report_period = 320; // slots
int max_csi_reports = MAX_MOBILES_PER_GNB << 1; // 2 reports per UE (RSRP and RI-PMI-CQI)
int available_report_occasions = max_meas_report_period * ul_slots_period / n_slots_period;
int nb_pucch2 = (max_csi_reports / (available_report_occasions + 1)) + 1;
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
// in current implementation we need (nb_pucch2 * pucch2_size) prbs for PUCCH2
// and MAX_MOBILES_PER_GNB prbs for PUCCH1
// checked for validity in verify_radio_configuration
AssertFatal((nb_pucch2 * pucch2_size) + MAX_MOBILES_PER_GNB <= bwp_size,
"Cannot allocate all required PUCCH resources for max number of %d UEs in BWP with %d PRBs\n",
MAX_MOBILES_PER_GNB,
bwp_size);
return nb_pucch2;
}
NR_SearchSpace_t *rrc_searchspace_config(bool is_common,
int searchspaceid,
int coresetid,
@@ -1226,32 +1205,26 @@ static void set_dl_DataToUL_ACK(NR_PUCCH_Config_t *pucch_Config, int min_feedbac
}
// PUCCH resource set 0 for configuration with O_uci <= 2 bits and/or a positive or negative SR (section 9.2.1 of 38.213)
static void config_pucch_resset0(const NR_ServingCellConfigCommon_t *scc,
NR_PUCCH_Config_t *pucch_Config,
int uid,
int curr_bwp,
const NR_UE_NR_Capability_t *uecap,
const nr_pdsch_AntennaPorts_t *ap)
static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config,
NR_PUCCH_ResourceSet_t *pucchresset,
int id,
const nr_pdsch_AntennaPorts_t *ap,
const NR_UE_NR_Capability_t *uecap)
{
NR_PUCCH_ResourceSet_t *pucchresset = calloc(1,sizeof(*pucchresset));
pucchresset->pucch_ResourceSetId = 0;
NR_PUCCH_ResourceId_t *pucchid = calloc(1,sizeof(*pucchid));
*pucchid = 0;
asn1cSeqAdd(&pucchresset->resourceList.list,pucchid);
pucchresset->maxPayloadSize = NULL;
NR_PUCCH_ResourceId_t *pucchid = calloc(1, sizeof(*pucchid));
*pucchid = id;
asn1cSeqAdd(&pucchresset->resourceList.list, pucchid);
if(uecap) {
long *pucch_F0_2WithoutFH = uecap->phy_Parameters.phy_ParametersFRX_Diff->pucch_F0_2WithoutFH;
AssertFatal(pucch_F0_2WithoutFH == NULL,"UE does not support PUCCH F0 without frequency hopping. Current configuration is without FH\n");
AssertFatal(!pucch_F0_2WithoutFH, "UE doesn't support PUCCH F0 without frequency hopping. In OAI PUCCH0 is without FH.\n");
}
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
NR_PUCCH_Resource_t *pucchres0 = calloc(1,sizeof(*pucchres0));
pucchres0->pucch_ResourceId = *pucchid;
int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp, ap);
pucchres0->startingPRB = (pucch2_size * num_pucch2) + uid;
pucchres0->startingPRB = pucch2_size * id;
// checked for validity in verify_radio_configuration
AssertFatal(pucchres0->startingPRB < curr_bwp, "Not enough resources in current BWP (size %d) to allocate uid %d\n", curr_bwp, uid);
pucchres0->intraSlotFrequencyHopping = NULL;
pucchres0->secondHopPRB = NULL;
pucchres0->format.present = NR_PUCCH_Resource__format_PR_format0;
@@ -1259,37 +1232,30 @@ static void config_pucch_resset0(const NR_ServingCellConfigCommon_t *scc,
pucchres0->format.choice.format0->initialCyclicShift = 0;
pucchres0->format.choice.format0->nrofSymbols = 1;
pucchres0->format.choice.format0->startingSymbolIndex = 13;
asn1cSeqAdd(&pucch_Config->resourceToAddModList->list,pucchres0);
asn1cSeqAdd(&pucch_Config->resourceSetToAddModList->list,pucchresset);
asn1cSeqAdd(&pucch_Config->resourceToAddModList->list, pucchres0);
}
// PUCCH resource set 1 for configuration with O_uci > 2 bits (currently format2)
static void config_pucch_resset1(const NR_ServingCellConfigCommon_t *scc,
NR_PUCCH_Config_t *pucch_Config,
int uid,
int curr_bwp,
const NR_UE_NR_Capability_t *uecap,
const nr_pdsch_AntennaPorts_t *ap)
static void config_pucch_resset1(NR_PUCCH_Config_t *pucch_Config,
NR_PUCCH_ResourceSet_t *pucchresset,
int id,
const nr_pdsch_AntennaPorts_t *ap,
const NR_UE_NR_Capability_t *uecap)
{
NR_PUCCH_ResourceSet_t *pucchresset=calloc(1,sizeof(*pucchresset));
pucchresset->pucch_ResourceSetId = 1;
NR_PUCCH_ResourceId_t *pucchressetid=calloc(1,sizeof(*pucchressetid));
*pucchressetid = 2;
asn1cSeqAdd(&pucchresset->resourceList.list,pucchressetid);
pucchresset->maxPayloadSize = NULL;
NR_PUCCH_ResourceId_t *pucchressetid = calloc(1, sizeof(*pucchressetid));
*pucchressetid = (MAX_PUCCH_RESOURCES / 2) + id;
asn1cSeqAdd(&pucchresset->resourceList.list, pucchressetid);
if(uecap) {
long *pucch_F0_2WithoutFH = uecap->phy_Parameters.phy_ParametersFRX_Diff->pucch_F0_2WithoutFH;
AssertFatal(pucch_F0_2WithoutFH == NULL,"UE does not support PUCCH F2 without frequency hopping. Current configuration is without FH\n");
AssertFatal(!pucch_F0_2WithoutFH, "UE does not support PUCCH2 without frequency hopping. In OAI PUCCH2 is without FH\n");
}
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
NR_PUCCH_Resource_t *pucchres2 = calloc(1,sizeof(*pucchres2));
pucchres2->pucch_ResourceId = *pucchressetid;
int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp, ap);
pucchres2->startingPRB = pucch2_size * (uid % num_pucch2);
pucchres2->startingPRB = pucch2_size * id;
pucchres2->intraSlotFrequencyHopping = NULL;
pucchres2->secondHopPRB = NULL;
pucchres2->format.present = NR_PUCCH_Resource__format_PR_format2;
@@ -1297,10 +1263,11 @@ static void config_pucch_resset1(const NR_ServingCellConfigCommon_t *scc,
pucchres2->format.choice.format2->nrofPRBs = pucch2_size;
pucchres2->format.choice.format2->nrofSymbols = 1;
pucchres2->format.choice.format2->startingSymbolIndex = 13;
asn1cSeqAdd(&pucch_Config->resourceToAddModList->list,pucchres2);
asn1cSeqAdd(&pucch_Config->resourceSetToAddModList->list,pucchresset);
asn1cSeqAdd(&pucch_Config->resourceToAddModList->list, pucchres2);
}
static void config_pucch_f2(NR_PUCCH_Config_t *pucch_Config)
{
pucch_Config->format2 = calloc(1,sizeof(*pucch_Config->format2));
pucch_Config->format2->present = NR_SetupRelease_PUCCH_FormatConfig_PR_setup;
NR_PUCCH_FormatConfig_t *pucchfmt2 = calloc(1,sizeof(*pucchfmt2));
@@ -1311,7 +1278,6 @@ static void config_pucch_resset1(const NR_ServingCellConfigCommon_t *scc,
*pucchfmt2->maxCodeRate = NR_PUCCH_MaxCodeRate_zeroDot15;
pucchfmt2->nrofSlots = NULL;
pucchfmt2->pi2BPSK = NULL;
// to check UE capabilities for that in principle
pucchfmt2->simultaneousHARQ_ACK_CSI = calloc(1,sizeof(*pucchfmt2->simultaneousHARQ_ACK_CSI));
*pucchfmt2->simultaneousHARQ_ACK_CSI = NR_PUCCH_FormatConfig__simultaneousHARQ_ACK_CSI_true;
@@ -1354,67 +1320,62 @@ static void set_pucch_power_config(NR_PUCCH_Config_t *pucch_Config)
asn1cSeqAdd(&pucch_Config->spatialRelationInfoToAddModList->list,pucchspatial);
}
static void set_SR_periodandoffset(NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig, int scs)
static void set_SR_periodandoffset(NR_SchedulingRequestResourceConfig_t *srResourceConfig, NR_UE_UL_RRC_info_t sr_info)
{
const frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
int sr_slot = 1; // in FDD SR in slot 1
if (fs->frame_type == TDD)
sr_slot = get_first_ul_slot(fs, true);
schedulingRequestResourceConfig->periodicityAndOffset = calloc(1,sizeof(*schedulingRequestResourceConfig->periodicityAndOffset));
if(sr_slot < 10 && scs < NR_SubcarrierSpacing_kHz60){
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl10 = sr_slot;
int period = sr_info.period;
srResourceConfig->periodicityAndOffset = calloc(1, sizeof(*srResourceConfig->periodicityAndOffset));
struct NR_SchedulingRequestResourceConfig__periodicityAndOffset *periodicityAndOffset = srResourceConfig->periodicityAndOffset;
if(period == 10) {
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10;
periodicityAndOffset->choice.sl10 = sr_info.offset;
return;
}
else if(sr_slot < 20 && scs < NR_SubcarrierSpacing_kHz120){
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl20 = sr_slot;
} else if(period == 20) {
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20;
periodicityAndOffset->choice.sl20 = sr_info.offset;
return;
}
else if(sr_slot < 40){
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl40 = sr_slot;
} else if(period == 40) {
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40;
periodicityAndOffset->choice.sl40 = sr_info.offset;
return;
}
else if(sr_slot < 80 || scs == NR_SubcarrierSpacing_kHz15){
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl80 = sr_slot;
} else if(period == 80) {
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80;
periodicityAndOffset->choice.sl80 = sr_info.offset;
return;
}
else if(sr_slot < 160 || scs == NR_SubcarrierSpacing_kHz30){
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl160 = sr_slot;
} else if(period == 160) {
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160;
periodicityAndOffset->choice.sl160 = sr_info.offset;
return;
}
else if(sr_slot < 320 || scs == NR_SubcarrierSpacing_kHz60){
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl320 = sr_slot;
} else if(period == 320) {
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320;
periodicityAndOffset->choice.sl320 = sr_info.offset;
return;
}
else {
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640;
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl640 = sr_slot;
} else {
periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640;
periodicityAndOffset->choice.sl640 = sr_info.offset;
}
}
static void scheduling_request_config(NR_PUCCH_Config_t *pucch_Config, int scs)
static int get_pucch_start_idx(int bwp_start, int pucch2_size)
{
// format with <=2 bits in pucch resource set 0
NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0];
// assigning the 1st pucch resource in the set to scheduling request
NR_PUCCH_ResourceId_t *pucchressetid = pucchresset->resourceList.list.array[0];
return bwp_start / pucch2_size + (bwp_start % pucch2_size > 0);
}
pucch_Config->schedulingRequestResourceToAddModList = calloc(1,sizeof(*pucch_Config->schedulingRequestResourceToAddModList));
NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig = calloc(1,sizeof(*schedulingRequestResourceConfig));
static int get_num_pucch(int bwp_start, int bwp_size, int pucch2_size)
{
int start_prb = ceil(bwp_start / pucch2_size) * pucch2_size; // first PRB of first valid group
int available = bwp_start + bwp_size - start_prb; // PRBs from there to end of BWP
return min(MAX_PUCCH_PER_SET, available / pucch2_size);
}
static void scheduling_request_config(NR_PUCCH_Config_t *pucch_Config, NR_UE_UL_RRC_info_t sr_info)
{
pucch_Config->schedulingRequestResourceToAddModList = calloc(1, sizeof(*pucch_Config->schedulingRequestResourceToAddModList));
NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig = calloc(1, sizeof(*schedulingRequestResourceConfig));
schedulingRequestResourceConfig->schedulingRequestResourceId = 1;
schedulingRequestResourceConfig->schedulingRequestID = 0;
set_SR_periodandoffset(schedulingRequestResourceConfig, scs);
set_SR_periodandoffset(schedulingRequestResourceConfig, sr_info);
schedulingRequestResourceConfig->resource = calloc(1,sizeof(*schedulingRequestResourceConfig->resource));
*schedulingRequestResourceConfig->resource = *pucchressetid;
*schedulingRequestResourceConfig->resource = sr_info.resource;
asn1cSeqAdd(&pucch_Config->schedulingRequestResourceToAddModList->list,schedulingRequestResourceConfig);
}
@@ -1875,9 +1836,39 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t
return bwp;
}
static NR_PUCCH_Config_t *config_pucch(const NR_UE_NR_Capability_t *uecap,
int bwp_start,
int bwp_size,
const nr_pdsch_AntennaPorts_t *ap,
NR_UE_UL_RRC_info_t sr_info)
{
NR_PUCCH_Config_t *pucch_Config = calloc_or_fail(1, sizeof(*pucch_Config));
pucch_Config->resourceSetToAddModList = calloc_or_fail(1, sizeof(*pucch_Config->resourceSetToAddModList));
pucch_Config->resourceSetToReleaseList = NULL;
pucch_Config->resourceToAddModList = calloc_or_fail(1, sizeof(*pucch_Config->resourceToAddModList));
pucch_Config->resourceToReleaseList = NULL;
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
int pucch_start_idx = get_pucch_start_idx(bwp_start, pucch2_size);
int num_pucch = get_num_pucch(bwp_start, bwp_size, pucch2_size);
NR_PUCCH_ResourceSet_t *pucchresset0 = calloc_or_fail(1, sizeof(*pucchresset0));
pucchresset0->pucch_ResourceSetId = 0;
for (int i = 0; i < num_pucch; i++)
config_pucch_resset0(pucch_Config, pucchresset0, i + pucch_start_idx, ap, uecap);
asn1cSeqAdd(&pucch_Config->resourceSetToAddModList->list, pucchresset0);
NR_PUCCH_ResourceSet_t *pucchresset1 = calloc_or_fail(1, sizeof(*pucchresset1));
pucchresset1->pucch_ResourceSetId = 1;
for (int i = 0; i < num_pucch; i++)
config_pucch_resset1(pucch_Config, pucchresset1, i + pucch_start_idx, ap, uecap);
config_pucch_f2(pucch_Config);
asn1cSeqAdd(&pucch_Config->resourceSetToAddModList->list, pucchresset1);
scheduling_request_config(pucch_Config, sr_info);
return pucch_Config;
}
static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
int uid,
int maxMIMO_Layers,
NR_UE_UL_RRC_info_t sr_info,
const nr_mac_config_t *configuration,
const NR_ServingCellConfigCommon_t *scc,
const NR_UE_NR_Capability_t *uecap)
@@ -1896,7 +1887,6 @@ static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
ubwp->bwp_Common->genericParameters.cyclicPrefix = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.cyclicPrefix;
}
int curr_bwp = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE);
ubwp->bwp_Common->rach_ConfigCommon = is_SA ? NULL : clone_rach_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon);
ubwp->bwp_Common->pusch_ConfigCommon = clone_pusch_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon);
ubwp->bwp_Common->pucch_ConfigCommon = CALLOC(1,sizeof(struct NR_SetupRelease_PUCCH_ConfigCommon));
@@ -1912,25 +1902,20 @@ static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA,
ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated));
}
int bwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
int bwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
ubwp->bwp_Dedicated->pucch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pucch_Config));
ubwp->bwp_Dedicated->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup;
NR_PUCCH_Config_t *pucch_Config = calloc(1,sizeof(*pucch_Config));
ubwp->bwp_Dedicated->pucch_Config->choice.setup = pucch_Config;
pucch_Config->resourceSetToAddModList = calloc(1,sizeof(*pucch_Config->resourceSetToAddModList));
pucch_Config->resourceSetToReleaseList = NULL;
pucch_Config->resourceToAddModList = calloc(1,sizeof(*pucch_Config->resourceToAddModList));
pucch_Config->resourceToReleaseList = NULL;
config_pucch_resset0(scc, pucch_Config, uid, curr_bwp, uecap, &configuration->pdsch_AntennaPorts);
config_pucch_resset1(scc, pucch_Config, uid, curr_bwp, uecap, &configuration->pdsch_AntennaPorts);
NR_PUCCH_Config_t *pucch_Config = config_pucch(uecap, bwp_start, bwp_size, &configuration->pdsch_AntennaPorts, sr_info);
set_pucch_power_config(pucch_Config);
scheduling_request_config(pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing);
ubwp->bwp_Dedicated->pucch_Config->choice.setup = pucch_Config;
set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME);
ubwp->bwp_Dedicated->pusch_Config = config_pusch(configuration, scc, uecap);
ubwp->bwp_Dedicated->srs_Config = get_config_srs(scc,
NULL,
curr_bwp,
bwp_size,
uid,
ubwp->bwp_Id,
maxMIMO_Layers,
@@ -1952,46 +1937,34 @@ static void set_phr_config(NR_MAC_CellGroupConfig_t *mac_CellGroupConfig)
mac_CellGroupConfig->phr_Config->choice.setup->phr_Tx_PowerFactorChange = NR_PHR_Config__phr_Tx_PowerFactorChange_dB1;
}
static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc,
NR_CSI_ReportConfig_t *csirep,
int uid,
int curr_bwp,
const nr_pdsch_AntennaPorts_t *antennaports,
bool is_rsrp)
static void set_csi_meas_periodicity(NR_CSI_ReportConfig_t *csirep, NR_UE_UL_RRC_info_t csi_info, bool is_rsrp)
{
const int ideal_period = set_ideal_period(true);
const int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp, antennaports);
const int idx = (uid * 2 / num_pucch2) + is_rsrp;
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
int offset = get_ul_slot_offset(fs, idx, true);
LOG_D(NR_MAC, "set_csi_meas_periodicity: uid = %d, offset = %d, ideal_period = %d", uid, offset, ideal_period);
// checked for validity in verify_radio_configuration
AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n");
if (check_periodicity(4, ideal_period, fs)) {
int offset = is_rsrp ? csi_info.offset : csi_info.offset2;
if (csi_info.period == 4) {
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots4;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4 = offset;
} else if (check_periodicity(5, ideal_period, fs)) {
} else if (csi_info.period == 5) {
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots5;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5 = offset;
} else if (check_periodicity(8, ideal_period, fs)) {
} else if (csi_info.period == 8) {
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots8;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8 = offset;
} else if (check_periodicity(10, ideal_period, fs)) {
} else if (csi_info.period == 10) {
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots10;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10 = offset;
} else if (check_periodicity(16, ideal_period, fs)) {
} else if (csi_info.period == 16) {
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots16;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16 = offset;
} else if (check_periodicity(20, ideal_period, fs)) {
} else if (csi_info.period == 20) {
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots20;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20 = offset;
} else if (check_periodicity(40, ideal_period, fs)) {
} else if (csi_info.period == 40) {
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots40;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40 = offset;
} else if (check_periodicity(80, ideal_period, fs)) {
} else if (csi_info.period == 80) {
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots80;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80 = offset;
} else if (check_periodicity(160, ideal_period, fs)) {
} else if (csi_info.period == 160) {
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots160;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160 = offset;
} else {
@@ -2109,14 +2082,12 @@ static NR_CodebookConfig_t *config_csi_codebook(const nr_pdsch_AntennaPorts_t *a
}
static void config_csi_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
const NR_ServingCellConfigCommon_t *servingcellconfigcommon,
NR_PUCCH_CSI_Resource_t *pucchcsires,
struct NR_SetupRelease_PDSCH_Config *pdsch_Config,
const nr_pdsch_AntennaPorts_t *antennaports,
NR_UE_UL_RRC_info_t csi_info,
const int max_layers,
int rep_id,
int uid,
int curr_bwp)
int rep_id)
{
int resource_id = -1;
int im_id = -1;
@@ -2145,7 +2116,7 @@ static void config_csi_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
csirep->nzp_CSI_RS_ResourcesForInterference = NULL;
csirep->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic;
csirep->reportConfigType.choice.periodic = calloc(1, sizeof(*csirep->reportConfigType.choice.periodic));
set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, antennaports, false);
set_csi_meas_periodicity(csirep, csi_info, false);
asn1cSeqAdd(&csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list, pucchcsires);
csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI;
csirep->reportQuantity.choice.cri_RI_PMI_CQI = (NULL_t)0;
@@ -2208,9 +2179,8 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
const NR_ServingCellConfigCommon_t *servingcellconfigcommon,
NR_PUCCH_CSI_Resource_t *pucchcsires,
const nr_mac_config_t *configuration,
NR_UE_UL_RRC_info_t csi_info,
int rep_id,
int uid,
int curr_bwp,
uint64_t ssb_bitmap)
{
int resource_id = -1;
@@ -2239,7 +2209,7 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
csirep->nzp_CSI_RS_ResourcesForInterference = NULL;
csirep->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic;
csirep->reportConfigType.choice.periodic = calloc(1, sizeof(*csirep->reportConfigType.choice.periodic));
set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, pdschap, true);
set_csi_meas_periodicity(csirep, csi_info, true);
asn1cSeqAdd(&csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list, pucchcsires);
if (configuration->report_type == SSB_SINR) {
csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_none;
@@ -3354,36 +3324,30 @@ static void fill_harq_IEs(NR_ServingCellConfig_t *scc, int num_dlharq, int num_u
static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellConfigCommon_t *scc,
const nr_mac_config_t *configuration,
NR_UE_UL_RRC_info_t sr_info,
int maxMIMO_Layers,
const NR_UE_NR_Capability_t *uecap,
int id)
{
NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1, sizeof(*initialUplinkBWP));
NR_BWP_t *genericParameters = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
int curr_bwp = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
int bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
int bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
initialUplinkBWP->pucch_Config = calloc(1, sizeof(*initialUplinkBWP->pucch_Config));
initialUplinkBWP->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup;
NR_PUCCH_Config_t *pucch_Config = calloc(1, sizeof(*pucch_Config));
initialUplinkBWP->pucch_Config->choice.setup = pucch_Config;
pucch_Config->resourceSetToAddModList = calloc(1, sizeof(*pucch_Config->resourceSetToAddModList));
pucch_Config->resourceSetToReleaseList = NULL;
pucch_Config->resourceToAddModList = calloc(1, sizeof(*pucch_Config->resourceToAddModList));
pucch_Config->resourceToReleaseList = NULL;
config_pucch_resset0(scc, pucch_Config, id, curr_bwp, uecap, &configuration->pdsch_AntennaPorts);
config_pucch_resset1(scc, pucch_Config, id, curr_bwp, uecap, &configuration->pdsch_AntennaPorts);
NR_PUCCH_Config_t *pucch_Config = config_pucch(NULL, bwp_start, bwp_size, &configuration->pdsch_AntennaPorts, sr_info);
set_pucch_power_config(pucch_Config);
initialUplinkBWP->pucch_Config->choice.setup = pucch_Config;
initialUplinkBWP->pusch_Config = config_pusch(configuration, scc, uecap);
initialUplinkBWP->srs_Config = get_config_srs(scc,
uecap,
curr_bwp,
bwp_size,
id,
0,
maxMIMO_Layers,
configuration->minRXTXTIME,
configuration->do_SRS);
scheduling_request_config(pucch_Config, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing);
set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME);
return initialUplinkBWP;
}
@@ -3443,6 +3407,8 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
const nr_mac_config_t *configuration,
const NR_PUCCH_Config_t *pucch_Config,
NR_UE_UL_RRC_info_t csi_info,
int uid,
int bwp_id,
uint64_t bitmap,
@@ -3502,8 +3468,6 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
csires1->bwp_Id = bwp_id;
csires1->resourceType = NR_CSI_ResourceConfig__resourceType_periodic;
asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires1);
int pucch_Resource = 2;
if (configuration->do_CSIRS) {
NR_CSI_ResourceConfig_t *csires0 = calloc(1, sizeof(*csires0));
csires0->csi_ResourceConfigId = bwp_id;
@@ -3535,28 +3499,25 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
NR_PUCCH_CSI_Resource_t *pucchcsi = calloc(1, sizeof(*pucchcsi));
pucchcsi->uplinkBandwidthPartId = bwp_id;
pucchcsi->pucch_Resource = pucch_Resource;
pucchcsi->pucch_Resource = csi_info.resource + (MAX_PUCCH_RESOURCES / 2);
config_csi_meas_report(csi_MeasConfig,
scc,
pucchcsi,
pdsch_Config,
&configuration->pdsch_AntennaPorts,
csi_info,
*configDedicated->pdsch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers,
bwp_id,
uid,
curr_bwp);
bwp_id);
}
NR_PUCCH_CSI_Resource_t *pucchrsrp = calloc(1, sizeof(*pucchrsrp));
pucchrsrp->uplinkBandwidthPartId = bwp_id;
pucchrsrp->pucch_Resource = pucch_Resource;
pucchrsrp->pucch_Resource = csi_info.resource + (MAX_PUCCH_RESOURCES / 2);
config_rsrp_meas_report(csi_MeasConfig,
uecap,
scc,
pucchrsrp,
configuration,
csi_info,
bwp_id + 10,
uid,
curr_bwp,
bitmap);
return csi_MeasConfig;
}
@@ -3564,6 +3525,8 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf
static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
const NR_ServingCellConfigCommon_t *scc,
const nr_mac_config_t *configuration,
NR_UE_UL_RRC_info_t sr_info,
NR_UE_UL_RRC_info_t csi_info,
int ssb_index)
{
NR_SpCellConfig_t *SpCellConfig = calloc(1, sizeof(*SpCellConfig));
@@ -3601,15 +3564,18 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
asn1cCallocOne(configDedicated->firstActiveDownlinkBWP_Id, first_active_bwp);
asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_bwp);
NR_PUCCH_Config_t *pucch_Config = NULL;
if (first_active_bwp == 0) {
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, NULL, uid);
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, sr_info, maxMIMO_Layers, NULL, uid);
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, bitmap, NULL, configuration);
pucch_Config = uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup;
} else {
configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList));
NR_BWP_Downlink_t *bwp = config_downlinkBWP(scc, NULL, false, true, configuration);
asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp);
uplinkConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList));
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(true, uid, maxMIMO_Layers, configuration, scc, NULL);
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(true, uid, maxMIMO_Layers, sr_info, configuration, scc, NULL);
pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup;
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp);
}
@@ -3619,6 +3585,8 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
NULL,
scc,
configuration,
pucch_Config,
csi_info,
uid,
first_active_bwp,
bitmap,
@@ -3755,6 +3723,64 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId,
return rlc_BearerConfig;
}
bool set_ul_periodic_resources(int **list,
const nr_mac_config_t *configuration,
NR_UE_UL_RRC_info_t *info,
const frame_structure_t *fs,
bool is_csi,
int id,
int bwp_start,
int bwp_size,
int period)
{
const nr_pdsch_AntennaPorts_t *ap = &configuration->pdsch_AntennaPorts;
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
int pucch_start_idx = get_pucch_start_idx(bwp_start, pucch2_size);
int num_pucch = get_num_pucch(bwp_start, bwp_size, pucch2_size);
AssertFatal(num_pucch > 0, "No PUCCH could be allocated\n");
if (info->allocated) {
// if the already allocated resource can be still used in current BWP
if (info->resource >= pucch_start_idx && info->resource < pucch_start_idx + num_pucch) {
if (list[info->resource][info->offset] == id)
return true;
else {
LOG_E(NR_MAC, "Resource should be allocated but not present in the list\n");
return false;
}
}
// old resource is outside new BWP range — release it before reallocating
list[info->resource][info->offset] = -1;
if (is_csi)
list[info->resource][info->offset2] = -1; // if CSI has a second slot
info->allocated = false;
}
int pucch_res = pucch_start_idx + (id % num_pucch);
do {
int idx = is_csi;
int offset = get_ul_slot_offset(fs, idx, true);
while (offset < period) {
if (list[pucch_res][offset] == -1) {
info->resource = pucch_res;
info->offset = offset;
if (is_csi) {
int offset2 = get_ul_slot_offset(fs, idx - 1, true);
info->offset2 = offset2;
list[pucch_res][offset2] = id;
}
info->period = period;
info->allocated = true;
list[pucch_res][offset] = id;
return true;
}
idx += 2;
offset = get_ul_slot_offset(fs, idx, true);
}
pucch_res = (pucch_res == pucch_start_idx + num_pucch - 1) ? pucch_start_idx : pucch_res + 1;
} while (pucch_res != pucch_start_idx + (id % num_pucch));
return false;
}
static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *configuration)
{
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
@@ -3772,34 +3798,12 @@ static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon
LOG_E(NR_RRC, "UID %d, cannot allocate resources for CSI-RS, rejecting UE\n", uid);
return false; // cannot allocate resources for CSI-RS
}
const nr_pdsch_AntennaPorts_t *ap = &configuration->pdsch_AntennaPorts;
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp, ap);
int pucchres0_startingPRB = (pucch2_size * num_pucch2) + uid;
// see config_pucch_resset0
if (pucchres0_startingPRB >= curr_bwp) {
LOG_E(NR_RRC, "UID %d, cannot allocate resources for PUCCH0, rejecting UE\n", uid);
return false; // cannot allocate resources for PUCCH0
}
// see get_nb_pucch2_per_slot
if ((num_pucch2 * pucch2_size) + MAX_MOBILES_PER_GNB > curr_bwp) {
LOG_E(NR_RRC, "UID %d, cannot allocate resources for PUCCH2, rejecting UE\n", uid);
return false; // cannot allocate resources for PUCCH2
}
const int idx = (uid * 2 / num_pucch2) + 1;
int offset = get_ul_slot_offset(fs, idx, true);
// see set_csi_meas_periodicity
if (offset >= 320) {
LOG_E(NR_RRC, "UID %d, cannot allocate resources for CSI reporting, rejecting UE\n", uid);
return false; // cannot allocate resources for CSI report
}
return true;
}
NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
NR_UE_UL_RRC_info_t sr_info,
NR_UE_UL_RRC_info_t csi_info,
const NR_ServingCellConfigCommon_t *scc,
const nr_mac_config_t *configuration,
const nr_rlc_configuration_t *default_rlc_config,
@@ -3808,7 +3812,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
if (!verify_radio_configuration(uid, scc, configuration))
return NULL;
NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, configuration, ssb_index);
NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, configuration, sr_info, csi_info, ssb_index);
NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(*cellGroupConfig));
cellGroupConfig->cellGroupId = 0;
@@ -3837,6 +3841,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
const nr_mac_config_t *configuration,
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
NR_UE_UL_RRC_info_t sr_info,
NR_UE_UL_RRC_info_t csi_info,
int uid,
int old_bwp,
int new_bwp,
@@ -3850,6 +3856,7 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
nr_mac_config_t local_config = *configuration;
long ul_maxMIMO_Layers = set_ul_max_layers(configuration, uecap);
local_config.first_active_bwp = new_bwp;
NR_PUCCH_Config_t *pucch_Config = NULL;
uint64_t bitmap = get_ssb_bitmap(scc);
// add new BWP
if (new_bwp == 0) {
@@ -3857,8 +3864,9 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
configDedicated->initialDownlinkBWP = calloc_or_fail(1, sizeof(*configDedicated->initialDownlinkBWP));
if (!uplinkConfig->initialUplinkBWP)
uplinkConfig->initialUplinkBWP = calloc_or_fail(1, sizeof(*uplinkConfig->initialUplinkBWP));
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, &local_config, ul_maxMIMO_Layers, uecap, uid);
configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, bitmap, uecap, &local_config);
uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, &local_config, sr_info, ul_maxMIMO_Layers, uecap, uid);
pucch_Config = uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup;
} else {
if (!configDedicated->downlinkBWP_ToAddModList)
configDedicated->downlinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToAddModList));
@@ -3867,7 +3875,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
if (!uplinkConfig->uplinkBWP_ToAddModList)
uplinkConfig->uplinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList));
NR_BWP_Uplink_t *ul_bwp = config_uplinkBWP(true, uid, ul_maxMIMO_Layers, &local_config, scc, uecap);
NR_BWP_Uplink_t *ul_bwp = config_uplinkBWP(true, uid, ul_maxMIMO_Layers, sr_info, &local_config, scc, uecap);
pucch_Config = ul_bwp->bwp_Dedicated->pucch_Config->choice.setup;
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ul_bwp);
}
@@ -3876,6 +3885,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
uecap,
scc,
&local_config,
pucch_Config,
csi_info,
uid,
*uplinkConfig->firstActiveUplinkBWP_Id,
bitmap,
@@ -3896,18 +3907,21 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_beam_switch(NR_CellGroupConfig_
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
int uid,
const NR_PUCCH_Config_t *pucch_Config,
NR_UE_UL_RRC_info_t csi_info,
int bwp,
int ssb_index)
{
NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig;
NR_ServingCellConfig_t *configDedicated = spCellConfig->spCellConfigDedicated;
uint64_t bitmap = get_ssb_bitmap(scc);
ASN_STRUCT_FREE(asn_DEF_NR_CSI_MeasConfig, configDedicated->csi_MeasConfig->choice.setup);
configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated,
uecap,
scc,
configuration,
pucch_Config,
csi_info,
uid,
bwp,
bitmap,
@@ -4057,6 +4071,8 @@ static NR_ServingCellConfigCommon_t *clone_ServingCellConfigCommon(const NR_Serv
NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigCommon_t *servingcellconfigcommon,
const NR_UE_NR_Capability_t *uecap,
NR_UE_UL_RRC_info_t sr_info,
NR_UE_UL_RRC_info_t csi_info,
int scg_id,
int servCellIndex,
const nr_mac_config_t *configuration,
@@ -4148,7 +4164,8 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
// Uplink BWPs
int firstActiveUplinkBWP_Id = 1;
ulConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*ulConfig->uplinkBWP_ToAddModList));
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(false, uid, maxMIMO_Layers, configuration, servingcellconfigcommon, uecap);
NR_BWP_Uplink_t *ubwp = config_uplinkBWP(false, uid, maxMIMO_Layers, sr_info, configuration, servingcellconfigcommon, uecap);
NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup;
asn1cSeqAdd(&ulConfig->uplinkBWP_ToAddModList->list, ubwp);
ulConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*ulConfig->firstActiveUplinkBWP_Id));
*ulConfig->firstActiveUplinkBWP_Id = firstActiveUplinkBWP_Id;
@@ -4206,6 +4223,8 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
uecap,
servingcellconfigcommon,
configuration,
pucch_Config,
csi_info,
uid,
firstActiveUplinkBWP_Id,
bitmap,
@@ -4276,6 +4295,47 @@ NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t u
return reconfigurationWithSync;
}
void config_ul_rrc_info(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, int scs, int bw)
{
// to have a constant periodicity report among all BWPs we need to set it according to the smallest configured BWP
const nr_pdsch_AntennaPorts_t *ap = &config->pdsch_AntennaPorts;
int pucch2_size = get_pucch2_size(ap->N1 * ap->N2 * ap->XP);
nrmac->ul_rrc_info.max_num_res = bw / pucch2_size;
int min_num_pucch = get_num_pucch(0, bw, pucch2_size);
for (int i = 0; i < config->num_additional_bwps; i++) {
int bwp_size = NRRIV2BW(config->bwp_config[i].location_and_bw, MAX_BWP_SIZE);
int bwp_start = NRRIV2PRBOFFSET(config->bwp_config[i].location_and_bw, MAX_BWP_SIZE);
int num_pucch = get_num_pucch(bwp_start, bwp_size, pucch2_size);
if (num_pucch < min_num_pucch)
min_num_pucch = num_pucch;
}
const frame_structure_t *fs = &nrmac->frame_structure;
int period = fs->numb_slots_period;
int n_ul_slots = get_ul_slots_per_period(fs);
while (period < 10 || n_ul_slots * min_num_pucch < MAX_MOBILES_PER_GNB || period <= (80 << scs)) {
period *= 2;
n_ul_slots *= 2;
}
nrmac->ul_rrc_info.sr_period = period;
nrmac->ul_rrc_info.sr_resources = malloc_or_fail(nrmac->ul_rrc_info.max_num_res * sizeof(int*));
for (int i = 0; i < nrmac->ul_rrc_info.max_num_res; i++)
nrmac->ul_rrc_info.sr_resources[i] = malloc_or_fail(period * sizeof(int));
int ideal_csi_period = set_ideal_period(true) / min_num_pucch;
period = 5;
while (!check_periodicity(period, ideal_csi_period, fs) || period <= 160) // max CSI periodicity 320
period *= 2;
nrmac->ul_rrc_info.csimeas_period = period;
nrmac->ul_rrc_info.csimeas_resources = malloc_or_fail(nrmac->ul_rrc_info.max_num_res * sizeof(int*));
for (int i = 0; i < nrmac->ul_rrc_info.max_num_res; i++)
nrmac->ul_rrc_info.csimeas_resources[i] = malloc_or_fail(period * sizeof(int));
for (int k = 0; k < nrmac->ul_rrc_info.max_num_res; k++) {
for (int i = 0; i < nrmac->ul_rrc_info.sr_period; i++)
nrmac->ul_rrc_info.sr_resources[k][i] = -1;
for (int j = 0; j < nrmac->ul_rrc_info.csimeas_period; j++)
nrmac->ul_rrc_info.csimeas_resources[k][j] = -1;
}
}
NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len)
{

View File

@@ -16,16 +16,15 @@
#include "NR_UL-CCCH-Message.h"
#include "f1ap_messages_types.h"
#include "common/platform_types.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "common/utils/nr/nr_common.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_configuration.h"
struct NR_MeasurementTimingConfiguration;
struct NR_PDSCH_TimeDomainResourceAllocationList;
// forward declaration of MAC configuration parameters, definition is included in C file
typedef struct nr_mac_config_s nr_mac_config_t;
typedef enum nr_srs_type_e nr_srs_type_t;
typedef struct nr_mac_timers nr_mac_timers_t;
typedef struct measgap_config measgap_config_t;
typedef struct NR_UE_UL_RRC_info NR_UE_UL_RRC_info_t;
void nr_rrc_config_dl_tda(NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList,
frame_type_t frame_type,
@@ -70,8 +69,18 @@ void free_SIB1_NR(NR_BCCH_DL_SCH_Message_t *sib1);
int encode_SIB_NR(NR_BCCH_DL_SCH_Message_t *sib, uint8_t *buffer, int max_buffer_size);
void add_sib_to_systeminformation(NR_SystemInformation_IEs_t *si, struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type);
NR_SIB19_r17_t *get_SIB19_NR(const NR_ServingCellConfigCommon_t *scc);
bool set_ul_periodic_resources(int **list,
const nr_mac_config_t *configuration,
NR_UE_UL_RRC_info_t *info,
const frame_structure_t *fs,
bool is_csi,
int id,
int bwp_start,
int bwp_size,
int period);
NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
NR_UE_UL_RRC_info_t sr_info,
NR_UE_UL_RRC_info_t csi_info,
const NR_ServingCellConfigCommon_t *scc,
const nr_mac_config_t *configuration,
const nr_rlc_configuration_t *default_rlc_config,
@@ -88,6 +97,8 @@ int encode_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, uint8_t *buffe
* parameter servingcellconfigdedicated! */
NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigCommon_t *servingcellconfigcommon,
const NR_UE_NR_Capability_t *uecap,
NR_UE_UL_RRC_info_t sr_info,
NR_UE_UL_RRC_info_t csi_info,
int scg_id,
int servCellIndex,
const nr_mac_config_t *configuration,
@@ -112,6 +123,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
const nr_mac_config_t *configuration,
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
NR_UE_UL_RRC_info_t sr_info,
NR_UE_UL_RRC_info_t csi_info,
int uid,
int old_bwp,
int new_bwp,
@@ -121,6 +134,8 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_beam_switch(NR_CellGroupConfig_
const NR_UE_NR_Capability_t *uecap,
const NR_ServingCellConfigCommon_t *scc,
int uid,
const NR_PUCCH_Config_t *pucch_Config,
NR_UE_UL_RRC_info_t csi_info,
int bwp,
int ssb_index);
NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len);