Refactor DLSCH post processor into post_process_dlsch()

Introduce a struct with information on FAPI structures to save resource
and data allocation into. It's in nr_mac_gNB.h because the next commits
will reuse this for all preprocessors.
This commit is contained in:
Robert Schmidt
2025-10-30 19:14:06 +01:00
parent 2f636037ee
commit ce744fd24f
2 changed files with 383 additions and 359 deletions
@@ -641,6 +641,11 @@ static void pf_dl(module_id_t module_id,
const uint32_t b = UE->mac_stats.dl.current_bytes; const uint32_t b = UE->mac_stats.dl.current_bytes;
UE->dl_thr_ue = (1 - a) * UE->dl_thr_ue + a * b; UE->dl_thr_ue = (1 - a) * UE->dl_thr_ue + a * b;
/* Check if this UE should get TA (every 100 frames). If we add the CE,
* ta_apply will be reset */
if (frame == ((sched_ctrl->ta_frame + 100) % 1024))
sched_ctrl->ta_apply = true;
int total_rem_ues = 0; int total_rem_ues = 0;
for (int i = 0; i < num_beams; i++) for (int i = 0; i < num_beams; i++)
total_rem_ues += remainUEs[i]; total_rem_ues += remainUEs[i];
@@ -1010,53 +1015,17 @@ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu
return pdsch_pdu; return pdsch_pdu;
} }
void nr_schedule_ue_spec(module_id_t module_id, void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE_info_t *UE, NR_sched_pdsch_t *sched_pdsch)
frame_t frame,
slot_t slot,
nfapi_nr_dl_tti_request_t *DL_req,
nfapi_nr_tx_data_request_t *TX_req)
{ {
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; int CC_id = 0;
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ int module_id = 0;
AssertFatal(pthread_mutex_trylock(&gNB_mac->sched_lock) == EBUSY, frame_t frame = pdsch->frame;
"this function should be called with the scheduler mutex locked\n"); slot_t slot = pdsch->slot;
if (!is_dl_slot(slot, &gNB_mac->frame_structure)) const NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[CC_id].ServingCellConfigCommon;
return;
/* PREPROCESSOR */
gNB_mac->pre_processor_dl(module_id, frame, slot);
const int CC_id = 0;
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon;
NR_UEs_t *UE_info = &gNB_mac->UE_info;
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE);
UE_iterator(UE_info->connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP; NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;
if (!nr_mac_ue_is_active(UE) && !get_softmodem_params()->phy_test)
continue;
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
UE->mac_stats.dl.current_bytes = 0;
UE->mac_stats.dl.current_rbs = 0;
/* update TA and set ta_apply every 100 frames.
* Possible improvement: take the periodicity from input file.
* If such UE is not scheduled now, it will be by the preprocessor later.
* If we add the CE, ta_apply will be reset */
if (frame == ((sched_ctrl->ta_frame + 100) % 1024) && !nr_timer_is_active(&sched_ctrl->transm_interrupt)) {
sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */
LOG_D(NR_MAC, "[UE %04x][%d.%d] UL timing alignment procedures: setting flag for Timing Advance command\n", UE->rnti, frame, slot);
}
if (sched_pdsch->rbSize <= 0)
continue;
const rnti_t rnti = UE->rnti; const rnti_t rnti = UE->rnti;
/* POST processing */ /* POST processing */
@@ -1125,38 +1094,39 @@ void nr_schedule_ue_spec(module_id_t module_id,
const int coresetid = sched_ctrl->coreset->controlResourceSetId; const int coresetid = sched_ctrl->coreset->controlResourceSetId;
/* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it */ /* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it */
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][coresetid]; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = nr_mac->pdcch_pdu_idx[CC_id][coresetid];
if (!pdcch_pdu) { if (!pdcch_pdu) {
LOG_D(NR_MAC, "creating pdcch pdu, pdcch_pdu = NULL. \n"); LOG_D(NR_MAC, "creating pdcch pdu, pdcch_pdu = NULL. \n");
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &pdsch->dl_req->dl_tti_pdu_list[pdsch->dl_req->nPDUs];
memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
dl_req->nPDUs += 1; pdsch->dl_req->nPDUs += 1;
pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
LOG_D(NR_MAC,"Trying to configure DL pdcch for UE %04x, bwp %d, cs %d\n", UE->rnti, bwp_id, coresetid); LOG_D(NR_MAC,"Trying to configure DL pdcch for UE %04x, bwp %d, cs %d\n", UE->rnti, bwp_id, coresetid);
NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; NR_ControlResourceSet_t *coreset = sched_ctrl->coreset;
nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch); nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch);
gNB_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu; nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu;
} }
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &pdsch->dl_req->dl_tti_pdu_list[pdsch->dl_req->nPDUs];
memset(dl_tti_pdsch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); memset(dl_tti_pdsch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdsch_pdu)); dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdsch_pdu));
dl_req->nPDUs += 1; pdsch->dl_req->nPDUs += 1;
/* SCF222: PDU index incremented for each PDSCH PDU sent in TX control /* SCF222: PDU index incremented for each PDSCH PDU sent in TX control
* message. This is used to associate control information to data and is * message. This is used to associate control information to data and is
* reset every slot. */ * reset every slot. */
const int pduindex = gNB_mac->pdu_index[CC_id]++; const int pduindex = nr_mac->pdu_index[CC_id]++;
// TODO: verify the case where maxMIMO_Layers is NULL, in which case // TODO: verify the case where maxMIMO_Layers is NULL, in which case
// in principle maxMIMO_layers should be given by the maximum number of layers // in principle maxMIMO_layers should be given by the maximum number of layers
// for PDSCH supported by the UE for the serving cell (5.4.2.1 of 38.212) // for PDSCH supported by the UE for the serving cell (5.4.2.1 of 38.212)
long maxMIMO_Layers = UE->sc_info.maxMIMO_Layers_PDSCH ? *UE->sc_info.maxMIMO_Layers_PDSCH : 1; long maxMIMO_Layers = UE->sc_info.maxMIMO_Layers_PDSCH ? *UE->sc_info.maxMIMO_Layers_PDSCH : 1;
const int nl_tbslbrm = min(maxMIMO_Layers, 4); const int nl_tbslbrm = min(maxMIMO_Layers, 4);
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = prepare_pdsch_pdu(dl_tti_pdsch_pdu, nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = prepare_pdsch_pdu(dl_tti_pdsch_pdu,
gNB_mac, nr_mac,
UE, UE,
sched_pdsch, sched_pdsch,
current_BWP->pdsch_Config, current_BWP->pdsch_Config,
@@ -1182,7 +1152,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
/* DCI payload */ /* DCI payload */
const int rnti_type = TYPE_C_RNTI_; const int rnti_type = TYPE_C_RNTI_;
dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(gNB_mac, dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(nr_mac,
UE, UE,
rnti_type, rnti_type,
sched_ctrl->search_space->searchSpaceType->present, sched_ctrl->search_space->searchSpaceType->present,
@@ -1230,7 +1200,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
sched_ctrl->search_space, sched_ctrl->search_space,
sched_ctrl->coreset, sched_ctrl->coreset,
UE->pdsch_HARQ_ACK_Codebook, UE->pdsch_HARQ_ACK_Codebook,
gNB_mac->cset0_bwp_size); nr_mac->cset0_bwp_size);
LOG_D(NR_MAC, LOG_D(NR_MAC,
"coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", "coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
@@ -1263,7 +1233,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock.buf, TBS)); T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock.buf, TBS));
UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize; UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize;
gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize; nr_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize;
} else { /* initial transmission */ } else { /* initial transmission */
LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot); LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot);
uint8_t *buf = allocate_transportBlock_buffer(&harq->transportBlock, TBS); uint8_t *buf = allocate_transportBlock_buffer(&harq->transportBlock, TBS);
@@ -1278,7 +1248,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
DevAssert(TBS > written); DevAssert(TBS > written);
int dlsch_total_bytes = 0; int dlsch_total_bytes = 0;
/* next, get RLC data */ /* next, get RLC data */
start_meas(&gNB_mac->rlc_data_req); start_meas(&nr_mac->rlc_data_req);
int sdus = 0; int sdus = 0;
if (sched_ctrl->num_total_bytes > 0) { if (sched_ctrl->num_total_bytes > 0) {
@@ -1359,7 +1329,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
} }
} }
stop_meas(&gNB_mac->rlc_data_req); stop_meas(&nr_mac->rlc_data_req);
// Add padding header and zero rest out if there is space left // Add padding header and zero rest out if there is space left
if (bufEnd-buf > 0) { if (bufEnd-buf > 0) {
@@ -1377,7 +1347,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
UE->mac_stats.dl.num_mac_sdu += sdus; UE->mac_stats.dl.num_mac_sdu += sdus;
UE->mac_stats.dl.current_rbs = sched_pdsch->rbSize; UE->mac_stats.dl.current_rbs = sched_pdsch->rbSize;
UE->mac_stats.dl.total_sdu_bytes += dlsch_total_bytes; UE->mac_stats.dl.total_sdu_bytes += dlsch_total_bytes;
gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize; nr_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize;
/* save retransmission information */ /* save retransmission information */
harq->sched_pdsch = *sched_pdsch; harq->sched_pdsch = *sched_pdsch;
@@ -1397,16 +1367,59 @@ void nr_schedule_ue_spec(module_id_t module_id,
T(T_GNB_MAC_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(sched_pdsch->mcs), T_INT(TBS)); T(T_GNB_MAC_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(sched_pdsch->mcs), T_INT(TBS));
} }
const int ntx_req = TX_req->Number_of_PDUs; const int ntx_req = pdsch->TX_req->Number_of_PDUs;
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; nfapi_nr_pdu_t *tx_req = &pdsch->TX_req->pdu_list[ntx_req];
tx_req->PDU_index = pduindex; tx_req->PDU_index = pduindex;
tx_req->num_TLV = 1; tx_req->num_TLV = 1;
tx_req->TLVs[0].length = TBS; tx_req->TLVs[0].length = TBS;
tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length); tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length);
memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock.buf, TBS); memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock.buf, TBS);
TX_req->Number_of_PDUs++; pdsch->TX_req->Number_of_PDUs++;
TX_req->SFN = frame; pdsch->TX_req->SFN = frame;
TX_req->Slot = slot; pdsch->TX_req->Slot = slot;
}
void nr_schedule_ue_spec(module_id_t module_id,
frame_t frame,
slot_t slot,
nfapi_nr_dl_tti_request_t *DL_req,
nfapi_nr_tx_data_request_t *TX_req)
{
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
AssertFatal(pthread_mutex_trylock(&gNB_mac->sched_lock) == EBUSY,
"this function should be called with the scheduler mutex locked\n");
if (!is_dl_slot(slot, &gNB_mac->frame_structure))
return;
/* PREPROCESSOR */
gNB_mac->pre_processor_dl(module_id, frame, slot);
const int CC_id = 0;
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon;
NR_UEs_t *UE_info = &gNB_mac->UE_info;
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
post_process_pdsch_t pdsch = { frame, slot, dl_req, TX_req };
const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE);
UE_iterator(UE_info->connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (!nr_mac_ue_is_active(UE) && !get_softmodem_params()->phy_test)
continue;
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
UE->mac_stats.dl.current_bytes = 0;
UE->mac_stats.dl.current_rbs = 0;
if (sched_pdsch->rbSize <= 0)
continue;
post_process_dlsch(gNB_mac, &pdsch, UE, sched_pdsch);
/* mark UE as scheduled */ /* mark UE as scheduled */
sched_pdsch->rbSize = 0; sched_pdsch->rbSize = 0;
} }
+11
View File
@@ -821,6 +821,17 @@ typedef struct {
#define UE_iterator(BaSe, VaR) for (NR_UE_info_t **VaR##pptr=BaSe, *VaR=*VaR##pptr; VaR; VaR=*(++VaR##pptr)) #define UE_iterator(BaSe, VaR) for (NR_UE_info_t **VaR##pptr=BaSe, *VaR=*VaR##pptr; VaR; VaR=*(++VaR##pptr))
typedef struct {
/// current frame
frame_t frame;
/// current slot
slot_t slot;
/// FAPI DL req in which allocations are made
nfapi_nr_dl_tti_request_body_t *dl_req;
/// TX_data request holds the actual data
nfapi_nr_tx_data_request_t *TX_req;
} post_process_pdsch_t;
typedef struct { typedef struct {
/// current frame for DCI /// current frame for DCI
frame_t frame; frame_t frame;