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:
@@ -192,10 +192,10 @@ In the `MACRLCs` section of the gNB/DU configuration file:
|
||||
* `identity_precoding_matrix` (default 0=false): flag to enable to use only
|
||||
the identity precoding matrix in DL precoding
|
||||
* `set_analog_beamforming` (default 0=false): flag to enable analog
|
||||
beamforming
|
||||
* `beam_duration`: duration/number of consecutive slots for a given set of
|
||||
beamforming (for more information [`analog_beamforming.md`](../analog_beamforming.md))
|
||||
* `beam_duration` (default 1): duration/number of consecutive slots for a given set of
|
||||
beams, depending on hardware switching performance
|
||||
* `beams_per_period`: set of beams that can be simultaneously allocated in a
|
||||
* `beams_per_period` (default 1): set of beams that can be simultaneously allocated in a
|
||||
period (`beam_duration`)
|
||||
|
||||
In the `gNBs` section of the gNB/DU configuration file: some of the parameters
|
||||
|
||||
@@ -84,6 +84,7 @@ Legacy unmaintained files:
|
||||
- [L1 threads in NR-UE](./nr-ue-design.md)
|
||||
- [Information on gNB MAC](./MAC/mac-usage.md)
|
||||
- [Information on gNB RRC](./RRC/rrc-usage.md)
|
||||
- [Information on analog beamforming implementation](./analog_beamforming.md)
|
||||
|
||||
Legacy unmaintained files:
|
||||
- [`5Gnas.md`](./5Gnas.md)
|
||||
|
||||
+4
-9
@@ -220,14 +220,10 @@ Calls nr_schedule_ulsch(): It is divided into the "preprocessor" and the
|
||||
"postprocessor": the first makes the scheduling decisions, the second fills
|
||||
nFAPI structures to indicate to the PHY what it is supposed to do. To signal
|
||||
which users have how many resources, the preprocessor populates the
|
||||
NR_sched_pusch_t (for values changing every TTI, e.g., frequency domain
|
||||
allocation) and NR_sched_pusch_save_t (for values changing less frequently, at
|
||||
least in FR1 [to my understanding], e.g., DMRS fields when the time domain
|
||||
allocation stays between TTIs) structures. Furthermore, the preprocessor is an
|
||||
NR_sched_pusch_t structures. Furthermore, the preprocessor is an
|
||||
exchangeable module that schedules differently based on a particular
|
||||
use-case/deployment type, e.g., one user for phytest [in
|
||||
nr_ul_preprocessor_phytest()], multiple users in FR1
|
||||
[nr_fr1_ulsch_preprocessor()], or maybe FR2 [does not exist yet]:
|
||||
use-case/deployment type, e.g., one user for phytest in
|
||||
[nr_ul_preprocessor_phytest()], multiple users in [nr_ulsch_preprocessor()]:
|
||||
* calls preprocessor via pre_processor_ul(): the preprocessor is responsible
|
||||
for allocating CCEs (using allocate_nr_CCEs()) and deciding on resource
|
||||
allocation for the UEs including TB size. Note that we do not yet have
|
||||
@@ -258,8 +254,7 @@ NR_UE_sched_ctrl_t structure of affected users. In particular, the field rbSize
|
||||
decides whether a user is to be allocated. Furthermore, the preprocessor is an
|
||||
exchangeable module that schedules differently based on a particular
|
||||
use-case/deployment type, e.g., one user for phytest [in
|
||||
nr_preprocessor_phytest()], multiple users in FR1
|
||||
[nr_fr1_dlsch_preprocessor()], or maybe FR2 [does not exist yet].
|
||||
nr_preprocessor_phytest()], multiple users [nr_dlsch_preprocessor()].
|
||||
* calls preprocessor via pre_processor_dl(): the preprocessor is responsible
|
||||
for allocating CCEs and PUCCH (using allocate_nr_CCEs() and
|
||||
nr_acknack_scheduling()) and deciding on the frequency/time domain
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
This document explains the implementation of analog beamforming in OAI codebase.
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
# Introduction to analog beamforming
|
||||
|
||||
Beamforming is a technique applied to antenna arrays to create a directional radiation pattern. This often consists in providing a different phase shift to each element of the array such that signals with a different angle of arrival/departure experience a change in radiation pattern because of constructive or destructive interference.
|
||||
|
||||
There are three main beamforming techinques: analog, digital and hybrid. The names refer to the phase shift application before or after the digital to analog conversion (or analog to digital in reception). When we speak about analog beamforming we generally refer to a techinique where the phase shifts that produce the beam stearing are applied by the radio unit (RU) choosing from a finite set of steering directions. The advantage of analog beamforming is a simplified analog circuitry and therefore reduced costs.
|
||||
|
||||
The presence of a limited number of predefined beams at RU poses constraints to the scheduler at gNB. As a matter of fact, the scheduler can serve only a limited number of beams, depending on the RU characteristics (possibly only 1), in a given time scale, that also depends on the RU characteristics (e.g. 1 slot or 1 symbol). This limitation doesn't exist for digital beamforming.
|
||||
|
||||
# Configuration file fields for analog beamforming
|
||||
|
||||
A set of parameters in configuration files controls the implementation of analog beamforming and instructs the scheduler on how to behave in such scenarios. Since most notably this technique in 5G is employed in FR2, the configuration file example currently available is a RFsim one for band 261. [Config file example](../ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf)
|
||||
|
||||
In the `MACRLC` section of configuration files, there are three new parameters: `set_analog_beamforming`, `beam_duration` and `beams_per_period`. The explanation of these parameters is here provided:
|
||||
- `set_analog_beamforming` can be set to 1 or 0 to activate or desactivate analog beamforming (default value is 0)
|
||||
- `beam_duration` is the number of slots (currently minimum duration of a beam) the scheduler is tied to a beam (default value is 1)
|
||||
- `beams_per_period` is the number of concurrent beams the RU can handle in the beam duration (default value is 1)
|
||||
|
||||
In the `gNBs` section of the configuration file, under the phyisical parameters, a vector field containing the set of beam indices to be provided by the OAI L1 to the RU is also required. This field is called `beam_weights`. In current implementation, the number of beam indices should be equal to the number of SSBs transmitted.
|
||||
|
||||
# Implementation in OAI scheduler
|
||||
|
||||
A new MAC structure `NR_beam_info_t` controls the behavior of the scheduler in presence of analog beamforming. Besides the already mentioned parameters `beam_duration` and `beams_per_period`, the structure also holds a matrix `beam_allocation[i][j]`, whose indices `i` and `j` stands respectively for the number of beams in the period and the slot index (the size of the latter depends on the frame characteristics).
|
||||
This matrix contains the beams already allocated in a given slot, to flag the scheduler to use one of these to schedule a UE in one of these beams. If the matrix is full (all the beams in the given period, e.g. slot) are already allocated, the scheduler can't allocate a UE in a new beam.
|
||||
To this goal, we extended the virtual resource block (VRB) map by one dimension to also contain information per allocated beam. As said, the scheduler can independently schedule users in a number of beams up to `beams_per_period` concurrently.
|
||||
|
||||
It is important to note that in current implementation, there are several periodical channels, e.g. PRACH or PUCCH for CSI et cetera, that have the precendence in being assigned a beam, that is because the scheduling is automatic, set in RRC configuration, and not up to the scheduler. For these instances, we assume the beam is available (if not there are assertions to stop the process). For data channels, the currently implemented PF scheduler is used. The only modification is that a UE can be served only if there is a free beam available or the one of the beams already in use correspond to that UE beam.
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user