Merge remote-tracking branch 'origin/refactor-ulsch' into integration_2025_w33 (!3521)

Refactor ULSCH scheduler towards more TDD pattern flexibility

Refactors ULSCH scheduler, notably to support "UL-heavy" TDD patterns,
e.g., DSUUU. Also allows to run TDD pattern2 with UL slots, which was a
limitation in the previous code.
This commit is contained in:
Robert Schmidt
2025-08-14 14:30:58 +02:00
147 changed files with 1019 additions and 1172 deletions
@@ -66,7 +66,7 @@ bool read_mac_sm(void* data)
}
if (is_ul_slot(rd->slot, &RC.nrmac[mod_id]->frame_structure)) {
rd->ul_curr_tbs = UE->mac_stats.ul.current_bytes;
rd->ul_sched_rb = sched_ctrl->sched_pusch.rbSize;
rd->ul_sched_rb = UE->mac_stats.ul.current_rbs;
}
rd->rnti = UE->rnti;
+1 -1
View File
@@ -228,7 +228,7 @@
{GNB_CONFIG_STRING_PREAMBLERECEIVEDTARGETPOWER,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower,.defint64val=-118,TYPE_INT64,0/*75*/},\
{GNB_CONFIG_STRING_PREAMBLETRANSMAX,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleTransMax,.defint64val=NR_RACH_ConfigGeneric__preambleTransMax_n10,TYPE_INT64,0/*76*/},\
{GNB_CONFIG_STRING_POWERRAMPINGSTEP,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.powerRampingStep,.defint64val=NR_RACH_ConfigGeneric__powerRampingStep_dB2,TYPE_INT64,0/*77*/},\
{GNB_CONFIG_STRING_RARESPONSEWINDOW,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow,.defint64val=NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20,TYPE_INT64,0/*78*/},\
{GNB_CONFIG_STRING_RARESPONSEWINDOW,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow,.defint64val=-1,TYPE_INT64,0/*78*/},\
{GNB_CONFIG_STRING_SSBPERRACHOCCASIONANDCBPREAMBLESPERSSBPR,NULL,0,.uptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present,.defuintval=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one,TYPE_UINT,0/*79*/},\
{GNB_CONFIG_STRING_SSBPERRACHOCCASIONANDCBPREAMBLESPERSSB,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one,.defint64val=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB__one_n64,TYPE_INT64,0 /*80*/}, \
{GNB_CONFIG_STRING_RACONTENTIONRESOLUTIONTIMER,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer,.defint64val=NR_RACH_ConfigCommon__ra_ContentionResolutionTimer_sf64,TYPE_INT64,0/*81*/},\
+11 -7
View File
@@ -575,6 +575,14 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap)
rach_ConfigCommon->msg3_transformPrecoder = NULL;
}
// by default, select ra_ResponseWindow automatically
if (rach_ConfigCommon->rach_ConfigGeneric.ra_ResponseWindow < 0) {
int mu = *scc->ssbSubcarrierSpacing;
// will select: mu=0 => 4 (10 slots), mu=1 => 5 (20 slots), mu>=3 => 7 (80 slots)
rach_ConfigCommon->rach_ConfigGeneric.ra_ResponseWindow = min(NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80, NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10 + mu);
}
DevAssert(rach_ConfigCommon->rach_ConfigGeneric.ra_ResponseWindow >= 0);
// prepare DL Allocation lists
nr_rrc_config_dl_tda(dlcc->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList,
frame_type,
@@ -1157,7 +1165,7 @@ bool is_pattern2_config(paramdef_t *param)
return true;
}
static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cfg, int minRXTXTIME)
static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cfg, int minRXTXTIME, int do_SRS)
{
NR_ServingCellConfigCommon_t *scc = calloc_or_fail(1, sizeof(*scc));
uint64_t ssb_bitmap=0xff;
@@ -1198,10 +1206,6 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf
struct NR_TDD_UL_DL_ConfigCommon *tdd = scc->tdd_UL_DL_ConfigurationCommon;
tdd->pattern2 = calloc_or_fail(1, sizeof(*tdd->pattern2));
*scc->tdd_UL_DL_ConfigurationCommon->pattern2 = p2;
AssertFatal(p2.nrofUplinkSlots ^ scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,
"UL slots in pattern1 (%ld) and pattern2 (%ld) are mutually exclusive (e.g. DDDFUU DDDD, DDDD DDDFUU)\n",
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,
p2.nrofUplinkSlots);
}
struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
LOG_I(RRC,
@@ -1223,7 +1227,7 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf
check_ssb_raster(ssb_freq, *frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
fix_scc(scc, ssb_bitmap);
}
nr_rrc_config_ul_tda(scc, minRXTXTIME);
nr_rrc_config_ul_tda(scc, minRXTXTIME, do_SRS);
// the gNB uses the servingCellConfigCommon everywhere, even when it should use the servingCellConfigCommonSIB.
// previously (before this commit), the following fields were indirectly populated through get_SIB1_NR().
@@ -1688,7 +1692,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
config.num_agg_level_candidates[PDCCH_AGG_LEVEL8],
config.num_agg_level_candidates[PDCCH_AGG_LEVEL16]);
NR_ServingCellConfigCommon_t *scc = get_scc_config(cfg, config.minRXTXTIME);
NR_ServingCellConfigCommon_t *scc = get_scc_config(cfg, config.minRXTXTIME, config.do_SRS);
//xer_fprint(stdout, &asn_DEF_NR_ServingCellConfigCommon, scc);
NR_ServingCellConfig_t *scd = get_scd_config(cfg);
@@ -76,7 +76,7 @@ bool is_dl_slot(const slot_t slot, const frame_structure_t *fs);
bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs);
int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd);
void config_frame_structure(int mu,
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
const NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
uint8_t tdd_period,
uint8_t frame_type,
frame_structure_t *fs);
@@ -98,7 +98,7 @@ int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd)
*
* @return Number of slots in the configured TDD period
*/
static uint8_t set_tdd_bmap_period(NR_TDD_UL_DL_Pattern_t *pattern, tdd_period_config_t *pc, int8_t curr_total_slot)
static uint8_t set_tdd_bmap_period(const NR_TDD_UL_DL_Pattern_t *pattern, tdd_period_config_t *pc, int8_t curr_total_slot)
{
int8_t n_dl_slot = pattern->nrofDownlinkSlots;
int8_t n_ul_slot = pattern->nrofUplinkSlots;
@@ -154,7 +154,7 @@ static uint8_t set_tdd_bmap_period(NR_TDD_UL_DL_Pattern_t *pattern, tdd_period_c
*
* @return void
*/
static void config_tdd_patterns(NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_structure_t *fs)
static void config_tdd_patterns(const NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_structure_t *fs)
{
int num_of_patterns = 1;
uint8_t nb_slots_p2 = 0;
@@ -188,7 +188,7 @@ static void config_tdd_patterns(NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_structur
* @param fs pointer to the frame structure to update
*/
void config_frame_structure(int mu,
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
const NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
uint8_t tdd_period,
uint8_t frame_type,
frame_structure_t *fs)
+25
View File
@@ -832,6 +832,28 @@ static void config_sched_ctrlCommon(gNB_MAC_INST *nr_mac)
nr_mac->cset0_bwp_size = type0_PDCCH_CSS_config.num_rbs;
}
/**
* \brief Initializes the UL TDA information at the scheduler, as used for
* every UE in UL. This just copies the information from the SCC into a smaller
* list. Note that this list should not be modified, as get_num_ul_tda() and
* nr_rrc_config_ul_tda() are designed to work in sync (get_num_ul_tda()
* assumes an ordering, output by nr_rrc_config_ul_tda()).
*/
static void init_ul_tda_info(const NR_PUSCH_TimeDomainResourceAllocationList_t *l, seq_arr_t *sa_tda)
{
DevAssert(l->list.count > 0 && l->list.count <= 16);
DevAssert(seq_arr_size(sa_tda) == 0);
for (int i = 0; i < l->list.count; ++i) {
NR_PUSCH_TimeDomainResourceAllocation_t *t = l->list.array[i];
DevAssert(t->k2);
NR_tda_info_t tda = { .mapping_type = typeB, .k2 = *t->k2, .valid_tda = true };
SLIV2SL(t->startSymbolAndLength, &tda.startSymbolIndex, &tda.nrOfSymbols);
LOG_I(NR_MAC, "TDA index %d: start %d length %d k2 %ld\n", i, tda.startSymbolIndex, tda.nrOfSymbols, tda.k2);
seq_arr_push_back(sa_tda, &tda, sizeof(tda));
}
}
void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config)
{
DevAssert(nrmac != NULL);
@@ -878,6 +900,9 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
if (IS_SA_MODE(get_softmodem_params()))
config_sched_ctrlCommon(nrmac);
seq_arr_init(&nrmac->ul_tda, sizeof(NR_tda_info_t));
init_ul_tda_info(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList, &nrmac->ul_tda);
}
bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib])
+2 -10
View File
@@ -1013,18 +1013,10 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc,
if (fs->frame_type == TDD && !is_ul_slot(temp_slot, fs))
continue;
const tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap;
int s = get_slot_idx_in_period(temp_slot, fs);
// check if enough symbols in case of mixed slot
const tdd_bitmap_t *bm = &fs->period_cfg.tdd_slot_bitmap[s];
bool is_mixed = is_mixed_slot(s, fs);
// if the mixed slot has not enough symbols, skip
if (is_mixed && tdd_slot_bitmap[s].num_ul_symbols < 3)
continue;
uint16_t slot_mask =
is_mixed ? SL_to_bitmap(NR_NUMBER_OF_SYMBOLS_PER_SLOT - tdd_slot_bitmap[s].num_ul_symbols,
tdd_slot_bitmap[s].num_ul_symbols)
: 0x3fff;
uint16_t slot_mask = is_mixed ? SL_to_bitmap(NR_NUMBER_OF_SYMBOLS_PER_SLOT - bm->num_ul_symbols, bm->num_ul_symbols) : 0x3fff;
long startSymbolAndLength = tda_list->list.array[i]->startSymbolAndLength;
int start, nr;
SLIV2SL(startSymbolAndLength, &start, &nr);
@@ -554,6 +554,7 @@ static bool allocate_dl_retransmission(module_id_t module_id,
false,
sched_ctrl->pdcch_cl_adjust);
if (CCEIndex<0) {
sched_ctrl->dl_cce_fail++;
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find free CCE for DL DCI retransmission\n", UE->rnti, frame, slot);
return false;
}
@@ -806,6 +807,7 @@ static void pf_dl(module_id_t module_id,
false,
sched_ctrl->pdcch_cl_adjust);
if (CCEIndex < 0) {
sched_ctrl->dl_cce_fail++;
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, slots_per_frame, beam.new_beam);
iterator++;
@@ -208,9 +208,11 @@ uint32_t target_ul_mcs = 9;
uint32_t target_ul_bw = 50;
uint32_t target_ul_Nl = 1;
uint64_t ulsch_slot_bitmap = (1 << 8);
bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot)
void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch)
{
gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
int frame = pp_pusch->frame;
int slot = pp_pusch->slot;
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_COMMON_channels_t *cc = nr_mac->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
@@ -219,7 +221,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo
AssertFatal(nr_mac->UE_info.connected_ue_list[1] == NULL,
"cannot handle more than one UE\n");
if (UE == NULL)
return false;
return;
const int CC_id = 0;
@@ -229,72 +231,54 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo
/* return if all UL HARQ processes wait for feedback */
if (sched_ctrl->retrans_ul_harq.head == -1 && sched_ctrl->available_ul_harq.head == -1) {
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UE has no free UL HARQ process, skipping\n", UE->rnti, frame, slot);
return false;
return;
}
NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList = get_ul_tdalist(ul_bwp,
sched_ctrl->coreset->controlResourceSetId,
sched_ctrl->search_space->searchSpaceType->present,
TYPE_C_RNTI_);
const int temp_tda = get_ul_tda(nr_mac, frame, slot);
if (temp_tda < 0)
return false;
AssertFatal(temp_tda < tdaList->list.count, "time domain assignment %d >= %d\n", temp_tda, tdaList->list.count);
const int mu = ul_bwp->scs;
int K2 = get_K2(tdaList, temp_tda, mu, scc);
int slots_frame = nr_mac->frame_structure.numb_slots_frame;
const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER;
const int sched_slot = (slot + K2) % slots_frame;
const int tda = get_ul_tda(nr_mac, sched_frame, sched_slot);
if (tda < 0)
return false;
AssertFatal(tda < tdaList->list.count,
"time domain assignment %d >= %d\n",
tda,
tdaList->list.count);
/* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE
* limitations). Note that if K2 or the TDD configuration is changed, below
* conditions might exclude each other and never be true */
int slot_period = sched_slot % nr_mac->frame_structure.numb_slots_period;
if (!is_xlsch_in_slot(ulsch_slot_bitmap, slot_period))
return false;
uint16_t rbStart = 0;
uint16_t rbSize;
const int bw = ul_bwp->BWPSize;
const int BWPStart = ul_bwp->BWPStart;
uint16_t rbStart = 0;
uint16_t rbSize = min(bw, target_ul_bw);
if (target_ul_bw>bw)
rbSize = bw;
else
rbSize = target_ul_bw;
DevAssert(seq_arr_size(&nr_mac->ul_tda) > 0);
const int tda = 0;
NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp,
sched_ctrl->coreset->controlResourceSetId,
sched_ctrl->search_space->searchSpaceType->present,
TYPE_C_RNTI_,
tda);
if (!tda_info.valid_tda)
return false;
sched_ctrl->sched_pusch.tda_info = tda_info;
sched_ctrl->sched_pusch.time_domain_allocation = tda;
DevAssert(tda_info.valid_tda);
int K2 = tda_info.k2 + get_NTN_Koffset(scc);
int slots_frame = nr_mac->frame_structure.numb_slots_frame;
const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER;
const int sched_slot = (slot + K2) % slots_frame;
/* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE
* limitations). Note that if K2 or the TDD configuration is changed, below
* conditions might exclude each other and never be true */
int slot_period = sched_slot % nr_mac->frame_structure.numb_slots_period;
if (!is_xlsch_in_slot(ulsch_slot_bitmap, slot_period))
return;
// TODO implement beam procedures for phy-test mode
int beam = 0;
const NR_tda_info_t *tda_p;
const int n_tda = get_num_ul_tda(nr_mac, sched_slot, tda_info.k2, &tda_p);
DevAssert(n_tda > 0);
/* check only the first TDA: we are only interested in finding out if this TDA fits completely */
int rb_s = rbStart, rb_l = rbSize;
get_best_ul_tda(nr_mac, beam, tda_p, 1, sched_frame, sched_slot, &rb_s, &rb_l);
DevAssert(rb_s == rbStart && rb_l == rbSize);
const int buffer_index = ul_buffer_index(sched_frame, sched_slot, slots_frame, nr_mac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[beam][buffer_index * MAX_BWP_SIZE];
for (int i = rbStart; i < rbStart + rbSize; ++i) {
if ((vrb_map_UL[i+BWPStart] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) != 0) {
LOG_E(MAC, "%4d.%2d RB %d is already reserved, cannot schedule UE\n", frame, slot, i);
return false;
return;
}
}
sched_ctrl->sched_pusch.slot = sched_slot;
sched_ctrl->sched_pusch.frame = sched_frame;
int CCEIndex = get_cce_index(nr_mac,
CC_id, slot, UE->rnti,
&sched_ctrl->aggregation_level,
@@ -306,45 +290,50 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo
0);
if (CCEIndex < 0) {
LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__);
return false;
return;
}
sched_ctrl->cce_index = CCEIndex;
const int mcs = target_ul_mcs;
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
sched_pusch->mcs = mcs;
sched_ctrl->ul_bler_stats.mcs = mcs; /* for logging output */
sched_pusch->rbStart = rbStart;
sched_pusch->rbSize = rbSize;
/* get the PID of a HARQ process awaiting retransmission, or -1 for "any new" */
sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head;
NR_sched_pusch_t sched = {
.frame = sched_frame,
.slot = sched_slot,
.rbSize = rbSize,
.rbStart = rbStart,
.mcs = target_ul_mcs,
// R, Qm, tb_size set further below
// PID of a HARQ process awaiting retransmission, or -1 for "any new"
.ul_harq_pid = sched_ctrl->retrans_ul_harq.head,
.nrOfLayers = target_ul_Nl,
// tpmi in post-process
.time_domain_allocation = tda,
.tda_info = tda_info,
.dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, target_ul_Nl),
.bwp_info = get_pusch_bwp_start_size(UE),
};
sched_ctrl->ul_bler_stats.mcs = sched.mcs; /* for logging output */
/* Calculate TBS from MCS */
sched_pusch->nrOfLayers = target_ul_Nl;
sched_pusch->R = nr_get_code_rate_ul(mcs, ul_bwp->mcs_table);
sched_pusch->Qm = nr_get_Qm_ul(mcs, ul_bwp->mcs_table);
sched.R = nr_get_code_rate_ul(sched.mcs, ul_bwp->mcs_table);
sched.Qm = nr_get_Qm_ul(sched.mcs, ul_bwp->mcs_table);
if (ul_bwp->pusch_Config->tp_pi2BPSK
&& ((ul_bwp->mcs_table == 3 && mcs < 2) || (ul_bwp->mcs_table == 4 && mcs < 6))) {
sched_pusch->R >>= 1;
sched_pusch->Qm <<= 1;
&& ((ul_bwp->mcs_table == 3 && sched.mcs < 2) || (ul_bwp->mcs_table == 4 && sched.mcs < 6))) {
sched.R >>= 1;
sched.Qm <<= 1;
}
NR_pusch_dmrs_t dmrs = get_ul_dmrs_params(scc,
ul_bwp,
&tda_info,
sched_pusch->nrOfLayers);
sched_ctrl->sched_pusch.dmrs_info = dmrs;
sched.tb_size = nr_compute_tbs(sched.Qm,
sched.R,
sched.rbSize,
tda_info.nrOfSymbols,
sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb,
0, // nb_rb_oh
0,
sched.nrOfLayers /* NrOfLayers */)
>> 3;
sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
sched_pusch->R,
sched_pusch->rbSize,
tda_info.nrOfSymbols,
dmrs.N_PRB_DMRS * dmrs.num_dmrs_symb,
0, // nb_rb_oh
0,
sched_pusch->nrOfLayers /* NrOfLayers */)
>> 3;
/* save allocation to FAPI structures */
post_process_ulsch(nr_mac, pp_pusch, UE, &sched);
/* mark the corresponding RBs as used */
fill_pdcch_vrb_map(nr_mac,
@@ -356,5 +345,4 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo
for (int rb = rbStart; rb < rbStart + rbSize; rb++)
vrb_map_UL[rb+BWPStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
return true;
}
@@ -2700,7 +2700,6 @@ NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroup
/* set illegal time domain allocation to force recomputation of all fields */
sched_ctrl->sched_pdsch.time_domain_allocation = -1;
sched_ctrl->sched_pusch.time_domain_allocation = -1;
/* Set default BWPs */
AssertFatal(UE->sc_info.n_ul_bwp <= NR_MAX_NUM_BWP, "uplinkBWP_ToAddModList has %d BWP!\n", UE->sc_info.n_ul_bwp);
@@ -2775,8 +2774,6 @@ bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */
sched_ctrl->sched_srs.frame = -1;
sched_ctrl->sched_srs.slot = -1;
sched_ctrl->pdcch_cl_adjust = 0;
reset_srs_stats(UE);
+16 -32
View File
@@ -471,9 +471,15 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac,
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SRS in any available beam\n");
uint16_t *vrb_map_UL = &nrmac->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;
uint16_t num = 1 << srs_pdu->num_symbols; // 0,1,2 means 1,2,4 symbols, see 222.10.04 table 3-105
uint16_t mask = SL_to_bitmap(srs_pdu->time_start_position, num);
DevAssert(mask != 0);
for (int i = 0; i < srs_pdu->bwp_size; ++i) {
int rb = i + srs_pdu->bwp_start;
uint16_t alloc = vrb_map_UL[rb] & mask;
AssertFatal(nrmac->ulprbbl[rb] != 0 || alloc == 0, "RB %d not free for SRS: alloc 0x%02x for mask 0x%02x\n", rb, alloc, mask);
vrb_map_UL[rb] |= mask;
}
}
static void nr_fill_nfapi_srs(gNB_MAC_INST *nrmac,
@@ -512,9 +518,7 @@ static void nr_fill_nfapi_srs(gNB_MAC_INST *nrmac,
*********************************************************************/
void nr_schedule_srs(int module_id, frame_t frame, int slot)
{
const int CC_id = 0;
gNB_MAC_INST *nrmac = RC.nrmac[module_id];
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
@@ -526,12 +530,6 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot)
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
if(sched_ctrl->sched_srs.srs_scheduled && sched_ctrl->sched_srs.frame == frame && sched_ctrl->sched_srs.slot == slot) {
sched_ctrl->sched_srs.frame = -1;
sched_ctrl->sched_srs.slot = -1;
sched_ctrl->sched_srs.srs_scheduled = false;
}
if ((sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) || nr_timer_is_active(&sched_ctrl->transm_interrupt)) {
continue;
}
@@ -566,34 +564,20 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot)
continue;
}
NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList = get_ul_tdalist(current_BWP,
sched_ctrl->coreset->controlResourceSetId,
sched_ctrl->search_space->searchSpaceType->present,
TYPE_C_RNTI_);
const int num_tda = tdaList->list.count;
int max_k2 = 0;
// avoid last one in the list (for msg3)
for (int i = 0; i < num_tda - 1; i++) {
int k2 = get_K2(tdaList, i, current_BWP->scs, scc);
max_k2 = k2 > max_k2 ? k2 : max_k2;
}
// we are sheduling SRS max_k2 slot in advance for the presence of SRS to be taken into account when scheduling PUSCH
const int n_slots_frame = nrmac->frame_structure.numb_slots_frame;
const int sched_slot = (slot + max_k2) % n_slots_frame;
const int sched_frame = (frame + (slot + max_k2) / n_slots_frame) % MAX_FRAME_NUMBER;
const int n_ahead = n_slots_frame - 1 + get_NTN_Koffset(nrmac->common_channels[0].ServingCellConfigCommon);
const int sched_slot = (slot + n_ahead) % n_slots_frame;
const int sched_frame = (frame + (slot + n_ahead) / n_slots_frame) % MAX_FRAME_NUMBER;
const uint16_t period = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present];
const uint16_t offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p);
// Check if UE will transmit the SRS in this frame
if ((sched_frame * n_slots_frame + sched_slot - offset) % period == 0) {
LOG_D(NR_MAC," %d.%d Scheduling SRS reception for %d.%d\n", frame, slot, sched_frame, sched_slot);
nr_fill_nfapi_srs(nrmac, CC_id, UE, sched_frame, sched_slot, srs_resource_set, srs_resource);
sched_ctrl->sched_srs.frame = sched_frame;
sched_ctrl->sched_srs.slot = sched_slot;
sched_ctrl->sched_srs.srs_scheduled = true;
}
if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0)
continue;
LOG_D(NR_MAC," %d.%d Scheduling SRS reception for %d.%d\n", frame, slot, sched_frame, sched_slot);
nr_fill_nfapi_srs(nrmac, CC_id, UE, sched_frame, sched_slot, srs_resource_set, srs_resource);
}
}
}
File diff suppressed because it is too large Load Diff
+12 -7
View File
@@ -149,7 +149,7 @@ uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs);
void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot);
/* \brief UL preprocessor for phytest: schedules UE_id 0 with fixed MCS on a
* fixed set of resources */
bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot);
void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch);
void handle_nr_uci_pucch_0_1(module_id_t mod_id,
frame_t frame,
@@ -286,11 +286,6 @@ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac,
NR_BWP_DownlinkDedicated_t *bwp_dedicated,
NR_ControlResourceSetId_t coreset_id);
long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList,
int time_domain_assignment,
int mu,
const NR_ServingCellConfigCommon_t *scc);
const NR_DMRS_UplinkConfig_t *get_DMRS_UplinkConfig(const NR_PUSCH_Config_t *pusch_Config, const NR_tda_info_t *tda_info);
NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc,
@@ -417,7 +412,15 @@ void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl);
bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE);
NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti);
int get_dl_tda(const gNB_MAC_INST *nrmac, int slot);
int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot);
int get_num_ul_tda(gNB_MAC_INST *nrmac, int slot, int k2, const NR_tda_info_t **first_idx);
const NR_tda_info_t *get_best_ul_tda(const gNB_MAC_INST *nrmac,
int beam,
const NR_tda_info_t *tdas,
int n_tda,
int frame,
int slot,
int *rb_start,
int *rb_len);
int get_cce_index(const gNB_MAC_INST *nrmac,
const int CC_id,
@@ -498,4 +501,6 @@ void prepare_du_configuration_update(gNB_MAC_INST *mac,
const NR_BCCH_DL_SCH_Message_t *sib1);
void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group);
void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE_info_t *UE, NR_sched_pusch_t *sched_pusch);
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
+6 -4
View File
@@ -168,12 +168,13 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
output += snprintf(output,
end - output,
", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS (%d) %d\n",
", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS (%d) %d CCE fail %d\n",
stats->dl.errors,
stats->pucch0_DTX,
sched_ctrl->dl_bler_stats.bler,
UE->current_DL_BWP.mcsTableIdx,
sched_ctrl->dl_bler_stats.mcs);
sched_ctrl->dl_bler_stats.mcs,
sched_ctrl->dl_cce_fail);
if (reset_rsrp) {
stats->num_rsrp_meas = 0;
stats->cumul_rsrp = 0;
@@ -187,7 +188,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
output += snprintf(output,
end - output,
", ulsch_errors %"PRIu64", ulsch_DTX %d, BLER %.5f MCS (%d) %d (Qm %d deltaMCS %d dB) NPRB %d SNR %d.%d dB\n",
", ulsch_errors %"PRIu64", ulsch_DTX %d, BLER %.5f MCS (%d) %d (Qm %d deltaMCS %d dB) NPRB %d SNR %d.%d dB CCE fail %d\n",
stats->ul.errors,
stats->ulsch_DTX,
sched_ctrl->ul_bler_stats.bler,
@@ -197,7 +198,8 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
UE->mac_stats.deltaMCS,
UE->mac_stats.NPRB,
sched_ctrl->pusch_snrx10 / 10,
sched_ctrl->pusch_snrx10 % 10);
sched_ctrl->pusch_snrx10 % 10,
sched_ctrl->ul_cce_fail);
output += snprintf(output,
end - output,
"UE %04x: MAC: TX %14"PRIu64" RX %14"PRIu64" bytes\n",
+31 -14
View File
@@ -403,7 +403,6 @@ typedef struct NR_pusch_dmrs {
typedef struct NR_sched_pusch {
int frame;
int slot;
int mu;
/// RB allocation within active uBWP
uint16_t rbSize;
@@ -430,12 +429,6 @@ typedef struct NR_sched_pusch {
int phr_txpower_calc;
} NR_sched_pusch_t;
typedef struct NR_sched_srs {
int frame;
int slot;
bool srs_scheduled;
} NR_sched_srs_t;
typedef struct NR_pdsch_dmrs {
uint8_t dmrs_ports_id;
uint8_t N_PRB_DMRS;
@@ -592,6 +585,7 @@ typedef struct {
/// corresponding to the sched_pusch/sched_pdsch structures below
int cce_index;
uint8_t aggregation_level;
uint32_t dl_cce_fail, ul_cce_fail;
/// Array of PUCCH scheduling information
/// Its size depends on TDD configuration and max feedback time
@@ -599,12 +593,6 @@ typedef struct {
NR_sched_pucch_t *sched_pucch;
int sched_pucch_size;
/// Sched PUSCH: scheduling decisions, copied into HARQ and cleared every TTI
NR_sched_pusch_t sched_pusch;
/// Sched SRS: scheduling decisions
NR_sched_srs_t sched_srs;
/// uplink bytes that are currently scheduled
int sched_ul_bytes;
/// estimation of the UL buffer size
@@ -804,8 +792,23 @@ typedef struct {
#define UE_iterator(BaSe, VaR) NR_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++)))
typedef struct {
/// current frame for DCI
frame_t frame;
/// current slot for DCI
slot_t slot;
/// FAPI UL_DCI.request in which allocations are to be made
nfapi_nr_ul_dci_request_t *ul_dci_req;
/// group PDCCH PDU per CORESET
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_coreset[MAX_NUM_CORESET];
} post_process_pusch_t;
/* forward declaration to use in nr_pp_impl_dl */
struct gNB_MAC_INST_s;
typedef struct gNB_MAC_INST_s gNB_MAC_INST;
typedef void (*nr_pp_impl_dl)(module_id_t mod_id, frame_t frame, slot_t slot);
typedef bool (*nr_pp_impl_ul)(module_id_t mod_id, frame_t frame, slot_t slot);
typedef void (*nr_pp_impl_ul)(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch);
typedef struct f1_config_t {
f1ap_setup_req_t *setup_req;
@@ -823,6 +826,14 @@ typedef struct {
uint64_t used_prb_aggregate;
} mac_stats_t;
/// helper type to encapsulate a frame/slot combination in a single type.
/// Currently only used in the UL preprocessor. Note: if you use this type
/// further, please refactor it into a common type first.
typedef struct fsn {
frame_t f;
slot_t s;
} fsn_t;
/*! \brief top level eNB MAC structure */
typedef struct gNB_MAC_INST_s {
/// Ethernet parameters for northbound midhaul interface
@@ -924,6 +935,12 @@ typedef struct gNB_MAC_INST_s {
bool identity_pm;
int precoding_matrix_size[NR_MAX_NB_LAYERS];
int fapi_beam_index[MAX_NUM_OF_SSB];
/// dedicate UL TDA, common for all UEs
seq_arr_t ul_tda;
/// next UL slot to schedule
fsn_t ul_next;
nr_mac_rrc_ul_if_t mac_rrc;
f1_config_t f1_config;
int16_t frame;
+83 -58
View File
@@ -1048,91 +1048,116 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc
}
}
static struct NR_PUSCH_TimeDomainResourceAllocation *set_TimeDomainResourceAllocation(const int k2, uint8_t index, int ul_symb)
static struct NR_PUSCH_TimeDomainResourceAllocation *set_TimeDomainResourceAllocation(const int k2, long sliv)
{
struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAlloc = calloc_or_fail(1, sizeof(*puschTdrAlloc));
puschTdrAlloc->k2 = calloc_or_fail(1, sizeof(*puschTdrAlloc->k2));
*puschTdrAlloc->k2 = k2;
puschTdrAlloc->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB;
switch (index) {
case 0:
puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 13);
break;
case 1:
puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 12);
break;
case 2:
// UL TDA index 2 for mixed slot (TDD)
puschTdrAlloc->startSymbolAndLength =
get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one
break;
case 3: {
// UL TDA index 3 for msg3 in the mixed slot (TDD)
int no_mix_slot = ul_symb < 3 ? 1 : 0; // we need at least 2 symbols for scheduling Msg3
*puschTdrAlloc->k2 += no_mix_slot;
if (no_mix_slot)
puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 13); // full allocation if there is no mixed slot
else
puschTdrAlloc->startSymbolAndLength =
get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one
}
break;
default:
break;
}
puschTdrAlloc->startSymbolAndLength = sliv;
return puschTdrAlloc;
}
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay)
static int tda_cmp(const void *tda_a, const void *tda_b)
{
//TODO change to accomodate for SRS
const NR_PUSCH_TimeDomainResourceAllocation_t *a = *(const NR_PUSCH_TimeDomainResourceAllocation_t **)tda_a;
const NR_PUSCH_TimeDomainResourceAllocation_t *b = *(const NR_PUSCH_TimeDomainResourceAllocation_t **)tda_b;
DevAssert(a->k2 && b->k2);
if (*a->k2 < *b->k2)
return -1; // smaller first
if (*a->k2 > *b->k2)
return 1;
// same k2: order from big to small TDA number
int as, al, bs, bl;
SLIV2SL(a->startSymbolAndLength, &as, &al);
SLIV2SL(b->startSymbolAndLength, &bs, &bl);
if (al < bl)
return 1; // bigger first
if (al > bl)
return -1;
return 0;
}
const NR_PUSCH_TimeDomainResourceAllocationList_t *tda =
/* \brief Set up a list of time domain allocations as suitable for the TDD
* pattern. This will be used by get_num_ul_tda(), which requires a specific
* ordering, hence we qsort() the list at the end according to tda_cmp(). */
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, int do_SRS)
{
NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list =
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
AssertFatal(tda->list.count == 0, "already have pusch_TimeDomainAllocationList members\n");
AssertFatal(tda_list->list.count == 0, "already have pusch_TimeDomainAllocationList members\n");
const int k2 = min_fb_delay;
int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
struct NR_SetupRelease_PUSCH_ConfigCommon *pusch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon;
const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
// UL TDA index 0 is basic slot configuration starting in symbol 0 til the last but one symbol
asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, set_TimeDomainResourceAllocation(k2, 0, 0));
NR_PUSCH_TimeDomainResourceAllocation_t *tda;
tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 13));
asn1cSeqAdd(&tda_list->list, tda);
// UL TDA index 1 in case of SRS
asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, set_TimeDomainResourceAllocation(k2, 1, 0));
if (do_SRS) {
tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 12));
asn1cSeqAdd(&tda_list->list, tda);
}
if (scc->tdd_UL_DL_ConfigurationCommon) {
int ul_symb = 0;
NR_TDD_UL_DL_Pattern_t *p1 = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
int ul_symb = p1->nrofUplinkSymbols;
NR_TDD_UL_DL_Pattern_t *p2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2;
if (p2 && p2->nrofUplinkSymbols)
AssertFatal(p2->nrofUplinkSymbols == p1->nrofUplinkSymbols,
"nrofDownlinkSymbols in pattern1 %ld and pattern2 %ld must be the same in current implementation\n",
p1->nrofUplinkSymbols,
AssertFatal(p2->nrofUplinkSymbols == ul_symb,
"nrofDownlinkSymbols in pattern1 %d and pattern2 %ld must be the same in current implementation\n",
ul_symb,
p2->nrofUplinkSymbols);
if (p1->nrofUplinkSymbols) {
ul_symb = p1->nrofUplinkSymbols;
} else if (p2) {
ul_symb = p1->nrofUplinkSymbols;
}
if (ul_symb>1) {
// UL TDA index 2 for mixed slot (TDD)
asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,
set_TimeDomainResourceAllocation(k2, 2, ul_symb));
}
// UL TDA index 3 for msg3 in the mixed slot (TDD)
AssertFatal(!p2 || p2->nrofDownlinkSlots >= p2->nrofUplinkSlots,
"nrofDownlinkSlots must be larger than nrofUplinkSlots for pattern2 in current implementation\n");
int N_dl1 = p1->nrofDownlinkSlots;
int N_ul1 = p1->nrofUplinkSlots;
int N_dl2 = p2 ? p2->nrofDownlinkSlots : 0;
int N_ul2 = p2 ? p2->nrofUplinkSlots : 0;
int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon);
int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx);
int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame;
int k2_msg3 = nb_slots_per_period - get_delta_for_k2(mu);
struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAllocMsg3 = set_TimeDomainResourceAllocation(k2_msg3, 3, ul_symb);
if (*puschTdrAllocMsg3->k2 < min_fb_delay)
*puschTdrAllocMsg3->k2 += nb_slots_per_period;
AssertFatal(*puschTdrAllocMsg3->k2 < 33,
"Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n",
*puschTdrAllocMsg3->k2);
asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, puschTdrAllocMsg3);
// make TDA for the mixed slot
long mixed_sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1);
if (ul_symb > 1 && (k2 <= N_dl1 || (p2 && N_ul2 == 0))) {
// UL TDA index 2 for mixed slot (TDD) (no pattern 2 and enough DL slots, or pattern2 only DL)
tda = set_TimeDomainResourceAllocation(k2, mixed_sliv); // to be reached from suitable DL slot
asn1cSeqAdd(&tda_list->list, tda);
} else if (ul_symb > 1 && !p2 && k2 > N_dl1) { // k2 > N_Dl1
// UL TDA for mixed slot without pattern 2 and less DL slots than k2
tda = set_TimeDomainResourceAllocation(nb_slots_per_period, mixed_sliv); // to be reached from last DL (mixed) slot, if any
asn1cSeqAdd(&tda_list->list, tda);
} else if (ul_symb > 1 && N_ul2 > 0 && k2 > N_dl1) {
// we have pattern 2 with UL, and less p1 DL slots than k2
tda = set_TimeDomainResourceAllocation(N_dl1 + N_ul2 + 1, mixed_sliv);
asn1cSeqAdd(&tda_list->list, tda);
} else {
AssertFatal(ul_symb == 0, "unhandled case of mixed slot: N_dl1 %d N_ul1 %d N_dl2 %d N_ul2 %d\n", N_dl1, N_ul1, N_dl2, N_ul2);
}
// make TDA for UL slots that are not reachable within k2/min_rxtxtime
int N_ul = max(N_ul1, N_ul2);
if (N_ul > k2) {
// enforce that with k2, we could reach all but one slot (which is mixed
// and taken into account above
AssertFatal(N_dl1 >= k2 - 1, "cannot fulfil TDD pattern: N_dl1 %d, k2 %d\n", N_dl1, k2);
for (int i = k2 + 1; i <= N_ul; ++i) {
tda = set_TimeDomainResourceAllocation(i, get_SLIV(0, 13));
asn1cSeqAdd(&tda_list->list, tda);
if (do_SRS) {
tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 12));
asn1cSeqAdd(&tda_list->list, tda);
}
}
}
}
AssertFatal(tda_list->list.count <= 16, "cannot reach all UL slots with current TDD configuration\n");
qsort(tda_list->list.array, tda_list->list.count, sizeof(tda_list->list.array), tda_cmp);
}
static void set_dl_DataToUL_ACK(NR_PUCCH_Config_t *pucch_Config, int min_feedback_time, NR_SubcarrierSpacing_t subcarrierSpacing)
+1 -1
View File
@@ -51,7 +51,7 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc
frame_type_t frame_type,
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
int curr_bwp);
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay);
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, int do_SRS);
NR_SearchSpace_t *rrc_searchspace_config(bool is_common,
int searchspaceid,
int coresetid,