Merge branch 'eurecom-develop' into episys/merge_nsa_w_develop

At this point we are successfully able to build.
Additionally, we can run the scenario,
however, it does not pass. It seems that the gNB
is not connecting to the proxy correctly. Just
wanted to push the progress so far. FYI, the items
that had to be changed to correct the linking issues
were the following:

 - mac_rrc_data_ind_ue vs. nr_mac_rrc_data_ind_ue
 - rrc_data_req vs. nr_rrc_data_req
 - mac_rrc_data_req_ue vs. nr_mac_rrc_data_req_ue
 - rrc_data_req_ue vs. rrc_data_req_nr_ue
 - rrc_data_req vs. nr_rrc_data_req

The listed functions should be declard in the LTE/NR
UE directory depending on the functionality. Several
were mixed. i.e.: LTE functions being called in NR UE.

Also, removing siWindowLength, siWindowLength_int,
SIBType, SIBPeriod, and siPeriod_int from the NR UE RRC.
These variable were not used in the NR UE and are defined
for LTE only.

Lastly, in the NR_IF_Module.c of the NR UE, the global
variable def_dci_pdu_rel15 is not accessible. Need to
revisit this. For not it is commented out.
This commit is contained in:
Melissa Elkadi
2021-08-11 10:23:42 -07:00
826 changed files with 81314 additions and 30890 deletions
+2 -2
View File
@@ -750,7 +750,7 @@ void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PH
recvFs6Ul(bufferZone, nbBlocks, eNB, ul_propa);
// dirty memory allocation in OAI...
for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++)
for (int i = 0; i < NUMBER_OF_UCI_MAX; i++)
if ( eNB->uci_vars[i].frame == proc->frame_rx &&
eNB->uci_vars[i].subframe == proc->subframe_rx )
eNB->uci_vars[i].active=0;
@@ -1145,7 +1145,7 @@ void appendFs6DLUEcch(uint8_t *bufferZone, PHY_VARS_eNB *eNB, int frame, int sub
commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte;
bool first_UE=true;
for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) {
for (int i = 0; i < NUMBER_OF_UCI_MAX; i++) {
LTE_eNB_UCI *uci = &(eNB->uci_vars[i]);
if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) {
+23 -8
View File
@@ -73,17 +73,19 @@ int sync_var=-1; //!< protected by mutex \ref sync_mutex.
int config_sync_var=-1;
volatile int oai_exit = 0;
double cpuf;
THREAD_STRUCT thread_struct;
uint16_t sf_ahead=4;
//uint16_t slot_ahead=6;
int otg_enabled;
uint64_t downlink_frequency[MAX_NUM_CCs][4];
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
int split73;
int usrp_tx_thread = 0;
char * split73_config;
int split73;
AGENT_RRC_xface *agent_rrc_xface[NUM_MAX_ENB]= {0};
AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB]= {0};
uint8_t proto_agent_flag = 0;
void flexran_agent_slice_update(mid_t module_idP) {
}
int proto_agent_start(mod_id_t mod_id, const cudu_params_t *p){
@@ -202,7 +204,6 @@ void init_eNB_afterRU(void) {
for (int inst=0; inst<RC.nb_inst; inst++) {
for (int CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) {
PHY_VARS_eNB *eNB = RC.eNB[inst][CC_id];
phy_init_lte_eNB(eNB,0,0);
eNB->frame_parms.nb_antennas_rx = 0;
eNB->frame_parms.nb_antennas_tx = 0;
eNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *));
@@ -228,12 +229,26 @@ void init_eNB_afterRU(void) {
for (int ce_level=0; ce_level<4; ce_level++)
eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i];
eNB->common_vars.rxdataF[aa] = eNB->RU_list[ru_id]->common.rxdataF[i];
}
}
AssertFatal( eNB->frame_parms.nb_antennas_rx > 0 && eNB->frame_parms.nb_antennas_rx < 4, "");
AssertFatal( eNB->frame_parms.nb_antennas_tx > 0 && eNB->frame_parms.nb_antennas_rx < 4, "");
AssertFatal( eNB->frame_parms.nb_antennas_rx > 0 && eNB->frame_parms.nb_antennas_rx < 5, "");
AssertFatal( eNB->frame_parms.nb_antennas_tx > 0 && eNB->frame_parms.nb_antennas_rx < 5, "");
phy_init_lte_eNB(eNB,0,0);
// need to copy rxdataF after L1 variables are allocated
for (int inst=0; inst<RC.nb_inst; inst++) {
for (int CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) {
PHY_VARS_eNB *eNB = RC.eNB[inst][CC_id];
for (int ru_id=0,aa=0; ru_id<eNB->num_RU; ru_id++) {
for (int i=0; i<eNB->RU_list[ru_id]->nb_rx; aa++,i++)
eNB->common_vars.rxdataF[aa] = eNB->RU_list[ru_id]->common.rxdataF[i];
}
}
}
LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx);
init_transport(eNB);
//init_precoding_weights(RC.eNB[inst][CC_id]);
@@ -800,7 +815,7 @@ int init_rf(RU_t *ru) {
pthread_setname_np(pthread_self(),name);
return ret;
}
void ocp_init_RU(RU_t *ru, char *rf_config_file, int send_dmrssync) {
PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL;
int i;
@@ -1318,7 +1333,7 @@ int main ( int argc, char **argv ) {
// end of CI modifications
//getchar();
if(IS_SOFTMODEM_DOFORMS)
if(IS_SOFTMODEM_DOSCOPE)
load_softscope("enb", NULL);
itti_wait_tasks_end();
@@ -1327,7 +1342,7 @@ int main ( int argc, char **argv ) {
// stop threads
if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
if(IS_SOFTMODEM_DOFORMS)
if(IS_SOFTMODEM_DOSCOPE)
end_forms();
LOG_I(ENB_APP,"stopping MODEM threads\n");
+382
View File
@@ -0,0 +1,382 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file oairu.c
* \brief Top-level threads for radio-unit
* \author R. Knopp
* \date 2020
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sched.h>
#include "assertions.h"
#include "PHY/types.h"
#include "PHY/defs_RU.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
#include "../../ARCH/COMMON/common_lib.h"
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
#include "PHY/phy_vars.h"
#include "SCHED/sched_common_vars.h"
#include "PHY/TOOLS/phy_scope_interface.h"
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "PHY/INIT/phy_init.h"
#include "openair2/ENB_APP/enb_paramdef.h"
#include "system.h"
#include <executables/split_headers.h>
#include <executables/softmodem-common.h>
#include <executables/thread-common.h>
static int DEFBANDS[] = {7};
static int DEFENBS[] = {0};
static int DEFBFW[] = {0x00007fff};
THREAD_STRUCT thread_struct;
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
int config_sync_var=-1;
volatile int oai_exit = 0;
uint16_t sf_ahead = 4;
RU_t ru_m;
extern void init_RU0(RU_t *ru,int ru_id,char *rf_config_file, int send_dmrssync);
extern void init_RU_proc(RU_t *ru);
extern void kill_RU_proc(RU_t *ru);
extern void set_function_spec_param(RU_t *ru);
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
void nfapi_setmode(nfapi_mode_t nfapi_mode) { return; }
void exit_function(const char *file, const char *function, const int line, const char *s) {
if (s != NULL) {
printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
}
close_log_mem();
oai_exit = 1;
if (ru_m.rfdevice.trx_end_func) {
ru_m.rfdevice.trx_end_func(&ru_m.rfdevice);
ru_m.rfdevice.trx_end_func = NULL;
}
if (ru_m.ifdevice.trx_end_func) {
ru_m.ifdevice.trx_end_func(&ru_m.ifdevice);
ru_m.ifdevice.trx_end_func = NULL;
}
pthread_mutex_destroy(ru_m.ru_mutex);
pthread_cond_destroy(ru_m.ru_cond);
sleep(1); //allow lte-softmodem threads to exit first
exit(1);
}
static void get_options(void) {
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
get_common_options(SOFTMODEM_ENB_BIT );
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
//RCConfig();
}
extern void phy_free_RU(RU_t *);
nfapi_mode_t nfapi_getmode(void) {
return(NFAPI_MODE_PNF);
}
void oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {
AssertFatal(1==0,"This is bad ... please check why we get here\n");
}
void wait_eNBs(void){ return; }
uint64_t downlink_frequency[MAX_NUM_CCs][4];
int main ( int argc, char **argv )
{
if ( load_configmodule(argc,argv,0) == NULL) {
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
}
logInit();
printf("Reading in command-line options\n");
get_options ();
if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
fprintf(stderr,"Getting configuration failed\n");
exit(-1);
}
#if T_TRACER
T_Config_Init();
#endif
printf("configuring for RRU\n");
#ifndef PACKAGE_VERSION
# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
/* Read configuration */
printf("About to Init RU threads\n");
RU_t *ru=&ru_m;
paramdef_t RUParams[] = RUPARAMS_DESC;
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL);
int j=0;
uint64_t ru_mask=1;
pthread_mutex_t ru_mutex; pthread_mutex_init(&ru_mutex,NULL);
pthread_cond_t ru_cond; pthread_cond_init(&ru_cond,NULL);
ru->ru_mask= &ru_mask;
ru->ru_mutex = &ru_mutex;
ru->ru_cond = &ru_cond;
ru->if_timing = synch_to_ext_device;
ru->num_eNB = 0;
ru->has_ctrl_prt = 1;
if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) {
ru->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr));
}
if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) {
if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) {
ru->openair0_cfg.clock_source = internal;
LOG_D(PHY, "RU clock source set as internal\n");
} else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) {
ru->openair0_cfg.clock_source = external;
LOG_D(PHY, "RU clock source set as external\n");
} else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) {
ru->openair0_cfg.clock_source = gpsdo;
LOG_D(PHY, "RU clock source set as gpsdo\n");
} else {
LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr));
}
}
else {
ru->openair0_cfg.clock_source = unset;
}
if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) {
if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) {
ru->openair0_cfg.time_source = internal;
LOG_D(PHY, "RU time source set as internal\n");
} else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) {
ru->openair0_cfg.time_source = external;
LOG_D(PHY, "RU time source set as external\n");
} else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) {
ru->openair0_cfg.time_source = gpsdo;
LOG_D(PHY, "RU time source set as gpsdo\n");
} else {
LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr));
}
}
else {
ru->openair0_cfg.time_source = unset;
}
if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) {
if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) {
AssertFatal(1==0,"IF_NAME is required\n");
} else {
ru->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr));
ru->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr));
ru->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr));
ru->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr);
ru->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr);
// Check if control port set
if (!(config_isparamset(RUParamList.paramarray[j],RU_REMOTE_PORTC_IDX)) ) {
printf("Removing control port for RU %d\n",j);
ru->has_ctrl_prt = 0;
} else {
ru->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr);
ru->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr);
printf(" Control port %u \n",ru->eth_params.my_portc);
}
if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) {
ru->if_south = LOCAL_RF;
ru->function = NGFI_RRU_IF5;
ru->eth_params.transp_preference = ETH_UDP_MODE;
printf("Setting function for RU %d to NGFI_RRU_IF5 (udp)\n",j);
} else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) {
ru->if_south = LOCAL_RF;
ru->function = NGFI_RRU_IF5;
ru->eth_params.transp_preference = ETH_RAW_MODE;
printf("Setting function for RU %d to NGFI_RRU_IF5 (raw)\n",j);
} else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) {
ru->if_south = LOCAL_RF;
ru->function = NGFI_RRU_IF4p5;
ru->eth_params.transp_preference = ETH_UDP_IF4p5_MODE;
printf("Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n",j);
} else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) {
ru->if_south = LOCAL_RF;
ru->function = NGFI_RRU_IF4p5;
ru->eth_params.transp_preference = ETH_RAW_IF4p5_MODE;
printf("Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j);
}
printf("RU %d is_slave=%s\n",j,*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr));
if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) ru->is_slave=1;
else ru->is_slave=0;
printf("RU %d ota_sync_enabled=%s\n",j,*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr));
if (strcmp(*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr), "yes") == 0) ru->ota_sync_enable=1;
else ru->ota_sync_enable=0;
}
ru->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);;
ru->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr);
ru->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt;
/* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */
ru->sf_extension = *(RUParamList.paramarray[j][RU_SF_EXTENSION_IDX].uptr);
for (int i=0; i<ru->num_bands; i++) ru->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i];
} //strcmp(local_rf, "yes") == 0
else {
printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr));
ru->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr));
ru->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr));
ru->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr));
ru->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr);
ru->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr);
ru->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr);
ru->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr);
if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) {
ru->if_south = REMOTE_IF5;
ru->function = NGFI_RAU_IF5;
ru->eth_params.transp_preference = ETH_UDP_MODE;
} else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) {
ru->if_south = REMOTE_IF5;
ru->function = NGFI_RAU_IF5;
ru->eth_params.transp_preference = ETH_RAW_MODE;
} else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) {
ru->if_south = REMOTE_IF4p5;
ru->function = NGFI_RAU_IF4p5;
ru->eth_params.transp_preference = ETH_UDP_IF4p5_MODE;
} else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) {
ru->if_south = REMOTE_IF4p5;
ru->function = NGFI_RAU_IF4p5;
ru->eth_params.transp_preference = ETH_RAW_IF4p5_MODE;
}
if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) ru->is_slave=1;
else ru->is_slave=0;
} /* strcmp(local_rf, "yes") != 0 */
ru->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr);
ru->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr);
ru->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr);
ru->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr);
set_worker_conf("WORKER_ENABLE");
mlockall(MCL_CURRENT | MCL_FUTURE);
pthread_cond_init(&sync_cond,NULL);
pthread_mutex_init(&sync_mutex, NULL);
init_RU0(ru,0,get_softmodem_params()->rf_config_file,get_softmodem_params()->send_dmrs_sync);
ru->rf_map.card=0;
ru->rf_map.chain=(get_softmodem_params()->chain_offset);
LOG_I(PHY, "Initializing RRU descriptor : (%s,%s,%d)\n", ru_if_types[ru->if_south], NB_timing[ru->if_timing], ru->function);
set_function_spec_param(ru);
LOG_I(PHY, "Starting ru_thread , is_slave %d, send_dmrs %d\n", ru->is_slave, ru->generate_dmrs_sync);
init_RU_proc(ru);
pthread_mutex_lock(&ru_mutex);
while (ru_mask>0)
pthread_cond_wait(&ru_cond,&ru_mutex);
pthread_mutex_unlock(&ru_mutex);
LOG_I(PHY,"RU configured, unlocking threads\n");
config_sync_var=0;
pthread_mutex_lock(&sync_mutex);
sync_var=0;
pthread_cond_broadcast(&sync_cond);
pthread_mutex_unlock(&sync_mutex);
while (oai_exit==0) sleep(1);
// stop threads
kill_RU_proc(ru);
phy_free_RU(ru);
free_lte_top();
end_configmodule();
if (ru->rfdevice.trx_end_func) {
ru->rfdevice.trx_end_func(&ru->rfdevice);
ru->rfdevice.trx_end_func = NULL;
}
if (ru->ifdevice.trx_end_func) {
ru->ifdevice.trx_end_func(&ru->ifdevice);
ru->ifdevice.trx_end_func = NULL;
}
logClean();
printf("Bye.\n");
return 0;
}
+128 -678
View File
@@ -81,10 +81,13 @@
#include "s1ap_eNB.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
#include <executables/softmodem-common.h>
#include "T.h"
#include "nfapi/oai_integration/vendor_ext.h"
#include <nfapi/oai_integration/nfapi_pnf.h>
#include <openair1/PHY/NR_TRANSPORT/nr_ulsch.h>
#include <PHY/NR_ESTIMATION/nr_ul_estimation.h>
//#define DEBUG_THREADS 1
//#define USRP_DEBUG 1
@@ -92,17 +95,6 @@
// extern openair0_device openair0;
extern volatile int start_gNB;
extern volatile int start_UE;
extern volatile int oai_exit;
extern openair0_config_t openair0_cfg[MAX_CARDS];
extern int transmission_mode;
extern uint16_t sf_ahead;
extern uint16_t sl_ahead;
//pthread_t main_gNB_thread;
time_stats_t softmodem_stats_mt; // main thread
@@ -111,40 +103,43 @@ time_stats_t softmodem_stats_rxtx_sf; // total tx time
time_stats_t nfapi_meas; // total tx time
time_stats_t softmodem_stats_rx_sf; // total rx time
/* mutex, cond and variable to serialize phy proc TX calls
* (this mechanism may be relaxed in the future for better
* performances)
*/
static struct {
pthread_mutex_t mutex_phy_proc_tx;
pthread_cond_t cond_phy_proc_tx;
volatile uint8_t phy_proc_CC_id;
} sync_phy_proc;
extern double cpuf;
void init_gNB(int,int);
void stop_gNB(int nb_inst);
int wakeup_txfh(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, int frame_tx, int slot_tx, uint64_t timestamp_tx);
int wakeup_tx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, uint64_t timestamp_tx);
#include "executables/thread-common.h"
//extern PARALLEL_CONF_t get_thread_parallel_conf(void);
//extern WORKER_CONF_t get_thread_worker_conf(void);
void wakeup_prach_gNB(PHY_VARS_gNB *gNB, RU_t *ru, int frame, int subframe);
extern uint8_t nfapi_mode;
extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
extern void oai_slot_ind(uint16_t sfn, uint16_t slot);
extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
//#define TICK_TO_US(ts) (ts.diff)
#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, char *thread_name) {
void tx_func(void *param) {
processingData_L1_t *info = (processingData_L1_t *) param;
PHY_VARS_gNB *gNB = info->gNB;
int frame_tx = info->frame_tx;
int slot_tx = info->slot_tx;
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
// start FH TX processing
notifiedFIFO_elt_t *res;
res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
processingData_RU_t *syncMsg = (processingData_RU_t *)NotifiedFifoData(res);
syncMsg->frame_tx = frame_tx;
syncMsg->slot_tx = slot_tx;
syncMsg->timestamp_tx = info->timestamp_tx;
syncMsg->ru = gNB->RU_list[0];
res->key = slot_tx;
pushTpool(gNB->threadPool, res);
}
void rx_func(void *param) {
processingData_L1_t *info = (processingData_L1_t *) param;
PHY_VARS_gNB *gNB = info->gNB;
int frame_rx = info->frame_rx;
int slot_rx = info->slot_rx;
int frame_tx = info->frame_tx;
int slot_tx = info->slot_tx;
sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe;
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
@@ -235,22 +230,6 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
rnti_to_remove_count = 0;
if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1);
/*
// if this is IF5 or 3GPP_gNB
if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx);
}
*/
// Call the scheduler
pthread_mutex_lock(&gNB->UL_INFO_mutex);
gNB->UL_INFO.frame = frame_rx;
gNB->UL_INFO.slot = slot_rx;
gNB->UL_INFO.module_id = gNB->Mod_id;
gNB->UL_INFO.CC_id = gNB->CC_id;
gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
pthread_mutex_unlock(&gNB->UL_INFO_mutex);
// RX processing
int tx_slot_type; int rx_slot_type;
if(NFAPI_MODE != NFAPI_MONOLITHIC) { //slot selection routines not working properly in nfapi, so temporarily hardcoding
@@ -288,33 +267,47 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
L1_nr_prach_procedures(gNB,frame_rx,slot_rx);
//apply the rx signal rotation here
apply_nr_rotation_ul(&gNB->frame_parms,
gNB->common_vars.rxdataF[0],
slot_rx,
0,
gNB->frame_parms.Ncp==EXTENDED?12:14,
gNB->frame_parms.ofdm_symbol_size);
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
}
if (oai_exit) return(-1);
// *****************************************
// TX processing for subframe n+sf_ahead
// run PHY TX procedures the one after the other for all CCs to avoid race conditions
// (may be relaxed in the future for performance reasons)
// *****************************************
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
if(get_thread_parallel_conf() != PARALLEL_RU_L1_TRX_SPLIT) {
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
apply_nr_rotation_ul(&gNB->frame_parms,
gNB->common_vars.rxdataF[aa],
slot_rx,
0,
gNB->frame_parms.Ncp==EXTENDED?12:14,
gNB->frame_parms.ofdm_symbol_size);
}
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
}
stop_meas( &softmodem_stats_rxtx_sf );
LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
// Call the scheduler
start_meas(&gNB->ul_indication_stats);
pthread_mutex_lock(&gNB->UL_INFO_mutex);
gNB->UL_INFO.frame = frame_rx;
gNB->UL_INFO.slot = slot_rx;
gNB->UL_INFO.module_id = gNB->Mod_id;
gNB->UL_INFO.CC_id = gNB->CC_id;
gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
pthread_mutex_unlock(&gNB->UL_INFO_mutex);
stop_meas(&gNB->ul_indication_stats);
notifiedFIFO_elt_t *res;
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
processingData_L1_t *syncMsg = (processingData_L1_t *)NotifiedFifoData(res);
syncMsg->gNB = gNB;
syncMsg->frame_rx = frame_rx;
syncMsg->slot_rx = slot_rx;
syncMsg->frame_tx = frame_tx;
syncMsg->slot_tx = slot_tx;
syncMsg->timestamp_tx = info->timestamp_tx;
res->key = slot_tx;
pushTpool(gNB->threadPool, res);
}
#if 0
LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now,
@@ -354,568 +347,60 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
TICK_TO_US(gNB->ulsch_tc_intl2_stats)
);
#endif
return(0);
}
static void *gNB_L1_thread_tx(void *param) {
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
gNB_L1_proc_t *gNB_proc = &gNB->proc;
gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB_proc->L1_proc_tx;
//PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
char thread_name[100];
sprintf(thread_name,"gNB_L1_thread_tx\n");
while (!oai_exit) {
if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 1 );
if (oai_exit) break;
// *****************************************
// TX processing for subframe n+4
// run PHY TX procedures the one after the other for all CCs to avoid race conditions
// (may be relaxed in the future for performance reasons)
// *****************************************
int frame_tx = L1_proc_tx->frame_tx;
int slot_tx = L1_proc_tx->slot_tx;
uint64_t timestamp_tx = L1_proc_tx->timestamp_tx;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,slot_tx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,frame_tx);
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 1 );
pthread_mutex_lock( &L1_proc_tx->mutex );
L1_proc_tx->instance_cnt = -1;
// the thread can now be woken up
if (pthread_cond_signal(&L1_proc_tx->cond) != 0) {
LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
exit_fun( "ERROR pthread_cond_signal" );
}
pthread_mutex_unlock(&L1_proc_tx->mutex);
wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 0 );
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 );
}
return 0;
}
/*!
* \brief The RX UE-specific and TX thread of gNB.
* \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
static void *gNB_L1_thread( void *param ) {
static int gNB_thread_rxtx_status;
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
gNB_L1_proc_t *gNB_proc = &gNB->proc;
gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc;
//PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
char thread_name[100];
// set default return value
// set default return value
gNB_thread_rxtx_status = 0;
sprintf(thread_name,"gNB_L1_thread");
while (!oai_exit) {
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 );
if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 );
int frame_rx = L1_proc->frame_rx;
int slot_rx;
if (NFAPI_MODE == NFAPI_MODE_PNF)
slot_rx = (L1_proc->slot_rx) + 1;
else
slot_rx = L1_proc->slot_rx;
int frame_tx = L1_proc->frame_tx;
int slot_tx = L1_proc->slot_tx;
uint64_t timestamp_tx = L1_proc->timestamp_tx;
if(NFAPI_MODE==NFAPI_MODE_VNF)
if (gNB->CC_id==0) {
int next_slot;
next_slot = (slot_rx + 1) % 20;
int next_frame_rx = (frame_rx + ((slot_rx + 1) % 20 == 0)) % 1024;
int next_frame_tx = (frame_tx + ((slot_rx + 1) % 20 == 0)) % 1024;
if (rxtx(gNB, next_frame_rx, next_slot, next_frame_tx, next_slot, thread_name) < 0) break;
}
if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 );
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,slot_rx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,frame_tx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_GNB,frame_rx);
if (oai_exit) break;
if (gNB->CC_id==0) {
if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break;
}
if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break;
if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx);
else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(gNB,L1_proc,frame_tx,slot_tx,timestamp_tx);
} // while !oai_exit
LOG_D(PHY, " *** Exiting gNB thread RXn_TXnp4\n");
gNB_thread_rxtx_status = 0;
return &gNB_thread_rxtx_status;
}
#if 0
// Wait for gNB application initialization to be complete (gNB registration to MME)
static void wait_system_ready (char *message, volatile int *start_flag) {
static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....",
" ....", " ...", " ..", " .", " "
};
int i = 0;
while ((!oai_exit) && (*start_flag == 0)) {
LOG_N(EMU, message, indicator[i]);
fflush(stdout);
i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
usleep(200000);
}
LOG_D(EMU,"\n");
}
#endif
void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct RU_t_s *ru) {
gNB_L1_proc_t *proc = &gNB->proc;
gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
RU_proc_t *ru_proc=&ru->proc;
proc->frame_rx = frame_rx;
proc->slot_rx = slot_rx;
sl_ahead = sf_ahead*fp->slots_per_subframe;
if (!oai_exit) {
T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->slot_rx));
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
L1_proc->frame_rx = ru_proc->frame_rx;
L1_proc->slot_rx = ru_proc->tti_rx;
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
if (rxtx(gNB,L1_proc->frame_rx,L1_proc->slot_rx,L1_proc->frame_tx,L1_proc->slot_tx,string) < 0) LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id);
ru_proc->timestamp_tx = L1_proc->timestamp_tx;
ru_proc->tti_tx = L1_proc->slot_tx;
ru_proc->frame_tx = L1_proc->frame_tx;
}
}
int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot_tx,uint64_t timestamp_tx) {
RU_t *ru;
RU_proc_t *ru_proc;
int waitret = 0, ret = 0, time_ns = 1000*1000;
struct timespec now, abstime;
// note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time
// note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1);
time_ns = time_ns/gNB->frame_parms.slots_per_subframe;
AssertFatal((ret = pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret);
while (proc->instance_cnt_RUs < 0) {
clock_gettime(CLOCK_REALTIME, &now);
abstime.tv_sec = now.tv_sec;
abstime.tv_nsec = now.tv_nsec + time_ns;
if (abstime.tv_nsec >= 1000*1000*1000) {
abstime.tv_nsec -= 1000*1000*1000;
abstime.tv_sec += 1;
}
if((waitret = pthread_cond_timedwait(&proc->cond_RUs,&proc->mutex_RUs_tx,&abstime)) == 0) break; // this unlocks mutex_rxtx while waiting and then locks it again
}
proc->instance_cnt_RUs = -1;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
AssertFatal((ret = pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0);
if (waitret == ETIMEDOUT) {
LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx);
AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
gNB->proc.RU_mask_tx = 0;
AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret);
proc->instance_cnt_RUs = 0;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0);
return(-1);
}
for(int i=0; i<gNB->num_RU; i++)
{
ru = gNB->RU_list[i];
ru_proc = &ru->proc;
if (ru_proc->instance_cnt_gNBs == 0) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1);
LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->tti_tx, proc->frame_rx, proc->slot_rx);
AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
gNB->proc.RU_mask_tx = 0;
AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0);
return(-1);
}
AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret);
ru_proc->instance_cnt_gNBs = 0;
ru_proc->timestamp_tx = timestamp_tx;
ru_proc->tti_tx = slot_tx;
ru_proc->frame_tx = frame_tx;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs);
LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx);
// the thread can now be woken up
AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0,
"[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret);
}
return(0);
}
int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_tx,uint64_t timestamp_tx) {
gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB->proc.L1_proc_tx;
int ret;
AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret);
while(L1_proc_tx->instance_cnt == 0) {
pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex);
}
L1_proc_tx->instance_cnt = 0;
L1_proc_tx->slot_rx = slot_rx;
L1_proc_tx->frame_rx = frame_rx;
L1_proc_tx->slot_tx = slot_tx;
L1_proc_tx->frame_tx = frame_tx;
L1_proc_tx->timestamp_tx = timestamp_tx;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0);
// the thread can now be woken up
// the thread can now be woken up
AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n");
AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret);
return(0);
}
int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
gNB_L1_proc_t *proc=&gNB->proc;
gNB_L1_rxtx_proc_t *L1_proc=&proc->L1_proc;
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
RU_proc_t *ru_proc=&ru->proc;
int ret;
int i;
struct timespec abstime;
int time_ns = 50000;
int wait_timer = 0;
bool do_last_check = 1;
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret);
for (i=0; i<gNB->num_RU; i++) {
if (ru == gNB->RU_list[i]) {
if ((proc->RU_mask&(1<<i)) > 0)
LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask);
proc->RU_mask |= (1<<i);
}
}
if (proc->RU_mask != (1<<gNB->num_RU)-1) { // not all RUs have provided their information so return
LOG_E(PHY,"Not all RUs have provided their info\n");
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret);
return(0);
}
else { // all RUs have provided their information so continue on and wakeup gNB processing
proc->RU_mask = 0;
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret);
}
// wake up TX for subframe n+sf_ahead
// lock the TX mutex and make sure the thread is ready
while (wait_timer < 200) {
clock_gettime(CLOCK_REALTIME, &abstime);
abstime.tv_nsec = abstime.tv_nsec + time_ns;
if (abstime.tv_nsec >= 1000*1000*1000) {
abstime.tv_nsec -= 1000*1000*1000;
abstime.tv_sec += 1;
}
AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
if (L1_proc->instance_cnt == 0) { // L1_thread is busy so wait for a bit
AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
wait_timer += 50;
usleep(50);
}
else {
do_last_check = 0;
break;
}
}
if (do_last_check) {
AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe
AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx);
return (-1);
}
}
++L1_proc->instance_cnt;
// We have just received and processed the common part of a subframe, say n.
// TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
// transmitted timestamp of the next TX slot (first).
// The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
// we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti,
// and proc->slot_tx = proc->slot_rx+sf_ahead
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
L1_proc->frame_rx = ru_proc->frame_rx;
L1_proc->slot_rx = ru_proc->tti_rx;
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sf_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sf_ahead);
pthread_mutex_unlock( &L1_proc->mutex );
// the thread can now be woken up
if (pthread_cond_signal(&L1_proc->cond) != 0) {
LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n");
exit_fun( "ERROR pthread_cond_signal" );
return(-1);
}
return(0);
}
/*
void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) {
gNB_L1_proc_t *proc = &gNB->proc;
LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms;
int i;
if (ru!=NULL) {
pthread_mutex_lock(&proc->mutex_RU_PRACH);
for (i=0;i<gNB->num_RU;i++) {
if (ru == gNB->RU_list[i]) {
LOG_D(PHY,"frame %d, subframe %d: RU %d for gNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,gNB->Mod_id,proc->RU_mask_prach,gNB->num_RU);
if ((proc->RU_mask_prach&(1<<i)) > 0)
LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information (PRACH) from RU %d (num_RU %d, mask %x) has not been served yet!\n",
gNB->Mod_id,frame,subframe,ru->idx,gNB->num_RU,proc->RU_mask_prach);
proc->RU_mask_prach |= (1<<i);
}
}
if (proc->RU_mask_prach != (1<<gNB->num_RU)-1) { // not all RUs have provided their information so return
pthread_mutex_unlock(&proc->mutex_RU_PRACH);
return;
}
else { // all RUs have provided their information so continue on and wakeup gNB processing
proc->RU_mask_prach = 0;
pthread_mutex_unlock(&proc->mutex_RU_PRACH);
}
}
// check if we have to detect PRACH first
if (is_prach_subframe(fp,frame,subframe)>0) {
LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
if (proc->instance_cnt_prach == 0) {
LOG_W(PHY,"[gNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe);
return;
}
// wake up thread for PRACH RX
if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
exit_fun( "error locking mutex_prach" );
return;
}
++proc->instance_cnt_prach;
// set timing for prach thread
proc->frame_prach = frame;
proc->subframe_prach = subframe;
// the thread can now be woken up
if (pthread_cond_signal(&proc->cond_prach) != 0) {
LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB PRACH thread %d\n", proc->thread_index);
exit_fun( "ERROR pthread_cond_signal" );
return;
}
pthread_mutex_unlock( &proc->mutex_prach );
}
}*/
/*!
* \brief The prach receive thread of gNB.
* \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
/*
static void* gNB_thread_prach( void* param ) {
static int gNB_thread_prach_status;
PHY_VARS_gNB *gNB= (PHY_VARS_gNB *)param;
gNB_L1_proc_t *proc = &gNB->proc;
// set default return value
gNB_thread_prach_status = 0;
while (!oai_exit) {
if (oai_exit) break;
if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break;
LOG_D(PHY,"Running gNB prach procedures\n");
prach_procedures(gNB ,0);
if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break;
}
LOG_I(PHY, "Exiting gNB thread PRACH\n");
gNB_thread_prach_status = 0;
return &gNB_thread_prach_status;
}
*/
extern void init_td_thread(PHY_VARS_gNB *);
extern void init_te_thread(PHY_VARS_gNB *);
static void *process_stats_thread(void *param) {
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
reset_meas(&gNB->phy_proc_tx);
reset_meas(&gNB->dlsch_encoding_stats);
reset_meas(&gNB->dlsch_scrambling_stats);
reset_meas(&gNB->dlsch_modulation_stats);
reset_meas(&gNB->phy_proc_rx);
reset_meas(&gNB->ul_indication_stats);
reset_meas(&gNB->rx_pusch_stats);
reset_meas(&gNB->ulsch_decoding_stats);
wait_sync("process_stats_thread");
while(!oai_exit)
{
sleep(1);
print_meas(&gNB->dlsch_encoding_stats, "pdsch_encoding", NULL, NULL);
print_meas(&gNB->dlsch_scrambling_stats, "pdsch_scrambling", NULL, NULL);
print_meas(&gNB->dlsch_modulation_stats, "pdsch_modulation", NULL, NULL);
print_meas(&gNB->phy_proc_tx, "L1 Tx processing", NULL, NULL);
print_meas(&gNB->dlsch_encoding_stats, "DLSCH encoding", NULL, NULL);
print_meas(&gNB->phy_proc_rx, "L1 Rx processing", NULL, NULL);
print_meas(&gNB->ul_indication_stats, "UL Indication", NULL, NULL);
print_meas(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL);
print_meas(&gNB->ulsch_decoding_stats, "PUSCH decoding", NULL, NULL);
}
return(NULL);
}
void *nrL1_stats_thread(void *param) {
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
wait_sync("L1_stats_thread");
FILE *fd;
while (!oai_exit) {
sleep(1);
fd=fopen("nrL1_stats.log","w");
AssertFatal(fd!=NULL,"Cannot open nrL1_stats.log\n");
dump_nr_I0_stats(fd,gNB);
dump_pusch_stats(fd,gNB);
// nr_dump_uci_stats(fd,eNB,eNB->proc.L1_proc_tx.frame_tx);
fclose(fd);
}
return(NULL);
}
void init_gNB_proc(int inst) {
int i=0;
int CC_id = 0;
void init_gNB_Tpool(int inst) {
PHY_VARS_gNB *gNB;
gNB_L1_proc_t *proc;
gNB_L1_rxtx_proc_t *L1_proc,*L1_proc_tx;
// LOG_I(PHY,"%s(inst:%d) RC.nb_nr_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_nr_CC[inst]);
gNB = RC.gNB[inst];
LOG_I(PHY,"Initializing gNB processes instance:%d CC_id %d \n",inst,CC_id);
proc = &gNB->proc;
L1_proc = &proc->L1_proc;
L1_proc_tx = &proc->L1_proc_tx;
L1_proc->instance_cnt = -1;
L1_proc_tx->instance_cnt = -1;
L1_proc->instance_cnt_RUs = 0;
L1_proc_tx->instance_cnt_RUs = 0;
proc->instance_cnt_prach = -1;
proc->instance_cnt_asynch_rxtx = -1;
proc->CC_id = CC_id;
proc->first_rx =1;
proc->first_tx =1;
proc->RU_mask =0;
proc->RU_mask_tx = (1<<gNB->num_RU)-1;
proc->RU_mask_prach =0;
pthread_mutex_init( &gNB->UL_INFO_mutex, NULL);
pthread_mutex_init( &L1_proc->mutex, NULL);
pthread_mutex_init( &L1_proc_tx->mutex, NULL);
pthread_cond_init( &L1_proc->cond, NULL);
pthread_cond_init( &L1_proc_tx->cond, NULL);
pthread_mutex_init( &proc->mutex_prach, NULL);
pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
pthread_mutex_init( &proc->mutex_RU,NULL);
pthread_mutex_init( &proc->mutex_RU_tx,NULL);
pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
pthread_cond_init( &proc->cond_prach, NULL);
pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
LOG_I(PHY,"gNB->single_thread_flag:%d\n", gNB->single_thread_flag);
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
threadCreate( &L1_proc->pthread, gNB_L1_thread, gNB, "L1_proc", -1, OAI_PRIORITY_RT );
threadCreate( &L1_proc_tx->pthread, gNB_L1_thread_tx, gNB,"L1_proc_tx", -1, OAI_PRIORITY_RT);
}
if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
//pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB );
char name[16];
if (gNB->single_thread_flag==0) {
snprintf( name, sizeof(name), "L1 %d", i );
pthread_setname_np( L1_proc->pthread, name );
snprintf( name, sizeof(name), "L1TX %d", i );
pthread_setname_np( L1_proc_tx->pthread, name );
}
AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach);
/* setup PHY proc TX sync mechanism */
pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL);
pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL);
sync_phy_proc.phy_proc_CC_id = 0;
gNB_L1_proc_t *proc = &gNB->proc;
// ULSCH decoding threadpool
gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
LOG_I(PHY,"Number of threads requested in config file: %d, Number of threads available on this machine: %d\n",gNB->pusch_proc_threads,numCPU);
int threadCnt = min(numCPU, gNB->pusch_proc_threads);
if (threadCnt < 2) LOG_E(PHY,"Number of threads for gNB should be more than 1. Allocated only %d\n",threadCnt);
char ul_pool[80];
sprintf(ul_pool,"-1");
int s_offset = 0;
@@ -923,71 +408,44 @@ void init_gNB_proc(int inst) {
sprintf(ul_pool+2+s_offset,",-1");
s_offset += 3;
}
if (getenv("noThreads")) strcpy(ul_pool, "n");
initTpool(ul_pool, gNB->threadPool, false);
// ULSCH decoder result FIFO
gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
initNotifiedFIFO(gNB->respDecode);
}
// L1 RX result FIFO
gNB->resp_L1 = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
initNotifiedFIFO(gNB->resp_L1);
// L1 TX result FIFO
gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
initNotifiedFIFO(gNB->resp_L1_tx);
// RU TX result FIFO
gNB->resp_RU_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
initNotifiedFIFO(gNB->resp_RU_tx);
// Stats measurement thread
if(opp_enabled == 1) threadCreate(&proc->process_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW);
}
/*!
* \brief Terminate gNB TX and RX threads.
*/
void kill_gNB_proc(int inst) {
int *status;
PHY_VARS_gNB *gNB;
gNB_L1_proc_t *proc;
gNB_L1_rxtx_proc_t *L1_proc, *L1_proc_tx;
gNB=RC.gNB[inst];
proc = &gNB->proc;
L1_proc = &proc->L1_proc;
L1_proc_tx = &proc->L1_proc_tx;
LOG_I(PHY, "Killing TX inst %d\n",inst );
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
pthread_mutex_lock(&L1_proc->mutex);
L1_proc->instance_cnt = 0;
pthread_cond_signal(&L1_proc->cond);
pthread_mutex_unlock(&L1_proc->mutex);
pthread_mutex_lock(&L1_proc_tx->mutex);
L1_proc_tx->instance_cnt = 0;
pthread_cond_signal(&L1_proc_tx->cond);
pthread_mutex_unlock(&L1_proc_tx->mutex);
}
proc->instance_cnt_prach = 0;
pthread_cond_signal( &proc->cond_prach );
pthread_cond_signal( &proc->cond_asynch_rxtx );
pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
// LOG_D(PHY, "joining pthread_prach\n");
// pthread_join( proc->pthread_prach, (void**)&status );
LOG_I(PHY, "Destroying prach mutex/cond\n");
pthread_mutex_destroy( &proc->mutex_prach );
pthread_cond_destroy( &proc->cond_prach );
LOG_I(PHY, "Destroying UL_INFO mutex\n");
pthread_mutex_destroy(&gNB->UL_INFO_mutex);
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
LOG_I(PHY, "Joining L1_proc mutex/cond\n");
pthread_join( L1_proc->pthread, (void **)&status );
LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n");
pthread_join( L1_proc_tx->pthread, (void **)&status );
}
LOG_I(PHY, "Destroying L1_proc mutex/cond\n");
pthread_mutex_destroy( &L1_proc->mutex );
pthread_cond_destroy( &L1_proc->cond );
LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n");
pthread_mutex_destroy( &L1_proc_tx->mutex );
pthread_cond_destroy( &L1_proc_tx->cond );
pthread_mutex_destroy( &proc->mutex_RU );
pthread_mutex_destroy( &proc->mutex_RU_tx );
}
void reset_opp_meas(void) {
int sfn;
reset_meas(&softmodem_stats_mt);
@@ -1055,15 +513,9 @@ printf("after %p\n", gNB->common_vars.rxdataF[aa]);
* (not tested in other modes).
*/
//init_precoding_weights(RC.gNB[inst]);
init_gNB_proc(inst);
init_gNB_Tpool(inst);
}
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
RC.ru[ru_id]->nr_wakeup_rxtx = wakeup_rxtx;
// RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_gNB;
RC.ru[ru_id]->gNB_top = gNB_top;
}
}
void init_gNB(int single_thread_flag,int wait_for_sync) {
@@ -1072,18 +524,16 @@ void init_gNB(int single_thread_flag,int wait_for_sync) {
PHY_VARS_gNB *gNB;
if (RC.gNB == NULL) {
RC.gNB = (PHY_VARS_gNB **) malloc((1+RC.nb_nr_L1_inst)*sizeof(PHY_VARS_gNB *));
for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
RC.gNB[inst] = (PHY_VARS_gNB *) malloc(sizeof(PHY_VARS_gNB));
memset((void*)RC.gNB[inst],0,sizeof(PHY_VARS_gNB));
}
RC.gNB = (PHY_VARS_gNB **) calloc(1+RC.nb_nr_L1_inst, sizeof(PHY_VARS_gNB *));
LOG_I(PHY,"gNB L1 structure RC.gNB allocated @ %p\n",RC.gNB);
}
LOG_I(PHY,"gNB L1 structure RC.gNB allocated @ %p\n",RC.gNB);
for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
LOG_I(PHY,"[lte-softmodem.c] gNB structure RC.gNB[%d] allocated @ %p\n",inst,RC.gNB[inst]);
if (RC.gNB[inst] == NULL) {
RC.gNB[inst] = (PHY_VARS_gNB *) calloc(1, sizeof(PHY_VARS_gNB));
LOG_I(PHY,"[nr-gnb.c] gNB structure RC.gNB[%d] allocated @ %p\n",inst,RC.gNB[inst]);
}
gNB = RC.gNB[inst];
gNB->abstraction_flag = 0;
gNB->single_thread_flag = single_thread_flag;
@@ -1113,7 +563,7 @@ void init_gNB(int single_thread_flag,int wait_for_sync) {
}
LOG_I(PHY,"[nr-softmodem.c] gNB structure allocated\n");
LOG_I(PHY,"[nr-gnb.c] gNB structure allocated\n");
}
+309 -743
View File
File diff suppressed because it is too large Load Diff
+7 -2
View File
@@ -68,11 +68,16 @@
#define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n"
#define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n"
#define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n"
#define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n"
#define CONFIG_HLP_DLMCS_PHYTEST "Set the downlink MCS for PHYTEST mode\n"
#define CONFIG_HLP_DLNL_PHYTEST "Set the downlink nrOfLayers for PHYTEST mode\n"
#define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n"
#define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n"
#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n"
#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n"
#define CONFIG_HLP_ULMCS_PHYTEST "Set the uplink MCS for PHYTEST mode\n"
#define CONFIG_HLP_DLBW_PHYTEST "Set the number of PRBs used for DLSCH in PHYTEST mode\n"
#define CONFIG_HLP_ULBW_PHYTEST "Set the number of PRBs used for ULSCH in PHYTEST mode\n"
#define CONFIG_HLP_DLBM_PHYTEST "Bitmap for DLSCH slots (slot 0 starts at LSB)\n"
#define CONFIG_HLP_ULBM_PHYTEST "Bitmap for ULSCH slots (slot 0 starts at LSB)\n"
#define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n"
#define CONFIG_HLP_UE "Set the lte softmodem as a UE\n"
#define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n"
+76 -61
View File
@@ -85,6 +85,7 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "x2ap_eNB.h"
#include "ngap_gNB.h"
#include "gnb_paramdef.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "nfapi/oai_integration/vendor_ext.h"
pthread_cond_t nfapi_sync_cond;
@@ -92,7 +93,7 @@ pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
extern uint8_t nfapi_mode; // Default to monolithic mode
THREAD_STRUCT thread_struct;
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
@@ -114,7 +115,6 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
//Temp fix for inexistent NR upper layer
unsigned char NB_gNB_INST = 1;
static char *itti_dump_file = NULL;
int UE_scan = 1;
int UE_scan_carrier = 0;
@@ -136,9 +136,6 @@ double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
double rx_gain_off = 0.0;
double sample_rate=30.72e6;
double bw = 10.0e6;
static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/;
@@ -163,15 +160,20 @@ int otg_enabled;
//static NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
//static nfapi_nr_config_request_t *config[MAX_NUM_CCs];
uint32_t target_dl_mcs = 28; //maximum allowed mcs
uint32_t target_ul_mcs = 20;
uint32_t timing_advance = 0;
uint64_t num_missed_slots=0; // counter for the number of missed slots
#include <executables/split_headers.h>
#include <SIMULATION/ETH_TRANSPORT/proto.h>
int split73=0;
void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) {
AssertFatal(false, "Must not be called in this context\n");
}
void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) {
AssertFatal(false, "Must not be called in this context\n");
}
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
@@ -182,7 +184,6 @@ extern void *udp_eNB_task(void *args_p);
int transmission_mode=1;
int emulate_rf = 0;
int numerology = 0;
int usrp_tx_thread = 0;
static char *parallel_config = NULL;
@@ -344,7 +345,7 @@ int create_gNB_tasks(uint32_t gnb_nb) {
}
if (AMF_MODE_ENABLED && (get_softmodem_params()->phy_test==0 && get_softmodem_params()->do_ra==0 && get_softmodem_params()->sa==0)) {
if (AMF_MODE_ENABLED) {
if (gnb_nb > 0) {
/*
if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) {
@@ -369,25 +370,31 @@ int create_gNB_tasks(uint32_t gnb_nb) {
}
}
if (itti_create_task (TASK_GTPV1_U, &gtpv1u_gNB_task, NULL) < 0) {
/*if (itti_create_task (TASK_GTPV1_U, &nr_gtpv1u_gNB_task, NULL) < 0) {
LOG_E(GTPU, "Create task for GTPV1U failed\n");
return -1;
}
}*/
}
}
if (gnb_nb > 0) {
if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) {
LOG_E(GNB_APP, "Create task for gNB APP failed\n");
return -1;
}
LOG_I(NR_RRC,"Creating NR RRC gNB Task\n");
LOG_I(NR_RRC,"Creating NR RRC gNB Task\n");
if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) {
LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n");
return -1;
}
//Use check on x2ap to consider the NSA scenario and check on AMF_MODE_ENABLED for the SA scenario
if(is_x2ap_enabled() || AMF_MODE_ENABLED){
if (itti_create_task (TASK_GTPV1_U, &nr_gtpv1u_gNB_task, NULL) < 0) {
LOG_E(GTPU, "Create task for GTPV1U failed\n");
return -1;
}
}
}
return 0;
@@ -626,33 +633,36 @@ static void wait_nfapi_init(char *thread_name) {
}
void init_pdcp(void) {
//if (!NODE_IS_DU(RC.rrc[0]->node_type)) {
pdcp_layer_init();
uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
(PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;
if (IS_SOFTMODEM_NOS1) {
printf("IS_SOFTMODEM_NOS1 option enabled \n");
pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ;
}
if (!NODE_IS_DU(RC.nrrrc[0]->node_type)) {
// pdcp_layer_init();
uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
(PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;
if (IS_SOFTMODEM_NOS1) {
printf("IS_SOFTMODEM_NOS1 option enabled \n");
pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT;
}
nr_pdcp_module_init(pdcp_initmask, 0);
/*if (NODE_IS_CU(RC.rrc[0]->node_type)) {
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
} else {*/
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
//}
/*} else {
if (NODE_IS_CU(RC.nrrrc[0]->node_type)) {
LOG_I(PDCP, "node is CU, pdcp send rlc_data_req by proto_agent \n");
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
} else {
LOG_I(PDCP, "node is gNB \n");
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
}
} else {
LOG_I(PDCP, "node is DU, rlc send pdcp_data_ind by proto_agent \n");
pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind);
}*/
}
}
int main( int argc, char **argv )
{
int ru_id, CC_id = 0;
start_background_system();
///static configuration for NR at the moment
@@ -680,8 +690,8 @@ int main( int argc, char **argv )
}
openair0_cfg[0].threequarter_fs = threequarter_fs;
AMF_MODE_ENABLED = !IS_SOFTMODEM_NOS1; //!get_softmodem_params()->phy_test;
NGAP_CONF_MODE = !IS_SOFTMODEM_NOS1; //!get_softmodem_params()->phy_test;
AMF_MODE_ENABLED = get_softmodem_params()->sa;
NGAP_CONF_MODE = get_softmodem_params()->sa;
if (get_softmodem_params()->do_ra)
AssertFatal(get_softmodem_params()->phy_test == 0,"RA and phy_test are mutually exclusive\n");
@@ -812,36 +822,38 @@ if(IS_SOFTMODEM_NOS1)
wait_nfapi_init("main?");
}
printf("wait RUs\n");
wait_RUs();
printf("ALL RUs READY!\n");
printf("RC.nb_RU:%d\n", RC.nb_RU);
// once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
printf("ALL RUs ready - init gNBs\n");
if(IS_SOFTMODEM_DOFORMS) {
sleep(1);
scopeParms_t p;
p.argc=&argc;
p.argv=argv;
p.gNB=RC.gNB[0];
p.ru=RC.ru[0];
load_softscope("nr",&p);
}
if (RC.nb_nr_L1_inst > 0) {
printf("wait RUs\n");
wait_RUs();
printf("ALL RUs READY!\n");
printf("RC.nb_RU:%d\n", RC.nb_RU);
// once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
printf("ALL RUs ready - init gNBs\n");
if(IS_SOFTMODEM_DOSCOPE) {
sleep(1);
scopeParms_t p;
p.argc=&argc;
p.argv=argv;
p.gNB=RC.gNB[0];
p.ru=RC.ru[0];
load_softscope("nr",&p);
}
if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF) {
printf("Not NFAPI mode - call init_eNB_afterRU()\n");
init_eNB_afterRU();
} else {
printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n");
}
if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF) {
printf("Not NFAPI mode - call init_eNB_afterRU()\n");
init_eNB_afterRU();
} else {
printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n");
}
printf("ALL RUs ready - ALL gNBs ready\n");
// connect the TX/RX buffers
printf("Sending sync to all threads\n");
pthread_mutex_lock(&sync_mutex);
sync_var=0;
pthread_cond_broadcast(&sync_cond);
pthread_mutex_unlock(&sync_mutex);
printf("ALL RUs ready - ALL gNBs ready\n");
// connect the TX/RX buffers
printf("Sending sync to all threads\n");
pthread_mutex_lock(&sync_mutex);
sync_var=0;
pthread_cond_broadcast(&sync_cond);
pthread_mutex_unlock(&sync_mutex);
}
printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
end_configmodule();
printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
@@ -879,7 +891,10 @@ if(IS_SOFTMODEM_NOS1)
printf("stopping MODEM threads\n");
// cleanup
stop_gNB(NB_gNB_INST);
stop_RU(NB_RU);
if (RC.nb_nr_L1_inst > 0) {
stop_RU(NB_RU);
}
/* release memory used by the RU/gNB threads (incomplete), after all
* threads have been stopped (they partially use the same memory) */
+14 -4
View File
@@ -18,19 +18,29 @@
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define CMDLINE_PARAMS_DESC_GNB { \
{"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \
{"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \
{"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, i8ptr:&threequarter_fs, defintval:0, TYPE_INT8, 0}, \
{"K" , CONFIG_HLP_ITTIL, PARAMFLAG_NOFREE, strptr:&itti_dump_file, defstrval:"/tmp/itti.dump", TYPE_STRING, 0}, \
{"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \
{"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \
{"m" , CONFIG_HLP_DLMCS_PHYTEST,0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \
{"l" , CONFIG_HLP_DLNL_PHYTEST,0, uptr:&target_dl_Nl, defintval:0, TYPE_UINT, 0}, \
{"t" , CONFIG_HLP_ULMCS_PHYTEST,0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \
{"M" , CONFIG_HLP_DLBW_PHYTEST,0, uptr:&target_dl_bw, defintval:0, TYPE_UINT, 0}, \
{"T" , CONFIG_HLP_ULBW_PHYTEST,0, uptr:&target_ul_bw, defintval:0, TYPE_UINT, 0}, \
{"D" , CONFIG_HLP_DLBM_PHYTEST,0, u64ptr:&dlsch_slot_bitmap, defintval:0, TYPE_UINT64, 0}, \
{"U" , CONFIG_HLP_ULBM_PHYTEST,0, u64ptr:&ulsch_slot_bitmap, defintval:0, TYPE_UINT64, 0}, \
{"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, iptr:&usrp_tx_thread, defstrval:0, TYPE_INT, 0}, \
{"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \
}
#include "threads_t.h"
extern threads_t threads;
extern uint32_t target_dl_mcs;
extern uint32_t target_dl_Nl;
extern uint32_t target_ul_mcs;
extern uint32_t target_dl_bw;
extern uint32_t target_ul_bw;
extern uint64_t dlsch_slot_bitmap;
extern uint64_t ulsch_slot_bitmap;
// In nr-gnb.c
extern void init_gNB(int single_thread_flag,int wait_for_sync);
+131 -127
View File
@@ -28,6 +28,8 @@
#include "SCHED_NR_UE/defs.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "LAYER2/nr_pdcp/nr_pdcp_entity.h"
//#include "executables/softmodem-common.h"
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
/*
* NR SLOT PROCESSING SEQUENCE
@@ -91,6 +93,8 @@
#else
#define DURATION_RX_TO_TX (6) /* For LTE, this duration is fixed to 4 and it is linked to LTE standard for both modes FDD/TDD */
#endif
#define RX_JOB_ID 0x1010
#define TX_JOB_ID 100
typedef enum {
pss = 0,
@@ -112,6 +116,7 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
ue->Mod_id = UE_id;
ue->mac_enabled = 1;
ue->if_inst = nr_ue_if_module_init(0);
ue->dci_thres = 0;
// Setting UE mode to NOT_SYNCHED by default
for (gNB_id = 0; gNB_id < nb_connected_gNB; gNB_id++){
@@ -287,11 +292,11 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
mac->dl_info.dci_ind = NULL;
mac->dl_info.rx_ind = NULL;
if (is_nr_DL_slot(mac->scc, ul_info.slot_rx))
if (is_nr_DL_slot(mac->scc->tdd_UL_DL_ConfigurationCommon, ul_info.slot_rx))
{
nr_ue_dl_indication(&mac->dl_info, &ul_time_alignment);
}
if (is_nr_UL_slot(mac->scc, ul_info.slot_tx))
if (is_nr_UL_slot(mac->scc->tdd_UL_DL_ConfigurationCommon, ul_info.slot_tx, mac->frame_type))
{
LOG_D(NR_MAC, "Slot %d. calling nr_ue_ul_ind() from %s\n", ul_info.slot_tx, __FUNCTION__);
nr_ue_ul_indication(&ul_info);
@@ -367,10 +372,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
* \param arg is a pointer to a \ref PHY_VARS_NR_UE structure.
*/
typedef struct syncData_s {
UE_nr_rxtx_proc_t proc;
PHY_VARS_NR_UE *UE;
} syncData_t;
typedef nr_rxtx_thread_data_t syncData_t;
static void UE_synch(void *arg) {
syncData_t *syncD=(syncData_t *) arg;
@@ -475,43 +477,6 @@ static void UE_synch(void *arg) {
openair0_cfg[UE->rf_map.card].rx_freq[0],
openair0_cfg[UE->rf_map.card].tx_freq[0]);
// reconfigure for potentially different bandwidth
switch(UE->frame_parms.N_RB_DL) {
case 6:
openair0_cfg[UE->rf_map.card].sample_rate =1.92e6;
openair0_cfg[UE->rf_map.card].rx_bw =.96e6;
openair0_cfg[UE->rf_map.card].tx_bw =.96e6;
// openair0_cfg[0].rx_gain[0] -= 12;
break;
case 25:
openair0_cfg[UE->rf_map.card].sample_rate =7.68e6;
openair0_cfg[UE->rf_map.card].rx_bw =2.5e6;
openair0_cfg[UE->rf_map.card].tx_bw =2.5e6;
// openair0_cfg[0].rx_gain[0] -= 6;
break;
case 50:
openair0_cfg[UE->rf_map.card].sample_rate =15.36e6;
openair0_cfg[UE->rf_map.card].rx_bw =5.0e6;
openair0_cfg[UE->rf_map.card].tx_bw =5.0e6;
// openair0_cfg[0].rx_gain[0] -= 3;
break;
case 100:
openair0_cfg[UE->rf_map.card].sample_rate=30.72e6;
openair0_cfg[UE->rf_map.card].rx_bw=10.0e6;
openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
// openair0_cfg[0].rx_gain[0] -= 0;
break;
case 66:
openair0_cfg[UE->rf_map.card].sample_rate=122.88e6;
openair0_cfg[UE->rf_map.card].rx_bw=100.e6;
openair0_cfg[UE->rf_map.card].tx_bw=100.e6;
break;
}
if (UE->mode != loop_through_memory) {
UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
//UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
@@ -554,11 +519,16 @@ static void UE_synch(void *arg) {
}
}
void processSlotTX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
void processSlotTX(void *arg) {
nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg;
UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
PHY_VARS_NR_UE *UE = rxtxD->UE;
fapi_nr_config_request_t *cfg = &UE->nrUE_config;
int tx_slot_type = nr_ue_slot_select(cfg, proc->frame_tx, proc->nr_slot_tx);
uint8_t gNB_id = 0;
LOG_D(PHY,"%d.%d => slot type %d\n",proc->frame_tx,proc->nr_slot_tx,tx_slot_type);
if (tx_slot_type == NR_UPLINK_SLOT || tx_slot_type == NR_MIXED_SLOT){
// trigger L2 to run ue_scheduler thru IF module
@@ -585,10 +555,14 @@ void processSlotTX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
}
}
void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
void processSlotRX(void *arg) {
nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg;
UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
PHY_VARS_NR_UE *UE = rxtxD->UE;
fapi_nr_config_request_t *cfg = &UE->nrUE_config;
int rx_slot_type = nr_ue_slot_select(cfg, proc->frame_rx, proc->nr_slot_rx);
int tx_slot_type = nr_ue_slot_select(cfg, proc->frame_tx, proc->nr_slot_tx);
uint8_t gNB_id = 0;
if (rx_slot_type == NR_DOWNLINK_SLOT || rx_slot_type == NR_MIXED_SLOT){
@@ -604,44 +578,56 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, no_relay, NULL );
#else
uint64_t a=rdtsc();
phy_procedures_nrUE_RX(UE, proc, gNB_id, get_nrUE_params()->nr_dlsch_parallel);
phy_procedures_nrUE_RX(UE, proc, gNB_id, get_nrUE_params()->nr_dlsch_parallel, &rxtxD->txFifo);
LOG_D(PHY, "In %s: slot %d, time %lu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc()-a)/3500);
#endif
if(IS_SOFTMODEM_NOS1){
if(IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa){
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
protocol_ctxt_t ctxt;
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO, mac->crnti, proc->frame_rx, proc->nr_slot_rx, 0);
pdcp_run(&ctxt);
/* send tick to RLC and PDCP every ms */
if (proc->nr_slot_rx % UE->frame_parms.slots_per_subframe == 0) {
void nr_rlc_tick(int frame, int subframe);
void nr_pdcp_tick(int frame, int subframe);
nr_rlc_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe);
nr_pdcp_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe);
}
}
// Wait for PUSCH processing to finish
notifiedFIFO_elt_t *res;
res = pullTpool(&rxtxD->txFifo,&(get_nrUE_params()->Tpool));
delNotifiedFIFO_elt(res);
} else {
processSlotTX(rxtxD);
}
}
if (tx_slot_type == NR_UPLINK_SLOT || tx_slot_type == NR_MIXED_SLOT){
if (UE->UE_mode[gNB_id] <= PUSCH) {
if (get_softmodem_params()->usim_test==0) {
pucch_procedures_ue_nr(UE,
gNB_id,
proc,
FALSE);
}
/*!
* \brief This is the UE thread for RX subframe n and TX subframe n+4.
* This thread performs the phy_procedures_UE_RX() on every received slot.
* then, if TX is enabled it performs TX for n+4.
* \param arg is a pointer to a \ref PHY_VARS_NR_UE structure.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
LOG_D(PHY, "Sending Uplink data \n");
nr_ue_pusch_common_procedures(UE,
proc->nr_slot_tx,
&UE->frame_parms,1);
}
typedef struct processingData_s {
UE_nr_rxtx_proc_t proc;
PHY_VARS_NR_UE *UE;
} processingData_t;
void UE_processing(void *arg) {
processingData_t *rxtxD = (processingData_t *) arg;
UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
PHY_VARS_NR_UE *UE = rxtxD->UE;
int slot_tx = proc->nr_slot_tx;
int frame_tx = proc->frame_tx;
processSlotRX(UE, proc);
processSlotTX(UE, proc);
ue_ta_procedures(UE, slot_tx, frame_tx);
if (UE->UE_mode[gNB_id] > NOT_SYNCHED && UE->UE_mode[gNB_id] < PUSCH) {
nr_ue_prach_procedures(UE, proc, gNB_id);
}
LOG_D(PHY,"****** end TX-Chain for AbsSubframe %d.%d ******\n", proc->frame_tx, proc->nr_slot_tx);
}
ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx);
}
void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) {
@@ -758,25 +744,44 @@ void *UE_thread(void *arg) {
int start_rx_stream = 0;
AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "");
UE->rfdevice.host_type = RAU_HOST;
UE->lost_sync = 0;
UE->is_synchronized = 0;
AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n");
notifiedFIFO_t nf;
initNotifiedFIFO(&nf);
int nbSlotProcessing=0;
int thread_idx=0;
notifiedFIFO_t freeBlocks;
initNotifiedFIFO_nothreadSafe(&freeBlocks);
int nbSlotProcessing=0;
int thread_idx=0;
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
int timing_advance = UE->timing_advance;
for (int i=0; i<RX_NB_TH+1; i++) // RX_NB_TH working + 1 we are making to be pushed
pushNotifiedFIFO_nothreadSafe(&freeBlocks,
newNotifiedFIFO_elt(sizeof(processingData_t), 0,&nf,UE_processing));
bool syncRunning=false;
const int nb_slot_frame = UE->frame_parms.slots_per_frame;
int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0;
for (int i=0; i<NR_RX_NB_TH+1; i++) {// NR_RX_NB_TH working + 1 we are making to be pushed
notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), RX_JOB_ID,&nf,processSlotRX);
nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(newElt);
initNotifiedFIFO(&curMsg->txFifo);
pushNotifiedFIFO_nothreadSafe(&freeBlocks, newElt);
}
while (!oai_exit) {
if (UE->lost_sync) {
int nb = abortTpool(&(get_nrUE_params()->Tpool),RX_JOB_ID);
nb += abortNotifiedFIFO(&nf, RX_JOB_ID);
LOG_I(PHY,"Number of aborted slots %d\n",nb);
for (int i=0; i<nb; i++)
pushNotifiedFIFO_nothreadSafe(&freeBlocks, newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), RX_JOB_ID,&nf,processSlotRX));
nbSlotProcessing = 0;
UE->is_synchronized = 0;
UE->lost_sync = 0;
}
if (syncRunning) {
notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool));
@@ -786,9 +791,10 @@ void *UE_thread(void *arg) {
if (UE->is_synchronized) {
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
// shift the frame index with all the frames we trashed meanwhile we perform the synch search
decoded_frame_rx=(decoded_frame_rx + (!UE->init_sync_frame) + trashed_frames) % MAX_FRAME_NUMBER;
decoded_frame_rx=(decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER;
}
delNotifiedFIFO_elt(res);
start_rx_stream=0;
} else {
readFrame(UE, &timestamp, true);
trashed_frames+=2;
@@ -835,13 +841,13 @@ void *UE_thread(void *arg) {
// whatever means thread_idx
// Fix me: will be wrong when slot 1 is slow, as slot 2 finishes
// Slot 3 will overlap if RX_NB_TH is 2
// Slot 3 will overlap if NR_RX_NB_TH is 2
// this is general failure in UE !!!
thread_idx = absolute_slot % RX_NB_TH;
thread_idx = absolute_slot % NR_RX_NB_TH;
int slot_nr = absolute_slot % nb_slot_frame;
notifiedFIFO_elt_t *msgToPush;
AssertFatal((msgToPush=pullNotifiedFIFO_nothreadSafe(&freeBlocks)) != NULL,"chained list failure");
processingData_t *curMsg=(processingData_t *)NotifiedFifoData(msgToPush);
nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(msgToPush);
curMsg->UE=UE;
// update thread index for received subframe
curMsg->proc.thread_id = thread_idx;
@@ -869,18 +875,18 @@ void *UE_thread(void *arg) {
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
txp[i] = (void *)&UE->common_vars.txdata[i][UE->frame_parms.get_samples_slot_timestamp(
((slot_nr + DURATION_RX_TO_TX - RX_NB_TH)%nb_slot_frame),&UE->frame_parms,0)];
((slot_nr + DURATION_RX_TO_TX - NR_RX_NB_TH)%nb_slot_frame),&UE->frame_parms,0)];
int readBlockSize, writeBlockSize;
if (slot_nr<(nb_slot_frame - 1)) {
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms);
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - RX_NB_TH) % nb_slot_frame, &UE->frame_parms);
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - NR_RX_NB_TH) % nb_slot_frame, &UE->frame_parms);
} else {
UE->rx_offset_diff = computeSamplesShift(UE);
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) -
UE->rx_offset_diff;
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - RX_NB_TH) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff;
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - NR_RX_NB_TH) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff;
}
AssertFatal(readBlockSize ==
@@ -907,31 +913,33 @@ void *UE_thread(void *arg) {
}
curMsg->proc.timestamp_tx = timestamp+
UE->frame_parms.get_samples_slot_timestamp(slot_nr,
&UE->frame_parms,DURATION_RX_TO_TX) - firstSymSamp;
UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,DURATION_RX_TO_TX)
- firstSymSamp;
notifiedFIFO_elt_t *res;
while (nbSlotProcessing >= RX_NB_TH) {
while (nbSlotProcessing >= NR_RX_NB_TH) {
res=pullTpool(&nf, &(get_nrUE_params()->Tpool));
nbSlotProcessing--;
processingData_t *tmp=(processingData_t *)res->msgData;
nr_rxtx_thread_data_t *tmp=(nr_rxtx_thread_data_t *)res->msgData;
if (tmp->proc.decoded_frame_rx != -1)
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
else
else
decoded_frame_rx=-1;
pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
}
if ( decoded_frame_rx>0 && decoded_frame_rx != curMsg->proc.frame_rx)
if (decoded_frame_rx>0 && decoded_frame_rx != curMsg->proc.frame_rx)
LOG_E(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n",
decoded_frame_rx, curMsg->proc.frame_rx );
decoded_frame_rx, curMsg->proc.frame_rx);
// use previous timing_advance value to compute writeTimestamp
writeTimestamp = timestamp + UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms,DURATION_RX_TO_TX - RX_NB_TH) -
firstSymSamp - openair0_cfg[0].tx_sample_advance - UE->N_TA_offset - timing_advance;
writeTimestamp = timestamp+
UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,DURATION_RX_TO_TX
- NR_RX_NB_TH) - firstSymSamp - openair0_cfg[0].tx_sample_advance -
UE->N_TA_offset - timing_advance;
// but use current UE->timing_advance value to compute writeBlockSize
if (UE->timing_advance != timing_advance) {
@@ -940,51 +948,47 @@ void *UE_thread(void *arg) {
}
int flags = 0;
int slot_tx_usrp = slot_nr + DURATION_RX_TO_TX - RX_NB_TH;
uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
uint8_t num_UL_slots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots +
(mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0);
uint8_t first_tx_slot = tdd_period - num_UL_slots;
if (slot_tx_usrp%tdd_period==first_tx_slot)
flags=2;
else if (slot_tx_usrp%tdd_period==first_tx_slot+num_UL_slots-1)
flags = 3;
else if (slot_tx_usrp%tdd_period>first_tx_slot)
int slot_tx_usrp = slot_nr + DURATION_RX_TO_TX - NR_RX_NB_TH;
if (openair0_cfg[0].duplex_mode == duplex_mode_TDD) {
uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
int nrofUplinkSlots = 0;
if (mac->scc_SIB)
nrofUplinkSlots = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
else if (mac->scc)
nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSlots != 0);
uint8_t first_tx_slot = tdd_period - num_UL_slots;
if (slot_tx_usrp % tdd_period == first_tx_slot)
flags = 2;
else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1)
flags = 3;
else if (slot_tx_usrp % tdd_period > first_tx_slot)
flags = 1;
} else {
flags = 1;
}
if (flags || IS_SOFTMODEM_RFSIM)
AssertFatal( writeBlockSize ==
UE->rfdevice.trx_write_func(&UE->rfdevice,
writeTimestamp,
txp,
writeBlockSize,
UE->frame_parms.nb_antennas_tx,
flags),"");
AssertFatal(writeBlockSize ==
UE->rfdevice.trx_write_func(&UE->rfdevice,
writeTimestamp,
txp,
writeBlockSize,
UE->frame_parms.nb_antennas_tx,
flags),"");
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
memset(txp[i], 0, writeBlockSize);
nbSlotProcessing++;
msgToPush->key=slot_nr;
LOG_D(PHY,"Number of slots being processed at the moment: %d\n",nbSlotProcessing);
pushTpool(&(get_nrUE_params()->Tpool), msgToPush);
if (IS_SOFTMODEM_RFSIM) { //getenv("RFSIMULATOR")
// FixMe: Wait previous thread is done, because race conditions seems too bad
// in case of actual RF board, the overlap between threads mitigate the issue
// We must receive one message, that proves the slot processing is done
res=pullTpool(&nf, &(get_nrUE_params()->Tpool));
nbSlotProcessing--;
processingData_t *tmp=(processingData_t *)res->msgData;
if (tmp->proc.decoded_frame_rx != -1)
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
else
decoded_frame_rx=-1;
//decoded_frame_rx=tmp->proc.decoded_frame_rx;
pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
}
} // while !oai_exit
return NULL;
+65 -117
View File
@@ -82,12 +82,15 @@ unsigned short config_frames[4] = {2,9,11,13};
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
#include "PHY/TOOLS/phy_scope_interface.h"
#include "PHY/TOOLS/nr_phy_scope.h"
#define NRUE_MAIN
#include <executables/nr-uesoftmodem.h>
#include "executables/softmodem-common.h"
#include "executables/thread-common.h"
#include "nr_nas_msg_sim.h"
extern const char *duplex_mode[];
THREAD_STRUCT thread_struct;
nrUE_params_t nrUE_params;
// Thread variables
pthread_cond_t nfapi_sync_cond;
@@ -146,11 +149,11 @@ int card_offset = 0;
uint64_t num_missed_slots = 0; // counter for the number of missed slots
int transmission_mode = 1;
int numerology = 0;
int usrp_tx_thread = 0;
int oaisim_flag = 0;
int emulate_rf = 0;
char uecap_xer[1024],uecap_xer_in=0;
uint32_t N_RB_DL = 106;
char uecap_xer_in = 0;
char uecap_xer[1024];
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
* this is very hackish - find a proper solution
@@ -188,6 +191,7 @@ int create_tasks_nrue(uint32_t ue_nb) {
itti_wait_ready(1);
if (ue_nb > 0) {
LOG_I(NR_RRC,"create TASK_RRC_NRUE \n");
if (itti_create_task (TASK_RRC_NRUE, rrc_nrue_task, NULL) < 0) {
LOG_E(NR_RRC, "Create task for RRC UE failed\n");
return -1;
@@ -200,6 +204,11 @@ int create_tasks_nrue(uint32_t ue_nb) {
return -1;
}
}
if (itti_create_task (TASK_NAS_NRUE, nas_nrue_task, NULL) < 0) {
LOG_E(NR_RRC, "Create task for NAS UE failed\n");
return -1;
}
itti_wait_ready(0);
return 0;
}
@@ -238,9 +247,16 @@ nrUE_params_t *get_nrUE_params(void) {
}
/* initialie thread pools used for NRUE processing paralleliation */
void init_tpools(uint8_t nun_dlsch_threads) {
char *params=calloc(1,(RX_NB_TH*3)+1);
for (int i=0; i<RX_NB_TH; i++) {
memcpy(params+(i*3),"-1,",3);
char *params = NULL;
if (IS_SOFTMODEM_RFSIM) {
params = calloc(1,2);
memcpy(params,"N",1);
}
else {
params = calloc(1,(NR_RX_NB_TH*NR_NB_TH_SLOT*3)+1);
for (int i=0; i<NR_RX_NB_TH*NR_NB_TH_SLOT; i++) {
memcpy(params+(i*3),"-1,",3);
}
}
initTpool(params, &(nrUE_params.Tpool), false);
free(params);
@@ -264,7 +280,6 @@ static void get_options(void) {
printf("%s\n",uecap_xer);
uecap_xer_in=1;
} /* UE with config file */
init_tpools(nrUE_params.nr_dlsch_parallel);
}
// set PHY vars from command line
@@ -327,8 +342,9 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
LOG_I(PHY, "Set UE frame_type %d\n", fp->frame_type);
}
LOG_I(PHY, "Set UE N_RB_DL %d\n", fp->N_RB_DL);
fp->N_RB_DL = N_RB_DL;
LOG_I(PHY, "Set UE N_RB_DL %d\n", N_RB_DL);
LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs);
}
@@ -340,92 +356,10 @@ void init_openair0(void) {
for (card=0; card<MAX_CARDS; card++) {
uint64_t dl_carrier, ul_carrier;
openair0_cfg[card].configFilename = NULL;
openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs;
numerology = frame_parms->numerology_index;
if(frame_parms->N_RB_DL == 66) {
if (numerology==3) {
openair0_cfg[card].sample_rate=122.88e6;
openair0_cfg[card].samples_per_frame = 1228800;
} else {
LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n");
exit(-1);
}
}else if(frame_parms->N_RB_DL == 32) {
if (numerology==3) {
openair0_cfg[card].sample_rate=61.44e6;
openair0_cfg[card].samples_per_frame = 614400;
} else {
LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n");
exit(-1);
}
}else if(frame_parms->N_RB_DL == 217) {
if (numerology==1) {
if (frame_parms->threequarter_fs) {
openair0_cfg[card].sample_rate=92.16e6;
openair0_cfg[card].samples_per_frame = 921600;
}
else {
openair0_cfg[card].sample_rate=122.88e6;
openair0_cfg[card].samples_per_frame = 1228800;
}
} else {
LOG_E(PHY,"Unsupported numerology!\n");
exit(-1);
}
} else if(frame_parms->N_RB_DL == 273) {
if (numerology==1) {
if (frame_parms->threequarter_fs) {
AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n");
}
else {
openair0_cfg[card].sample_rate=122.88e6;
openair0_cfg[card].samples_per_frame = 1228800;
}
} else {
LOG_E(PHY,"Unsupported numerology!\n");
exit(-1);
}
} else if(frame_parms->N_RB_DL == 106) {
if (numerology==0) {
if (frame_parms->threequarter_fs) {
openair0_cfg[card].sample_rate=23.04e6;
openair0_cfg[card].samples_per_frame = 230400;
} else {
openair0_cfg[card].sample_rate=30.72e6;
openair0_cfg[card].samples_per_frame = 307200;
}
} else if (numerology==1) {
if (frame_parms->threequarter_fs) {
openair0_cfg[card].sample_rate=46.08e6;
openair0_cfg[card].samples_per_frame = 460800;
}
else {
openair0_cfg[card].sample_rate=61.44e6;
openair0_cfg[card].samples_per_frame = 614400;
}
} else if (numerology==2) {
openair0_cfg[card].sample_rate=122.88e6;
openair0_cfg[card].samples_per_frame = 1228800;
} else {
LOG_E(PHY,"Unsupported numerology!\n");
exit(-1);
}
} else if(frame_parms->N_RB_DL == 50) {
openair0_cfg[card].sample_rate=15.36e6;
openair0_cfg[card].samples_per_frame = 153600;
} else if (frame_parms->N_RB_DL == 25) {
openair0_cfg[card].sample_rate=7.68e6;
openair0_cfg[card].samples_per_frame = 76800;
} else if (frame_parms->N_RB_DL == 6) {
openair0_cfg[card].sample_rate=1.92e6;
openair0_cfg[card].samples_per_frame = 19200;
}
else {
LOG_E(PHY,"Unknown NB_RB %d!\n",frame_parms->N_RB_DL);
exit(-1);
}
openair0_cfg[card].configFilename = NULL;
openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs;
openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3;
openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame;
if (frame_parms->frame_type==TDD)
openair0_cfg[card].duplex_mode = duplex_mode_TDD;
@@ -436,11 +370,12 @@ void init_openair0(void) {
openair0_cfg[card].num_rb_dl = frame_parms->N_RB_DL;
openair0_cfg[card].clock_source = get_softmodem_params()->clock_source;
openair0_cfg[card].time_source = get_softmodem_params()->timing_source;
openair0_cfg[card].tx_num_channels = min(2, frame_parms->nb_antennas_tx);
openair0_cfg[card].rx_num_channels = min(2, frame_parms->nb_antennas_rx);
openair0_cfg[card].tx_num_channels = min(4, frame_parms->nb_antennas_tx);
openair0_cfg[card].rx_num_channels = min(4, frame_parms->nb_antennas_rx);
LOG_I(PHY, "HW: Configuring card %d, tx/rx num_channels %d/%d, duplex_mode %s\n",
LOG_I(PHY, "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n",
card,
openair0_cfg[card].sample_rate,
openair0_cfg[card].tx_num_channels,
openair0_cfg[card].rx_num_channels,
duplex_mode[openair0_cfg[card].duplex_mode]);
@@ -472,9 +407,10 @@ void init_pdcp(int ue_id) {
}
pdcp_layer_init();
nr_pdcp_module_init(pdcp_initmask, ue_id);
//nr_DRB_preconfiguration();
//pdcp_module_init(pdcp_initmask, 0);
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
LOG_I(PDCP, "Before getting out from init_pdcp() \n");
}
// Stupid function addition because UE itti messages queues definition is common with eNB
@@ -502,6 +438,7 @@ int main( int argc, char **argv ) {
get_options (); //Command-line options specific for NRUE
get_common_options(SOFTMODEM_5GUE_BIT );
init_tpools(nrUE_params.nr_dlsch_parallel);
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
#if T_TRACER
T_Config_Init();
@@ -527,7 +464,7 @@ int main( int argc, char **argv ) {
init_NR_UE(1,rrc_config_path);
int mode_offset = get_softmodem_params()->nsa ? NUMBER_OF_UE_MAX : 0;
int node_number = get_softmodem_params()->node_number;
uint16_t node_number = get_softmodem_params()->node_number;
ue_id_g = (node_number == 0) ? 0 : node_number - 2;
AssertFatal(ue_id_g >= 0, "UE id is expected to be nonnegative.\n");
@@ -555,6 +492,7 @@ int main( int argc, char **argv ) {
LOG_E(NR_RRC,"Cannot create ITTI tasks for RRC layer of nr-UE\n");
exit(-1);
}
if (!get_softmodem_params()->nsa) {
for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
PHY_vars_UE_g[0][CC_id] = (PHY_VARS_NR_UE *)malloc(sizeof(PHY_VARS_NR_UE));
@@ -568,22 +506,28 @@ int main( int argc, char **argv ) {
mac->if_module->phy_config_request(&mac->phy_config);
fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config;
if (get_softmodem_params()->sa) { // set frame config to initial values from command line and assume that the SSB is centered on the grid
nrUE_config->ssb_config.scs_common = get_softmodem_params()->numerology;
nrUE_config->carrier_config.dl_grid_size[nrUE_config->ssb_config.scs_common] = UE[CC_id]->frame_parms.N_RB_DL;
nrUE_config->carrier_config.ul_grid_size[nrUE_config->ssb_config.scs_common] = UE[CC_id]->frame_parms.N_RB_DL;
nrUE_config->carrier_config.dl_frequency = (downlink_frequency[0][0] -(6*UE[CC_id]->frame_parms.N_RB_DL*(15000<<nrUE_config->ssb_config.scs_common)))/1000;
nrUE_config->carrier_config.uplink_frequency = (downlink_frequency[0][0] -(6*UE[CC_id]->frame_parms.N_RB_DL*(15000<<nrUE_config->ssb_config.scs_common)))/1000;
nrUE_config->ssb_table.ssb_offset_point_a = (UE[CC_id]->frame_parms.N_RB_DL - 20)>>1;
nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
init_symbol_rotation(&UE[CC_id]->frame_parms, 0);
init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
#ifdef FR2_TEST
// Overwrite DL frequency (for FR2 testing)
if (downlink_frequency[0][0]!=0){
frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
if (frame_parms[CC_id]->frame_type == TDD)
frame_parms[CC_id]->ul_CarrierFreq = downlink_frequency[0][0];
// Initialize values, will be updated upon SIB1 reception
nrUE_config->cell_config.frame_duplex_type = TDD;
nrUE_config->ssb_table.ssb_mask_list[0].ssb_mask = 0xFFFFFFFF;
nrUE_config->ssb_table.ssb_period = 1;
}
#endif
nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config,
mac->scc == NULL ? 78 : *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
init_symbol_rotation(&UE[CC_id]->frame_parms);
init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
}
init_NR_UE_threads(1);
printf("UE threads created by %ld\n", gettid());
init_openair0();
// init UE_PF_PO and mutex lock
pthread_mutex_init(&ue_pf_po_mutex, NULL);
@@ -591,18 +535,22 @@ int main( int argc, char **argv ) {
configure_linux();
mlockall(MCL_CURRENT | MCL_FUTURE);
if(IS_SOFTMODEM_DOFORMS) {
if(IS_SOFTMODEM_DOSCOPE) {
load_softscope("nr",PHY_vars_UE_g[0][0]);
}
init_NR_UE_threads(1);
printf("UE threads created by %ld\n", gettid());
}
config_sync_var=0;
// wait for end of program
printf("TYPE <CTRL-C> TO TERMINATE\n");
#if 0
if (create_tasks_nrue(1) < 0) {
printf("cannot create ITTI tasks\n");
exit(-1); // need a softer mode
}
#endif
// Sleep a while before checking all parameters have been used
// Some are used directly in external threads, asynchronously
sleep(20);
+1 -4
View File
@@ -56,7 +56,7 @@
{"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&(UE->UE_scan_carrier), defintval:0, TYPE_INT, 0}, \
{"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&(UE->UE_fo_compensation), defintval:0, TYPE_INT, 0}, \
{"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \
{"r" , CONFIG_HLP_PRB, 0, iptr:&(fp->N_RB_DL), defintval:25, TYPE_UINT, 0}, \
{"r" , CONFIG_HLP_PRB, 0, uptr:&(N_RB_DL), defuintval:160, TYPE_UINT, 0}, \
{"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \
{"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \
@@ -73,9 +73,6 @@ extern uint64_t get_nrUE_optmask(void);
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
extern nrUE_params_t *get_nrUE_params(void);
#ifdef NRUE_MAIN
nrUE_params_t nrUE_params;
#endif
// In nr-ue.c
extern int setup_nr_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
+4 -7
View File
@@ -61,8 +61,6 @@ uint32_t do_forms=0;
unsigned int mmapped_dma=0;
int8_t threequarter_fs=0;
uint32_t target_dl_mcs = 28; //maximum allowed mcs
uint32_t target_ul_mcs = 20;
int chain_offset=0;
uint16_t sl_ahead=6;
uint16_t sf_ahead=6;
@@ -70,16 +68,15 @@ uint32_t timing_advance = 0;
int transmission_mode=1;
int emulate_rf = 0;
int numerology = 0;
int usrp_tx_thread = 0;
int config_sync_var=-1;
pthread_mutex_t nfapi_sync_mutex;
pthread_cond_t nfapi_sync_cond;
int nfapi_sync_var=-1;
uint8_t nfapi_mode = NFAPI_MONOLITHIC; // Default to monolithic mode
double cpuf;
THREAD_STRUCT thread_struct;
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
@@ -95,7 +92,8 @@ time_stats_t nfapi_meas; // total tx time
time_stats_t softmodem_stats_rx_sf; // total rx time
// not used but needed for link
openair0_config_t openair0_cfg[MAX_CARDS];
uint16_t slot_ahead=6;
msc_interface_t msc_interface;
AGENT_RRC_xface *agent_rrc_xface[NUM_MAX_ENB];
AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
int flexran_agent_start(mid_t mod_id) {
@@ -122,7 +120,6 @@ int restart_L1L2(module_id_t gnb_id) {
}
static int wait_for_sync = 0;
static char *itti_dump_file = NULL;
static double snr_dB=20;
static int DEFBANDS[] = {7};
static int DEFENBS[] = {0};
@@ -996,7 +993,7 @@ int main( int argc, char **argv ) {
(void *)NULL, "time_meas", -1, OAI_PRIORITY_RT_LOW);
}
if(IS_SOFTMODEM_DOFORMS) {
if(IS_SOFTMODEM_DOSCOPE) {
scopeParms_t tmp= {&argc, argv, &ru, RC.gNB[0]};
load_softscope("nr",&tmp);
}
+16 -9
View File
@@ -45,6 +45,8 @@
static softmodem_params_t softmodem_params;
char *parallel_config=NULL;
char *worker_config=NULL;
msc_interface_t msc_interface;
int usrp_tx_thread = 0;
uint8_t nfapi_mode=0;
@@ -86,8 +88,8 @@ char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr) {
void get_common_options(uint32_t execmask) {
uint32_t online_log_messages=0;
uint32_t glog_level=0 ;
uint32_t start_telnetsrv = 0;
uint32_t noS1 = 0, nokrnmod = 0, nonbiot = 0;
uint32_t start_telnetsrv = 0, start_telnetclt = 0;
uint32_t noS1 = 0, nokrnmod = 1, nonbiot = 0;
uint32_t rfsim = 0, basicsim = 0, do_forms = 0;
char *logmem_filename = NULL;
paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
@@ -95,21 +97,26 @@ void get_common_options(uint32_t execmask) {
checkedparam_t cmdline_log_CheckParams[] = CMDLINE_LOGPARAMS_CHECK_DESC;
check_execmask(execmask);
config_get( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL);
config_set_checkfunctions(cmdline_logparams, cmdline_log_CheckParams,
sizeof(cmdline_logparams)/sizeof(paramdef_t));
config_get( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL);
if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) {
int numparams=sizeof(cmdline_logparams)/sizeof(paramdef_t);
config_set_checkfunctions(cmdline_logparams, cmdline_log_CheckParams,numparams);
config_get( cmdline_logparams,numparams,NULL);
if(config_isparamset(cmdline_logparams,config_paramidx_fromname(cmdline_logparams,numparams, CONFIG_FLOG_OPT))) {
set_glog_onlinelog(online_log_messages);
}
if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) {
if(config_isparamset(cmdline_logparams,config_paramidx_fromname(cmdline_logparams,numparams, CONFIG_LOGL_OPT))) {
set_glog(glog_level);
}
if (start_telnetsrv) {
load_module_shlib("telnetsrv",NULL,0,NULL);
}
if (start_telnetclt) {
set_softmodem_optmask(SOFTMODEM_TELNETCLT_BIT);
}
if (logmem_filename != NULL && strlen(logmem_filename) > 0) {
log_mem_filename = &logmem_filename[0];
@@ -140,7 +147,7 @@ void get_common_options(uint32_t execmask) {
}
if (do_forms) {
set_softmodem_optmask(SOFTMODEM_DOFORMS_BIT);
set_softmodem_optmask(SOFTMODEM_DOSCOPE_BIT);
}
if(parallel_config != NULL) set_parallel_conf(parallel_config);
+47 -24
View File
@@ -73,6 +73,7 @@ extern "C"
#define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n"
#define CONFIG_HLP_256QAM "Use the 256 QAM mcs table for PDSCH\n"
#define CONFIG_HLP_NONSTOP "Go back to frame sync mode after 100 consecutive PBCH failures\n"
//#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation"
#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n"
#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n"
@@ -84,13 +85,17 @@ extern "C"
#define CONFIG_HLP_TNOFORK "to ease debugging with gdb\n"
#define CONFIG_HLP_NUMEROLOGY "adding numerology for 5G\n"
#define CONFIG_HLP_BAND "band index\n"
#define CONFIG_HLP_EMULATE_RF "Emulated RF enabled(disable by defult)\n"
#define CONFIG_HLP_PARALLEL_CMD "three config for level of parallelism 'PARALLEL_SINGLE_THREAD', 'PARALLEL_RU_L1_SPLIT', or 'PARALLEL_RU_L1_TRX_SPLIT'\n"
#define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n"
#define CONFIG_HLP_USRP_THREAD "having extra thead for usrp tx\n"
#define CONFIG_HLP_NOS1 "Disable s1 interface\n"
#define CONFIG_HLP_RFSIM "Run in rf simulator mode (also known as basic simulator)\n"
#define CONFIG_HLP_NOKRNMOD "(noS1 only): Use tun instead of namesh module \n"
#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n"
#define CONFIG_HLP_USRP_THREAD "having extra thead for usrp tx\n"
#define CONFIG_HLP_NFAPI "Change the nFAPI mode for NR\n"
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -107,6 +112,7 @@ extern "C"
#define SINGLE_THREAD_FLAG softmodem_params.single_thread_flag
#define CHAIN_OFFSET softmodem_params.chain_offset
#define NUMEROLOGY softmodem_params.numerology
#define BAND softmodem_params.band
#define EMULATE_RF softmodem_params.emulate_rf
#define CLOCK_SOURCE softmodem_params.clock_source
#define TIMING_SOURCE softmodem_params.timing_source
@@ -116,27 +122,30 @@ extern "C"
#define NFAPI softmodem_params.nfapi
#define NSA softmodem_params.nsa
#define NODE_NUMBER softmodem_params.node_number
#define NON_STOP softmodem_params.non_stop
#define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
extern int usrp_tx_thread;
#define CMDLINE_PARAMS_DESC { \
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)},\
{"split73", CONFIG_HLP_SPLIT73, 0, strptr:(char **)&SPLIT73, defstrval:NULL, TYPE_STRING, sizeof(SPLIT73)},\
{"thread-pool", CONFIG_HLP_TPOOL, 0, strptr:(char **)&TP_CONFIG, defstrval:"n", TYPE_STRING, sizeof(TP_CONFIG)}, \
{"split73", CONFIG_HLP_SPLIT73, 0, strptr:(char **)&SPLIT73, defstrval:NULL, TYPE_STRING, sizeof(SPLIT73)}, \
{"thread-pool", CONFIG_HLP_TPOOL, 0, strptr:(char **)&TP_CONFIG, defstrval:"n", TYPE_STRING, sizeof(TP_CONFIG)}, \
{"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \
{"do-ra", CONFIG_HLP_DORA, PARAMFLAG_BOOL, iptr:&DO_RA, defintval:0, TYPE_INT, 0}, \
{"sa", CONFIG_HLP_SA, PARAMFLAG_BOOL, iptr:&SA, defintval:0, TYPE_INT, 0}, \
{"sa", CONFIG_HLP_SA, PARAMFLAG_BOOL, iptr:&SA, defintval:0, TYPE_INT, 0}, \
{"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \
{"clock-source", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \
{"time-source", CONFIG_HLP_TME, 0, uptr:&TIMING_SOURCE, defintval:0, TYPE_UINT, 0}, \
{"clock-source", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \
{"time-source", CONFIG_HLP_TME, 0, uptr:&TIMING_SOURCE, defintval:0, TYPE_UINT, 0}, \
{"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&WAIT_FOR_SYNC, defintval:0, TYPE_INT, 0}, \
{"single-thread-enable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&SINGLE_THREAD_FLAG, defintval:0, TYPE_INT, 0}, \
{"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0, TYPE_UINT64, 0}, \
{"CO" , CONFIG_HLP_ULF, 0, iptr:&(uplink_frequency_offset[0][0]), defintval:0, TYPE_INT, 0}, \
{"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:3619200000, TYPE_UINT64, 0}, \
{"CO" , CONFIG_HLP_ULF, 0, iptr:&(uplink_frequency_offset[0][0]), defintval:0, TYPE_INT, 0}, \
{"a" , CONFIG_HLP_CHOFF, 0, iptr:&CHAIN_OFFSET, defintval:0, TYPE_INT, 0}, \
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:1, TYPE_INT, 0}, \
{"band" , CONFIG_HLP_BAND, PARAMFLAG_BOOL, iptr:&BAND, defintval:78, TYPE_INT, 0}, \
{"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&EMULATE_RF, defintval:0, TYPE_INT, 0}, \
{"parallel-config", CONFIG_HLP_PARALLEL_CMD, 0, strptr:(char **)&parallel_config, defstrval:NULL, TYPE_STRING, 0}, \
{"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
@@ -146,9 +155,11 @@ extern "C"
{"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \
{"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \
{"use-256qam-table", CONFIG_HLP_256QAM, PARAMFLAG_BOOL, iptr:&USE_256QAM_TABLE, defintval:0, TYPE_INT, 0}, \
{"nfapi", CONFIG_HLP_NFAPI, 0, u8ptr:&nfapi_mode, defintval:0, TYPE_UINT8, 0}, \
{"nsa", CONFIG_HLP_NSA, PARAMFLAG_BOOL, iptr:&NSA, defintval:0, TYPE_INT, 0}, \
{"node-number", NULL, 0, u16ptr:&NODE_NUMBER, defuintval:0, TYPE_UINT16, 0}, \
{"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, iptr:&usrp_tx_thread, defstrval:0, TYPE_INT, 0}, \
{"nfapi", CONFIG_HLP_NFAPI, 0, u8ptr:&nfapi_mode, defintval:0, TYPE_UINT8, 0}, \
{"non-stop", CONFIG_HLP_NONSTOP, PARAMFLAG_BOOL, iptr:&NON_STOP, defintval:0, TYPE_INT, 0}, \
}
#define CONFIG_HLP_NSA "Enable NSA mode \n"
@@ -157,23 +168,22 @@ extern "C"
#define CONFIG_HLP_LOGV "Set the global log verbosity \n"
#define CONFIG_HLP_TELN "Start embedded telnet server \n"
#define CONFIG_HLP_MSC "Enable the MSC tracing utility \n"
/*----------------------------------------------------------------------------------------------------------------------------*/
/* command line parameters for LOG utility */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*----------------------------------------------------------------------------------------------------------------------------*/
#define CONFIG_FLOG_OPT "R"
#define CONFIG_LOGL_OPT "g"
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
/* command line parameters for LOG utility */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
#define START_MSC softmodem_params.start_msc
#define CMDLINE_LOGPARAMS_DESC { \
{"R" , CONFIG_HLP_FLOG, 0, uptr:&online_log_messages, defintval:1, TYPE_INT, 0}, \
{"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \
{"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \
{"msc", CONFIG_HLP_MSC, PARAMFLAG_BOOL, uptr:&START_MSC, defintval:0, TYPE_UINT, 0}, \
{"log-mem", NULL, 0, strptr:(char **)&logmem_filename, defstrval:NULL, TYPE_STRING, 0}, \
{CONFIG_FLOG_OPT , CONFIG_HLP_FLOG, 0, uptr:&online_log_messages, defintval:1, TYPE_INT, 0}, \
{CONFIG_LOGL_OPT , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \
{"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \
{"msc", CONFIG_HLP_MSC, PARAMFLAG_BOOL, uptr:&START_MSC, defintval:0, TYPE_UINT, 0}, \
{"log-mem", NULL, 0, strptr:(char **)&logmem_filename, defstrval:NULL, TYPE_STRING, 0}, \
{"telnetclt", NULL, 0, uptr:&start_telnetclt, defstrval:NULL, TYPE_UINT, 0}, \
}
#define CMDLINE_ONLINELOG_IDX 0
#define CMDLINE_GLOGLEVEL_IDX 1
#define CMDLINE_GLOGVERBO_IDX 2
#define CMDLINE_STARTTELN_IDX 3
/* check function for global log level */
#define CMDLINE_LOGPARAMS_CHECK_DESC { \
@@ -182,6 +192,7 @@ extern "C"
{ .s5= {NULL} } , \
{ .s5= {NULL} } , \
{ .s5= {NULL} } , \
{ .s5= {NULL} } , \
}
/***************************************************************************************************************************************/
@@ -192,8 +203,9 @@ extern "C"
#define SOFTMODEM_RFSIM_BIT (1<<10)
#define SOFTMODEM_BASICSIM_BIT (1<<11)
#define SOFTMODEM_SIML1_BIT (1<<12)
#define SOFTMODEM_DOFORMS_BIT (1<<15)
#define SOFTMODEM_DOSCOPE_BIT (1<<15)
#define SOFTMODEM_RECPLAY_BIT (1<<16)
#define SOFTMODEM_TELNETCLT_BIT (1<<17)
#define SOFTMODEM_ENB_BIT (1<<20)
#define SOFTMODEM_GNB_BIT (1<<21)
#define SOFTMODEM_4GUE_BIT (1<<22)
@@ -208,8 +220,9 @@ extern "C"
#define IS_SOFTMODEM_RFSIM ( get_softmodem_optmask() & SOFTMODEM_RFSIM_BIT)
#define IS_SOFTMODEM_BASICSIM ( get_softmodem_optmask() & SOFTMODEM_BASICSIM_BIT)
#define IS_SOFTMODEM_SIML1 ( get_softmodem_optmask() & SOFTMODEM_SIML1_BIT)
#define IS_SOFTMODEM_DOFORMS ( get_softmodem_optmask() & SOFTMODEM_DOFORMS_BIT)
#define IS_SOFTMODEM_DOSCOPE ( get_softmodem_optmask() & SOFTMODEM_DOSCOPE_BIT)
#define IS_SOFTMODEM_IQPLAYER ( get_softmodem_optmask() & SOFTMODEM_RECPLAY_BIT)
#define IS_SOFTMODEM_TELNETCLT_BIT ( get_softmodem_optmask() & SOFTMODEM_TELNETCLT_BIT)
#define IS_SOFTMODEM_ENB_BIT ( get_softmodem_optmask() & SOFTMODEM_ENB_BIT)
#define IS_SOFTMODEM_GNB_BIT ( get_softmodem_optmask() & SOFTMODEM_GNB_BIT)
#define IS_SOFTMODEM_4GUE_BIT ( get_softmodem_optmask() & SOFTMODEM_4GUE_BIT)
@@ -230,6 +243,7 @@ typedef struct {
int single_thread_flag; //eNodeB only
int chain_offset;
int numerology;
int band;
unsigned int start_msc;
uint32_t clock_source;
uint32_t timing_source;
@@ -239,6 +253,7 @@ typedef struct {
uint8_t nfapi;
int nsa;
uint16_t node_number;
int non_stop;
} softmodem_params_t;
extern uint64_t get_softmodem_optmask(void);
@@ -250,6 +265,14 @@ extern char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr);
extern void set_softmodem_sighandler(void);
extern uint64_t downlink_frequency[MAX_NUM_CCs][4];
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
extern int usrp_tx_thread;
extern uint16_t sl_ahead;
extern uint16_t sf_ahead;
extern volatile int oai_exit;
void tx_func(void *param);
void rx_func(void *param);
void ru_tx_func(void *param);
extern uint8_t nfapi_mode;
extern int16_t vnf_pnf_sfnslot_delta;
#ifdef __cplusplus
+1 -1
View File
@@ -3,7 +3,7 @@
#include "PHY/defs_common.h"
THREAD_STRUCT thread_struct;
extern THREAD_STRUCT thread_struct;
static inline void set_parallel_conf(char *parallel_conf) {
mapping config[]= {