Merge remote-tracking branch 'origin/nr-ue-slot-tx-cleanup' into integration_2025_w15 (!3312)

NR UE: enable concurrent UL slot processing

This commit introduces support for concurrent UL slot processing
Key changes:

- Increased number of UL actors from 1 to 2
- fix several issues related to writing to global variables inside processSlotTX
- Ensure in-order execution of if_module calls by utilizing the preexisting dynamic_barrier structure.

Note: for NTN, concurrent UL slot processing does not work. A flag
`--num-ul-actors X` has been introduced that allows to fix the number of
UL actors to `X` (default is 2).
This commit is contained in:
Robert Schmidt
2025-04-11 16:26:41 +02:00
12 changed files with 39 additions and 35 deletions
@@ -110,7 +110,7 @@ services:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
environment:
USE_ADDITIONAL_OPTIONS: --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time
USE_ADDITIONAL_OPTIONS: --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74 --rfsimulator.serveraddr 192.168.71.140 --num-ul-actors 1 --log_config.global_log_options level,nocolor,time
depends_on:
- oai-gnb
networks:
+10 -4
View File
@@ -104,7 +104,9 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg);
static void start_process_slot_tx(void* arg) {
notifiedFIFO_elt_t *newTx = arg;
nr_rxtx_thread_data_t *curMsgTx = NotifiedFifoData(newTx);
pushNotifiedFIFO(&curMsgTx->UE->ul_actor.fifo, newTx);
int num_ul_actors_to_use =
get_nrUE_params()->num_ul_actors == 0 ? NUM_UL_ACTORS : min(get_nrUE_params()->num_ul_actors, NUM_UL_ACTORS);
pushNotifiedFIFO(&curMsgTx->UE->ul_actors[curMsgTx->proc.nr_slot_tx % num_ul_actors_to_use].fifo, newTx);
}
static size_t dump_L1_UE_meas_stats(PHY_VARS_NR_UE *ue, char *output, size_t max_len)
@@ -585,6 +587,7 @@ void processSlotTX(void *arg)
UE->if_inst->sl_indication(&sl_indication);
stop_meas(&UE->ue_ul_indication_stats);
}
dynamic_barrier_join(rxtxD->next_barrier);
if (phy_data.sl_tx_action) {
@@ -611,12 +614,14 @@ void processSlotTX(void *arg)
UE->if_inst->ul_indication(&ul_indication);
stop_meas(&UE->ue_ul_indication_stats);
}
dynamic_barrier_join(rxtxD->next_barrier);
phy_procedures_nrUE_TX(UE, proc, &phy_data);
}
} else {
dynamic_barrier_join(rxtxD->next_barrier);
}
RU_write(rxtxD, sl_tx_action);
dynamic_barrier_join(rxtxD->next_barrier);
TracyCZoneEnd(ctx);
}
@@ -656,7 +661,9 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
for (int i = 0; i < NUM_DL_ACTORS; i++) {
flush_actor(UE->dl_actors + i);
}
flush_actor(&UE->ul_actor);
for (int i = 0; i < NUM_UL_ACTORS; i++) {
flush_actor(UE->ul_actors + i);
}
clean_UE_harq(UE);
UE->is_synchronized = 0;
@@ -1186,7 +1193,6 @@ void *UE_thread(void *arg)
curMsgTx->proc.timestamp_tx = writeTimestamp;
curMsgTx->UE = UE;
curMsgTx->proc.nr_slot_tx_offset = nr_slot_tx_offset;
int slot = curMsgTx->proc.nr_slot_tx;
int slot_and_frame = slot + curMsgTx->proc.frame_tx * UE->frame_parms.slots_per_frame;
int next_tx_slot_and_frame = absolute_slot + duration_rx_to_tx + 1;
+6 -2
View File
@@ -508,7 +508,9 @@ int main(int argc, char **argv)
for (int i = 0; i < NUM_DL_ACTORS; i++) {
init_actor(&UE[CC_id]->dl_actors[i], "DL_", -1);
}
init_actor(&UE[CC_id]->ul_actor, "UL_", -1);
for (int i = 0; i < NUM_UL_ACTORS; i++) {
init_actor(&UE[CC_id]->ul_actors[i], "UL_", -1);
}
init_nr_ue_vars(UE[CC_id], inst);
if (UE[CC_id]->sl_mode) {
@@ -578,7 +580,9 @@ int main(int argc, char **argv)
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
PHY_VARS_NR_UE *phy_vars = PHY_vars_UE_g[0][CC_id];
if (phy_vars) {
shutdown_actor(&phy_vars->ul_actor);
for (int i = 0; i < NUM_UL_ACTORS; i++) {
shutdown_actor(&phy_vars->ul_actors[i]);
}
for (int i = 0; i < NUM_DL_ACTORS; i++) {
shutdown_actor(&phy_vars->dl_actors[i]);
}
+3
View File
@@ -15,6 +15,7 @@
#define CONFIG_HLP_NTN_INIT_TIME_DRIFT "Initial NTN DL time drift (feeder link and service link), given in µs/s\n"
#define CONFIG_HLP_AUTONOMOUS_TA "Autonomously update TA based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite)\n"
#define CONFIG_HLP_AGC "Rx Gain control used for UE\n"
#define CONFIG_HLP_NUM_UL_ACTORS "Number of UL actors to use. Set to 0 to use the default value\n"
/***************************************************************************************************************************************/
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
@@ -66,6 +67,7 @@
{"ntn-initial-time-drift", CONFIG_HLP_NTN_INIT_TIME_DRIFT, 0, .dblptr=&(nrUE_params.ntn_init_time_drift), .defdblval=0.0, TYPE_DOUBLE, 0}, \
{"autonomous-ta", CONFIG_HLP_AUTONOMOUS_TA, PARAMFLAG_BOOL, .iptr=&(nrUE_params.autonomous_ta), .defintval=0, TYPE_INT, 0}, \
{"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \
{"num-ul-actors", CONFIG_HLP_NUM_UL_ACTORS, 0, .iptr=&nrUE_params.num_ul_actors, .defintval=0, TYPE_INT, 0}, \
}
// clang-format on
@@ -101,6 +103,7 @@ typedef struct {
double rx_gain_off;
int vcdflag;
int tx_max_power;
int num_ul_actors;
} nrUE_params_t;
extern uint64_t get_nrUE_optmask(void);
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
-6
View File
@@ -171,7 +171,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
NR_DL_FRAME_PARMS *const fp = &ue->frame_parms;
NR_UE_COMMON *const common_vars = &ue->common_vars;
NR_UE_PRACH **const prach_vars = ue->prach_vars;
NR_UE_SRS **const srs_vars = ue->srs_vars;
LOG_I(PHY, "Initializing UE vars for gNB TXant %u, UE RXant %u\n", fp->nb_antennas_tx, fp->nb_antennas_rx);
@@ -257,8 +256,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
// DLSCH
for (int gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) {
prach_vars[gNB_id] = malloc16_clear(sizeof(NR_UE_PRACH));
srs_vars[gNB_id] = malloc16_clear(sizeof(NR_UE_SRS));
srs_vars[gNB_id]->active = false;
// ceil((NB_RB*8(max allocation per RB)*2(QPSK))/32)
ue->nr_csi_info = malloc16_clear(sizeof(nr_csi_info_t));
@@ -318,8 +315,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
free_and_zero(ue->nr_srs_info);
free_and_zero(ue->srs_vars[gNB_id]);
free_and_zero(ue->prach_vars[gNB_id]);
}
@@ -487,7 +482,6 @@ void clean_UE_harq(PHY_VARS_NR_UE *UE)
for (int harq_pid = 0; harq_pid < NR_MAX_ULSCH_HARQ_PROCESSES; harq_pid++) {
NR_UL_UE_HARQ_t *ul_harq_process = &UE->ul_harq_processes[harq_pid];
ul_harq_process->tx_status = NEW_TRANSMISSION_HARQ;
ul_harq_process->ULstatus = SCH_IDLE;
ul_harq_process->round = 0;
}
}
@@ -46,8 +46,6 @@ typedef enum {
typedef struct {
/// HARQ tx status
harq_result_t tx_status;
/// Status Flag indicating for this ULSCH (idle,active,disabled)
SCH_status_t ULstatus;
/// Last TPC command
uint8_t TPC;
/// Length of ACK information (bits)
@@ -87,6 +85,7 @@ typedef struct {
} NR_UL_UE_HARQ_t;
typedef struct {
SCH_status_t status;
/// NDAPI struct for UE
nfapi_nr_ue_pusch_pdu_t pusch_pdu;
// UL number of harq processes
+1 -8
View File
@@ -471,7 +471,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
if (UE->ul_harq_processes[harq_pid].ULstatus != ACTIVE)
if (phy_data->ulsch.status != ACTIVE)
return;
start_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
@@ -542,8 +542,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
/////////////////////////ULSCH coding/////////////////////////
if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids) == -1) {
NR_UL_UE_HARQ_t *harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
harq_process_ulsch->ULstatus = SCH_IDLE;
stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
return;
}
@@ -820,12 +818,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
} // symbol loop
} // port loop
NR_UL_UE_HARQ_t *harq_process_ulsch = NULL;
harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
harq_process_ulsch->ULstatus = SCH_IDLE;
stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
}
uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
@@ -426,14 +426,15 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu,
int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
c16_t **txdataF,
nr_phy_data_tx_t *phy_data,
bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT])
{
if(!ue->srs_vars[0]->active) {
if(phy_data->srs_vars.active == false) {
return -1;
}
ue->srs_vars[0]->active = false;
nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t*)&ue->srs_vars[0]->srs_config_pdu;
// TODO: This is wrong: casting from UE fapi to gNB NFAPI srs pdu
nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t *)&phy_data->srs_vars.srs_config_pdu;
int first_srs_symbol = ue->frame_parms.symbols_per_slot - 1 - srs_config_pdu->time_start_position;
// Num consecutive SRS symbols according to 38.211 6.4.1.4.1
@@ -78,7 +78,10 @@ int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource,
@param rxtx context
@param current gNB_id identifier
@returns 0 if srs is transmitted -1 otherwise */
int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_t **txdataF, bool was_symbol_used[14]);
int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
c16_t **txdataF,
nr_phy_data_tx_t *phy_data,
bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]);
#endif /* SRS_MODULATION_NR_H */
+4 -3
View File
@@ -82,6 +82,7 @@
/// suppress compiler warning for unused arguments
#define UNUSED(x) (void)x;
#define NUM_DL_ACTORS 4
#define NUM_UL_ACTORS 2
// Set the number of barriers for processSlotTX to 512. This value has to be at least 483 for NTN where
// DL-to-UL offset is up to 483. The selected value is also half of the frame range so that
@@ -401,7 +402,6 @@ typedef struct PHY_VARS_NR_UE_s {
nr_synch_request_t synch_request;
NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX];
NR_UE_SRS *srs_vars[NUMBER_OF_CONNECTED_gNB_MAX];
NR_UE_PRS *prs_vars[NR_MAX_PRS_COMB_SIZE];
uint8_t prs_active_gNBs;
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES];
@@ -514,7 +514,7 @@ typedef struct PHY_VARS_NR_UE_s {
sl_nr_ue_phy_params_t SL_UE_PHY_PARAMS;
Actor_t sync_actor;
Actor_t dl_actors[NUM_DL_ACTORS];
Actor_t ul_actor;
Actor_t ul_actors[NUM_UL_ACTORS];
ntn_config_message_t* ntn_config_message;
pthread_t main_thread;
pthread_t stat_thread;
@@ -571,6 +571,7 @@ typedef struct {
typedef struct nr_phy_data_tx_s {
NR_UE_ULSCH_t ulsch;
NR_UE_PUCCH pucch_vars;
NR_UE_SRS srs_vars;
// Sidelink Rx action decided by MAC
sl_nr_tx_config_type_enum_t sl_tx_action;
@@ -597,7 +598,7 @@ typedef struct nr_rxtx_thread_data_s {
PHY_VARS_NR_UE *UE;
int writeBlockSize;
nr_phy_data_t phy_data;
dynamic_barrier_t *next_barrier;
dynamic_barrier_t* next_barrier;
} nr_rxtx_thread_data_t;
typedef struct LDPCDecode_ue_s {
+3 -3
View File
@@ -518,7 +518,7 @@ static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_r
pdu->pusch_config_pdu.tx_request_body.pdu_length);
}
harq_process_ul_ue->ULstatus = ACTIVE;
phy_data->ulsch.status = ACTIVE;
pdu->pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
} break;
@@ -549,8 +549,8 @@ static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_r
case FAPI_NR_UL_CONFIG_TYPE_SRS:
// srs config pdu
phy->srs_vars[0]->srs_config_pdu = pdu->srs_config_pdu;
phy->srs_vars[0]->active = true;
phy_data->srs_vars.srs_config_pdu = pdu->srs_config_pdu;
phy_data->srs_vars.active = true;
pdu->pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
break;
+1 -1
View File
@@ -290,7 +290,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF, was_symbol_used);
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, was_symbol_used);
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, phy_data, was_symbol_used);
pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF, was_symbol_used);