Merge remote-tracking branch 'origin/NR_gNB_MAC_improvements_for_analog_beam_management' into integration_2025_w02 (!3101)

NR gNB improvements for analog beam management

- Improvements at gNB MAC layer to properly handle analog beam
  management for all channels
- Simple beam switching mechanism based on UE RSRP report
This commit is contained in:
Robert Schmidt
2025-01-10 11:44:45 +01:00
14 changed files with 349 additions and 492 deletions
+2 -2
View File
@@ -564,8 +564,8 @@ typedef struct nr_csi_report {
NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type;
long periodicity;
uint16_t offset;
long ** SSB_Index_list;
long ** CSI_Index_list;
long **SSB_Index_list;
long **CSI_Index_list;
// uint8_t nb_of_nzp_csi_report;
uint8_t nb_of_csi_ssb_report;
L1_RSRP_bitlen_t CSI_report_bitlen;
@@ -116,6 +116,7 @@ void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slot, int
idx_to_clear = (idx_to_clear + beam_info->beam_allocation_size - 1) % beam_info->beam_allocation_size;
if (slot % beam_info->beam_duration == 0) {
// resetting previous period allocation
LOG_D(NR_MAC, "%d.%d Clear beam information for index %d\n", frame, slot, idx_to_clear);
for (int i = 0; i < beam_info->beams_per_period; i++)
beam_info->beam_allocation[i][idx_to_clear] = -1;
}
@@ -427,6 +427,7 @@ static bool allocate_dl_retransmission(module_id_t module_id,
sub_frame_t slot,
int *n_rb_sched,
NR_UE_info_t *UE,
int beam_idx,
int current_harq_pid)
{
@@ -447,7 +448,7 @@ static bool allocate_dl_retransmission(module_id_t module_id,
const int coresetid = sched_ctrl->coreset->controlResourceSetId;
const int tda = get_dl_tda(nr_mac, scc, slot);
AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n");
AssertFatal(tda >= 0,"Unable to find PDSCH time domain allocation in list\n");
/* Check first whether the old TDA can be reused
* this helps allocate retransmission when TDA changes (e.g. new nrOfSymbols > old nrOfSymbols) */
@@ -468,8 +469,7 @@ static bool allocate_dl_retransmission(module_id_t module_id,
reuse_old_tda ? "reuse" : "do not reuse",
layers == retInfo->nrOfLayers ? "same" : "different");
// TODO assuming beam 0 for now
uint16_t *rballoc_mask = nr_mac->common_channels[CC_id].vrb_map[0];
uint16_t *rballoc_mask = nr_mac->common_channels[CC_id].vrb_map[beam_idx];
dl_bwp_info_t bwp_info = get_bwp_start_size(nr_mac, UE);
int rbStart = bwp_info.bwpStart;
@@ -541,16 +541,13 @@ static bool allocate_dl_retransmission(module_id_t module_id,
retInfo->tda_info = temp_tda;
}
// TODO properly set the beam index (currently only done for RA)
int beam = 0;
/* Find a free CCE */
int CCEIndex = get_cce_index(nr_mac,
CC_id,
slot,
UE->rnti,
&sched_ctrl->aggregation_level,
beam,
beam_idx,
sched_ctrl->search_space,
sched_ctrl->coreset,
&sched_ctrl->sched_pdcch,
@@ -566,7 +563,7 @@ static bool allocate_dl_retransmission(module_id_t module_id,
int alloc = -1;
if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, current_harq_pid)) {
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex);
alloc = nr_acknack_scheduling(nr_mac, UE, frame, slot, beam, r_pucch, 0);
alloc = nr_acknack_scheduling(nr_mac, UE, frame, slot, UE->UE_beam_index, r_pucch, 0);
if (alloc < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find PUCCH for DL DCI retransmission\n", UE->rnti, frame, slot);
return false;
@@ -574,12 +571,7 @@ static bool allocate_dl_retransmission(module_id_t module_id,
}
sched_ctrl->cce_index = CCEIndex;
fill_pdcch_vrb_map(nr_mac,
CC_id,
&sched_ctrl->sched_pdcch,
CCEIndex,
sched_ctrl->aggregation_level,
beam);
fill_pdcch_vrb_map(nr_mac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, beam_idx);
/* just reuse from previous scheduling opportunity, set new start RB */
sched_ctrl->sched_pdsch = *retInfo;
sched_ctrl->sched_pdsch.rbStart = rbStart - bwp_info.bwpStart;
@@ -608,13 +600,16 @@ static void pf_dl(module_id_t module_id,
sub_frame_t slot,
NR_UE_info_t **UE_list,
int max_num_ue,
int n_rb_sched)
int num_beams,
int n_rb_sched[num_beams])
{
gNB_MAC_INST *mac = RC.nrmac[module_id];
NR_ServingCellConfigCommon_t *scc=mac->common_channels[0].ServingCellConfigCommon;
// UEs that could be scheduled
UEsched_t UE_sched[MAX_MOBILES_PER_GNB + 1] = {0};
int remainUEs = max_num_ue;
int remainUEs[num_beams];
for (int i = 0; i < num_beams; i++)
remainUEs[i] = max_num_ue;
int curUE = 0;
int CC_id = 0;
@@ -638,23 +633,30 @@ static void pf_dl(module_id_t module_id,
const uint32_t b = UE->mac_stats.dl.current_bytes;
UE->dl_thr_ue = (1 - a) * UE->dl_thr_ue + a * b;
if (remainUEs == 0)
int total_rem_ues = 0;
for (int i = 0; i < num_beams; i++)
total_rem_ues += remainUEs[i];
if (total_rem_ues == 0)
continue;
/* retransmission */
if (sched_pdsch->dl_harq_pid >= 0) {
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info,
frame,
slot,
UE->UE_beam_index,
nr_slots_per_frame[current_BWP->scs]);
bool sch_ret = beam.idx >= 0;
/* Allocate retransmission */
bool r = allocate_dl_retransmission(module_id, frame, slot, &n_rb_sched, UE, sched_pdsch->dl_harq_pid);
if (!r) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] DL retransmission could not be allocated\n",
UE->rnti,
frame,
slot);
if (sch_ret)
sch_ret = allocate_dl_retransmission(module_id, frame, slot, &n_rb_sched[beam.idx], UE, beam.idx, sched_pdsch->dl_harq_pid);
if (!sch_ret) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] DL retransmission could not be allocated\n", UE->rnti, frame, slot);
reset_beam_status(&mac->beam_info, frame, slot, UE->UE_beam_index, nr_slots_per_frame[current_BWP->scs], beam.new_beam);
continue;
}
/* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
remainUEs--;
remainUEs[beam.idx]--;
} else {
/* skip this UE if there are no free HARQ processes. This can happen e.g.
@@ -716,7 +718,7 @@ static void pf_dl(module_id_t module_id,
const int min_rbSize = 5;
/* Loop UE_sched to find max coeff and allocate transmission */
while (remainUEs> 0 && n_rb_sched >= min_rbSize && iterator->UE != NULL) {
while (iterator->UE != NULL) {
NR_UE_sched_ctrl_t *sched_ctrl = &iterator->UE->UE_sched_ctrl;
const uint16_t rnti = iterator->UE->rnti;
@@ -732,6 +734,29 @@ static void pf_dl(module_id_t module_id,
iterator++;
continue;
}
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info,
frame,
slot,
iterator->UE->UE_beam_index,
nr_slots_per_frame[dl_bwp->scs]);
if (beam.idx < 0) {
// no available beam
iterator++;
continue;
}
if (remainUEs[beam.idx] == 0 || n_rb_sched[beam.idx] < min_rbSize) {
reset_beam_status(&mac->beam_info,
frame,
slot,
iterator->UE->UE_beam_index,
nr_slots_per_frame[dl_bwp->scs],
beam.new_beam);
iterator++;
continue;
}
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
sched_pdsch->dl_harq_pid = sched_ctrl->available_dl_harq.head;
@@ -754,8 +779,7 @@ static void pf_dl(module_id_t module_id,
const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
// TODO assuming beam 0 for now
uint16_t *rballoc_mask = mac->common_channels[CC_id].vrb_map[0];
uint16_t *rballoc_mask = mac->common_channels[CC_id].vrb_map[beam.idx];
dl_bwp_info_t bwp_info = get_bwp_start_size(mac, iterator->UE);
int rbStart = 0; // WRT BWP start
int rbStop = bwp_info.bwpSize - 1;
@@ -782,24 +806,24 @@ static void pf_dl(module_id_t module_id,
continue;
}
// TODO properly set the beam index (currently only done for RA)
int beam = 0;
int CCEIndex = get_cce_index(mac,
CC_id,
slot,
iterator->UE->rnti,
&sched_ctrl->aggregation_level,
beam,
beam.idx,
sched_ctrl->search_space,
sched_ctrl->coreset,
&sched_ctrl->sched_pdcch,
false);
if (CCEIndex<0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find free CCE for DL DCI\n",
rnti,
frame,
slot);
if (CCEIndex < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find free CCE for DL DCI\n", rnti, frame, slot);
reset_beam_status(&mac->beam_info,
frame,
slot,
iterator->UE->UE_beam_index,
nr_slots_per_frame[dl_bwp->scs],
beam.new_beam);
iterator++;
continue;
}
@@ -810,19 +834,22 @@ static void pf_dl(module_id_t module_id,
int alloc = -1;
if (!get_FeedbackDisabled(iterator->UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) {
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex);
alloc = nr_acknack_scheduling(mac, iterator->UE, frame, slot, beam, r_pucch, 0);
alloc = nr_acknack_scheduling(mac, iterator->UE, frame, slot, iterator->UE->UE_beam_index, r_pucch, 0);
if (alloc < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find PUCCH for DL DCI\n",
rnti,
frame,
slot);
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find PUCCH for DL DCI\n", rnti, frame, slot);
reset_beam_status(&mac->beam_info,
frame,
slot,
iterator->UE->UE_beam_index,
nr_slots_per_frame[dl_bwp->scs],
beam.new_beam);
iterator++;
continue;
}
}
sched_ctrl->cce_index = CCEIndex;
fill_pdcch_vrb_map(mac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, beam);
fill_pdcch_vrb_map(mac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, beam.idx);
sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc, dl_bwp, tda_info, sched_pdsch->nrOfLayers);
sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx);
@@ -851,25 +878,30 @@ static void pf_dl(module_id_t module_id,
sched_pdsch->rbStart = rbStart;
sched_pdsch->tb_size = TBS;
/* transmissions: directly allocate */
n_rb_sched -= sched_pdsch->rbSize;
n_rb_sched[beam.idx] -= sched_pdsch->rbSize;
for (int rb = bwp_start; rb < sched_pdsch->rbSize; rb++)
rballoc_mask[rb + sched_pdsch->rbStart] |= slbitmap;
remainUEs--;
remainUEs[beam.idx]--;
iterator++;
}
}
static void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot)
static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot)
{
NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info;
gNB_MAC_INST *mac = RC.nrmac[module_id];
NR_UEs_t *UE_info = &mac->UE_info;
if (UE_info->list[0] == NULL)
return;
NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon;
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
int num_beams = mac->beam_info.beam_allocation ? mac->beam_info.beams_per_period : 1;
int n_rb_sched[num_beams];
for (int i = 0; i < num_beams; i++)
n_rb_sched[i] = bw;
/* Retrieve amount of data to send for this UE */
nr_store_dlsch_buffer(module_id, frame, slot);
@@ -881,15 +913,10 @@ static void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_
max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET);
/* proportional fair scheduling algorithm */
pf_dl(module_id,
frame,
slot,
UE_info->list,
max_sched_ues,
bw); // we set the whole BW as max number
pf_dl(module_id, frame, slot, UE_info->list, max_sched_ues, num_beams, n_rb_sched);
}
nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id) {
nr_pp_impl_dl nr_init_dlsch_preprocessor(int CC_id) {
/* during initialization: no mutex needed */
/* in the PF algorithm, we have to use the TBsize to compute the coefficient.
* This would include the number of DMRS symbols, which in turn depends on
@@ -914,7 +941,7 @@ nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id) {
}
}
return nr_fr1_dlsch_preprocessor;
return nr_dlsch_preprocessor;
}
void nr_schedule_ue_spec(module_id_t module_id,
@@ -558,23 +558,13 @@ int get_cce_index(const gNB_MAC_INST *nrmac,
const uint32_t Y = is_common ? 0 : get_Y(ss, slot, rnti);
uint8_t nr_of_candidates;
for (int i=0; i<5; i++) {
for (int i = 0; i < 5; i++) {
// for now taking the lowest value among the available aggregation levels
find_aggregation_candidates(aggregation_level,
&nr_of_candidates,
ss,
1<<i);
if(nr_of_candidates>0)
find_aggregation_candidates(aggregation_level, &nr_of_candidates, ss, 1 << i);
if(nr_of_candidates > 0)
break;
}
int CCEIndex = find_pdcch_candidate(nrmac,
CC_id,
*aggregation_level,
nr_of_candidates,
beam_idx,
sched_pdcch,
coreset,
Y);
int CCEIndex = find_pdcch_candidate(nrmac, CC_id, *aggregation_level, nr_of_candidates, beam_idx, sched_pdcch, coreset, Y);
return CCEIndex;
}
@@ -3185,7 +3175,7 @@ void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST
}
}
static inline int get_beam_index(const NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame)
static inline int get_beam_index(const NR_beam_info_t *beam_info, int frame, int slot, int slots_per_frame)
{
return ((frame * slots_per_frame + slot) / beam_info->beam_duration) % beam_info->beam_allocation_size;
}
@@ -3196,7 +3186,7 @@ NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame,
if (!beam_info->beam_allocation)
return (NR_beam_alloc_t) {.new_beam = false, .idx = 0};
const int index = get_beam_index(beam_info, frame, slot, beam_index, slots_per_frame);
const int index = get_beam_index(beam_info, frame, slot, slots_per_frame);
for (int i = 0; i < beam_info->beams_per_period; i++) {
NR_beam_alloc_t beam_struct = {.new_beam = false, .idx = i};
int *beam = &beam_info->beam_allocation[i][index];
@@ -3204,8 +3194,10 @@ NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame,
beam_struct.new_beam = true;
*beam = beam_index;
}
if (*beam == beam_index)
if (*beam == beam_index) {
LOG_D(NR_MAC, "%d.%d Using beam structure with index %d for beam %d (%s)\n", frame, slot, beam_struct.idx, beam_index, beam_struct.new_beam ? "new beam" : "old beam");
return beam_struct;
}
}
return (NR_beam_alloc_t) {.new_beam = false, .idx = -1};
@@ -3215,13 +3207,25 @@ void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_
{
if(!new_beam) // need to reset only if the beam was allocated specifically for this instance
return;
const int index = get_beam_index(beam_info, frame, slot, beam_index, slots_per_frame);
const int index = get_beam_index(beam_info, frame, slot, slots_per_frame);
for (int i = 0; i < beam_info->beams_per_period; i++) {
if (beam_info->beam_allocation[i][index] == beam_index)
beam_info->beam_allocation[i][index] = -1;
}
}
void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE)
{
RSRP_report_t *rsrp_report = &UE->UE_sched_ctrl.CSI_report.ssb_rsrp_report;
// simple beam switching algorithm -> we select beam with highest RSRP from CSI report
int new_bf_index = get_fapi_beamforming_index(mac, rsrp_report->resource_id[0]);
if (UE->UE_beam_index == new_bf_index)
return; // no beam change needed
LOG_I(NR_MAC, "[UE %x] Switching to beam with ID %d (SSB number %d)\n", UE->rnti, new_bf_index, rsrp_report->resource_id[0]);
UE->UE_beam_index = new_bf_index;
}
void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_len, void *data)
{
gNB_MAC_INST *mac = RC.nrmac[0];
+10 -4
View File
@@ -411,6 +411,7 @@ void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr
}
static void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu,
int frame,
int slot,
int module_id,
int CC_id,
@@ -469,9 +470,14 @@ static void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu,
srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index];
srs_pdu->beamforming.prg_size = 1;
}
// TODO properly use beam allocation
uint16_t *vrb_map_UL = &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[0][buffer_index * MAX_BWP_SIZE];
srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index;
NR_beam_alloc_t beam = beam_allocation_procedure(&RC.nrmac[module_id]->beam_info,
frame,
slot,
UE->UE_beam_index,
nr_slots_per_frame[current_BWP->scs]);
AssertFatal(beam.idx >= 0, "Cannot allocate SRS in any available beam\n");
uint16_t *vrb_map_UL = &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[beam.idx][buffer_index * MAX_BWP_SIZE];
uint64_t mask = SL_to_bitmap(srs_pdu->time_start_position, srs_pdu->num_symbols);
for (int i = 0; i < srs_pdu->bwp_size; ++i)
vrb_map_UL[i + srs_pdu->bwp_start] |= mask;
@@ -497,7 +503,7 @@ static void nr_fill_nfapi_srs(int module_id,
memset(srs_pdu, 0, sizeof(nfapi_nr_srs_pdu_t));
future_ul_tti_req->n_pdus += 1;
index = ul_buffer_index(frame, slot, UE->current_UL_BWP.scs, RC.nrmac[module_id]->vrb_map_UL_size);
nr_configure_srs(srs_pdu, slot, module_id, CC_id, UE, srs_resource_set, srs_resource, index);
nr_configure_srs(srs_pdu, frame, slot, module_id, CC_id, UE, srs_resource_set, srs_resource, index);
}
/*******************************************************************
+61 -321
View File
@@ -36,8 +36,6 @@
extern RAN_CONTEXT_t RC;
static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac,
frame_t frame,
sub_frame_t slot,
@@ -97,13 +95,6 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac,
#define MIN_RSRP_VALUE -141
#define MAX_RSRP_VALUE -43
#define MAX_NUM_SSB 128
#define MAX_SSB_SCHED 8
#define L1_RSRP_HYSTERIS 10 //considering 10 dBm as hysterisis for avoiding frequent SSB Beam Switching. !Fixme provide exact value if any
//#define L1_DIFF_RSRP_STEP_SIZE 2
static int ssb_index_sorted[MAX_NUM_SSB] = {0};
static int ssb_rsrp_sorted[MAX_NUM_SSB] = {0};
//Measured RSRP Values Table 10.1.16.1-1 from 36.133
//Stored all the upper limits[Max RSRP Value of corresponding index]
@@ -164,9 +155,7 @@ static int get_pucch_index(int frame, int slot, int n_slots_frame, const NR_TDD_
}
void nr_schedule_pucch(gNB_MAC_INST *nrmac,
frame_t frameP,
sub_frame_t slotP)
void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP)
{
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
@@ -207,9 +196,7 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac,
}
}
void nr_csi_meas_reporting(int Mod_idP,
frame_t frame,
sub_frame_t slot)
void nr_csi_meas_reporting(int Mod_idP,frame_t frame, sub_frame_t slot)
{
const int CC_id = 0;
gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP];
@@ -279,9 +266,10 @@ void nr_csi_meas_reporting(int Mod_idP,
int bwp_start = ul_bwp->BWPStart;
// going through the list of PUCCH resources to find the one indexed by resource_id
int beam_idx = 0; // TODO proper beam allocation
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");
const int index = ul_buffer_index(sched_frame, sched_slot, ul_bwp->scs, nrmac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &nrmac->common_channels[0].vrb_map_UL[beam_idx][index * MAX_BWP_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];
@@ -402,71 +390,6 @@ static void handle_dl_harq(NR_UE_info_t * UE,
}
}
static int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, NR_UE_info_t *UE)
{
const NR_PDSCH_Config_t *pdsch_Config = UE->current_DL_BWP.pdsch_Config;
int nb_tci_states = pdsch_Config ? pdsch_Config->tci_StatesToAddModList->list.count : 0;
NR_TCI_State_t *tci =NULL;
for(int i=0; i<nb_tci_states && i<64; i++) {
tci = (NR_TCI_State_t *)pdsch_Config->tci_StatesToAddModList->list.array[i];
if(tci != NULL) {
if(tci->qcl_Type1.referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) {
if(tci->qcl_Type1.referenceSignal.choice.ssb == ssb_index_t)
return tci->tci_StateId; // returned TCI state ID
}
// if type2 is configured
else if(tci->qcl_Type2 != NULL && tci->qcl_Type2->referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) {
if(tci->qcl_Type2->referenceSignal.choice.ssb == ssb_index_t)
return tci->tci_StateId; // returned TCI state ID
} else LOG_I(NR_MAC,"SSB index is not found in first 64 TCI states of TCI_statestoAddModList[%d]", i);
}
}
// tci state not identified in first 64 TCI States of PDSCH Config
return -1;
}
static int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, NR_UE_info_t *UE)
{
NR_TCI_State_t *tci =NULL;
NR_TCI_StateId_t *tci_id = NULL;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_ControlResourceSet_t *coreset = sched_ctrl->coreset;
int flag = 0;
int tci_stateID = -1;
const NR_PDSCH_Config_t *pdsch_Config = UE->current_DL_BWP.pdsch_Config;
int nb_tci_states = pdsch_Config ? pdsch_Config->tci_StatesToAddModList->list.count : 0;
for(int i=0; i<nb_tci_states && i<128; i++) {
tci = (NR_TCI_State_t *)pdsch_Config->tci_StatesToAddModList->list.array[i];
if(tci != NULL && tci->qcl_Type1.referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) {
if(tci->qcl_Type1.referenceSignal.choice.ssb == ssb_index_t) {
flag = 1;
tci_stateID = tci->tci_StateId;
break;
} else if(tci->qcl_Type2 != NULL && tci->qcl_Type2->referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) {
flag = 1;
tci_stateID = tci->tci_StateId;
break;
}
}
if(flag != 0 && tci_stateID != -1 && coreset != NULL) {
for(i=0; i<64 && i<coreset->tci_StatesPDCCH_ToAddList->list.count; i++) {
tci_id = coreset->tci_StatesPDCCH_ToAddList->list.array[i];
if(tci_id != NULL && *tci_id == tci_stateID)
return tci_stateID;
}
}
}
// Need to implement once configuration is received
return -1;
}
//returns the measured RSRP value (upper limit)
static bool get_measured_rsrp(uint8_t index, int *rsrp)
{
@@ -481,197 +404,14 @@ static bool get_measured_rsrp(uint8_t index, int *rsrp)
}
//returns the differential RSRP value (upper limit)
static int get_diff_rsrp(uint8_t index, int strongest_rsrp) {
if(strongest_rsrp != -1) {
static int get_diff_rsrp(uint8_t index, int strongest_rsrp)
{
if(strongest_rsrp != -1)
return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index];
} else
else
return MIN_RSRP_VALUE;
}
//identifies the target SSB Beam index
//keeps the required date for PDCCH and PDSCH TCI state activation/deactivation CE consutruction globally
//handles triggering of PDCCH and PDSCH MAC CEs
static void tci_handling(NR_UE_info_t *UE, frame_t frame, slot_t slot)
{
int cqi_idx = 0;
int curr_ssb_beam_index = 0; //ToDo: yet to know how to identify the serving ssb beam index
uint8_t target_ssb_beam_index = curr_ssb_beam_index;
uint8_t is_triggering_ssb_beam_switch =0;
uint8_t ssb_idx = 0;
int pdsch_bwp_id = 0;
int ssb_index[MAX_NUM_SSB] = {0};
int ssb_rsrp[MAX_NUM_SSB] = {0};
uint8_t idx = 0;
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
uint8_t nr_ssbri_cri = 0;
uint8_t nb_of_csi_ssb_report = UE->csi_report_template[cqi_idx].nb_of_csi_ssb_report;
int better_rsrp_reported = -140-(-0); /*minimum_measured_RSRP_value - minimum_differntail_RSRP_value*///considering the minimum RSRP value as better RSRP initially
uint8_t diff_rsrp_idx = 0;
uint8_t i, j;
//bwp indicator
int n_dl_bwp = UE->sc_info.n_dl_bwp;
const int bwp_id = dl_bwp->bwp_id;
if (n_dl_bwp < 4)
pdsch_bwp_id = bwp_id;
else
pdsch_bwp_id = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212
/*Example:
CRI_SSBRI: 1 2 3 4| 5 6 7 8| 9 10 1 2|
nb_of_csi_ssb_report = 3 //3 sets as above
nr_ssbri_cri = 4 //each set has 4 elements
storing ssb indexes in ssb_index array as ssb_index[0] = 1 .. ssb_index[4] = 5
ssb_rsrp[0] = strongest rsrp in first set, ssb_rsrp[4] = strongest rsrp in second set, ..
idx: resource set index
*/
nr_ssbri_cri = sched_ctrl->CSI_report.ssb_cri_report.nr_ssbri_cri;
//extracting the ssb indexes
for (ssb_idx = 0; ssb_idx < nr_ssbri_cri; ssb_idx++) {
ssb_index[idx * nb_of_csi_ssb_report + ssb_idx] = sched_ctrl->CSI_report.ssb_cri_report.CRI_SSBRI[ssb_idx];
}
//if strongest measured RSRP is configured
int strongest_ssb_rsrp;
int rsrp_index = sched_ctrl->CSI_report.ssb_cri_report.RSRP;
bool valid = get_measured_rsrp(rsrp_index, &strongest_ssb_rsrp);
if (!valid) {
LOG_E(NR_MAC, "UE %04x: reported RSRP index %d invalid\n", UE->rnti, rsrp_index);
return;
}
ssb_rsrp[idx * nb_of_csi_ssb_report] = strongest_ssb_rsrp;
LOG_D(NR_MAC,"ssb_rsrp = %d\n",strongest_ssb_rsrp);
//if current ssb rsrp is greater than better rsrp
if(ssb_rsrp[idx * nb_of_csi_ssb_report] > better_rsrp_reported) {
better_rsrp_reported = ssb_rsrp[idx * nb_of_csi_ssb_report];
target_ssb_beam_index = idx * nb_of_csi_ssb_report;
}
for(diff_rsrp_idx =1; diff_rsrp_idx < nr_ssbri_cri; diff_rsrp_idx++) {
ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx] = get_diff_rsrp(sched_ctrl->CSI_report.ssb_cri_report.diff_RSRP[diff_rsrp_idx-1], strongest_ssb_rsrp);
//if current reported rsrp is greater than better rsrp
if(ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx] > better_rsrp_reported) {
better_rsrp_reported = ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx];
target_ssb_beam_index = idx * nb_of_csi_ssb_report + diff_rsrp_idx;
}
}
if(ssb_index[target_ssb_beam_index] != ssb_index[curr_ssb_beam_index] && ssb_rsrp[target_ssb_beam_index] > ssb_rsrp[curr_ssb_beam_index]) {
if( ssb_rsrp[target_ssb_beam_index] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) {
is_triggering_ssb_beam_switch = 1;
LOG_D(NR_MAC, "Triggering ssb beam switching using tci\n");
}
}
if(is_triggering_ssb_beam_switch) {
//filling pdcch tci state activativation mac ce structure fields
sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 1;
//OAI currently focusing on Non CA usecase hence 0 is considered as serving
//cell id
sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.servingCellId = 0; //0 for PCell as 38.331 v15.9.0 page 353 //serving cell id for which this MAC CE applies
sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId = 0; //coreset id for which the TCI State id is being indicated
/* 38.321 v15.8.0 page 66
TCI State ID: This field indicates the TCI state identified by TCI-StateId as specified in TS 38.331 [5] applicable
to the Control Resource Set identified by CORESET ID field.
If the field of CORESET ID is set to 0,
this field indicates a TCI-StateId for a TCI state of the first 64 TCI-states configured by tci-States-ToAddModList and tciStates-ToReleaseList in the PDSCH-Config in the active BWP.
If the field of CORESET ID is set to the other value than 0,
this field indicates a TCI-StateId configured by tci-StatesPDCCH-ToAddList and tciStatesPDCCH-ToReleaseList in the controlResourceSet identified by the indicated CORESET ID.
The length of the field is 7 bits
*/
if(sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId == 0) {
int tci_state_id = checkTargetSSBInFirst64TCIStates_pdschConfig(ssb_index[target_ssb_beam_index], UE);
if( tci_state_id != -1)
sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id;
else {
//identify the best beam within first 64 TCI States of PDSCH
//Config TCI-states-to-addModList
int flag = 0;
for(i =0; ssb_index_sorted[i]!=0; i++) {
tci_state_id = checkTargetSSBInFirst64TCIStates_pdschConfig(ssb_index_sorted[i],UE) ;
if(tci_state_id != -1 && ssb_rsrp_sorted[i] > ssb_rsrp[curr_ssb_beam_index] && ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) {
sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id;
flag = 1;
break;
}
}
if(flag == 0 || ssb_rsrp_sorted[i] < ssb_rsrp[curr_ssb_beam_index] || ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] < L1_RSRP_HYSTERIS) {
sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 0;
}
}
} else {
int tci_state_id = checkTargetSSBInTCIStates_pdcchConfig(ssb_index[target_ssb_beam_index], UE);
if (tci_state_id !=-1)
sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id;
else {
//identify the best beam within CORESET/PDCCH
////Config TCI-states-to-addModList
int flag = 0;
for(i =0; ssb_index_sorted[i]!=0; i++) {
tci_state_id = checkTargetSSBInTCIStates_pdcchConfig(ssb_index_sorted[i], UE);
if( tci_state_id != -1 && ssb_rsrp_sorted[i] > ssb_rsrp[curr_ssb_beam_index] && ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) {
sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id;
flag = 1;
break;
}
}
if(flag == 0 || ssb_rsrp_sorted[i] < ssb_rsrp[curr_ssb_beam_index] || ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] < L1_RSRP_HYSTERIS) {
sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 0;
}
}
}
sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tci_present_inDCI = sched_ctrl->coreset ?
sched_ctrl->coreset->tci_PresentInDCI : NULL;
//filling pdsch tci state activation deactivation mac ce structure fields
if(sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tci_present_inDCI) {
sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.is_scheduled = 1;
/*
Serving Cell ID: This field indicates the identity of the Serving Cell for which the MAC CE applies
Considering only PCell exists. Serving cell index of PCell is always 0, hence configuring 0
*/
sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.servingCellId = 0;
/*
BWP ID: This field indicates a DL BWP for which the MAC CE applies as the codepoint of the DCI bandwidth
part indicator field as specified in TS 38.212
*/
sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.bwpId = pdsch_bwp_id;
/*
* TODO ssb_rsrp_sort() API yet to code to find 8 best beams, rrc configuration
* is required
*/
for(i = 0; i<8; i++) {
sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.tciStateActDeact[i] = i;
}
sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.highestTciStateActivated = 8;
for(i = 0, j =0; i<MAX_TCI_STATES; i++) {
if(sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.tciStateActDeact[i]) {
sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.codepoint[j] = i;
j++;
}
}
}//tci_presentInDCI
}//is-triggering_beam_switch
} // tci handling
static uint8_t pickandreverse_bits(uint8_t *payload, uint16_t bitlen, uint8_t start_bit)
{
uint8_t rev_bits = 0;
@@ -680,17 +420,14 @@ static uint8_t pickandreverse_bits(uint8_t *payload, uint16_t bitlen, uint8_t st
return rev_bits;
}
static void evaluate_rsrp_report(NR_UE_info_t *UE,
static void evaluate_rsrp_report(gNB_MAC_INST *nrmac,
NR_UE_info_t *UE,
NR_UE_sched_ctrl_t *sched_ctrl,
uint8_t csi_report_id,
uint8_t *payload,
int *cumul_bits,
NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type)
{
nr_csi_report_t *csi_report = &UE->csi_report_template[csi_report_id];
uint8_t cri_ssbri_bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen;
uint16_t curr_payload;
/*! As per the spec 38.212 and table: 6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report
* the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE
* From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set
@@ -708,46 +445,52 @@ static void evaluate_rsrp_report(NR_UE_info_t *UE,
resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with
multiple simultaneous spatial domain receive filter
*/
nr_csi_report_t *csi_report = &UE->csi_report_template[csi_report_id];
RSRP_report_t *rsrp_report;
long **index_list;
switch (reportQuantity_type) {
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
rsrp_report = &sched_ctrl->CSI_report.ssb_rsrp_report;
index_list = csi_report->SSB_Index_list;
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP :
rsrp_report = &sched_ctrl->CSI_report.csirs_rsrp_report;
index_list = csi_report->CSI_Index_list;
break;
default :
AssertFatal(false, "Invalid RSRP report type\n");
}
sched_ctrl->CSI_report.ssb_cri_report.nr_ssbri_cri = csi_report->CSI_report_bitlen.nb_ssbri_cri;
for (int csi_ssb_idx = 0; csi_ssb_idx < sched_ctrl->CSI_report.ssb_cri_report.nr_ssbri_cri ; csi_ssb_idx++) {
curr_payload = pickandreverse_bits(payload, cri_ssbri_bitlen, *cumul_bits);
if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type) {
sched_ctrl->CSI_report.ssb_cri_report.CRI_SSBRI[csi_ssb_idx] =
*(csi_report->SSB_Index_list[cri_ssbri_bitlen>0?((curr_payload)&~(~1U<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]);
LOG_D(MAC,"SSB_index = %d\n",sched_ctrl->CSI_report.ssb_cri_report.CRI_SSBRI[csi_ssb_idx]);
}
else {
sched_ctrl->CSI_report.ssb_cri_report.CRI_SSBRI[csi_ssb_idx] =
*(csi_report->CSI_Index_list[cri_ssbri_bitlen>0?((curr_payload)&~(~1U<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]);
LOG_D(MAC,"CSI-RS Resource Indicator = %d\n",sched_ctrl->CSI_report.ssb_cri_report.CRI_SSBRI[csi_ssb_idx]);
}
*cumul_bits += cri_ssbri_bitlen;
rsrp_report->nr_reports = csi_report->CSI_report_bitlen.nb_ssbri_cri;
uint16_t curr_payload;
for (int i = 0; i < rsrp_report->nr_reports; i++) {
int bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen;
curr_payload = pickandreverse_bits(payload, bitlen, *cumul_bits);
rsrp_report->resource_id[i] = *(index_list[bitlen > 0 ? ((curr_payload) & ~(~1U << (bitlen - 1))) : bitlen]);
LOG_D(MAC,"SSB/CSI-RS index = %d\n", rsrp_report->resource_id[i]);
*cumul_bits += bitlen;
}
curr_payload = pickandreverse_bits(payload, 7, *cumul_bits);
sched_ctrl->CSI_report.ssb_cri_report.RSRP = curr_payload & 0x7f;
int rsrp_index = curr_payload & 0x7f;
*cumul_bits += 7;
for (int diff_rsrp_idx =0; diff_rsrp_idx < sched_ctrl->CSI_report.ssb_cri_report.nr_ssbri_cri - 1; diff_rsrp_idx++ ) {
curr_payload = pickandreverse_bits(payload, 4, *cumul_bits);
sched_ctrl->CSI_report.ssb_cri_report.diff_RSRP[diff_rsrp_idx] = curr_payload & 0x0f;
*cumul_bits += 4;
}
csi_report->nb_of_csi_ssb_report++;
int strongest_ssb_rsrp;
int rsrp_index = sched_ctrl->CSI_report.ssb_cri_report.RSRP;
bool valid = get_measured_rsrp(rsrp_index, &strongest_ssb_rsrp);
bool valid = get_measured_rsrp(rsrp_index, &rsrp_report->RSRP[0]);
if (!valid) {
LOG_E(NR_MAC, "UE %04x: reported RSRP index %d invalid\n", UE->rnti, rsrp_index);
return;
}
for (int i = 1; i < rsrp_report->nr_reports; i++) {
curr_payload = pickandreverse_bits(payload, 4, *cumul_bits);
rsrp_report->RSRP[i] = get_diff_rsrp(curr_payload & 0x0f, rsrp_report->RSRP[0]);
*cumul_bits += 4;
}
NR_mac_stats_t *stats = &UE->mac_stats;
// including ssb rsrp in mac stats
stats->cumul_rsrp += strongest_ssb_rsrp;
stats->cumul_rsrp += rsrp_report->RSRP[0];
stats->num_rsrp_meas++;
}
@@ -869,7 +612,7 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
frame_t frame,
slot_t slot,
NR_UE_info_t *UE,
NR_ServingCellConfigCommon_t *scc)
gNB_MAC_INST *nrmac)
{
/** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
uint8_t *payload = uci_pdu->csi_part1.csi_part1_payload;
@@ -899,12 +642,13 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
if ((n_slots_frame*frame + slot - offset)%period == 0) {
reportQuantity_type = csi_report->reportQuantity_type;
LOG_D(MAC,"SFN/SF:%d/%d reportQuantity type = %d\n",frame,slot,reportQuantity_type);
switch(reportQuantity_type){
switch(reportQuantity_type) {
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
evaluate_rsrp_report(UE,sched_ctrl,csi_report_id,payload,&cumul_bits,reportQuantity_type);
evaluate_rsrp_report(nrmac, UE, sched_ctrl, csi_report_id, payload, &cumul_bits, reportQuantity_type);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
evaluate_rsrp_report(UE,sched_ctrl,csi_report_id,payload,&cumul_bits,reportQuantity_type);
evaluate_rsrp_report(nrmac, UE, sched_ctrl, csi_report_id, payload, &cumul_bits, reportQuantity_type);
beam_selection_procedures(nrmac, UE);
break;
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report = true;
@@ -1074,7 +818,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
gNB_MAC_INST *nrmac = RC.nrmac[mod_id];
NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t * UE = find_nr_UE(&nrmac->UE_info, uci_234->rnti);
NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, uci_234->rnti);
if (!UE) {
NR_SCHED_UNLOCK(&nrmac->sched_lock);
LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti);
@@ -1122,9 +866,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
LOG_D(NR_MAC, "CSI CRC %d\n", uci_234->csi_part1.csi_part1_crc);
if (uci_234->csi_part1.csi_part1_crc != 1) {
// API to parse the csi report and store it into sched_ctrl
extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, nrmac->common_channels->ServingCellConfigCommon);
// TCI handling function
tci_handling(UE, frame, slot);
extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, nrmac);
}
free(uci_234->csi_part1.csi_part1_payload);
}
@@ -1241,7 +983,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
NR_UE_info_t *UE,
frame_t frame,
sub_frame_t slot,
int beam_index,
int ue_beam,
int r_pucch,
int is_common)
{
@@ -1331,7 +1073,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
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);
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, pucch_frame, pucch_slot, beam_index, n_slots_frame);
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,
"DL %4d.%2d, UL_ACK %4d.%2d beam resources for this occasion are already occupied, move to the following occasion\n",
@@ -1351,7 +1093,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
slot,
pucch_frame,
pucch_slot);
reset_beam_status(&mac->beam_info, pucch_frame, pucch_slot, beam_index, n_slots_frame, beam.new_beam);
reset_beam_status(&mac->beam_info, pucch_frame, pucch_slot, ue_beam, n_slots_frame, beam.new_beam);
continue;
}
// allocating a new PUCCH structure for this occasion
@@ -1403,10 +1145,10 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
int SR_period; int SR_offset;
find_period_offset_SR(SchedulingRequestResourceConfig,&SR_period,&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);
LOG_D(NR_MAC,"SR_resource_id %d: SR_period %d, SR_offset %d\n", SR_resource_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);
@@ -1419,7 +1161,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
if (*pucchresset->resourceList.list.array[i] == *PucchResourceId )
idx = i;
}
AssertFatal(idx>-1,"SR resource not found among PUCCH resources");
AssertFatal(idx > -1, "SR resource not found among PUCCH resources");
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
@@ -1427,10 +1169,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
const int pucch_index = get_pucch_index(SFN, slot, n_slots_frame, tdd, 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 == SFN && curr_pucch->ul_slot == slot && curr_pucch->resource_indicator == idx)
curr_pucch->sr_flag = true;
else if (curr_pucch->active) {
LOG_E(NR_MAC,
@@ -1443,9 +1182,10 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
continue;
}
else {
int beam_idx = 0; // TODO proper beam allocation
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, SFN, 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, ul_bwp->scs, nrmac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam_idx][index * MAX_BWP_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);
+118 -65
View File
@@ -1644,6 +1644,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac,
sub_frame_t slot,
uint16_t *rballoc_mask,
int *n_rb_sched,
int dci_beam_idx,
NR_UE_info_t* UE,
int harq_pid,
const NR_ServingCellConfigCommon_t *scc,
@@ -1733,7 +1734,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac,
slot,
UE->rnti,
&sched_ctrl->aggregation_level,
0, // TODO use beam index
dci_beam_idx,
sched_ctrl->search_space,
sched_ctrl->coreset,
&sched_ctrl->sched_pdcch,
@@ -1744,12 +1745,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac,
}
sched_ctrl->cce_index = CCEIndex;
fill_pdcch_vrb_map(nrmac,
CC_id,
&sched_ctrl->sched_pdcch,
CCEIndex,
sched_ctrl->aggregation_level,
0); // TODO use beam index when implemented
fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam_idx);
retInfo->frame = (frame + (slot + tda_info.k2) / nr_slots_per_frame[ul_bwp->scs]) % MAX_FRAME_NUMBER;
retInfo->slot = (slot + tda_info.k2) % nr_slots_per_frame[ul_bwp->scs];
@@ -1793,7 +1789,8 @@ static void pf_ul(module_id_t module_id,
int sched_slot,
NR_UE_info_t *UE_list[],
int max_num_ue,
int n_rb_sched)
int num_beams,
int n_rb_sched[num_beams])
{
const int CC_id = 0;
gNB_MAC_INST *nrmac = RC.nrmac[module_id];
@@ -1802,7 +1799,9 @@ static void pf_ul(module_id_t module_id,
const int min_rb = nrmac->min_grant_prb;
// UEs that could be scheduled
UEsched_t UE_sched[MAX_MOBILES_PER_GNB + 1] = {0};
int remainUEs = max_num_ue;
int remainUEs[num_beams];
for (int i = 0; i < num_beams; i++)
remainUEs[i] = max_num_ue;
int curUE = 0;
/* Loop UE_list to calculate throughput and coeff */
@@ -1823,42 +1822,66 @@ static void pf_ul(module_id_t module_id,
const uint32_t b = stats->current_bytes;
UE->ul_thr_ue = (1 - a) * UE->ul_thr_ue + a * b;
if(remainUEs == 0)
int total_rem_ues = 0;
for (int i = 0; i < num_beams; i++)
total_rem_ues += remainUEs[i];
if (total_rem_ues == 0)
continue;
int n_dl = nr_slots_per_frame[UE->current_DL_BWP.scs];
NR_beam_alloc_t dci_beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl);
if (dci_beam.idx < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", UE->rnti, frame, slot);
continue;
}
int n = nr_slots_per_frame[current_BWP->scs];
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n);
if (beam.idx < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", UE->rnti, frame, slot);
reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam);
continue;
}
const int index = ul_buffer_index(sched_frame, sched_slot, current_BWP->scs, nrmac->vrb_map_UL_size);
// TODO improve handling of beam in vrb_map (for now just using 0)
uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[0][index * MAX_BWP_SIZE];
uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
/* Check if retransmission is necessary */
sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head;
LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n",UE->rnti,sched_pusch->ul_harq_pid);
LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n", UE->rnti, sched_pusch->ul_harq_pid);
if (sched_pusch->ul_harq_pid >= 0) {
/* Allocate retransmission*/
const int tda = get_ul_tda(nrmac, scc, sched_frame, sched_slot);
bool r = allocate_ul_retransmission(nrmac, frame, slot, rballoc_mask, &n_rb_sched, UE, sched_pusch->ul_harq_pid, scc, tda);
bool r = allocate_ul_retransmission(nrmac,
frame,
slot,
rballoc_mask,
&n_rb_sched[beam.idx],
dci_beam.idx,
UE,
sched_pusch->ul_harq_pid,
scc,
tda);
if (!r) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UL retransmission could not be allocated\n",
UE->rnti,
frame,
slot);
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UL retransmission could not be allocated\n", UE->rnti, frame, slot);
reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam);
reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam);
continue;
}
else LOG_D(NR_MAC,"%4d.%2d UL Retransmission UE RNTI %04x to be allocated, max_num_ue %d\n",frame,slot,UE->rnti,max_num_ue);
else
LOG_D(NR_MAC,"%4d.%2d UL Retransmission UE RNTI %04x to be allocated, max_num_ue %d\n", frame, slot, UE->rnti,max_num_ue);
/* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
remainUEs--;
remainUEs[beam.idx]--;
continue;
}
}
/* skip this UE if there are no free HARQ processes. This can happen e.g.
* if the UE disconnected in L2sim, in which case the gNB is not notified
* (this can be considered a design flaw) */
if (sched_ctrl->available_ul_harq.head < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] has no free UL HARQ process, skipping\n",
UE->rnti,
frame,
slot);
reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam);
reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam);
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] has no free UL HARQ process, skipping\n", UE->rnti, frame, slot);
continue;
}
@@ -1866,8 +1889,10 @@ static void pf_ul(module_id_t module_id,
/* preprocessor computed sched_frame/sched_slot */
const bool do_sched = nr_UE_is_to_be_scheduled(scc, 0, UE, sched_frame, sched_slot, nrmac->ulsch_max_frame_inactivity);
LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n",UE->rnti,do_sched ? "yes" : "no");
LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n", UE->rnti, do_sched ? "yes" : "no");
if ((B == 0 && !do_sched) || nr_timer_is_active(&sched_ctrl->transm_interrupt)) {
reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam);
reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam);
continue;
}
@@ -1879,7 +1904,7 @@ static void pf_ul(module_id_t module_id,
sched_ctrl->ul_bler_stats.mcs = sched_pusch->mcs;
} else {
sched_pusch->mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->ul_bler_stats, max_mcs, frame);
LOG_D(NR_MAC,"%d.%d starting mcs %d bleri %f\n",frame,slot,sched_pusch->mcs,sched_ctrl->ul_bler_stats.bler);
LOG_D(NR_MAC,"%d.%d starting mcs %d bleri %f\n", frame, slot, sched_pusch->mcs, sched_ctrl->ul_bler_stats.bler);
}
/* Schedule UE on SR or UL inactivity and no data (otherwise, will be scheduled
* based on data to transmit) */
@@ -1889,16 +1914,15 @@ static void pf_ul(module_id_t module_id,
int CCEIndex = get_cce_index(nrmac,
CC_id, slot, UE->rnti,
&sched_ctrl->aggregation_level,
0, // TODO use beam index
dci_beam.idx,
sched_ctrl->search_space,
sched_ctrl->coreset,
&sched_ctrl->sched_pdcch,
false);
if (CCEIndex<0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI (BSR 0)\n",
UE->rnti,
frame,
slot);
if (CCEIndex < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI (BSR 0)\n", UE->rnti, frame, slot);
reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam);
reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam);
continue;
}
@@ -1910,10 +1934,7 @@ static void pf_ul(module_id_t module_id,
TYPE_C_RNTI_,
sched_pusch->time_domain_allocation);
AssertFatal(sched_pusch->tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n");
sched_pusch->dmrs_info = get_ul_dmrs_params(scc,
current_BWP,
&sched_pusch->tda_info,
sched_pusch->nrOfLayers);
sched_pusch->dmrs_info = get_ul_dmrs_params(scc, current_BWP, &sched_pusch->tda_info, sched_pusch->nrOfLayers);
int rbStart = 0; // wrt BWP start
LOG_D(NR_MAC,
@@ -1935,11 +1956,13 @@ static void pf_ul(module_id_t module_id,
rbStart,
min_rb,
bwpSize);
reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam);
reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam);
continue;
}
sched_ctrl->cce_index = CCEIndex;
fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, 0); // TODO use beam index
fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx);
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
sched_pusch->mcs = min(nrmac->min_grant_mcs, sched_pusch->mcs);
@@ -1977,11 +2000,11 @@ static void pf_ul(module_id_t module_id,
sched_pusch->phr_txpower_calc);
/* Mark the corresponding RBs as used */
n_rb_sched -= sched_pusch->rbSize;
n_rb_sched[beam.idx] -= sched_pusch->rbSize;
for (int rb = bwpStart; rb < sched_ctrl->sched_pusch.rbSize; rb++)
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] |= slbitmap;
remainUEs--;
remainUEs[beam.idx]--;
continue;
}
@@ -2006,31 +2029,59 @@ static void pf_ul(module_id_t module_id,
UEsched_t *iterator=UE_sched;
/* Loop UE_sched to find max coeff and allocate transmission */
while (remainUEs > 0 && n_rb_sched >= min_rb && iterator->UE != NULL) {
while (iterator->UE != NULL) {
NR_UE_UL_BWP_t *current_BWP = &iterator->UE->current_UL_BWP;
NR_UE_DL_BWP_t *dl_BWP = &iterator->UE->current_DL_BWP;
NR_UE_sched_ctrl_t *sched_ctrl = &iterator->UE->UE_sched_ctrl;
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
int n = nr_slots_per_frame[current_BWP->scs];
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info,
sched_pusch->frame,
sched_pusch->slot,
iterator->UE->UE_beam_index,
n);
if (beam.idx < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", iterator->UE->rnti, frame, slot);
iterator++;
continue;
}
if (remainUEs[beam.idx] == 0 || n_rb_sched[beam.idx] < min_rb) {
reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam);
iterator++;
continue;
}
int n_dl = nr_slots_per_frame[dl_BWP->scs];
NR_beam_alloc_t dci_beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, n_dl);
if (dci_beam.idx < 0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", iterator->UE->rnti, frame, slot);
reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam);
iterator++;
continue;
}
int CCEIndex = get_cce_index(nrmac,
CC_id, slot, iterator->UE->rnti,
&sched_ctrl->aggregation_level,
0, // TODO use beam index
dci_beam.idx,
sched_ctrl->search_space,
sched_ctrl->coreset,
&sched_ctrl->sched_pdcch,
false);
if (CCEIndex<0) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI\n",
iterator->UE->rnti,
frame,
slot);
if (CCEIndex < 0) {
reset_beam_status(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, n_dl, dci_beam.new_beam);
reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam);
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI\n", iterator->UE->rnti, frame, slot);
iterator++;
continue;
}
else LOG_D(NR_MAC, "%4d.%2d free CCE for UL DCI UE %04x\n",frame,slot, iterator->UE->rnti);
else
LOG_D(NR_MAC, "%4d.%2d free CCE for UL DCI UE %04x\n", frame, slot, iterator->UE->rnti);
NR_UE_UL_BWP_t *current_BWP = &iterator->UE->current_UL_BWP;
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1;
sched_pusch->time_domain_allocation = get_ul_tda(nrmac, scc, sched_frame, sched_slot);
@@ -2040,14 +2091,10 @@ static void pf_ul(module_id_t module_id,
TYPE_C_RNTI_,
sched_pusch->time_domain_allocation);
AssertFatal(sched_pusch->tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n");
sched_pusch->dmrs_info = get_ul_dmrs_params(scc,
current_BWP,
&sched_pusch->tda_info,
sched_pusch->nrOfLayers);
sched_pusch->dmrs_info = get_ul_dmrs_params(scc, current_BWP, &sched_pusch->tda_info, sched_pusch->nrOfLayers);
const int index = ul_buffer_index(sched_frame, sched_slot, current_BWP->scs, nrmac->vrb_map_UL_size);
// TODO improve handling of beam in vrb_map (for now just using 0)
uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[0][index * MAX_BWP_SIZE];
uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE];
int rbStart = 0;
const uint16_t slbitmap = SL_to_bitmap(sched_pusch->tda_info.startSymbolIndex, sched_pusch->tda_info.nrOfSymbols);
@@ -2061,6 +2108,8 @@ static void pf_ul(module_id_t module_id,
max_rbSize++;
if (rbStart + min_rb >= bwpSize || max_rbSize < min_rb) {
reset_beam_status(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, n_dl, dci_beam.new_beam);
reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam);
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not allocate UL data: no resources (rbStart %d, min_rb %d, bwpSize %d)\n",
iterator->UE->rnti,
frame,
@@ -2135,19 +2184,19 @@ static void pf_ul(module_id_t module_id,
/* Mark the corresponding RBs as used */
sched_ctrl->cce_index = CCEIndex;
fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, 0); // TODO use beam index
fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx);
n_rb_sched -= sched_pusch->rbSize;
n_rb_sched[beam.idx] -= sched_pusch->rbSize;
for (int rb = bwpStart; rb < sched_ctrl->sched_pusch.rbSize; rb++)
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] |= slbitmap;
/* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
remainUEs--;
remainUEs[beam.idx]--;
iterator++;
}
}
static bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot)
static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot)
{
gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
// no UEs
@@ -2167,8 +2216,12 @@ static bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_
if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot))
return false;
int num_beams = nr_mac->beam_info.beam_allocation ? nr_mac->beam_info.beams_per_period : 1;
int bw = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
int len[num_beams];
for (int i = 0; i < num_beams; i++)
len[i] = bw;
int average_agg_level = 4; // TODO find a better estimation
int max_sched_ues = bw / (average_agg_level * NR_NB_REG_PER_CCE);
@@ -2176,11 +2229,11 @@ static bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_
max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET);
/* proportional fair scheduling algorithm */
pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.list, max_sched_ues, bw);
pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.list, max_sched_ues, num_beams, len);
return true;
}
nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id)
nr_pp_impl_ul nr_init_ulsch_preprocessor(int CC_id)
{
/* during initialization: no mutex needed */
/* in the PF algorithm, we have to use the TBsize to compute the coefficient.
@@ -2208,7 +2261,7 @@ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id)
>> 3;
}
}
return nr_fr1_ulsch_preprocessor;
return nr_ulsch_preprocessor;
}
void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, nfapi_nr_ul_dci_request_t *ul_dci_req)
+5 -5
View File
@@ -82,8 +82,8 @@ void nr_schedule_ue_spec(module_id_t module_id,
nfapi_nr_dl_tti_request_t *DL_req,
nfapi_nr_tx_data_request_t *TX_req);
/* \brief default FR1 DL preprocessor init routine, returns preprocessor to call */
nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id);
/* \brief default DL preprocessor init routine, returns preprocessor to call */
nr_pp_impl_dl nr_init_dlsch_preprocessor(int CC_id);
void schedule_nr_sib1(module_id_t module_idP,
frame_t frameP,
@@ -108,8 +108,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
* messages, statistics, HARQ handling, ... */
void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, nfapi_nr_ul_dci_request_t *ul_dci_req);
/* \brief default FR1 UL preprocessor init routine, returns preprocessor to call */
nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id);
/* \brief default UL preprocessor init routine, returns preprocessor to call */
nr_pp_impl_ul nr_init_ulsch_preprocessor(int CC_id);
/////// Random Access MAC-PHY interface functions and primitives ///////
@@ -447,7 +447,7 @@ void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST
int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx);
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame);
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame, bool new_beam);
void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE);
void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP);
size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp);
+2 -2
View File
@@ -294,8 +294,8 @@ void mac_top_init_gNB(ngran_node_t node_type,
RC.nrmac[i]->pre_processor_dl = nr_preprocessor_phytest;
RC.nrmac[i]->pre_processor_ul = nr_ul_preprocessor_phytest;
} else {
RC.nrmac[i]->pre_processor_dl = nr_init_fr1_dlsch_preprocessor(0);
RC.nrmac[i]->pre_processor_ul = nr_init_fr1_ulsch_preprocessor(0);
RC.nrmac[i]->pre_processor_dl = nr_init_dlsch_preprocessor(0);
RC.nrmac[i]->pre_processor_ul = nr_init_ulsch_preprocessor(0);
}
if (!IS_SOFTMODEM_NOSTATS)
threadCreate(&RC.nrmac[i]->stats_thread,
+7 -7
View File
@@ -523,16 +523,16 @@ struct CRI_RI_LI_PMI_CQI {
bool print_report;
};
typedef struct CRI_SSB_RSRP {
uint8_t nr_ssbri_cri;
uint8_t CRI_SSBRI[MAX_NR_OF_REPORTED_RS];
uint8_t RSRP;
uint8_t diff_RSRP[MAX_NR_OF_REPORTED_RS - 1];
} CRI_SSB_RSRP_t;
typedef struct RSRP_report {
uint8_t nr_reports;
uint8_t resource_id[MAX_NR_OF_REPORTED_RS];
int RSRP[MAX_NR_OF_REPORTED_RS];
} RSRP_report_t;
struct CSI_Report {
struct CRI_RI_LI_PMI_CQI cri_ri_li_pmi_cqi_report;
struct CRI_SSB_RSRP ssb_cri_report;
RSRP_report_t ssb_rsrp_report;
RSRP_report_t csirs_rsrp_report;
};
#define MAX_SR_BITLEN 8