mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 13:10:28 +00:00
Compare commits
8 Commits
develop
...
load-radio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3691075e05 | ||
|
|
53ade4237f | ||
|
|
594117e451 | ||
|
|
2d1d3b88a4 | ||
|
|
da5789a613 | ||
|
|
8adf30b17d | ||
|
|
b4f9d80f16 | ||
|
|
b556eb848b |
@@ -607,6 +607,11 @@ include_directories("${OPENAIR_DIR}")
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common/utils/T
|
||||
${CMAKE_CURRENT_BINARY_DIR}/common/utils/T)
|
||||
|
||||
include_directories(${OPENAIR_DIR}/common/utils/barrier)
|
||||
include_directories(${OPENAIR_DIR}/common/utils/actor)
|
||||
include_directories(${OPENAIR_DIR}/common/utils/threadPool)
|
||||
|
||||
|
||||
# set the T_LIB name to T if the target exists, otherwise leave empty
|
||||
set(T_LIB $<TARGET_NAME_IF_EXISTS:T>)
|
||||
|
||||
@@ -1781,9 +1786,6 @@ target_link_libraries(oairu PRIVATE
|
||||
SCHED_RU_LIB PHY_COMMON PHY_RU UTIL shlib_loader
|
||||
-Wl,--end-group z dl)
|
||||
|
||||
target_link_libraries(oairu PRIVATE pthread m CONFIG_LIB rt ${T_LIB})
|
||||
target_link_libraries(oairu PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
# force the generation of ASN.1 so that we don't need to wait during the build
|
||||
target_link_libraries(lte-softmodem PRIVATE
|
||||
asn1_lte_rrc asn1_s1ap asn1_m2ap asn1_m3ap asn1_x2ap)
|
||||
@@ -1822,6 +1824,30 @@ target_link_libraries(lte-uesoftmodem PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIE
|
||||
target_link_libraries(lte-uesoftmodem PRIVATE
|
||||
asn1_lte_rrc asn1_s1ap asn1_m2ap asn1_m3ap asn1_x2ap)
|
||||
|
||||
# nr RRU
|
||||
add_executable(oainr_ru
|
||||
${OPENAIR_DIR}/executables/nr-ru.c
|
||||
${OPENAIR_DIR}/openair1/PHY/INIT/nr_parms.c
|
||||
${OPENAIR_DIR}/openair1/SCHED_NR/phy_frame_config_nr.c
|
||||
${OPENAIR_DIR}/openair1/PHY/INIT/nr_parms.c
|
||||
${OPENAIR_DIR}/openair1/SCHED_NR/nr_prach_procedures.c
|
||||
${OPENAIR_DIR}/openair1/SCHED/phy_procedures_lte_common.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach.c
|
||||
${OPENAIR_DIR}/common/utils/nr/nr_common.c
|
||||
${OPENAIR_DIR}/radio/COMMON/common_lib.c
|
||||
${OPENAIR_DIR}/radio/COMMON/record_player.c
|
||||
${OPENAIR_DIR}/executables/softmodem-common.c
|
||||
${OPENAIR_DIR}/executables/main_nr_ru.c
|
||||
)
|
||||
target_link_libraries(oainr_ru PRIVATE
|
||||
-Wl,--start-group
|
||||
UTIL SCHED_RU_LIB PHY_COMMON PHY_RU shlib_loader
|
||||
-Wl,--end-group z dl)
|
||||
target_link_libraries(oainr_ru PRIVATE pthread m CONFIG_LIB rt ${T_LIB} utils
|
||||
barrier actor)
|
||||
target_link_libraries(oainr_ru PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_phy_common time_management)
|
||||
target_link_libraries(oainr_ru PUBLIC MAC_NR_COMMON)
|
||||
|
||||
# nr-softmodem
|
||||
###################################################
|
||||
|
||||
|
||||
@@ -87,6 +87,8 @@ Options:
|
||||
Makes the NR softmodem
|
||||
--RU
|
||||
Makes the OAI RRU
|
||||
--nrRU
|
||||
Makes the OAI nrRRU
|
||||
--UE
|
||||
Makes the UE specific parts (usim, nvram) from the given configuration file
|
||||
--nrUE
|
||||
@@ -242,6 +244,11 @@ function main() {
|
||||
TARGET_LIST="$TARGET_LIST oairu"
|
||||
echo_info "Will compile RRU"
|
||||
shift;;
|
||||
--nrRU)
|
||||
nrRU=1
|
||||
TARGET_LIST="$TARGET_LIST oainr_ru"
|
||||
echo_info "Will compile nrRRU"
|
||||
shift;;
|
||||
--UE)
|
||||
UE=1
|
||||
TARGET_LIST="$TARGET_LIST lte-uesoftmodem"
|
||||
@@ -492,7 +499,7 @@ function main() {
|
||||
if [[ $TARGET_LIST != "" ]] && [[ -f $OPENAIR_DIR/CMakeLists.txt ]]; then
|
||||
# add some default libraries that should always be built
|
||||
# for eNB, gNB, UEs, simulators
|
||||
if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then
|
||||
if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 || $nrRU == 1 ]]; then
|
||||
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts params_yaml vrtsim"
|
||||
fi
|
||||
|
||||
|
||||
221
executables/main_nr_ru.c
Normal file
221
executables/main_nr_ru.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* 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/oai_version.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
#include "common/ran_context.h"
|
||||
|
||||
|
||||
#include "radio/COMMON/common_lib.h"
|
||||
#include "radio/ETHERNET/if_defs.h"
|
||||
|
||||
#include "PHY/phy_vars.h"
|
||||
#include "PHY/phy_extern.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 "nfapi/oai_integration/vendor_ext.h"
|
||||
|
||||
#include <executables/softmodem-common.h>
|
||||
#include <executables/thread-common.h>
|
||||
|
||||
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;
|
||||
|
||||
int oai_exit = 0;
|
||||
int sf_ahead = 4;
|
||||
int emulate_rf = 0;
|
||||
|
||||
RAN_CONTEXT_t RC;
|
||||
|
||||
extern void kill_NR_RU_proc(int inst);
|
||||
extern void set_function_spec_param(RU_t *ru);
|
||||
extern void start_NR_RU(RU_t *ru);
|
||||
extern void init_NR_RU(configmodule_interface_t *cfg, char *);
|
||||
|
||||
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, const int assert) {
|
||||
|
||||
if (s != NULL) {
|
||||
printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
|
||||
}
|
||||
close_log_mem();
|
||||
oai_exit = 1;
|
||||
RU_t *ru = RC.ru[0];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(ru->ru_mutex);
|
||||
pthread_cond_destroy(ru->ru_cond);
|
||||
if (assert) {
|
||||
abort();
|
||||
} else {
|
||||
sleep(1); // allow lte-softmodem threads to exit first
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
static void get_options(configmodule_interface_t *cfg)
|
||||
{
|
||||
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
|
||||
get_common_options(cfg);
|
||||
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
|
||||
|
||||
// NRCConfig();
|
||||
}
|
||||
|
||||
|
||||
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; }
|
||||
void wait_gNBs(void){ return; }
|
||||
|
||||
struct timespec timespec_add(struct timespec,struct timespec) {struct timespec t={0}; return t;};
|
||||
struct timespec timespec_sub(struct timespec,struct timespec) {struct timespec t={0}; return t;};
|
||||
|
||||
void perform_symbol_rotation(NR_DL_FRAME_PARMS *fp, double f0, c16_t *symbol_rotation) {return;}
|
||||
void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp) {return;};
|
||||
int beam_index_allocation(int fapi_beam_index, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, int bitmap_symbols) {int i=0; return i;};
|
||||
void nr_fill_du(uint16_t N_ZC, const uint16_t *prach_root_sequence_map, uint16_t nr_du[NR_PRACH_SEQ_LEN_L - 1]) {return;};
|
||||
uint16_t nr_du[838];
|
||||
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
|
||||
configmodule_interface_t *uniqCfg = NULL;
|
||||
THREAD_STRUCT thread_struct;
|
||||
|
||||
void oru_init(ORU_t *oru);
|
||||
void *oru_north_read_thread(void *arg);
|
||||
void *oru_south_read_thread(void *arg);
|
||||
|
||||
int main ( int argc, char **argv )
|
||||
{
|
||||
memset(&RC,0,sizeof(RC));
|
||||
if ((uniqCfg = 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(uniqCfg);
|
||||
|
||||
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");
|
||||
// strdup to put the sring in the core file for post mortem identification
|
||||
LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION));
|
||||
|
||||
|
||||
/* Read configuration */
|
||||
|
||||
printf("About to Init RU threads\n");
|
||||
|
||||
lock_memory_to_ram();
|
||||
|
||||
RC.nb_RU=1;
|
||||
RC.ru = malloc(sizeof(RC.ru));
|
||||
|
||||
init_NR_RU(config_get_if(),NULL);
|
||||
load_dftslib();
|
||||
|
||||
RU_t *ru = RC.ru[0];
|
||||
ORU_t oru;
|
||||
oru.ru = ru;
|
||||
|
||||
oru_init(&oru);
|
||||
pthread_create(&oru.north_read_thread, NULL, oru_north_read_thread, (void *)&oru);
|
||||
pthread_create(&oru.south_read_thread, NULL, oru_south_read_thread, (void *)&oru);
|
||||
|
||||
while (oai_exit==0) sleep(1);
|
||||
// stop threads
|
||||
|
||||
kill_NR_RU_proc(0);
|
||||
|
||||
end_configmodule(uniqCfg);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -56,6 +56,8 @@ static int DEFBANDS[] = {7};
|
||||
static int DEFENBS[] = {0};
|
||||
static int DEFBFW[] = {0x00007fff};
|
||||
static int DEFRUTPCORES[] = {-1,-1,-1,-1};
|
||||
static int DEFBW[] = {273};
|
||||
static int DEFCARRIER[] = {3430560};
|
||||
|
||||
#include "ENB_APP/enb_paramdef.h"
|
||||
#include "GNB_APP/gnb_paramdef.h"
|
||||
@@ -68,6 +70,7 @@ static int DEFRUTPCORES[] = {-1,-1,-1,-1};
|
||||
#include "nfapi_interface.h"
|
||||
#include <nfapi/oai_integration/vendor_ext.h>
|
||||
#include "executables/nr-softmodem-common.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
|
||||
static void NRRCconfig_RU(configmodule_interface_t *cfg);
|
||||
|
||||
@@ -187,7 +190,7 @@ int connect_rau(RU_t *ru) {
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function);
|
||||
AssertFatal(1==0,"RU_function is unknown %d\n",ru->function);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -238,7 +241,7 @@ int connect_rau(RU_t *ru) {
|
||||
|
||||
// southbound IF5 fronthaul for 16-bit OAI format
|
||||
void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
|
||||
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
int offset = ru->nr_frame_parms->get_samples_slot_timestamp(slot,ru->nr_frame_parms,0);
|
||||
void *buffs[ru->nb_tx];
|
||||
for (int aid = 0; aid < ru->nb_tx; aid++)
|
||||
@@ -260,7 +263,7 @@ void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
|
||||
void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
|
||||
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
|
||||
LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.tti_tx);
|
||||
|
||||
@@ -377,7 +380,7 @@ void fh_if4p5_south_in(RU_t *ru,
|
||||
*slot = proc->tti_rx;
|
||||
}
|
||||
|
||||
if (ru == RC.ru[0]) {
|
||||
if (ru->idx == 0) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, f );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, sl);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
|
||||
@@ -453,7 +456,7 @@ void fh_if4p5_north_in(RU_t *ru,int *frame,int *slot) {
|
||||
} while (symbol_mask != symbol_mask_full);
|
||||
|
||||
// dump VCD output for first RU in list
|
||||
if (ru == RC.ru[0]) {
|
||||
if (ru->idx == 0) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, *frame );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, *slot );
|
||||
}
|
||||
@@ -529,7 +532,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
LOG_D(PHY,"RU %d/%d TST %llu, frame %d, subframe %d\n",ru->idx,0,(long long unsigned int)proc->timestamp_tx,frame_tx,slot_tx);
|
||||
|
||||
// dump VCD output for first RU in list
|
||||
if (ru == RC.ru[0]) {
|
||||
if (ru->idx == 0) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot_tx );
|
||||
}
|
||||
@@ -572,7 +575,7 @@ void *emulatedRF_thread(void *param) {
|
||||
int microsec = 500; // length of time to sleep, in miliseconds
|
||||
struct timespec req = {0};
|
||||
req.tv_sec = 0;
|
||||
req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2;
|
||||
req.tv_nsec = (proc->ru->numerology>0)? ((microsec * 1000L)/proc->ru->numerology):(microsec * 1000L)*2;
|
||||
wait_sync("emulatedRF_thread");
|
||||
|
||||
while(!oai_exit) {
|
||||
@@ -655,7 +658,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
proc->frame_rx,proc->tti_rx,proc->tti_tx,fp->slots_per_frame);
|
||||
|
||||
// dump VCD output for first RU in list
|
||||
if (ru == RC.ru[0]) {
|
||||
if (ru->idx == 0) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx );
|
||||
}
|
||||
@@ -683,7 +686,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
*slot = proc->tti_rx;
|
||||
}
|
||||
|
||||
if (!emulate_rf) {
|
||||
if (!ru->emulate_rf) {
|
||||
metadata mt = {.slot = *slot, .frame = *frame};
|
||||
gNBscopeCopyWithMetadata(ru, gNbTimeDomainSamples, rxp[0], sizeof(c16_t), 1, samples_per_slot, 0, &mt);
|
||||
}
|
||||
@@ -1010,7 +1013,7 @@ void ru_tx_func(void *param)
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm))
|
||||
ru->feptx_ofdm(ru, frame_tx, slot_tx);
|
||||
|
||||
if(!emulate_rf) {
|
||||
if(!ru->emulate_rf) {
|
||||
// do outgoing fronthaul (south) if needed
|
||||
if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out))
|
||||
ru->fh_south_out(ru, frame_tx, slot_tx, info->timestamp_tx);
|
||||
@@ -1080,7 +1083,7 @@ static bool wait_free_rx_tti(notifiedFIFO_t *L1_rx_out, bool rx_tti_busy[RU_RX_S
|
||||
if (!res)
|
||||
return false;
|
||||
processingData_L1_t *info = NotifiedFifoData(res);
|
||||
LOG_D(NR_PHY, "%d.%d Got access to RX slot %d.%d (%d)\n", frame_rx, slot_rx, info->frame_rx, info->slot_rx, idx);
|
||||
LOG_I(NR_PHY, "%d.%d Got access to RX slot %d.%d (%d)\n", frame_rx, slot_rx, info->frame_rx, info->slot_rx, idx);
|
||||
rx_tti_busy[info->slot_rx % RU_RX_SLOT_DEPTH] = false;
|
||||
if ((info->slot_rx % RU_RX_SLOT_DEPTH) == idx)
|
||||
not_done = false;
|
||||
@@ -1119,7 +1122,7 @@ void *ru_thread(void *param)
|
||||
fill_rf_config(ru, ru->rf_config_file);
|
||||
fill_split7_2_config(&ru->openair0_cfg.split7, &ru->config, fp->slots_per_frame, fp->ofdm_symbol_size);
|
||||
|
||||
if(!emulate_rf) {
|
||||
if(!ru->emulate_rf) {
|
||||
// Start IF device if any
|
||||
if (ru->nr_start_if) {
|
||||
LOG_I(PHY, "starting transport\n");
|
||||
@@ -1181,7 +1184,7 @@ void *ru_thread(void *param)
|
||||
pthread_mutex_unlock(&RC.ru_mutex);
|
||||
wait_sync("ru_thread");
|
||||
|
||||
if(!emulate_rf) {
|
||||
if(!ru->emulate_rf) {
|
||||
// Start RF device if any
|
||||
if (ru->start_rf) {
|
||||
if (ru->start_rf(ru) != 0)
|
||||
@@ -1370,7 +1373,7 @@ void init_RU_proc(RU_t *ru) {
|
||||
pthread_mutex_init( &proc->mutex_emulateRF,NULL);
|
||||
pthread_cond_init( &proc->cond_emulateRF, NULL);
|
||||
|
||||
if(emulate_rf)
|
||||
if(ru->emulate_rf)
|
||||
threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT );
|
||||
LOG_I(PHY, "Initialized RU proc %d (%s,%s),\n", ru->idx, NB_functions[ru->function], NB_timing[ru->if_timing]);
|
||||
}
|
||||
@@ -1585,6 +1588,7 @@ void set_function_spec_param(RU_t *ru)
|
||||
reset_meas(&ru->tx_fhaul);
|
||||
reset_meas(&ru->compression);
|
||||
reset_meas(&ru->transport);
|
||||
LOG_I(NR_PHY,"Setting IF4p5 (7.2 split)\n");
|
||||
} else if (ru->function == gNodeB_3GPP) {
|
||||
ru->do_prach = 0; // no prach processing in RU
|
||||
ru->feprx = nr_fep_tp; // this is frequency-shift + DFTs
|
||||
@@ -1692,9 +1696,10 @@ void init_NR_RU(configmodule_interface_t *cfg, char *rf_config_file)
|
||||
ru->num_gNB=1;
|
||||
}
|
||||
}
|
||||
|
||||
gNB_RC = RC.gNB[0];
|
||||
gNB0 = ru->gNB_list[0];
|
||||
if (RC.nb_nr_L1_inst > 0) {
|
||||
gNB_RC = RC.gNB[0];
|
||||
gNB0 = ru->gNB_list[0];
|
||||
}
|
||||
fp = ru->nr_frame_parms;
|
||||
LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
|
||||
|
||||
@@ -1715,6 +1720,9 @@ void init_NR_RU(configmodule_interface_t *cfg, char *rf_config_file)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
nr_ru_init_frame_parms(ru);
|
||||
}
|
||||
set_function_spec_param(ru);
|
||||
init_RU_proc(ru);
|
||||
if (ru->if_south != REMOTE_IF4p5) {
|
||||
@@ -1742,9 +1750,8 @@ void init_NR_RU(configmodule_interface_t *cfg, char *rf_config_file)
|
||||
LOG_D(HW,"[nr-softmodem.c] RU threads created\n");
|
||||
}
|
||||
|
||||
void start_NR_RU()
|
||||
void start_NR_RU(RU_t *ru)
|
||||
{
|
||||
RU_t *ru = RC.ru[0];
|
||||
start_RU_proc(ru);
|
||||
}
|
||||
|
||||
@@ -1854,7 +1861,7 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg)
|
||||
if (!(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX))) {
|
||||
RC.ru[j]->if_south = LOCAL_RF;
|
||||
RC.ru[j]->function = gNodeB_3GPP;
|
||||
LOG_D(PHY, "Setting function for RU %d to gNodeB_3GPP\n", j);
|
||||
LOG_I(NR_PHY, "Setting function for RU %d to gNodeB_3GPP\n", j);
|
||||
} else {
|
||||
RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr));
|
||||
RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr));
|
||||
@@ -1868,22 +1875,22 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg)
|
||||
RC.ru[j]->if_south = LOCAL_RF;
|
||||
RC.ru[j]->function = NGFI_RRU_IF5;
|
||||
RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE;
|
||||
LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF5 (udp)\n", j);
|
||||
LOG_I(NR_PHY, "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) {
|
||||
RC.ru[j]->if_south = LOCAL_RF;
|
||||
RC.ru[j]->function = NGFI_RRU_IF5;
|
||||
RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE;
|
||||
LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF5 (raw)\n", j);
|
||||
LOG_I(NR_PHY, "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) {
|
||||
RC.ru[j]->if_south = LOCAL_RF;
|
||||
RC.ru[j]->function = NGFI_RRU_IF4p5;
|
||||
RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE;
|
||||
LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n", j);
|
||||
LOG_I(NR_PHY, "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) {
|
||||
RC.ru[j]->if_south = LOCAL_RF;
|
||||
RC.ru[j]->function = NGFI_RRU_IF4p5;
|
||||
RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE;
|
||||
LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n", j);
|
||||
LOG_I(NR_PHY, "Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n", j);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1932,8 +1939,23 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg)
|
||||
RC.ru[j]->if_freq_offset = *(RUParamList.paramarray[j][RU_IF_FREQ_OFFSET].iptr);
|
||||
RC.ru[j]->sl_ahead = *(RUParamList.paramarray[j][RU_SL_AHEAD].iptr);
|
||||
RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt;
|
||||
for (int i = 0; i < RC.ru[j]->num_bands; i++)
|
||||
for (int i = 0; i < RC.ru[j]->num_bands; i++) {
|
||||
RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i];
|
||||
RC.ru[j]->bw_tx[i] = RUParamList.paramarray[j][RU_TX_BW_LIST_IDX].iptr[i];
|
||||
RC.ru[j]->bw_rx[i] = RUParamList.paramarray[j][RU_RX_BW_LIST_IDX].iptr[i];
|
||||
RC.ru[j]->carrier_freq_tx[i] = RUParamList.paramarray[j][RU_TX_CARRIER_LIST_IDX].iptr[i];
|
||||
RC.ru[j]->carrier_freq_rx[i] = RUParamList.paramarray[j][RU_RX_CARRIER_LIST_IDX].iptr[i];
|
||||
}
|
||||
RC.ru[j]->frame_type = *(RUParamList.paramarray[j][RU_FRAME_TYPE_IDX].iptr);
|
||||
RC.ru[j]->prach_config_index = *(RUParamList.paramarray[j][RU_PRACH_CONFIGID_IDX].iptr);
|
||||
RC.ru[j]->prach_msg1_freq = *(RUParamList.paramarray[j][RU_PRACH_MSG1FREQ_IDX].iptr);
|
||||
RC.ru[j]->numerology = *(RUParamList.paramarray[j][RU_NUMEROLOGY_IDX].iptr);
|
||||
RC.ru[j]->tdd_period = *(RUParamList.paramarray[j][RU_TDD_PERIOD_IDX].iptr);
|
||||
RC.ru[j]->num_DL_slots = *(RUParamList.paramarray[j][RU_NUM_DL_SLOTS_IDX].iptr);
|
||||
RC.ru[j]->num_UL_slots = *(RUParamList.paramarray[j][RU_NUM_UL_SLOTS_IDX].iptr);
|
||||
RC.ru[j]->num_DL_symbols = *(RUParamList.paramarray[j][RU_NUM_DL_SYMBOLS_IDX].iptr);
|
||||
RC.ru[j]->num_UL_symbols = *(RUParamList.paramarray[j][RU_NUM_UL_SYMBOLS_IDX].iptr);
|
||||
|
||||
RC.ru[j]->openair0_cfg.nr_flag = *(RUParamList.paramarray[j][RU_NR_FLAG].iptr);
|
||||
RC.ru[j]->openair0_cfg.nr_band = RC.ru[j]->band[0];
|
||||
RC.ru[j]->openair0_cfg.nr_scs_for_raster = *(RUParamList.paramarray[j][RU_NR_SCS_FOR_RASTER].iptr);
|
||||
@@ -1960,3 +1982,180 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg)
|
||||
return;
|
||||
}
|
||||
|
||||
void oru_init(ORU_t *oru) {
|
||||
RU_t *ru = oru->ru;
|
||||
struct NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nr_init_frame_parms(&ru->config, fp);
|
||||
nr_dump_frame_parms(fp);
|
||||
nr_phy_init_RU(ru);
|
||||
fill_rf_config(ru, ru->rf_config_file);
|
||||
fill_split7_2_config(&ru->openair0_cfg.split7, &ru->config, fp->slots_per_frame, fp->ofdm_symbol_size);
|
||||
if (setup_RU_buffers(ru) != 0) {
|
||||
LOG_E(PHY, "Exiting, cannot initialize RU Buffers\n");
|
||||
exit(-1);
|
||||
}
|
||||
openair0_load(&ru->rfdevice, "vrtsim", &ru->openair0_cfg, NULL);
|
||||
ru->rfdevice.trx_start_func(&ru->rfdevice);
|
||||
}
|
||||
|
||||
static void oru_tx_slot_processing(RU_t *ru, int frame, int slot, openair0_timestamp tx_timestamp)
|
||||
{
|
||||
LOG_I(PHY, "RU %d: Processing frame %d, slot %d\n", ru->idx, frame, slot);
|
||||
const NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
int slot_type = nr_slot_select(&ru->config, frame, slot % fp->slots_per_frame);
|
||||
if (slot_type != NR_UPLINK_SLOT) {
|
||||
for (int i = 0; i < ru->nb_tx; i++) {
|
||||
apply_nr_rotation_TX(fp,
|
||||
(c16_t *)ru->common.txdataF_BF[i],
|
||||
fp->symbol_rotation[0],
|
||||
slot,
|
||||
fp->N_RB_DL,
|
||||
0,
|
||||
fp->Ncp == EXTENDED ? 12 : 14);
|
||||
nr_feptx0(ru, slot, 0, 14, i);
|
||||
}
|
||||
}
|
||||
tx_rf(ru, frame, slot, tx_timestamp);
|
||||
}
|
||||
|
||||
void oru_keep_timing(ORU_t *oru, int frame, int slot)
|
||||
{
|
||||
if (oru->timing_initialized) {
|
||||
if (frame < oru->last_frame) {
|
||||
oru->hfn++;
|
||||
}
|
||||
} else {
|
||||
oru->first_frame = frame;
|
||||
oru->first_call_timestamp = oru->current_timestamp;
|
||||
oru->first_slot = slot;
|
||||
oru->timing_initialized = true;
|
||||
oru->hfn = 0;
|
||||
}
|
||||
oru->last_frame = frame;
|
||||
}
|
||||
|
||||
uint64_t oru_get_timestamp(ORU_t *oru, int frame, int slot)
|
||||
{
|
||||
AssertFatal(oru->timing_initialized, "oru_get_timestamp called before timing initialized\n");
|
||||
const NR_DL_FRAME_PARMS *fp = oru->ru->nr_frame_parms;
|
||||
int frames_since_first_call = frame - oru->first_frame + oru->hfn * 1024;
|
||||
openair0_timestamp timestamp = oru->first_call_timestamp + frames_since_first_call * fp->samples_per_frame;
|
||||
timestamp += fp->get_samples_slot_timestamp(slot, fp, 0) - fp->get_samples_slot_timestamp(oru->first_slot, fp, 0);
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
void *oru_north_read_thread(void *arg)
|
||||
{
|
||||
ORU_t *oru = (ORU_t *)arg;
|
||||
|
||||
RU_t *ru = (RU_t *)oru->ru;
|
||||
char threadname[40];
|
||||
sprintf(threadname, "oru_thread %u", ru->idx);
|
||||
|
||||
int cpu = sched_getcpu();
|
||||
if (ru->ru_thread_core > -1 && cpu != ru->ru_thread_core) {
|
||||
/* we start the ru_thread using threadCreate(), which already sets CPU
|
||||
* affinity; let's force it here again as per feature request #732 */
|
||||
cpu_set_t cpuset;
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(ru->ru_thread_core, &cpuset);
|
||||
int ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
|
||||
AssertFatal(ret == 0, "Error in pthread_getaffinity_np(): ret: %d, errno: %d", ret, errno);
|
||||
LOG_I(PHY, "RU %d: manually set CPU affinity to CPU %d\n", ru->idx, ru->ru_thread_core);
|
||||
}
|
||||
|
||||
// Start IF device if any
|
||||
if (ru->nr_start_if) {
|
||||
LOG_I(PHY, "starting transport\n");
|
||||
int ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params);
|
||||
AssertFatal(ret == 0, "RU %u: openair0_transport_init() ret %d: cannot initialize transport protocol\n", ru->idx, ret);
|
||||
|
||||
if (ru->ifdevice.get_internal_parameter != NULL) {
|
||||
void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_north_in");
|
||||
if (t != NULL)
|
||||
ru->fh_north_in = t;
|
||||
t = ru->ifdevice.get_internal_parameter("fh_if4p5_north_out");
|
||||
if (t != NULL)
|
||||
ru->fh_north_out = t;
|
||||
}
|
||||
|
||||
LOG_I(PHY, "Starting IF interface for RU %d, nb_rx %d\n", ru->idx, ru->nb_rx);
|
||||
AssertFatal(ru->nr_start_if(ru, NULL) == 0, "Could not start the IF device\n");
|
||||
|
||||
if (ru->has_ctrl_prt > 0) {
|
||||
ret = attach_rru(ru);
|
||||
AssertFatal(ret == 0, "Cannot connect to remote radio\n");
|
||||
}
|
||||
} else {
|
||||
AssertFatal(false, "RU %d: no IF device and no local RF\n", ru->idx);
|
||||
}
|
||||
|
||||
// Start RF device if any
|
||||
if (ru->start_rf) {
|
||||
if (ru->start_rf(ru) != 0)
|
||||
LOG_E(HW, "Could not start the RF device\n");
|
||||
else
|
||||
LOG_I(PHY, "RU %d rf device ready\n", ru->idx);
|
||||
} else
|
||||
LOG_I(PHY, "RU %d no rf device\n", ru->idx);
|
||||
|
||||
LOG_I(PHY, "RU %d RF started cpu_meas_enabled %d\n", ru->idx, cpu_meas_enabled);
|
||||
// start trx write thread
|
||||
if (usrp_tx_thread == 1) {
|
||||
if (ru->start_write_thread) {
|
||||
if (ru->start_write_thread(ru) != 0) {
|
||||
LOG_E(HW, "Could not start tx write thread\n");
|
||||
} else {
|
||||
LOG_I(PHY, "tx write thread ready\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int frame = 0, slot = 0;
|
||||
while (!oai_exit) {
|
||||
if (ru->fh_north_in) {
|
||||
ru->fh_north_in(ru, &frame, &slot);
|
||||
oru_keep_timing(oru, frame, slot);
|
||||
oru_tx_slot_processing(ru, frame, slot, oru_get_timestamp(oru, frame, slot));
|
||||
}
|
||||
else
|
||||
AssertFatal(1 == 0, "No fronthaul interface at north port");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Just used to obtain timing information for now. Should be used to read samples for RX chain
|
||||
void *oru_south_read_thread(void *arg)
|
||||
{
|
||||
ORU_t *oru = (ORU_t *)arg;
|
||||
RU_t *ru = (RU_t *)oru->ru;
|
||||
const int num_samples = 3000;
|
||||
c16_t void_samples[ru->nb_rx][num_samples];
|
||||
c16_t *void_samples_ptr[ru->nb_rx];
|
||||
for (int i = 0; i < ru->nb_rx; i++) {
|
||||
void_samples_ptr[i] = void_samples[i];
|
||||
}
|
||||
while (true) {
|
||||
if (oru->timing_initialized == false) {
|
||||
// Keep updating the timestamp until first xran call
|
||||
openair0_timestamp timestamp;
|
||||
ru->rfdevice.trx_read_func(
|
||||
&ru->rfdevice,
|
||||
×tamp,
|
||||
(void **)&void_samples_ptr,
|
||||
num_samples,
|
||||
ru->nb_rx);
|
||||
oru->current_timestamp = timestamp + num_samples;
|
||||
} else {
|
||||
openair0_timestamp dummy;
|
||||
ru->rfdevice.trx_read_func(
|
||||
&ru->rfdevice,
|
||||
&dummy,
|
||||
(void **)&void_samples_ptr,
|
||||
num_samples,
|
||||
ru->nb_rx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -492,7 +492,7 @@ int start_L1L2(module_id_t gnb_id)
|
||||
|
||||
init_NR_RU(config_get_if(), NULL);
|
||||
|
||||
start_NR_RU();
|
||||
start_NR_RU(RC.ru[0]);
|
||||
wait_RUs();
|
||||
init_eNB_afterRU();
|
||||
LOG_I(GNB_APP, "Sending sync to all threads\n");
|
||||
@@ -716,7 +716,7 @@ int main( int argc, char **argv ) {
|
||||
wait_f1_setup_response();
|
||||
|
||||
if (RC.nb_RU > 0)
|
||||
start_NR_RU();
|
||||
start_NR_RU(RC.ru[0]);
|
||||
|
||||
#ifdef ENABLE_AERIAL
|
||||
gNB_MAC_INST *nrmac = RC.nrmac[0];
|
||||
|
||||
@@ -47,7 +47,7 @@ extern void stop_gNB(int);
|
||||
// In nr-ru.c
|
||||
extern void init_NR_RU(configmodule_interface_t *cfg, char *);
|
||||
extern void init_RU_proc(RU_t *ru);
|
||||
extern void start_NR_RU(void);
|
||||
extern void start_NR_RU(RU_t *ru);
|
||||
extern void stop_RU(int nb_ru);
|
||||
extern void kill_NR_RU_proc(int inst);
|
||||
extern void set_function_spec_param(RU_t *ru);
|
||||
|
||||
@@ -35,20 +35,23 @@ void nr_phy_init_RU(RU_t *ru)
|
||||
|
||||
LOG_D(PHY, "Initializing RU signal buffers (if_south %s) nb_tx %d, nb_rx %d\n", ru_if_types[ru->if_south], ru->nb_tx, ru->nb_rx);
|
||||
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
ru->nb_log_antennas = 0;
|
||||
for (int n = 0; n < ru->num_gNB; n++) {
|
||||
if (cfg->carrier_config.num_tx_ant.value > ru->nb_log_antennas)
|
||||
ru->nb_log_antennas = cfg->carrier_config.num_tx_ant.value;
|
||||
ru->num_beams_period = 1;
|
||||
if (ru->num_gNB > 0) {
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
ru->nb_log_antennas = 0;
|
||||
for (int n = 0; n < ru->num_gNB; n++) {
|
||||
if (cfg->carrier_config.num_tx_ant.value > ru->nb_log_antennas)
|
||||
ru->nb_log_antennas = cfg->carrier_config.num_tx_ant.value;
|
||||
}
|
||||
nfapi_nr_analog_beamforming_ve_t *analog_config = &cfg->analog_beamforming_ve;
|
||||
ru->num_beams_period = analog_config->analog_bf_vendor_ext.value ? analog_config->num_beams_period_vendor_ext.value : 1;
|
||||
}
|
||||
else ru->nb_log_antennas = ru->nb_tx;
|
||||
|
||||
// copy configuration from gNB[0] in to RU, assume that all gNB instances sharing RU use the same configuration
|
||||
// (at least the parts that are needed by the RU, numerology and PRACH)
|
||||
|
||||
AssertFatal(ru->nb_log_antennas > 0 && ru->nb_log_antennas < 13, "ru->nb_log_antennas %d ! \n",ru->nb_log_antennas);
|
||||
|
||||
nfapi_nr_analog_beamforming_ve_t *analog_config = &cfg->analog_beamforming_ve;
|
||||
ru->num_beams_period = analog_config->analog_bf_vendor_ext.value ? analog_config->num_beams_period_vendor_ext.value : 1;
|
||||
int nb_tx_streams = ru->nb_tx * ru->num_beams_period;
|
||||
int nb_rx_streams = ru->nb_rx * ru->num_beams_period;
|
||||
LOG_I(NR_PHY, "nb_tx_streams %d, nb_rx_streams %d, num_Beams_period %d\n", nb_tx_streams, nb_rx_streams, ru->num_beams_period);
|
||||
|
||||
@@ -286,6 +286,93 @@ uint32_t get_samples_slot_timestamp(int slot, const NR_DL_FRAME_PARMS *fp, unsig
|
||||
return samp_count;
|
||||
}
|
||||
|
||||
void nr_ru_init_frame_parms(RU_t *ru) {
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
|
||||
fp->frame_type = ru->frame_type;
|
||||
ru->config.cell_config.frame_duplex_type.value = ru->frame_type;
|
||||
ru->config.cell_config.frame_duplex_type.tl.tag = 0x100D;
|
||||
fp->N_RB_DL = ru->bw_tx[0];
|
||||
ru->config.ssb_config.scs_common.value=ru->numerology;
|
||||
ru->config.carrier_config.dl_grid_size[ru->config.ssb_config.scs_common.value].value = ru->bw_tx[0];
|
||||
fp->N_RB_UL = ru->bw_rx[0];
|
||||
ru->config.carrier_config.ul_grid_size[ru->config.ssb_config.scs_common.value].value = ru->bw_rx[0];
|
||||
fp->numerology_index=ru->numerology;
|
||||
fp->nr_band = ru->band[0];
|
||||
LOG_I(NR_PHY,"Set RU frame type to %s, N_RB_DL %d, N_RB_UL %d, mu %d\n",ru->frame_type == TDD ? "TDD" : "FDD", ru->bw_tx[0],ru->bw_rx[0],ru->numerology);
|
||||
set_scs_parameters(fp,fp->numerology_index,ru->bw_tx[0]);
|
||||
fp->slots_per_frame = 10 * fp->slots_per_subframe;
|
||||
fp->nb_antennas_rx = ru->nb_rx;
|
||||
fp->nb_antennas_tx = ru->nb_tx;
|
||||
fp->symbols_per_slot=14;
|
||||
fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe;
|
||||
fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP;
|
||||
fp->samples_per_slot_wCP = fp->symbols_per_slot*fp->ofdm_symbol_size;
|
||||
fp->samples_per_slotN0 = (fp->nb_prefix_samples + fp->ofdm_symbol_size) * fp->symbols_per_slot;
|
||||
fp->samples_per_slot0 = fp->nb_prefix_samples0 + ((fp->symbols_per_slot-1)*fp->nb_prefix_samples) + (fp->symbols_per_slot*fp->ofdm_symbol_size);
|
||||
fp->samples_per_subframe = (fp->nb_prefix_samples0 + fp->ofdm_symbol_size) * 2 +
|
||||
(fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2);
|
||||
fp->get_samples_per_slot = &get_samples_per_slot;
|
||||
fp->get_samples_slot_timestamp = &get_samples_slot_timestamp;
|
||||
fp->get_slot_from_timestamp = &get_slot_from_timestamp;
|
||||
fp->samples_per_frame = 10 * fp->samples_per_subframe;
|
||||
fp->freq_range = (ru->carrier_freq_tx[0] < 6e6)? FR1 : FR2;
|
||||
|
||||
fp->dl_CarrierFreq = (double)ru->carrier_freq_tx[0] * 1000;
|
||||
fp->ul_CarrierFreq = (double)ru->carrier_freq_rx[0] * 1000;
|
||||
fp->Ncp = NORMAL;
|
||||
|
||||
// Split 7.2 parameters
|
||||
ru->config.prach_config.num_prach_fd_occasions.value = 1;
|
||||
ru->config.prach_config.prach_ConfigurationIndex.value = ru->prach_config_index;
|
||||
ru->config.prach_config.prach_ConfigurationIndex.tl.tag = 0x1029;
|
||||
ru->config.prach_config.num_prach_fd_occasions_list = malloc(sizeof(*ru->config.prach_config.num_prach_fd_occasions_list));
|
||||
ru->config.prach_config.num_prach_fd_occasions_list[0].k1.value = ru->prach_msg1_freq;
|
||||
if (ru->config.cell_config.frame_duplex_type.value == 1 /* TDD */) {
|
||||
ru->config.tdd_table.tdd_period.value = ru->tdd_period;
|
||||
ru->config.tdd_table.tdd_period.tl.tag = 0x1026;
|
||||
int numb_slots_frame = (1 << ru->numerology) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
int numb_period_frame = get_nb_periods_per_frame(ru->tdd_period);
|
||||
int numb_slots_period = numb_slots_frame / numb_period_frame;
|
||||
LOG_I(NR_PHY,
|
||||
"Set TDD Period Configuration: %d periods per frame, %d slots to be configured (%d DL, %d UL)\n",
|
||||
numb_period_frame,
|
||||
numb_slots_frame,
|
||||
ru->num_DL_slots + 1,
|
||||
ru->num_UL_slots + 1);
|
||||
ru->config.tdd_table.max_tdd_periodicity_list =
|
||||
malloc(sizeof(*ru->config.tdd_table.max_tdd_periodicity_list) * (numb_slots_frame));
|
||||
for (int n = 0; n < numb_slots_frame; n++) {
|
||||
int s = 0;
|
||||
int p = n % numb_slots_period;
|
||||
if (p < ru->num_DL_slots) {
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list =
|
||||
malloc(sizeof(*ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list)
|
||||
* NR_NUMBER_OF_SYMBOLS_PER_SLOT);
|
||||
for (s = 0; s < 14; s++)
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list[s].slot_config.value = 0;
|
||||
} else if (p == ru->num_DL_slots) {
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list =
|
||||
malloc(sizeof(*ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list)
|
||||
* NR_NUMBER_OF_SYMBOLS_PER_SLOT);
|
||||
for (s = 0; s < ru->num_DL_symbols; s++)
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list[s].slot_config.value = 0;
|
||||
for (; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT - ru->num_UL_symbols; s++)
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list[s].slot_config.value = 2;
|
||||
for (; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++)
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list[s].slot_config.value = 1;
|
||||
} else {
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list =
|
||||
malloc(sizeof(*ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list)
|
||||
* NR_NUMBER_OF_SYMBOLS_PER_SLOT);
|
||||
for (s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++)
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list[s].slot_config.value = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
|
||||
@@ -339,6 +426,7 @@ void nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, NR_DL_FRAME_PARMS *
|
||||
fp->N_ssb += ((fp->L_ssb >> (63-p)) & 0x01);
|
||||
|
||||
fp->print_ue_help_cmdline_log = true;
|
||||
fp->ofdm_offset_divisor = 8;
|
||||
}
|
||||
|
||||
int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
int nr_get_ssb_start_symbol(const NR_DL_FRAME_PARMS *fp, uint8_t i_ssb);
|
||||
void nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms);
|
||||
void nr_ru_init_frame_parms(RU_t *ru);
|
||||
int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band);
|
||||
void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint8_t mu, uint16_t nr_band);
|
||||
int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp,
|
||||
|
||||
@@ -487,6 +487,30 @@ typedef struct RU_t_s {
|
||||
int num_bands;
|
||||
/// band list
|
||||
int band[MAX_BANDS_PER_RRU];
|
||||
/// tx carrier
|
||||
uint64_t carrier_freq_tx[MAX_BANDS_PER_RRU];
|
||||
/// rx carrier
|
||||
uint64_t carrier_freq_rx[MAX_BANDS_PER_RRU];
|
||||
/// tx BW in PRBs
|
||||
int bw_tx[MAX_BANDS_PER_RRU];
|
||||
/// rx BW in PRBs
|
||||
int bw_rx[MAX_BANDS_PER_RRU];
|
||||
/// 3GPP FRAME Type FDD/TDD
|
||||
int frame_type;
|
||||
/// 3GPP PRACH configuration index
|
||||
int prach_config_index;
|
||||
/// 3GPP MSG1 Start frequency
|
||||
int prach_msg1_freq;
|
||||
/// 3GPP TDD periodicity (0.5 ms, 1 0.625ms, 2 1ms, 3 1.25ms, 4 2ms,5 2.5ms, 6 5ms, 7 10ms, 8 3ms, 9 4ms
|
||||
int tdd_period;
|
||||
/// number of DL slots
|
||||
int num_DL_slots;
|
||||
/// number of UL slots
|
||||
int num_UL_slots;
|
||||
/// number of DL symbols
|
||||
int num_DL_symbols;
|
||||
/// number of UL symbols
|
||||
int num_UL_symbols;
|
||||
/// number of RX paths on device
|
||||
int nb_rx;
|
||||
/// number of TX paths on device
|
||||
@@ -670,6 +694,18 @@ typedef struct RU_t_s {
|
||||
void* scopeData;
|
||||
} RU_t;
|
||||
|
||||
typedef struct {
|
||||
pthread_t north_read_thread;
|
||||
pthread_t south_read_thread;
|
||||
RU_t *ru;
|
||||
openair0_timestamp current_timestamp;
|
||||
openair0_timestamp first_call_timestamp;
|
||||
int first_frame;
|
||||
int first_slot;
|
||||
int last_frame;
|
||||
int hfn;
|
||||
bool timing_initialized;
|
||||
} ORU_t;
|
||||
|
||||
typedef enum {
|
||||
RAU_tick=0,
|
||||
|
||||
@@ -113,6 +113,21 @@ typedef enum {
|
||||
#define CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION "half_slot_parallelization"
|
||||
#define CONFIG_STRING_RU_RU_THREAD_CORE "ru_thread_core"
|
||||
#define CONFIG_STRING_RU_GPIO_CONTROL "gpio_controller"
|
||||
#define CONFIG_STRING_RU_TX_BW_LIST "tx_bw"
|
||||
#define CONFIG_STRING_RU_RX_BW_LIST "rx_bw"
|
||||
#define CONFIG_STRING_RU_CARRIER_TX_LIST "carrier_tx"
|
||||
#define CONFIG_STRING_RU_CARRIER_RX_LIST "carrier_rx"
|
||||
#define CONFIG_STRING_RU_FRAME_TYPE "frame_type"
|
||||
#define CONFIG_STRING_RU_PRACH_CONFIGID "prach_config_index"
|
||||
#define CONFIG_STRING_RU_PRACH_MSG1FREQ "prach_msg1_start"
|
||||
#define CONFIG_STRING_RU_NUMEROLOGY "mu"
|
||||
#define CONFIG_STRING_RU_TDD_PERIOD "tdd_period"
|
||||
#define CONFIG_STRING_RU_NUM_DL_SLOTS "num_dl_slots"
|
||||
#define CONFIG_STRING_RU_NUM_UL_SLOTS "num_ul_slots"
|
||||
#define CONFIG_STRING_RU_NUM_DL_SYMBOLS "num_dl_symbols"
|
||||
#define CONFIG_STRING_RU_NUM_UL_SYMBOLS "num_ul_symbols"
|
||||
|
||||
|
||||
|
||||
#define HLP_RU_SF_AHEAD "LTE TX processing advance"
|
||||
#define HLP_RU_SL_AHEAD "NR TX processing advance"
|
||||
@@ -126,6 +141,20 @@ typedef enum {
|
||||
#define HLP_RU_HALF_SLOT_PARALLELIZATION "run half slots in parallel in RU FEP"
|
||||
#define HLP_RU_RU_THREAD_CORE "id of core to pin ru_thread, -1 is default"
|
||||
#define HLP_RU_GPIO_CONTROL "set the GPIO control type for the RU"
|
||||
#define HLP_RU_TX_BW "set the TX bandwidth list per component carrier"
|
||||
#define HLP_RU_RX_BW "set the RX bandwidth list per component carrier"
|
||||
#define HLP_RU_CARRIER_TX "set the TX carrier frequencies per component carrier"
|
||||
#define HLP_RU_CARRIER_RX "set the RX carrier frequencies per component carrier"
|
||||
#define HLP_RU_FRAMETYPE "set the Frame type TDD/FDD of all component carriers"
|
||||
#define HLP_RU_PRACH_CONFIGID "set the PRACH configuration id of all component carriers"
|
||||
#define HLP_RU_PRACH_MSG1FREQ "set the PRACH MSG1 frequency of all component carriers"
|
||||
#define HLP_RU_NUMEROLOGY "set the numerology of the RU"
|
||||
#define HLP_RU_TDD_PERIOD "set the 3GPP TDD periodificty 0-9"
|
||||
#define HLP_RU_NUM_DL_SLOTS "set the number of DL Slots in TDD"
|
||||
#define HLP_RU_NUM_UL_SLOTS "set the number of UL Slots in TDD"
|
||||
#define HLP_RU_NUM_DL_SYMBOLS "set the number of DL symbols in the mixed slot"
|
||||
#define HLP_RU_NUM_UL_SYMBOLS "set the number of UL symbols in the mixed slot"
|
||||
|
||||
|
||||
#define RU_LOCAL_IF_NAME_IDX 0
|
||||
#define RU_LOCAL_ADDRESS_IDX 1
|
||||
@@ -170,6 +199,19 @@ typedef enum {
|
||||
#define RU_HALF_SLOT_PARALLELIZATION 40
|
||||
#define RU_RU_THREAD_CORE 41
|
||||
#define RU_GPIO_CONTROL 42
|
||||
#define RU_TX_BW_LIST_IDX 43
|
||||
#define RU_RX_BW_LIST_IDX 44
|
||||
#define RU_TX_CARRIER_LIST_IDX 45
|
||||
#define RU_RX_CARRIER_LIST_IDX 46
|
||||
#define RU_FRAME_TYPE_IDX 47
|
||||
#define RU_PRACH_CONFIGID_IDX 48
|
||||
#define RU_PRACH_MSG1FREQ_IDX 49
|
||||
#define RU_NUMEROLOGY_IDX 50
|
||||
#define RU_TDD_PERIOD_IDX 51
|
||||
#define RU_NUM_DL_SLOTS_IDX 52
|
||||
#define RU_NUM_UL_SLOTS_IDX 53
|
||||
#define RU_NUM_DL_SYMBOLS_IDX 54
|
||||
#define RU_NUM_UL_SYMBOLS_IDX 55
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* RU configuration parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
@@ -219,6 +261,19 @@ typedef enum {
|
||||
{CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION, HLP_RU_HALF_SLOT_PARALLELIZATION, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_RU_THREAD_CORE, HLP_RU_RU_THREAD_CORE, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_GPIO_CONTROL, HLP_RU_GPIO_CONTROL, 0, .strptr=NULL, .defstrval="generic", TYPE_STRING, 0}, \
|
||||
{CONFIG_STRING_RU_TX_BW_LIST, HLP_RU_TX_BW, 0, .iptr=NULL, .defintarrayval=DEFBW, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_RU_RX_BW_LIST, HLP_RU_RX_BW, 0, .iptr=NULL, .defintarrayval=DEFBW, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_RU_CARRIER_TX_LIST, HLP_RU_CARRIER_TX, 0, .iptr=NULL, .defintarrayval=DEFCARRIER, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_RU_CARRIER_RX_LIST, HLP_RU_CARRIER_RX, 0, .iptr=NULL, .defintarrayval=DEFCARRIER, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_RU_FRAME_TYPE, HLP_RU_FRAMETYPE, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_PRACH_CONFIGID, HLP_RU_PRACH_CONFIGID, 0, .uptr=NULL, .defintval=152, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_PRACH_MSG1FREQ, HLP_RU_PRACH_MSG1FREQ, 0, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_NUMEROLOGY, HLP_RU_NUMEROLOGY, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_TDD_PERIOD, HLP_RU_TDD_PERIOD, 0, .uptr=NULL, .defintval=5, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_NUM_DL_SLOTS, HLP_RU_NUM_DL_SLOTS, 0, .uptr=NULL, .defintval=3, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_NUM_UL_SLOTS, HLP_RU_NUM_UL_SLOTS, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_NUM_DL_SYMBOLS, HLP_RU_NUM_DL_SYMBOLS, 0, .uptr=NULL, .defintval=7, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_NUM_UL_SYMBOLS, HLP_RU_NUM_UL_SYMBOLS, 0, .uptr=NULL, .defintval=3, TYPE_UINT, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -84,7 +84,8 @@ static int DEFBANDS[] = {7};
|
||||
static int DEFENBS[] = {0};
|
||||
static int DEFBFW[] = {0x00007fff};
|
||||
static int DEFRUTPCORES[] = {-1,-1,-1,-1};
|
||||
|
||||
static int DEFBW[] = {273};
|
||||
static int DEFCARRIER[] = {3430560};
|
||||
/**
|
||||
* @brief Helper define to allocate and initialize SetupRelease structures
|
||||
*/
|
||||
|
||||
@@ -175,6 +175,19 @@ int openair0_transport_load(openair0_device *device,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int openair0_load(openair0_device *device, char *name, openair0_config_t *openair0_cfg, eth_params_t *eth_params)
|
||||
{
|
||||
loader_shlibfunc_t shlib_fdesc[1];
|
||||
int ret = 0;
|
||||
|
||||
shlib_fdesc[0].fname = eth_params == NULL ? "device_init" : "transport_init";
|
||||
|
||||
ret = load_module_shlib(name, shlib_fdesc, 1, NULL);
|
||||
AssertFatal((ret >= 0), "Library %s couldn't be loaded\n", name);
|
||||
|
||||
return ((devfunc_t)shlib_fdesc[0].fptr)(device, openair0_cfg, eth_params);
|
||||
}
|
||||
|
||||
static void writerEnqueue(re_order_t *ctx, openair0_timestamp timestamp, void **txp, int nsamps, int nbAnt, int flags)
|
||||
{
|
||||
pthread_mutex_lock(&ctx->mutex_store);
|
||||
|
||||
@@ -656,7 +656,7 @@ const char *get_devname(int devtype);
|
||||
int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
/*! \brief Initialize transport protocol . It returns 0 if OK */
|
||||
int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params);
|
||||
|
||||
int openair0_load(openair0_device *device, char *name, openair0_config_t *openair0_cfg, eth_params_t *eth_params);
|
||||
|
||||
/*! \brief Get current timestamp of USRP
|
||||
* \param device the hardware to use
|
||||
|
||||
@@ -33,7 +33,7 @@ endif()
|
||||
add_compile_options(-Wno-packed-not-aligned)
|
||||
|
||||
set_target_properties(oran_fhlib_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native")
|
||||
target_link_libraries(oran_fhlib_5g PRIVATE xran::xran ${dpdk_LINK_LIBRARIES} ${T_LIB} pthread dl rt m numa)
|
||||
target_link_libraries(oran_fhlib_5g PRIVATE MAC_NR_COMMON xran::xran ${dpdk_LINK_LIBRARIES} ${T_LIB} pthread dl rt m numa)
|
||||
target_include_directories(oran_fhlib_5g PRIVATE ${dpdk_INCLUDE_DIRS})
|
||||
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
|
||||
find_package(armral REQUIRED)
|
||||
|
||||
@@ -56,10 +56,33 @@ int xran_is_prach_slot(uint8_t PortId, uint32_t subframe_id, uint32_t slot_id);
|
||||
|
||||
#ifndef USE_POLLING
|
||||
extern notifiedFIFO_t oran_sync_fifo;
|
||||
extern notifiedFIFO_t dl_sync_fifo;
|
||||
#else
|
||||
volatile oran_sync_info_t oran_sync_info = {0};
|
||||
#endif
|
||||
|
||||
int32_t symbol_callback(void *args, struct xran_sense_of_time* p_sense_of_time)
|
||||
{
|
||||
uint32_t frame = p_sense_of_time->nFrameIdx;
|
||||
uint32_t slot = p_sense_of_time->nSlotIdx;
|
||||
uint32_t subframe = p_sense_of_time->nSubframeIdx;
|
||||
|
||||
const struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
|
||||
const int slots_in_sf = 1 << fh_cfg->frame_conf.nNumerology;
|
||||
uint32_t slot_in_frame = slot + subframe * slots_in_sf;
|
||||
|
||||
if (!first_call_set)
|
||||
return 0;
|
||||
|
||||
LOG_D(HW, "Push %d.%d (slot %d, subframe %d)\n", frame, slot_in_frame, slot, subframe);
|
||||
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(oran_sync_info_t), 0, NULL, NULL);
|
||||
oran_sync_info_t *info = NotifiedFifoData(req);
|
||||
info->sl = slot_in_frame;
|
||||
info->f = frame;
|
||||
pushNotifiedFIFO(&dl_sync_fifo, req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @details xran-specific callback, called when all packets for given CC and
|
||||
* 1/4, 1/2, 3/4, all symbols of a slot arrived. Currently, only used to get
|
||||
* timing information and unblock another thread in xran_fh_rx_read_slot()
|
||||
@@ -467,6 +490,154 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/** @details Read PDSCH data from xran buffers on the O-RU. If I/Q compression
|
||||
* (bitwidth < 16 bits) is configured, deccompresses the data before writing.
|
||||
* Prints ON TIME counters every 128 frames.
|
||||
*
|
||||
* Function is blocking and waits for next frame/slot combination. It is unblocked
|
||||
* by oai_xran_fh_rx_callback(). It writes the current slot into parameters
|
||||
* frame/slot. */
|
||||
int xran_fh_tx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
int32_t *pos = NULL;
|
||||
int idx = 0;
|
||||
// pull next even from oran_sync_fifo
|
||||
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&dl_sync_fifo);
|
||||
|
||||
notifiedFIFO_elt_t *f;
|
||||
while ((f = pollNotifiedFIFO(&dl_sync_fifo)) != NULL) {
|
||||
oran_sync_info_t *old_info = NotifiedFifoData(res);
|
||||
oran_sync_info_t *new_info = NotifiedFifoData(f);
|
||||
LOG_E(HW, "Detected double sync message %d.%d => %d.%d\n", old_info->f, old_info->sl, new_info->f, new_info->sl);
|
||||
delNotifiedFIFO_elt(res);
|
||||
res = f;
|
||||
}
|
||||
|
||||
oran_sync_info_t *info = NotifiedFifoData(res);
|
||||
|
||||
*slot = info->sl;
|
||||
*frame = info->f;
|
||||
delNotifiedFIFO_elt(res);
|
||||
|
||||
struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
|
||||
int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology;
|
||||
|
||||
int tti = slots_per_frame * (*frame) + (*slot);
|
||||
|
||||
const struct xran_fh_init *fh_init = get_xran_fh_init();
|
||||
int nPRBs = fh_cfg->nULRBs;
|
||||
int fftsize = 1 << fh_cfg->ru_conf.fftSize;
|
||||
|
||||
int slot_offset_rxdata = 3 & (*slot);
|
||||
uint32_t slot_size = 4 * 14 * fftsize;
|
||||
uint8_t *tx_data;
|
||||
uint8_t *start_ptr = NULL;
|
||||
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
|
||||
for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet.
|
||||
for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) {
|
||||
tx_data = (uint8_t *)ru->txdataF_BF[ant_id];
|
||||
start_ptr = tx_data + (slot_size * slot_offset_rxdata);
|
||||
const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf;
|
||||
// This loop would better be more inner to avoid confusion and maybe also errors.
|
||||
for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) {
|
||||
/* the callback is for mixed and UL slots. In mixed, we have to
|
||||
* skip DL and guard symbols. */
|
||||
if (is_tdd_ul_symbol(frame_conf, *slot, sym_idx))
|
||||
continue;
|
||||
|
||||
uint8_t *pData;
|
||||
oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru);
|
||||
uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
|
||||
struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData;
|
||||
|
||||
struct xran_prb_elm *pRbElm = &pPrbMap->prbMap[0];
|
||||
#ifdef E_RELEASE
|
||||
struct xran_section_desc *p_sec_desc = pRbElm->p_sec_desc[sym_idx][0];
|
||||
#elif defined F_RELEASE
|
||||
struct xran_section_desc *p_sec_desc = &pRbElm->sec_desc[sym_idx][0];
|
||||
#endif
|
||||
uint32_t one_rb_size =
|
||||
(((pRbElm->iqWidth == 0) || (pRbElm->iqWidth == 16)) ? (N_SC_PER_PRB * 2 * 2) : (3 * pRbElm->iqWidth + 1));
|
||||
if (fh_init->mtu < pRbElm->nRBSize * one_rb_size)
|
||||
pData = bufs->dst[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN]
|
||||
.pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT]
|
||||
.pData;
|
||||
else
|
||||
pData = p_sec_desc->pData;
|
||||
ptr = pData;
|
||||
pos = (int32_t *)(start_ptr + (4 * sym_idx * fftsize));
|
||||
if (ptr == NULL || pos == NULL)
|
||||
continue;
|
||||
|
||||
struct xran_prb_map *pRbMap = pPrbMap;
|
||||
|
||||
uint32_t idxElm = 0;
|
||||
uint8_t *src = (uint8_t *)ptr;
|
||||
|
||||
LOG_D(HW, "pRbMap->nPrbElm %d\n", pRbMap->nPrbElm);
|
||||
for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) {
|
||||
LOG_D(HW,
|
||||
"prbMap[%d] : PRBstart %d nPRBs %d\n",
|
||||
idxElm,
|
||||
pRbMap->prbMap[idxElm].nRBStart,
|
||||
pRbMap->prbMap[idxElm].nRBSize);
|
||||
pRbElm = &pRbMap->prbMap[idxElm];
|
||||
int pos_len = 0;
|
||||
int neg_len = 0;
|
||||
|
||||
if (pRbElm->nRBStart < (nPRBs >> 1)) // there are PRBs left of DC
|
||||
neg_len = min((nPRBs * 6) - (pRbElm->nRBStart * 12), pRbElm->nRBSize * N_SC_PER_PRB);
|
||||
pos_len = (pRbElm->nRBSize * N_SC_PER_PRB) - neg_len;
|
||||
|
||||
src = pData;
|
||||
// Calculation of the pointer for the section in the buffer.
|
||||
// positive half
|
||||
uint8_t *dst1 = (uint8_t *)(pos + (neg_len == 0 ? ((pRbElm->nRBStart * N_SC_PER_PRB) - (nPRBs * 6)) : 0));
|
||||
// negative half
|
||||
uint8_t *dst2 = (uint8_t *)(pos + (pRbElm->nRBStart * N_SC_PER_PRB) + fftsize - (nPRBs * 6));
|
||||
int32_t local_dst[pRbElm->nRBSize * N_SC_PER_PRB] __attribute__((aligned(64)));
|
||||
if (pRbElm->compMethod == XRAN_COMPMETHOD_NONE) {
|
||||
// NOTE: gcc 11 knows how to generate AVX2 for this!
|
||||
for (idx = 0; idx < pRbElm->nRBSize * N_SC_PER_PRB * 2; idx++)
|
||||
((int16_t *)local_dst)[idx] = ((int16_t)ntohs(((uint16_t *)src)[idx])) >> 2;
|
||||
memcpy((void *)dst2, (void *)local_dst, neg_len * 4);
|
||||
memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4);
|
||||
} else if (pRbElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
struct xranlib_decompress_request bfp_decom_req = {};
|
||||
struct xranlib_decompress_response bfp_decom_rsp = {};
|
||||
|
||||
int16_t payload_len = (3 * pRbElm->iqWidth + 1) * pRbElm->nRBSize;
|
||||
|
||||
bfp_decom_req.data_in = (int8_t *)src;
|
||||
bfp_decom_req.numRBs = pRbElm->nRBSize;
|
||||
bfp_decom_req.len = payload_len;
|
||||
bfp_decom_req.compMethod = pRbElm->compMethod;
|
||||
bfp_decom_req.iqWidth = pRbElm->iqWidth;
|
||||
|
||||
bfp_decom_rsp.data_out = (int16_t *)local_dst;
|
||||
bfp_decom_rsp.len = 0;
|
||||
|
||||
xranlib_decompress_avx512(&bfp_decom_req, &bfp_decom_rsp);
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
armral_bfp_decompression(pRbElm->iqWidth, pRbElm->nRBSize, (int8_t *)src, (int16_t *)local_dst);
|
||||
#else
|
||||
AssertFatal(1 == 0, "BFP compression not supported on this architecture");
|
||||
#endif
|
||||
memcpy((void *)dst2, (void *)local_dst, neg_len * 4);
|
||||
memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4);
|
||||
} else {
|
||||
printf("pRbElm->compMethod == %d is not supported\n", pRbElm->compMethod);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
} // sym_ind
|
||||
} // ant_ind
|
||||
} // vv_inf
|
||||
return (0);
|
||||
}
|
||||
|
||||
/** @details Write PDSCH IQ-data from OAI txdataF_BF buffer to xran buffers. If
|
||||
* I/Q compression (bitwidth < 16 bits) is configured, compresses the data
|
||||
* before writing. */
|
||||
|
||||
@@ -35,5 +35,6 @@ typedef struct {
|
||||
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status);
|
||||
/** @brief xran callback for time alignment, see xran_reg_physide_cb(). */
|
||||
int oai_physide_dl_tti_call_back(void *param);
|
||||
int32_t symbol_callback(void *args, struct xran_sense_of_time* p_sense_of_time);
|
||||
|
||||
#endif /* OAIORAN_H */
|
||||
|
||||
@@ -184,7 +184,8 @@ void print_fh_init(const struct xran_fh_init *fh_init)
|
||||
fh_init->filePrefix,
|
||||
fh_init->mtu,
|
||||
fh_init->p_o_du_addr);
|
||||
print_ether_addr(" p_o_ru_addr", fh_init->xran_ports * fh_init->io_cfg.num_vfs, (struct rte_ether_addr *)fh_init->p_o_ru_addr);
|
||||
if (fh_init->p_o_ru_addr) print_ether_addr(" p_o_ru_addr", fh_init->xran_ports * fh_init->io_cfg.num_vfs, (struct rte_ether_addr *)fh_init->p_o_ru_addr);
|
||||
else if (fh_init->p_o_du_addr) print_ether_addr(" p_o_du_addr", fh_init->xran_ports * fh_init->io_cfg.num_vfs, (struct rte_ether_addr *)fh_init->p_o_du_addr);
|
||||
printf("\
|
||||
totalBfWeights %d\n",
|
||||
fh_init->totalBfWeights);
|
||||
@@ -466,14 +467,14 @@ char bbdev_dev[32] = "";
|
||||
char bbdev_vfio_vf_token[64] = "";
|
||||
#endif
|
||||
|
||||
static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, int nump, const int num_rus)
|
||||
static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, int nump, const int num_peer, const int is_du)
|
||||
{
|
||||
DevAssert(fhip != NULL);
|
||||
int num_dev = gpd(fhip, nump, ORAN_CONFIG_DPDK_DEVICES)->numelt;
|
||||
AssertFatal(num_dev > 0, "need to provide DPDK devices for O-RAN 7.2 Fronthaul\n");
|
||||
AssertFatal(num_dev < 17, "too many DPDK devices for O-RAN 7.2 Fronthaul\n");
|
||||
|
||||
io_cfg->id = 0; // 0 -> xran as O-DU; 1 -> xran as O-RU
|
||||
io_cfg->id = 1-is_du; // 0 -> xran as O-DU; 1 -> xran as O-RU
|
||||
io_cfg->num_vfs = num_dev; // number of VFs for C-plane and U-plane (should be even); max = XRAN_VF_MAX
|
||||
io_cfg->num_rxq = 1; // number of RX queues per VF
|
||||
for (int i = 0; i < num_dev; ++i) {
|
||||
@@ -535,7 +536,7 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in
|
||||
io_cfg->io_sleep = 0; // enable sleep on PMD cores; 0 -> no sleep
|
||||
io_cfg->nEthLinePerPort = *gpd(fhip, nump, ORAN_CONFIG_NETHPERPORT)->uptr; // 1, 2, 3 total number of links per O-RU (Fronthaul Ethernet link)
|
||||
io_cfg->nEthLineSpeed = *gpd(fhip, nump, ORAN_CONFIG_NETHSPEED)->uptr; // 10G,25G,40G,100G speed of Physical connection on O-RU
|
||||
io_cfg->one_vf_cu_plane = (io_cfg->num_vfs == num_rus); // C-plane and U-plane use one VF
|
||||
io_cfg->one_vf_cu_plane = (io_cfg->num_vfs == num_peer); // C-plane and U-plane use one VF
|
||||
|
||||
/* eCPRI One-Way Delay Measurements common settings for O-DU and O-RU;
|
||||
use owdm to calculate T12 and T34 -> CUS specification, section 2.3.3.3;
|
||||
@@ -546,7 +547,7 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in
|
||||
/* if RU does support, io_cfg->eowd_cmn[0] should only be filled as id = O_DU; io_cfg->eowd_cmn[1] only used if id = O_RU */
|
||||
const uint16_t owdm_enable = *gpd(fhip, nump, ORAN_CONFIG_ECPRI_OWDM)->uptr;
|
||||
if (owdm_enable) {
|
||||
io_cfg->eowd_cmn[0].initiator_en = 1; // 1 -> initiator (always O-DU), 0 -> recipient (always O-RU)
|
||||
io_cfg->eowd_cmn[0].initiator_en = is_du ? 1 : 0; // 1 -> initiator (always O-DU), 0 -> recipient (always O-RU)
|
||||
io_cfg->eowd_cmn[0].numberOfSamples = 8; // total number of samples to be collected and averaged per port
|
||||
io_cfg->eowd_cmn[0].filterType = 0; // 0 -> simple average based on number of measurements; not used in xran in both E and F releases
|
||||
io_cfg->eowd_cmn[0].responseTo = 10000000; // response timeout in [ns]
|
||||
@@ -710,9 +711,17 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
|
||||
}
|
||||
}
|
||||
#else
|
||||
int num_rus = FH_ConfigList.numelt; // based on the number of fh_config sections -> number of RUs
|
||||
fh_init->xran_ports = num_rus; // since we use xran as O-DU, xran_ports is set to the number of RUs
|
||||
if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus))
|
||||
int num_peer = FH_ConfigList.numelt; // based on the number of fh_config sections
|
||||
int is_du=0;
|
||||
|
||||
int num_ru_addr = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->numelt;
|
||||
int num_du_addr = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->numelt;
|
||||
if (num_ru_addr > 0 && num_du_addr == 0) is_du = 1;
|
||||
else if (num_du_addr > 0 && num_ru_addr == 0) is_du = 0;
|
||||
else AssertFatal(1==0,"Illegal node configuration, num_du_addr %d, num_ru_addr %d\n",num_du_addr,num_ru_addr);
|
||||
fh_init->xran_ports = num_peer;
|
||||
|
||||
if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_peer, is_du))
|
||||
return false;
|
||||
if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, xran_cat))
|
||||
return false;
|
||||
@@ -720,16 +729,36 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
|
||||
communicated in a single xRAN network layer transaction. Supported 1500 bytes and 9600 bytes (Jumbo Frame);
|
||||
xran only checks if (MTU <= 1500), therefore setting any value > 1500, xran assumes 9600 value is used */
|
||||
fh_init->mtu = *gpd(fhip, nump, ORAN_CONFIG_MTU)->uptr;
|
||||
int num_ru_addr = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->numelt;
|
||||
fh_init->p_o_ru_addr = calloc(num_ru_addr, sizeof(struct rte_ether_addr));
|
||||
AssertFatal(fh_init->p_o_ru_addr != NULL, "out of memory\n");
|
||||
char **ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr;
|
||||
for (int i = 0; i < num_ru_addr; ++i) {
|
||||
struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_ru_addr;
|
||||
if (get_ether_addr(ru_addrs[i], &ea[i]) == NULL) {
|
||||
printf("could not read ethernet address '%s' for RU!\n", ru_addrs[i]);
|
||||
return false;
|
||||
}
|
||||
|
||||
fh_init->p_o_du_addr = NULL; // DPDK retreives DU MAC address within the xran library with rte_eth_macaddr_get() function
|
||||
|
||||
char **ru_addrs,**du_addrs;
|
||||
|
||||
if (is_du > 0) {
|
||||
fh_init->p_o_ru_addr = calloc(num_ru_addr, sizeof(struct rte_ether_addr));
|
||||
ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr;
|
||||
AssertFatal(fh_init->p_o_ru_addr != NULL, "out of memory\n");
|
||||
for (int i = 0; i < num_ru_addr; ++i) {
|
||||
struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_ru_addr;
|
||||
if (get_ether_addr(ru_addrs[i], &ea[i]) == NULL) {
|
||||
printf("could not read ethernet address '%s' for RU!\n", ru_addrs[i]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fh_init->p_o_du_addr = NULL;
|
||||
}
|
||||
else {
|
||||
fh_init->p_o_du_addr = calloc(num_du_addr, sizeof(struct rte_ether_addr));
|
||||
du_addrs = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->strlistptr;
|
||||
AssertFatal(fh_init->p_o_du_addr != NULL, "out of memory\n");
|
||||
for (int i = 0; i < num_du_addr; ++i) {
|
||||
struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_du_addr;
|
||||
if (get_ether_addr(du_addrs[i], &ea[i]) == NULL) {
|
||||
printf("could not read ethernet address '%s' for DU!\n", du_addrs[i]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fh_init->p_o_ru_addr = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -738,7 +767,6 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
|
||||
/* used to specify a unique prefix for shared memory, and files created by multiple DPDK processes;
|
||||
it is necessary */
|
||||
fh_init->filePrefix = strdup(*gpd(fhip, nump, ORAN_CONFIG_FILE_PREFIX)->strptr);
|
||||
fh_init->p_o_du_addr = NULL; // DPDK retreives DU MAC address within the xran library with rte_eth_macaddr_get() function
|
||||
fh_init->totalBfWeights = 0; // only used if id = O_RU (for emulation); C-plane extension types; section 5.4.6 of CUS spec
|
||||
|
||||
#ifdef F_RELEASE
|
||||
|
||||
@@ -298,6 +298,7 @@ static void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t stat
|
||||
}
|
||||
|
||||
static void oran_allocate_buffers(void *handle,
|
||||
bool is_du,
|
||||
int xran_inst,
|
||||
int num_sectors,
|
||||
oran_port_instance_t *portInstances,
|
||||
@@ -425,8 +426,20 @@ static void oran_allocate_buffers(void *handle,
|
||||
}
|
||||
}
|
||||
|
||||
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag);
|
||||
xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag);
|
||||
if (is_du) {
|
||||
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag);
|
||||
xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag);
|
||||
}
|
||||
else {
|
||||
static struct xran_sense_of_time symCbTime;
|
||||
// TODO: Check if symbol callback should also run in half slot
|
||||
xran_reg_sym_cb(handle, symbol_callback, NULL, &symCbTime, 13, XRAN_CB_SYM_TX_WIN_END);
|
||||
// Only setup UPlane/CPlane buffers for O-RU. O-RU does not need callback for PUSCH and PRACH as the timing will be reliant on
|
||||
// the underlying RF device
|
||||
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, NULL, NULL);
|
||||
// TODO: PRACH
|
||||
// TODO: Beamforming weights
|
||||
}
|
||||
}
|
||||
|
||||
int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_config *xran_fh_config)
|
||||
@@ -440,6 +453,7 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
bool is_du = xran_fh_init->io_cfg.id == 0;
|
||||
/** process all the O-RU|O-DU for use case */
|
||||
for (int32_t o_xu_id = 0; o_xu_id < xran_fh_init->xran_ports; o_xu_id++) {
|
||||
print_fh_config(&xran_fh_config[o_xu_id]);
|
||||
@@ -457,9 +471,9 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi
|
||||
pi->pusch_tag = tag;
|
||||
#ifdef E_RELEASE
|
||||
LOG_W(HW, "Please be aware that E release support will be removed in the future. Consider switching to F release.\n");
|
||||
oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, &xran_fh_config[o_xu_id]);
|
||||
oran_allocate_buffers(gxran_handle, is_du, o_xu_id, 1, pi, &xran_fh_config[o_xu_id]);
|
||||
#elif defined F_RELEASE
|
||||
oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]);
|
||||
oran_allocate_buffers(gxran_handle, is_du, o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]);
|
||||
#endif
|
||||
|
||||
if ((xret = xran_reg_physide_cb(gxran_handle, oai_physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI)) != XRAN_STATUS_SUCCESS) {
|
||||
|
||||
@@ -32,11 +32,12 @@
|
||||
#define ORAN_CONFIG_IO_CORE "io_core"
|
||||
#define ORAN_CONFIG_WORKER_CORES "worker_cores"
|
||||
#define ORAN_CONFIG_DU_KEYPAIR "du_key_pair" // only needed for M-plane
|
||||
#define ORAN_CONFIG_DU_ADDR "du_addr" // only needed for M-plane
|
||||
#define ORAN_CONFIG_VLAN_TAG "vlan_tag" // only needed for M-plane
|
||||
#define ORAN_CONFIG_RU_ADDR "ru_addr" // not needed if M-plane used
|
||||
#define ORAN_CONFIG_RU_IP_ADDR "ru_ip_addr" // only needed for M-plane
|
||||
#define ORAN_CONFIG_MTU "mtu" // not needed if M-plane used
|
||||
#define ORAN_CONFIG_DU_ADDR "du_addr"
|
||||
#define ORAN_CONFIG_RU_ADDR "ru_addr"
|
||||
#define ORAN_CONFIG_MTU "mtu"
|
||||
#define ORAN_CONFIG_FILE_PREFIX "file_prefix"
|
||||
#define ORAN_CONFIG_NETHPERPORT "eth_lines"
|
||||
#define ORAN_CONFIG_NETHSPEED "eth_speed"
|
||||
@@ -53,10 +54,10 @@
|
||||
{ORAN_CONFIG_IO_CORE, "DPDK Core used for IO\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintval=4, TYPE_INT, 0}, \
|
||||
{ORAN_CONFIG_WORKER_CORES, "CPU Cores to use for workers\n", PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=NULL,TYPE_UINTARRAY, 0}, \
|
||||
{ORAN_CONFIG_DU_KEYPAIR, "DU keypair for RU authentication\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
{ORAN_CONFIG_DU_ADDR, "Ether addr of DU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
{ORAN_CONFIG_VLAN_TAG, "VLAN tag\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
|
||||
{ORAN_CONFIG_RU_ADDR, "Ether addr of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
{ORAN_CONFIG_RU_IP_ADDR, "IP addr of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
{ORAN_CONFIG_DU_ADDR, "Ether addr of DU\n", 0, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
{ORAN_CONFIG_RU_ADDR, "Ether addr of RU\n", 0, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
{ORAN_CONFIG_MTU, "MTU of Eth interface\n", 0, .uptr=NULL, .defuintval=1500, TYPE_UINT, 0}, \
|
||||
{ORAN_CONFIG_FILE_PREFIX, "DPDK file-prefix\n", 0, .strptr=NULL, .defstrval="wls_0", TYPE_STRING, 0}, \
|
||||
{ORAN_CONFIG_NETHPERPORT, "number of links per port\n", 0, .uptr=NULL, .defuintval=1, TYPE_UINT, 0}, \
|
||||
|
||||
@@ -53,6 +53,7 @@ typedef struct {
|
||||
} oran_eth_state_t;
|
||||
|
||||
notifiedFIFO_t oran_sync_fifo;
|
||||
notifiedFIFO_t dl_sync_fifo;
|
||||
|
||||
int trx_oran_start(openair0_device *device)
|
||||
{
|
||||
@@ -210,6 +211,16 @@ int trx_oran_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void oran_fh_if4p5_north_in(RU_t *ru, int *frame, int *slot) {
|
||||
ru_info_t ru_info;
|
||||
ru_info.nb_rx = ru->nb_rx * ru->num_beams_period;
|
||||
ru_info.txdataF_BF = ru->common.txdataF_BF;
|
||||
start_meas(&ru->rx_fhaul);
|
||||
int ret = xran_fh_tx_read_slot(&ru_info, frame, slot);
|
||||
AssertFatal(ret == 0, "ORAN: %d.%d ORAN_fh_if4p5_north_in ERROR in RX function \n", *frame, *slot);
|
||||
stop_meas(&ru->rx_fhaul);
|
||||
}
|
||||
|
||||
void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
|
||||
{
|
||||
ru_info_t ru_info;
|
||||
@@ -286,6 +297,8 @@ void *get_internal_parameter(char *name)
|
||||
return (void *)oran_fh_if4p5_south_in;
|
||||
if (!strcmp(name, "fh_if4p5_south_out"))
|
||||
return (void *)oran_fh_if4p5_south_out;
|
||||
if (!strcmp(name, "fh_if4p5_north_in"))
|
||||
return (void *)oran_fh_if4p5_north_in;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -363,6 +376,7 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d
|
||||
// create message queues for ORAN sync
|
||||
|
||||
initNotifiedFIFO(&oran_sync_fifo);
|
||||
initNotifiedFIFO(&dl_sync_fifo);
|
||||
|
||||
eth->e.flags = ETH_RAW_IF4p5_MODE;
|
||||
eth->e.compression = NO_COMPRESS;
|
||||
|
||||
@@ -51,6 +51,7 @@ typedef struct ru_info_s {
|
||||
* @param frame output of the frame which has been read.
|
||||
* @param slot output of the slot which has been read. */
|
||||
int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot);
|
||||
int xran_fh_tx_read_slot(ru_info_t *ru, int *frame, int *slot);
|
||||
/** @brief Writes TX data (PDSCH) of given slot. */
|
||||
int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp);
|
||||
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ( { sst = 1; }); });
|
||||
|
||||
nr_cellid = 1;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
pdsch_AntennaPorts_XP = 2;
|
||||
pdsch_AntennaPorts_N1 = 2;
|
||||
maxMIMO_layers = 2;
|
||||
pusch_AntennaPorts = 4;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
|
||||
pdcch_ConfigSIB1 = (
|
||||
{
|
||||
controlResourceSetZero = 11;
|
||||
searchSpaceZero = 0;
|
||||
}
|
||||
);
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
# n_TimingAdvanceOffset = 0;
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# center frequency = 3450.72 MHz
|
||||
# selected SSB frequency = 3450.72 MHz
|
||||
absoluteFrequencySSB = 630048;
|
||||
dl_frequencyBand = 78;
|
||||
# frequency point A = 3401.58 MHz
|
||||
dl_absoluteFrequencyPointA = 626772;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 273;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
initialDLBWPlocationAndBandwidth = 1099; #38.101-1 Table 5.3.2-1
|
||||
#
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 11;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 273;
|
||||
pMax = 23;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 1099;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 159;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 22;
|
||||
zeroCorrelationZoneConfig = 15;
|
||||
preambleReceivedTargetPower = -104;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 7;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 2;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 5;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
# this is the offset between the last PRACH preamble power and the Msg3 PUSCH, 2 times the field value in dB
|
||||
msg3_DeltaPreamble = 2;
|
||||
p0_NominalWithGrant = -96;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 0;
|
||||
p0_nominal = -96;
|
||||
|
||||
ssb_PositionsInBurst_Bitmap = 0x1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 5;
|
||||
nrofDownlinkSlots = 3;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 1;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = 0;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ({ ipv4 = "172.21.6.5"; });
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 200;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
# dl_bler_target_upper = .35;
|
||||
# dl_bler_target_lower = .15;
|
||||
ul_bler_target_upper = .35;
|
||||
ul_bler_target_lower = .15;
|
||||
pusch_FailureThres = 100;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 130
|
||||
pucch0_dtx_threshold = 80;
|
||||
pusch_dtx_threshold = 10;
|
||||
tx_amp_backoff_dB = 20; # needs to match O-RU configuration
|
||||
L1_rx_thread_core = -1;
|
||||
L1_tx_thread_core = -1;
|
||||
phase_compensation = 1; # needs to match O-RU configuration
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "no";
|
||||
nb_tx = 4;
|
||||
nb_rx = 4;
|
||||
att_tx = 0;
|
||||
att_rx = 0;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
sf_extension = 0;
|
||||
eNB_instances = [0];
|
||||
ru_thread_core = -1;
|
||||
sl_ahead = 5;
|
||||
tr_preference = "raw_if4p5"; # important: activate FHI7.2
|
||||
do_precoding = 0; # needs to match O-RU configuration
|
||||
}
|
||||
);
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level = "info";
|
||||
hw_log_level = "info";
|
||||
phy_log_level = "info";
|
||||
mac_log_level = "info";
|
||||
rlc_log_level = "info";
|
||||
pdcp_log_level = "info";
|
||||
rrc_log_level = "info";
|
||||
ngap_log_level = "info";
|
||||
f1ap_log_level = "info";
|
||||
};
|
||||
|
||||
fhi_72 = {
|
||||
dpdk_devices = ("vdev=net_memif1,bsize=1514,role=client,socket=/tmp/memif.sock");
|
||||
system_core = 0;
|
||||
io_core = 1;
|
||||
worker_cores = (2);
|
||||
ru_addr = ("00:00:00:00:00:01");
|
||||
file_prefix = "gnb";
|
||||
dpdk_mem_size = 0;
|
||||
mtu = 1514;
|
||||
fh_config = ({
|
||||
T1a_cp_dl = (285, 429);
|
||||
T1a_cp_ul = (285, 429);
|
||||
T1a_up = (96, 196);
|
||||
Ta4 = (110, 180);
|
||||
ru_config = {
|
||||
iq_width = 16;
|
||||
iq_width_prach = 16;
|
||||
};
|
||||
prach_config = {
|
||||
kbar = 0;
|
||||
};
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "no";
|
||||
nb_tx = 4;
|
||||
nb_rx = 4;
|
||||
att_tx = 0;
|
||||
att_rx = 0;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
sf_extension = 0;
|
||||
eNB_instances = [0];
|
||||
ru_thread_core = -1;
|
||||
sl_ahead = 5;
|
||||
tr_preference = "raw_if4p5"; # important: activate FHI7.2
|
||||
do_precoding = 0; # needs to match O-RU configuration
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level = "info";
|
||||
hw_log_level = "info";
|
||||
phy_log_level = "info";
|
||||
mac_log_level = "info";
|
||||
rlc_log_level = "info";
|
||||
pdcp_log_level = "info";
|
||||
rrc_log_level = "info";
|
||||
ngap_log_level = "info";
|
||||
f1ap_log_level = "info";
|
||||
};
|
||||
|
||||
fhi_72 = {
|
||||
dpdk_devices = ("vdev=net_memif0,bsize=1514,role=server,socket=/tmp/memif.sock"); # one VF can be used as well
|
||||
dpdk_iova_mode = "VA";
|
||||
system_core = 10;
|
||||
io_core = 12;
|
||||
worker_cores = (14);
|
||||
du_addr = ("46:bd:39:e7:c3:23");
|
||||
file_prefix = "ru";
|
||||
dpdk_mem_size = 0;
|
||||
mtu = 1514;
|
||||
fh_config = ({
|
||||
T1a_cp_dl = (285, 429);
|
||||
T1a_cp_ul = (285, 429);
|
||||
T1a_up = (96, 196);
|
||||
Ta4 = (110, 180);
|
||||
ru_config = {
|
||||
iq_width = 16;
|
||||
iq_width_prach = 16;
|
||||
};
|
||||
prach_config = {
|
||||
kbar = 0;
|
||||
};
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user