With SC-FDMA, scheduler in uplink needs to schedule N_PRB=2^x3^y5^z

Signed-off-by: Calvin Peyron <calvin.peyron@open-cells.com>
This commit is contained in:
Calvin Peyron
2026-07-06 11:10:45 +02:00
parent 0dab3bb6a1
commit ad304b62d6
4 changed files with 48 additions and 25 deletions

View File

@@ -1733,6 +1733,21 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
else else
ul_bler_options->harq_round_max = *gpd(params, np, MACRLC_UL_HARQ_ROUND_MAX)->u8ptr; ul_bler_options->harq_round_max = *gpd(params, np, MACRLC_UL_HARQ_ROUND_MAX)->u8ptr;
RC.nrmac[j]->min_grant_prb = *gpd(params, np, MACRLC_MIN_GRANT_PRB)->u16ptr; RC.nrmac[j]->min_grant_prb = *gpd(params, np, MACRLC_MIN_GRANT_PRB)->u16ptr;
long sc_fdma = NR_PUSCH_Config__transformPrecoder_enabled;
NR_BWP_UplinkCommon_t *bwp = RC.nrmac[j]->common_channels[0].ServingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP;
if (bwp->rach_ConfigCommon->choice.setup->msg3_transformPrecoder != NULL)
sc_fdma = *bwp->rach_ConfigCommon->choice.setup->msg3_transformPrecoder;
int new_min = check_sc_fdma_rbsize(sc_fdma, RC.nrmac[j]->min_grant_prb);
// NR_PUSCH_Config__transformPrecoder_enabled = 0 | NR_PUSCH_Config__transformPrecoder_disabled = 1, so !uses_sc_fdma should
// be used
if (sc_fdma == NR_PUSCH_Config__transformPrecoder_enabled && RC.nrmac[j]->min_grant_prb != new_min) {
LOG_W(NR_MAC,
"min_rb value is set as %d. In SC-FDMA, it should be under format 2^x*3^y*5^z and has been automatically decreased "
"to %d.\n",
RC.nrmac[j]->min_grant_prb,
new_min);
RC.nrmac[j]->min_grant_prb = new_min;
}
RC.nrmac[j]->identity_pm = *gpd(params, np, MACRLC_IDENTITY_PM)->u8ptr; RC.nrmac[j]->identity_pm = *gpd(params, np, MACRLC_IDENTITY_PM)->u8ptr;
// PRB Blacklist // PRB Blacklist
uint16_t prbbl[MAX_BWP_SIZE] = {0}; uint16_t prbbl[MAX_BWP_SIZE] = {0};

View File

@@ -678,18 +678,6 @@ bool update_rb_mcs_tbs(NR_sched_pdsch_t *pdsch, uint32_t num_total_bytes, uint16
return true; return true;
} }
static bool multiple_2_3_5(int rb)
{
while (rb % 2 == 0)
rb /= 2;
while (rb % 3 == 0)
rb /= 3;
while (rb % 5 == 0)
rb /= 5;
return (rb == 1);
}
bool nr_find_nb_rb(uint16_t Qm, bool nr_find_nb_rb(uint16_t Qm,
uint16_t R, uint16_t R,
long transform_precoding, long transform_precoding,
@@ -702,10 +690,6 @@ bool nr_find_nb_rb(uint16_t Qm,
uint32_t *tbs, uint32_t *tbs,
uint16_t *nb_rb) uint16_t *nb_rb)
{ {
// for transform precoding only RB = 2^a_2 * 3^a_3 * 5^a_5 is allowed with a non-negative
while (transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled && !multiple_2_3_5(nb_rb_max))
nb_rb_max--;
/* is the maximum (not even) enough? */ /* is the maximum (not even) enough? */
*nb_rb = nb_rb_max; *nb_rb = nb_rb_max;
*tbs = nr_compute_tbs(Qm, R, *nb_rb, nb_symb_sch, nb_dmrs_prb, 0, 0, nrOfLayers) >> 3; *tbs = nr_compute_tbs(Qm, R, *nb_rb, nb_symb_sch, nb_dmrs_prb, 0, 0, nrOfLayers) >> 3;
@@ -727,11 +711,6 @@ bool nr_find_nb_rb(uint16_t Qm,
int hi = nb_rb_max; int hi = nb_rb_max;
int lo = nb_rb_min; int lo = nb_rb_min;
for (int p = (hi + lo) / 2; lo + 1 < hi; p = (hi + lo) / 2) { for (int p = (hi + lo) / 2; lo + 1 < hi; p = (hi + lo) / 2) {
// for transform precoding only RB = 2^a_2 * 3^a_3 * 5^a_5 is allowed with a non-negative
while(transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled &&
!multiple_2_3_5(p))
p++;
// If by increasing p for transform precoding we already hit the high, break to avoid infinite loop // If by increasing p for transform precoding we already hit the high, break to avoid infinite loop
if (p == hi) if (p == hi)
break; break;

View File

@@ -14,9 +14,33 @@
#include <openair2/UTIL/OPT/opt.h> #include <openair2/UTIL/OPT/opt.h>
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
static const uint16_t NR_TRANSFORM_PRECODE_RB_LUT[274] = {
0, 1, 2, 3, 4, 5, 6, 6, 8, 9, 10, 10, 12, 12, 12, 15, 16, 16, 18, 18, 20, 20, 20, 20, 24,
25, 25, 27, 27, 27, 30, 30, 32, 32, 32, 32, 36, 36, 36, 36, 40, 40, 40, 40, 40, 45, 45, 45, 48, 48,
50, 50, 50, 50, 54, 54, 54, 54, 54, 54, 60, 60, 60, 60, 64, 64, 64, 64, 64, 64, 64, 64, 72, 72, 72,
75, 75, 75, 75, 75, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 90, 90, 90, 90, 90, 90, 96, 96, 96, 96,
100, 100, 100, 100, 100, 100, 100, 100, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 120, 120, 120, 120, 120,
125, 125, 125, 128, 128, 128, 128, 128, 128, 128, 135, 135, 135, 135, 135, 135, 135, 135, 135, 144, 144, 144, 144, 144, 144,
150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 160, 160, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 192, 192, 192, 192, 192, 192, 192, 192,
200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 216, 216, 216, 216, 216, 216, 216, 216, 216,
225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243,
250, 250, 250, 250, 250, 250, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 270, 270, 270, 270};
//#define SRS_IND_DEBUG //#define SRS_IND_DEBUG
#define MAX_NUM_DATA_IND 1024 #define MAX_NUM_DATA_IND 1024
// With SC-FDMA the scheduler in uplink needs to schedule N_PRB=2^x3^y5^z
// Check 6.3.1.4 of 38.211
int check_sc_fdma_rbsize(long transform_precoding, uint16_t rb)
{
DevAssert(rb < 274);
if (transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) {
return NR_TRANSFORM_PRECODE_RB_LUT[rb];
}
return rb;
}
/* \brief Get the number of UL TDAs that could be used in slot, reachable /* \brief Get the number of UL TDAs that could be used in slot, reachable
* via specific k2. The output parameter first_idx is a pointer to the first * via specific k2. The output parameter first_idx is a pointer to the first
* suitable TDA, and the function returns the number of suitable TDAs, or 0. */ * suitable TDA, and the function returns the number of suitable TDAs, or 0. */
@@ -1760,11 +1784,11 @@ static int apply_ul_retransmission(gNB_MAC_INST *nrmac,
} else { } else {
/* TDA changed vs original retx: recompute DMRS and TB size for new TDA */ /* TDA changed vs original retx: recompute DMRS and TB size for new TDA */
NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, current_BWP, tda_info, nrOfLayers); NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, current_BWP, tda_info, nrOfLayers);
new_sched.rbSize = cand->sched_pusch.rbSize; new_sched.rbSize = check_sc_fdma_rbsize(current_BWP->transform_precoding, cand->sched_pusch.rbSize);
new_sched.rbStart = cand->sched_pusch.rbStart; new_sched.rbStart = cand->sched_pusch.rbStart;
new_sched.tb_size = nr_compute_tbs(retInfo->Qm, new_sched.tb_size = nr_compute_tbs(retInfo->Qm,
retInfo->R, retInfo->R,
cand->sched_pusch.rbSize, new_sched.rbSize,
tda_info->nrOfSymbols, tda_info->nrOfSymbols,
dmrs_info.N_PRB_DMRS * dmrs_info.num_dmrs_symb, dmrs_info.N_PRB_DMRS * dmrs_info.num_dmrs_symb,
0, 0,
@@ -1819,6 +1843,7 @@ static int apply_ul_new_transmission(gNB_MAC_INST *nrmac,
* time_domain_allocation, tda_info already set by pipeline stages). * time_domain_allocation, tda_info already set by pipeline stages).
* Fill remaining dispatch fields: R, Qm, tb_size, dmrs_info, bwp_info. */ * Fill remaining dispatch fields: R, Qm, tb_size, dmrs_info, bwp_info. */
NR_sched_pusch_t sched = cand->sched_pusch; NR_sched_pusch_t sched = cand->sched_pusch;
sched.rbSize = check_sc_fdma_rbsize(current_BWP->transform_precoding, sched.rbSize);
sched.frame = sched_frame; sched.frame = sched_frame;
sched.slot = sched_slot; sched.slot = sched_slot;
sched.ul_harq_pid = -1; sched.ul_harq_pid = -1;
@@ -2625,6 +2650,7 @@ bool nr_ul_check_phr(const nr_ul_sched_params_t *params,
pot.dmrs_info = dmrs_info; pot.dmrs_info = dmrs_info;
pot.nrOfLayers = cand->sched_pusch.nrOfLayers; pot.nrOfLayers = cand->sched_pusch.nrOfLayers;
pot.rbSize = rbSize; pot.rbSize = rbSize;
pot.rbSize = check_sc_fdma_rbsize(current_BWP->transform_precoding, pot.rbSize);
pot.mcs = mcs; pot.mcs = mcs;
uint16_t R; uint16_t R;
@@ -2646,8 +2672,9 @@ bool nr_ul_check_phr(const nr_ul_sched_params_t *params,
NR_sched_pusch_t p1 = pot; NR_sched_pusch_t p1 = pot;
int tp = tx_power; int tp = tx_power;
while (cand->ph < tp && p1.rbSize > params->min_rb) { while (cand->ph < tp && p1.rbSize > params->min_rb
p1.rbSize--; && check_sc_fdma_rbsize(current_BWP->transform_precoding, p1.rbSize - 1) >= params->min_rb) {
p1.rbSize = check_sc_fdma_rbsize(current_BWP->transform_precoding, --p1.rbSize);
p1.tb_size = nr_compute_tbs(p1.Qm, p1.R, p1.rbSize, p1.tda_info.nrOfSymbols, n_dmrs, 0, 0, p1.nrOfLayers) >> 3; p1.tb_size = nr_compute_tbs(p1.Qm, p1.R, p1.rbSize, p1.tda_info.nrOfSymbols, n_dmrs, 0, 0, p1.nrOfLayers) >> 3;
tp = compute_ph_rb_factor(current_BWP->scs, p1.rbSize) + (hasDeltaMCS ? compute_ph_mcs_factor(&p1) : 0); tp = compute_ph_rb_factor(current_BWP->scs, p1.rbSize) + (hasDeltaMCS ? compute_ph_mcs_factor(&p1) : 0);
} }

View File

@@ -89,6 +89,8 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_
/* \brief default UL preprocessor */ /* \brief default UL preprocessor */
void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch); void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch);
int check_sc_fdma_rbsize(long transform_precoding, uint16_t rb);
void nr_mac_pcch_queue_init(NR_COMMON_channels_t *cc); void nr_mac_pcch_queue_init(NR_COMMON_channels_t *cc);
void nr_mac_pcch_queue_free(NR_COMMON_channels_t *cc); void nr_mac_pcch_queue_free(NR_COMMON_channels_t *cc);
void nr_mac_pcch_enqueue(module_id_t module_id, uint64_t fiveg_s_tmsi, uint16_t ue_id); void nr_mac_pcch_enqueue(module_id_t module_id, uint64_t fiveg_s_tmsi, uint16_t ue_id);