Merge branch 'integration_2024_w35' into 'develop'

Integration: `2024.w35`

Closes #825

See merge request oai/openairinterface5g!2943

* !2181 ULSCH power computation
* !2915 benchmark for rotate_cpx_vector
* !2936 Avoid complete rebuild on cmake run with git info change
* !2855 NR UE replace phy_config_request_sent
* !2937 small fixes for rfsim
* !2925 CI: Increase tested throughput in SA 2x2 pipeline
* !2934 Run optimized parity check in ldpc encoder only on supported Zc values
* !2912 changes for multi-RU support in fhi72
* !2928 Distribution check: check for F40, remove old U/RHEL releases
* !2913 NR gNB cleanup
* !2927 Update Aerial docs to reference current version
* !2940 remove double define with nr_common.h
This commit is contained in:
Robert Schmidt
2024-09-02 13:26:45 +00:00
64 changed files with 1384 additions and 936 deletions
+15 -17
View File
@@ -84,7 +84,6 @@ set (OPENAIR2_DIR ${OPENAIR_DIR}/openair2)
set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3)
set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3)
set (OPENAIR_CMAKE ${OPENAIR_DIR}/cmake_targets)
set (OPENAIR_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY})
project (OpenAirInterface)
@@ -254,12 +253,6 @@ if(GIT_FOUND)
)
endif()
# Below is a hard-coded info
set (FIRMWARE_VERSION "No svn information")
add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"")
add_definitions("-DPACKAGE_VERSION=\"Branch: ${GIT_BRANCH} Abrev. Hash: ${GIT_COMMIT_HASH} Date: ${GIT_COMMIT_DATE}\"")
add_definitions("-DPACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"")
# Debug related options
#########################################
add_boolean_option(DEBUG_ASN1 False "Enable ASN1 debug logs" OFF)
@@ -544,16 +537,8 @@ add_boolean_option(NAS_UE True "NAS UE INSTANCE (<> NAS_MME)"
add_boolean_option(RRC_DEFAULT_RAB_IS_AM True "set the LTE RLC mode to AM for the default bearer, otherwise it is UM." ON)
# add the binary tree to the search path for include files
#######################################################
# We will find ConfigOAI.h after generation in target directory
include_directories("${OPENAIR_BIN_DIR}")
# add directories to find all include files
# the internal rule is to use generic names such as defs.h
# but to make it uniq name as adding the relative path in the include directtive
# example: #include "RRC/LTE/rrc_defs.h"
#find_path (include_dirs_all *.h ${OPENAIR_DIR})
#find_path (include_dirs_all *.h PATHS /usr/include NO_CMAKE_PATH)
#include_directories("${include_dirs_all}")
# We will find common/oai_version.h after generation in target directory
include_directories(${CMAKE_CURRENT_BINARY_DIR})
# Legacy exact order
@@ -2367,6 +2352,19 @@ if(ENABLE_TESTS)
add_library(GTest::gtest ALIAS gtest)
add_library(GTest::gtest_main ALIAS gtest_main)
endif()
find_package(benchmark)
if (NOT benchmark_FOUND)
message(STATUS "benchmark package not found, will download benchmark automatically. To prevent that install google benchmark on your system (libbenchmark-dev)")
include(FetchContent)
set(BENCHMARK_ENABLE_TESTING OFF)
FetchContent_Declare(
benchmark
GIT_REPOSITORY https://github.com/google/benchmark.git
GIT_TAG v1.9.0
)
FetchContent_MakeAvailable(benchmark)
endif()
endif()
add_subdirectory(common)
@@ -212,7 +212,7 @@ RUs = (
att_rx = 0;
bands = [77];
max_pdschReferenceSignalPower = -27;
max_rxgain = 72;
max_rxgain = 75;
eNB_instances = [0];
##beamforming 1x2 matrix: 1 layer x 2 antennas
bf_weights = [0x00007fff, 0x0000];
@@ -106,12 +106,12 @@
<testCase id="071100">
<class>Iperf</class>
<desc>iperf (DL/500Mbps/UDP)(30 sec)(single-ue profile)</desc>
<iperf_args>-u -b 500M -t 30 -R -O 10 -l 9000</iperf_args>
<desc>iperf (DL/600Mbps/UDP)(30 sec)(single-ue profile)</desc>
<iperf_args>-u -b 600M -t 30 -R -O 10 -l 9000</iperf_args>
<svr_id>matix-cn5g</svr_id>
<id>up2</id>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>50</iperf_bitrate_threshold>
<iperf_bitrate_threshold>70</iperf_bitrate_threshold>
</testCase>
<testCase id="071101">
@@ -116,8 +116,8 @@
<testCase id="071001">
<class>Iperf</class>
<desc>iperf (UL/130Mbps/UDP)(30 sec)(single-ue profile)</desc>
<iperf_args>-u -b 130M -t 30</iperf_args>
<desc>iperf (UL/180Mbps/UDP)(30 sec)(single-ue profile)</desc>
<iperf_args>-u -b 180M -t 30</iperf_args>
<svr_id>matix-cn5g</svr_id>
<id>up2</id>
<iperf_packetloss_threshold>10</iperf_packetloss_threshold>
@@ -6,7 +6,6 @@ cuBB_Path="${cuBB_SDK:-/opt/nvidia/cuBB}"
cd "$cuBB_Path" || exit 1
# Add gdrcopy to LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/nvidia/lib:/usr/local/nvidia/lib64:/opt/mellanox/dpdk/lib/x86_64-linux-gnu:/opt/mellanox/doca/lib/x86_64-linux-gnu:/opt/nvidia/cuBB/cuPHY-CP/external/gdrcopy/build/x86_64/
export LD_LIBRARY_PATH=$LD_LIBRART_PATH:"$cuBB_Path/gpu-dpdk/build/install/lib/x86_64-linux-gnu:$cuBB_Path/build/cuPHY-CP/cuphydriver/src"
# Restart MPS
# Export variables
+11 -9
View File
@@ -79,17 +79,19 @@
<main_exec>ldpctest</main_exec>
<main_exec_args>-l3872 -s10 -n100
-l4224 -s10 -n100
-l4576 -s10 -n100
-l4928 -s10 -n100
-l5280 -s10 -n100
-l5632 -s10 -n100
-l6336 -s10 -n100
-l7040 -s10 -n100
-l7744 -s10 -n100
-l8448 -s10 -n100</main_exec_args>
-l4576 -s10 -n100
-l4928 -s10 -n100
-l5280 -s10 -n100
-l5632 -s10 -n100
-l6336 -s10 -n100
-l7040 -s10 -n100
-l7744 -s10 -n100
-l8448 -s10 -n100
-l561 -s10 -n1
-l500 -s10 -n1</main_exec_args>
<tags>test1 test2 test3 test4 test5 test6 test7 test8 test9 test10</tags>
<search_expr_true>BLER 0.000000</search_expr_true>
<search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
<search_expr_false>segmentation fault|assertion|exiting|fatal|differ</search_expr_false>
<nruns>3</nruns>
</testCase>
+7 -16
View File
@@ -34,7 +34,7 @@ case "$OS_DISTRO" in
fedora) OS_BASEDISTRO="fedora"; INSTALLER="dnf"; CMAKE="cmake" ;;
rhel) OS_BASEDISTRO="fedora"; INSTALLER="dnf"; CMAKE="cmake3" ;;
rocky) OS_BASEDISTRO="fedora"; INSTALLER="dnf"; CMAKE="cmake" ;;
centos) OS_BASEDISTRO="centos"; INSTALLER="yum"; CMAKE="cmake3" ;;
centos) OS_BASEDISTRO="fedora"; INSTALLER="dnf"; CMAKE="cmake3" ;; # CentOS Stream
debian) OS_BASEDISTRO="debian"; INSTALLER="apt-get"; CMAKE="cmake" ;;
ubuntu) OS_BASEDISTRO="debian"; INSTALLER="apt-get"; CMAKE="cmake" ;;
esac
@@ -104,18 +104,10 @@ check_supported_distribution() {
local distribution=$(get_distribution_release)
case "$distribution" in
"ubuntu24.04") return 0 ;;
"ubuntu23.10") return 0 ;;
"ubuntu22.04") return 0 ;;
"ubuntu21.04") return 0 ;;
"ubuntu20.04") return 0 ;;
"debian11") return 0 ;;
"fedora36") return 0 ;;
"fedora37") return 0 ;;
"rhel7") return 0 ;;
"rhel7.6") return 0 ;;
"rhel7.7") return 0 ;;
"rhel7.8") return 0 ;;
"rhel7.9") return 0 ;;
"fedora40") return 0 ;;
"rhel8.2") return 0 ;;
"rhel8.3") return 0 ;;
"rhel8.4") return 0 ;;
@@ -129,8 +121,7 @@ check_supported_distribution() {
"rhel9.2") return 0 ;;
"rhel9.3") return 0 ;;
"rhel9.4") return 0 ;;
"centos7") return 0 ;;
"centos8") return 0 ;;
"centos9") return 0 ;; # CentOS stream
"rocky8.7") return 0 ;;
"rocky8.8") return 0 ;;
"rocky8.9") return 0 ;;
@@ -388,16 +379,16 @@ install_usrp_uhd_driver() {
# On newer kernels, it fails to install
$SUDO apt-get -y install uhd-host
fi
# quick workaround for RHE7.6
# quick workaround for below distributions
local distribution=$(get_distribution_release)
if [ -z $1 ]; then
if [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "rocky" ]]; then
if [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "rocky" ]] || [[ "$OS_DISTRO" == "centos" ]]; then
$SUDO /usr/local/bin/uhd_images_downloader
else
$SUDO uhd_images_downloader
fi
else
if [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "rocky" ]]; then
if [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "rocky" ]] || [[ "$OS_DISTRO" == "centos" ]]; then
$SUDO /usr/local/bin/uhd_images_downloader -i $1
else
$SUDO uhd_images_downloader -i $1
@@ -537,7 +528,7 @@ check_install_additional_tools (){
local optional_packages=""
if [[ "$OS_BASEDISTRO" == "debian" ]]; then
case "$(get_distribution_release)" in
"ubuntu20.04" | "ubuntu21.04" | "ubuntu22.04" | "debian11" )
"ubuntu20.04" | "ubuntu22.04" | "debian11" )
optional_packages="python3 python3-pip python3-dev python3-scipy python3-matplotlib python3-pyroute2 universal-ctags"
;;
esac
+2
View File
@@ -1 +1,3 @@
add_subdirectory(utils)
configure_file(oai_version.h.in oai_version.h @ONLY)
+32
View File
@@ -0,0 +1,32 @@
/*
* 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
*/
#ifndef OAI_VERSION_H_
#define OAI_VERSION_H_
#define GIT_BRANCH "@GIT_BRANCH@"
#define GIT_COMMIT_HASH "@GIT_COMMIT_HASH@"
#define GIT_COMMIT_DATE "@GIT_COMMIT_DATE@"
#define OAI_FIRMWARE_VERSION GIT_COMMIT_HASH
#define OAI_PACKAGE_VERSION "Branch: " GIT_BRANCH " Abrev. Hash: " GIT_COMMIT_HASH " Date: " GIT_COMMIT_DATE
#endif /* OAI_VERSION_H_ */
+1 -1
View File
@@ -6,7 +6,7 @@ int load_module_shlib(char *modname,loader_shlibfunc_t *farray, int numf)
* Formats the full shared library path, using the `modname` argument and the loader `shlibpath` and `shlibversion`configuration parameters.
* loads the shared library, using the dlopen system call
* looks for `< modname >_autoinit` symbol, using the `dlsym` system call and possibly call the corresponding function.
* looks for `< modname >_checkbuildver` symbol, using the `dlsym` system call and possibly calls the corresponding function. If the return value of this call is `-1`, program execution is stopped. It is the responsibility of the shared library developer to implement or not a `< modname >_checkbuildver` function and to decide if a version mismatch is a fatal condition. The `< modname >_checkbuildver` function must match the `checkverfunc_t` function type. The first argument is the main executable version, as set in the `PACKAGE_VERSION` macro defined in the [oai CMakeLists](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/CMakeLists.txt#L218), around line 218. The second argument points to the shared library version which should be set by the `< modname >_checkbuildver` function.
* looks for `< modname >_checkbuildver` symbol, using the `dlsym` system call and possibly calls the corresponding function. If the return value of this call is `-1`, program execution is stopped. It is the responsibility of the shared library developer to implement or not a `< modname >_checkbuildver` function and to decide if a version mismatch is a fatal condition. The `< modname >_checkbuildver` function must match the `checkverfunc_t` function type. The first argument is the main executable version, as set in the `OAI_PACKAGE_VERSION` macro defined in the [`common/CMakeLists`](../../../CMakeLists). The second argument points to the shared library version which should be set by the `< modname >_checkbuildver` function.
* If the farray pointer is null, looks for `< modname >_getfarray` symbol, calls the corresponding function when the symbol is found. `< modname >_getfarray` takes one argument, a pointer to a `loader_shlibfunc_t` array, and returns the number of items in this array, as defined by the `getfarrayfunc_t` type. The `loader_shlibfunc_t` array returned by the shared library must be fully filled (both `fname` and `fptr` fields).
* looks for the `numf` function symbols listed in the `farray[i].fname` arguments and set the corresponding `farray[i].fptr`function pointers
+2 -1
View File
@@ -38,6 +38,7 @@
#include <sys/ioctl.h>
#include <dlfcn.h>
#include "openair1/PHY/defs_common.h"
#include "common/oai_version.h"
#define LOAD_MODULE_SHLIB_MAIN
#include "common/config/config_userapi.h"
@@ -45,7 +46,7 @@
void loader_init(void) {
paramdef_t LoaderParams[] = LOADER_PARAMS_DESC;
loader_data.mainexec_buildversion = PACKAGE_VERSION;
loader_data.mainexec_buildversion = OAI_PACKAGE_VERSION;
int ret = config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), LOADER_CONFIG_PREFIX);
if (ret <0) {
printf("[LOADER] configuration couldn't be performed via config module, parameters set to default values\n");
+2 -4
View File
@@ -56,6 +56,7 @@
#include "common/utils/threadPool/thread-pool.h"
#include "executables/softmodem-common.h"
#include <readline/history.h>
#include "common/oai_version.h"
#include "telnetsrv_phycmd.h"
@@ -938,10 +939,7 @@ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmdde
against main exec version. version mismatch not considered as fatal (interfaces not supposed to change)
*/
int telnetsrv_checkbuildver(char *mainexec_buildversion, char **shlib_buildversion) {
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "standalone built: " __DATE__ __TIME__
#endif
*shlib_buildversion = PACKAGE_VERSION;
*shlib_buildversion = OAI_PACKAGE_VERSION;
if (strcmp(mainexec_buildversion, *shlib_buildversion) != 0) {
fprintf(stderr,"[TELNETSRV] shared lib version %s, doesn't match main version %s, compatibility should be checked\n",
+3 -3
View File
@@ -87,6 +87,6 @@ add_custom_target(
add_dependencies(websrv websrvfront)
# copy frontend files to a websrv subdirectory of where oai copy all built files
add_custom_command(TARGET websrvfront
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/frontend/dist/softmodem-ngx ${OPENAIR_BIN_DIR}/../websrv
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/helpfiles ${OPENAIR_BIN_DIR}/../websrv/helpfiles
COMMENT "Moving frontend files to:\n ${OPENAIR_BIN_DIR}/../websrv \n " )
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/frontend/dist/softmodem-ngx ${CMAKE_CURRENT_BINARY_DIR}/../websrv
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/helpfiles ${CMAKE_CURRENT_BINARY_DIR}/../websrv/helpfiles
COMMENT "Moving frontend files to: ${CMAKE_CURRENT_BINARY_DIR}/../websrv" )
+41 -17
View File
@@ -50,6 +50,7 @@ The UEs that have been tested and confirmed working with Aerial are the followin
|-----------------|-------------------------------|
| Sierra Wireless | EM9191 |
| Quectel | RM500Q-GL |
| Quectel | RM520N-GL |
| Apaltec | Tributo 5G-Dongle |
| OnePlus | Nord (AC2003) |
| Apple iPhone | 14 Pro (MQ0G3RX/A) (iOS 17.3) |
@@ -59,9 +60,9 @@ The UEs that have been tested and confirmed working with Aerial are the followin
The first step is to obtain the NVIDIA Aerial SDK, you'll need to request access [here](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/aerial-sdk).
After obtaining access to the SDK, you can refer to [this instructions page](https://docs.nvidia.com/aerial/aerial-research-cloud/current/index.html) to setup the L1 components using NVIDIAs' SDK manager, or to [this instructions page](https://developer.nvidia.com/docs/gputelecom/aerial-sdk/aerial-sdk-archive/aerial-sdk-23-2/index.html) in order to setup and install the components manually.
After obtaining access to the SDK, you can refer to [this instructions page](https://docs.nvidia.com/aerial/aerial-ran-colab-ota/current/index.html) to setup the L1 components using NVIDIAs' SDK manager, or to [this instructions page](https://docs.nvidia.com/aerial/cuda-accelerated-ran/index.html) in order to setup and install the components manually.
The currently used Aerial Version is 23-2, which is also the one currently used by the SDK Manager.
The currently used Aerial Version is 24-1, which is also the one currently used by the SDK Manager.
### CPU allocation
@@ -139,7 +140,7 @@ After=ptp4l.service
Restart=always
RestartSec=5s
Type=simple
ExecStart=/usr/sbin/phc2sys -a -r -r -n 24
ExecStart=/usr/sbin/phc2sys -a -r -n 24
[Install]
WantedBy=multi-user.target
@@ -154,7 +155,6 @@ Clone OAI code base in a suitable repository, here we are cloning in `~/openairi
```bash
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
cd ~/openairinterface5g/
git checkout Aerial_Integration
```
## Get nvIPC sources from the L1 container
@@ -174,27 +174,44 @@ If it is not running, you may start it and logging into the container by running
~$ docker start cuBB
cuBB
~$ docker exec -it cuBB bash
root@c_aerial_aerial:/opt/nvidia/cuBB#
aerial@c_aerial_aerial:/opt/nvidia/cuBB#
```
After logging into the container, we need to pack the nvIPC sources and copy them to the host ( the command creates a tar.gz file with the following name format: nvipc_src.yyyy.mm.dd.tar.gz)
After logging into the container, we need to pack the nvIPC sources and copy them to the host ( the command creates a tar.gz file with the following name format: nvipc_src.YYYY.MM.DD.tar.gz)
```bash
~$ docker exec -it cuBB bash
root@c_aerial_aerial:/opt/nvidia/cuBB# cd cuPHY-CP/gt_common_libs
root@c_aerial_aerial:/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs#./pack_nvipc.sh
nvipc_src.****.**.**/
aerial@c_aerial_aerial:/opt/nvidia/cuBB# cd cuPHY-CP/gt_common_libs
aerial@c_aerial_aerial:/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs#./pack_nvipc.sh
nvipc_src.YYYY.MM.DD/
...
---------------------------------------------
Pack nvipc source code finished:
/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs/nvipc_src.****.**.**.tar.gz
root@c_aerial_aerial:/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs# cp nvipc_src.****.**.**.tar.gz /opt/cuBB/share/
root@c_aerial_aerial:/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs# exit
/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs/nvipc_src.YYYY.MM.DD.tar.gz
aerial@c_aerial_aerial:/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs# sudo cp nvipc_src.yyyy.mm.dd.tar.gz /opt/cuBB/share/
aerial@c_aerial_aerial:/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs# exit
```
The file should now be present in the `~/openairinterface5g/ci-scripts/yaml_files/sa_gnb_aerial/` directory, from where it is moved into `~/openairinterface5g`
```bash
~$ mv ~/openairinterface5g/ci-scripts/yaml_files/sa_gnb_aerial/nvipc_src.****.**.**.tar.gz ~/openairinterface5g/
~$ mv ~/openairinterface5g/ci-scripts/yaml_files/sa_gnb_aerial/nvipc_src.YYYY.MM.DD.tar.gz ~/openairinterface5g/
```
Alternatively, after running `./pack_nvipc.sh` , you can exit the container and copy `nvipc_src.YYYY.MM.DD.tar.gz` using `docker cp`
```bash
~$ docker exec -it cuBB bash
aerial@c_aerial_aerial:/opt/nvidia/cuBB# cd cuPHY-CP/gt_common_libs
aerial@c_aerial_aerial:/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs#./pack_nvipc.sh
nvipc_src.YYYY.MM.DD/
...
---------------------------------------------
Pack nvipc source code finished:
/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs/nvipc_src.YYYY.MM.DD.tar.gz
aerial@c_aerial_aerial:/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs# exit
~$ docker cp nv-cubb:/opt/nvidia/cuBB/cuPHY-CP/gt_common_libs/nvipc_src.YYYY.MM.DD.tar.gz ~/openairinterface5g
```
*Important note:* For using docker cp, make sure to copy the entire name of the created nvipc_src tar.gz file.
With the nvIPC sources in the project directory, the docker image can be built.
## Building OAI gNB docker image
@@ -213,11 +230,14 @@ The process of preparing the L1 is covered on NVIDIAs' documentation, and falls
### Prepare the L1 image
After preparing the L1 software, the container needs to be committed in order for an image in which the L1 is ready to be executed, and that can be referenced by a docker-compose.yaml file later:
*Note:* In preparing the L1 image, the default L1 configuration file is cuphycontroller_P5G_FXN.yaml, located in `/opt/nvidia/cuBB/cuPHY-CP/cuphycontroller/config/`.
This is the file where the RU MAC address needs to be applied before commiting the image
```bash
~$ docker commit nv-cubb cubb-build:23-2
~$ docker commit nv-cubb cubb-build:24-1
~$ docker image ls
..
cubb-build 23-2 824156e0334c 2 weeks ago 40.1GB
cubb-build 24-1 824156e0334c 2 weeks ago 40.1GB
..
```
@@ -237,8 +257,12 @@ Both 'GNB_IPV4_ADDRESS_FOR_NG_AMF' and 'GNB_IPV4_ADDRESS_FOR_NGU' need to be set
### Running docker compose
#### Aerial L1 entrypoint script
Before running docker-compose, we can check which L1 configuration file is to be used by cuphycontroller_scf, this is set in the script [`aerial_l1_entrypoint.sh`](../ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh), which is used by the L1 container in order to start the L1 software, this begins by installing a module 'gdrcopy', setting up some environment variables, restarting NVIDIA MPS, and finally running cuphycontroller with an argument that represent which L1 configuration file is to be used, this argument may be changed by providing an argument in docker-compose.yaml.
When no argument is provided (this is the default behaviour), it uses "P5G_SCF_FXN" as a cuphycontroller_scf argument.
Before running docker-compose, we can check which L1 configuration file is to be used by cuphycontroller_scf.
This is set in the script [`aerial_l1_entrypoint.sh`](../ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh), which is used by the L1 container in order to start the L1 software.
The script begins by setting up some environment variables, restarting NVIDIA MPS, and finally running cuphycontroller_scf.
The L1 software is run with an argument that indicates which configuration file is to be used.
This argument may be changed by providing an argument to the [`aerial_l1_entrypoint.sh`](../ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh) call in [`docker-compose.yaml`](../ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml).
When no argument is provided (this is the default behaviour), it uses "P5G_FXN" as the cuphycontroller_scf argument.
After building the gNB image, and preparing the configuration file, the setup can be run with the following command:
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = OpenAirInterface
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER =
PROJECT_NUMBER = @GIT_COMMIT_HASH@ (@GIT_BRANCH@)
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
+138 -1
View File
@@ -626,7 +626,7 @@ In the following, we will use these short hands:
- `du-u-plane-mac-addr`: DU U plane MAC address
- `pci-address-u-plane-vf`: PCI bus address of the VF for U plane
In the configuration file, in option `fhi_72.dpdk_devices`, the first PCI address is for C-plane and the second for U-plane.
In the configuration file, in option `fhi_72.dpdk_devices`, the first PCI address is for U-plane and the second for C-plane.
For both the MAC addresses, you might use the MAC addresses which are
pre-configured in the RUs (typically `00:11:22:33:44:66`, but that is not
@@ -891,6 +891,143 @@ do not do any jumps (during the last hour). While an occasional jump is not
necessarily problematic for the gNB, many such messages mean that the system is
not working, and UEs might not be able to attach or reach good performance.
# Operation with multiple RUs
It is possible to connect up to 4 RUs to one DU at the same time and operate
them as a (single) distributed antenna (array). This works since all RUs and
the DU are synchronized onto a common clock using PTP. The assumed
configuration is that with N RUs each having an M×M configuration, we
effectively reach an (N×M)×(N×M) configuration.
Some caveats:
- Since it's a distributed antenna, this implies that this setup will deploy a
single cell only -- multiple cells on different RUs are not supported.
- All RUs should use the same MTU, so either "normal" (1500 byte) MTU or jumbo
frames, but not a mix of both.
- We tested only two RUs as of now, i.e., an 8×8 configuration.
- Testing is currently limited to 4 logical antenna ports in DL; in UL, up to 8 can be used.
For two RUs each using a 4x4 configuration, make sure to configure the 8x8
configuration, i.e., set `nb_tx` and `nb_rx` under `RUs` to 8 each (NOT two
RUs!). Also, set the antenna port information as listed above, i.e.,
```
pdsch_AntennaPorts_XP = 2;
pdsch_AntennaPorts_N1 = 2;
pusch_AntennaPorts = 8;
maxMIMO_layers = 2;
```
Once testing for 8 antenna ports in DL is complete, we will change pdsch_AntennaPorts_N1 to 4.
Next, configure the `fhi_72` section as indicated below:
```
fhi_72 = {
dpdk_devices = ("ru1_up_vf_pci", "ru1_cp_vf_pci", "ru2_up_vf_pci", "ru2_cp_vf_pci");
// core config as always
du_addr = ("du_ru1_up_mac_addr", "du_ru1_cp_mac_addr", "du_ru2_up_mac_addr", "du_ru2_cp_mac_addr");
ru_addr = ("ru1_up_mac_addr", "ru1_cp_mac_addr", "ru2_up_mac_addr", "ru2_cp_mac_addr");
// mtu, file_prefix ...
fh_config = (
{
// timing, ru_config, prach_config of RU1
},
{
// timing, ru_config, prach_config of RU2
}
);
};
```
i.e., for `dpdk_devices`, `du_addr`, and `ru_addr` is configured for
both RUs in a (flat) array, and the individual radio configuration is given for
each RU individually inside the `fh_config`.
<details>
<summary>Sample FHI 7.2 configuration for two RUs (Benetel 550 and 650)</summary>
```
fhi_72 = {
dpdk_devices = ("0000:01:01.0", "0000:01:01.1", "0000:01:01.2", "0000:01:01.3");
system_core = 0;
io_core = 1;
worker_cores = (2);
du_addr = ("00:11:22:33:44:66","00:11:22:33:44:67","00:11:22:33:44:66","00:11:22:33:44:67");
ru_addr = ("70:b3:d5:e1:5b:ff","70:b3:d5:e1:5b:ff","70:b3:d5:e1:5b:81", "70:b3:d5:e1:5b:81");
mtu = 9216;
file_prefix = "fhi_72";
fh_config = (
# RAN650
{
Tadv_cp_dl = 125;
T2a_cp_dl = (259, 500);
T2a_cp_ul = (25, 500);
T2a_up = (134, 375);
Ta3 = (152, 160);
T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336);
T1a_up = (294, 345);
Ta4 = (0, 200);
ru_config = {
iq_width = 9;
iq_width_prach = 9;
};
prach_config = {
eAxC_offset = 4;
};
},
# RAN550
{
Tadv_cp_dl = 125;
T2a_cp_dl = (259, 500);
T2a_cp_ul = (25, 500);
T2a_up = (134, 375);
Ta3 = (152, 160);
T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336);
T1a_up = (294, 345);
Ta4 = (0, 200);
ru_config = {
iq_width = 9;
iq_width_prach = 9;
};
prach_config = {
eAxC_offset = 4;
};
});
```
</details>
Compare also with the example (DU) configuration in
[`gnb-du.sa.band78.106prb.fhi72.8x8-benetel-650-550.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.fhi72.8x8-benetel-650-550.conf).
Afterwards, start the gNB with the modified configuration file. If everything
went well, you should see the RU counters for both RUs go up:
```
[NR_PHY] [o-du 0][rx 614400 pps 61440 kbps 844953][tx 1275076 pps 127488 kbps 1998585][Total Msgs_Rcvd 614400]
[NR_PHY] [o_du0][pusch0 107520 prach0 46080]
[NR_PHY] [o_du0][pusch1 107520 prach1 46080]
[NR_PHY] [o_du0][pusch2 107520 prach2 46080]
[NR_PHY] [o_du0][pusch3 107520 prach3 46080]
[NR_PHY] [o-du 1][rx 614400 pps 61440 kbps 844953][tx 1275076 pps 127488 kbps 1998585][Total Msgs_Rcvd 614400]
[NR_PHY] [o_du1][pusch0 107520 prach0 46080]
[NR_PHY] [o_du1][pusch1 107520 prach1 46080]
[NR_PHY] [o_du1][pusch2 107520 prach2 46080]
[NR_PHY] [o_du1][pusch3 107520 prach3 46080]
```
You can also verify that there is signal on all RX antennas like so:
```bash
$ cat nrL1_stats.log
[...]
max_IO = 66 (81), min_I0 = 0 (53), avg_I0 = 51 dB(46.48.45.46.51.56.55.45.)
PRACH I0 = 38.0 dB
```
Note the eight entries after `avg_IO`.
You should be able to connect a UE now.
# Contact in case of questions
+62
View File
@@ -107,3 +107,65 @@ that directory directly, which you might also use to compare to the
slight complication is due to using shell scripts. An easier way is to
directly declare the executable in `add_test()`, and `ctest` will locate and
run the executable properly.
# Benchmarking
Google benchmark can be used to profile and benchmark small pieces of code. See
`benchmark_rotate_vector` for reference implementation. To start benchmarking code,
write a benchmark first and compare your implementation against baseline result.
To ensure your results are reproducible see this [guide](https://github.com/google/benchmark/blob/main/docs/reducing_variance.md)
Example output follows:
```bash
2024-08-26T11:55:49+02:00
Running ./openair1/PHY/TOOLS/tests/benchmark_rotate_vector
Run on (8 X 4700 MHz CPU s)
CPU Caches:
L1 Data 48 KiB (x4)
L1 Instruction 32 KiB (x4)
L2 Unified 1280 KiB (x4)
L3 Unified 12288 KiB (x1)
Load Average: 0.51, 0.31, 0.29
***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead.
---------------------------------------------------------------------
Benchmark Time CPU Iterations
---------------------------------------------------------------------
BM_rotate_cpx_vector/100 43.1 ns 43.1 ns 16683136
BM_rotate_cpx_vector/256 70.1 ns 70.0 ns 9647446
BM_rotate_cpx_vector/1024 277 ns 277 ns 2378273
BM_rotate_cpx_vector/4096 1070 ns 1070 ns 654792
BM_rotate_cpx_vector/16384 4220 ns 4220 ns 169070
BM_rotate_cpx_vector/20000 5288 ns 5289 ns 136190
```
## Comparing results
Benchmark results can be output to json by using command line arguments, example below
```bash
./benchmark_rotate_vector --benchmark_out=file.json --benchmark_repetitions=10
```
These results can be compared by a tool provided with google benchmark
```bash
./compare.py benchmarks ../../file.json ../../file1.json
```
Example output:
```
Comparing ../../file.json to ../../file1.json
Benchmark Time CPU Time Old Time New CPU Old CPU New
--------------------------------------------------------------------------------------------------------------------------------
BM_rotate_cpx_vector/100 +0.3383 +0.3384 43 58 43 58
BM_rotate_cpx_vector/100 +0.2334 +0.2335 42 52 42 52
BM_rotate_cpx_vector/100 +0.1685 +0.1683 42 49 42 49
BM_rotate_cpx_vector/100 +0.1890 +0.1889 42 50 42 50
BM_rotate_cpx_vector/100 +0.0456 +0.0457 42 44 42 44
BM_rotate_cpx_vector/100 +0.0163 +0.0162 42 42 42 42
BM_rotate_cpx_vector/100 +0.0005 +0.0004 43 43 43 43
BM_rotate_cpx_vector/100 +0.0134 +0.0129 43 43 43 43
BM_rotate_cpx_vector/100 +0.0162 +0.0162 42 42 42 42
BM_rotate_cpx_vector/100 +0.0003 +0.0003 42 42 42 42
```
+2 -4
View File
@@ -37,6 +37,7 @@
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#include "assertions.h"
#include "common/oai_version.h"
#include "PHY/types.h"
@@ -466,11 +467,8 @@ int main ( int argc, char **argv )
init_opt();
// to make a graceful exit when ctrl-c is pressed
set_softmodem_sighandler();
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
// strdup to put the sring in the core file for post mortem identification
LOG_I(HW, "Version: %s\n", strdup(PACKAGE_VERSION));
LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION));
/* Read configuration */
if (RC.nb_inst > 0) {
+2 -4
View File
@@ -42,6 +42,7 @@
#include "pdcp.h"
#include "PHY/defs_UE.h"
#include "common/oai_version.h"
#include "common/ran_context.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
@@ -575,11 +576,8 @@ int main( int argc, char **argv ) {
pdcp_pc5_socket_init();
// to make a graceful exit when ctrl-c is pressed
set_softmodem_sighandler();
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
// strdup to put the sring in the core file for post mortem identification
LOG_I(HW, "Version: %s\n", strdup(PACKAGE_VERSION));
LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION));
// init the parameters
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+2 -4
View File
@@ -41,6 +41,7 @@
#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"
@@ -160,11 +161,8 @@ int main ( int argc, char **argv )
T_Config_Init();
#endif
printf("configuring for RRU\n");
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
// strdup to put the sring in the core file for post mortem identification
LOG_I(HW, "Version: %s\n", strdup(PACKAGE_VERSION));
LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION));
/* Read configuration */
+2 -4
View File
@@ -19,6 +19,7 @@
* contact@openairinterface.org
*/
#include "common/oai_version.h"
#include "common/utils/simple_executable.h"
#include "executables/softmodem-common.h"
#include "common/utils/ocp_itti/intertask_interface.h"
@@ -156,11 +157,8 @@ int main(int argc, char **argv)
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
}
logInit();
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
// strdup to put the sring in the core file for post mortem identification
LOG_I(HW, "Version: %s\n", strdup(PACKAGE_VERSION));
LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION));
set_softmodem_sighandler();
itti_init(TASK_MAX, tasks_info);
int rc;
+1 -2
View File
@@ -497,8 +497,7 @@ void init_gNB(int wait_for_sync) {
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 = RC.gNB[inst];
/*nr_polar_init(&gNB->nrPolar_params,
NR_POLAR_PBCH_MESSAGE_TYPE,
NR_POLAR_PBCH_PAYLOAD_BITS,
+2 -9
View File
@@ -28,6 +28,7 @@
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#include <common/utils/assertions.h>
#include "common/oai_version.h"
#include "PHY/types.h"
#include "common/ran_context.h"
@@ -162,11 +163,6 @@ void pdcp_run(const protocol_ctxt_t *const ctxt_pP)
abort();
}
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
* this is very hackish - find a proper solution
*/
uint8_t abstraction_flag=0;
/* forward declarations */
void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
@@ -644,11 +640,8 @@ int main( int argc, char **argv ) {
// initialize mscgen log after ITTI
init_opt();
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
// strdup to put the sring in the core file for post mortem identification
char *pckg = strdup(PACKAGE_VERSION);
char *pckg = strdup(OAI_PACKAGE_VERSION);
LOG_I(HW, "Version: %s\n", pckg);
// don't create if node doesn't connect to RRC/S1/GTP
+2 -5
View File
@@ -445,10 +445,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action)
radio_tx_burst_flag_t flags = TX_BURST_INVALID;
NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
if (mac->phy_config_request_sent &&
openair0_cfg[0].duplex_mode == duplex_mode_TDD &&
!get_softmodem_params()->continuous_tx) {
if (UE->received_config_request && openair0_cfg[0].duplex_mode == duplex_mode_TDD && !get_softmodem_params()->continuous_tx) {
// In case of Sidelink, USRP write needed only in case transmission
// needs to be done in this slot and not based on tdd ULDL configuration.
if (UE->sl_mode == 2) {
@@ -930,7 +927,7 @@ void *UE_thread(void *arg)
curMsg.proc.nr_slot_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
curMsg.proc.frame_rx = (absolute_slot / nb_slot_frame) % MAX_FRAME_NUMBER;
curMsg.proc.frame_tx = ((absolute_slot + DURATION_RX_TO_TX) / nb_slot_frame) % MAX_FRAME_NUMBER;
if (mac->phy_config_request_sent) {
if (UE->received_config_request) {
if (UE->sl_mode) {
curMsg.proc.rx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_rx, TDD);
curMsg.proc.tx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_tx, TDD);
+2 -9
View File
@@ -26,6 +26,7 @@
#include <signal.h>
#include "T.h"
#include "common/oai_version.h"
#include "assertions.h"
#include "PHY/types.h"
#include "PHY/defs_nr_UE.h"
@@ -430,11 +431,8 @@ int main(int argc, char **argv)
if (ouput_vcd) {
vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd");
}
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
// strdup to put the sring in the core file for post mortem identification
char *pckg = strdup(PACKAGE_VERSION);
char *pckg = strdup(OAI_PACKAGE_VERSION);
LOG_I(HW, "Version: %s\n", pckg);
PHY_vars_UE_g = malloc(sizeof(*PHY_vars_UE_g) * NB_UE_INST);
@@ -493,11 +491,7 @@ int main(int argc, char **argv)
get_softmodem_params()->numerology,
nr_band);
} else {
DevAssert(mac->if_module != NULL && mac->if_module->phy_config_request != NULL);
mac->if_module->phy_config_request(&mac->phy_config);
mac->phy_config_request_sent = true;
fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config;
nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, mac->nr_band);
}
@@ -511,7 +505,6 @@ int main(int argc, char **argv)
phycfg->sl_config_req.sl_carrier_config.sl_num_rx_ant = get_nrUE_params()->nb_antennas_rx;
phycfg->sl_config_req.sl_carrier_config.sl_num_tx_ant = get_nrUE_params()->nb_antennas_tx;
mac->if_module->sl_phy_config_request(phycfg);
mac->phy_config_request_sent = true;
sl_nr_ue_phy_params_t *sl_phy = &UE[CC_id]->SL_UE_PHY_PARAMS;
nr_init_frame_parms_ue_sl(&sl_phy->sl_frame_params,
&sl_phy->sl_config,
+2 -3
View File
@@ -260,9 +260,8 @@ void oai_create_gnb(void) {
PHY_VARS_gNB *gNB = RC.gNB[0];
RC.nb_nr_CC = (int *)malloc(sizeof(int)); // TODO: find a better function to place this in
gNB->Mod_id = bodge_counter;
gNB->CC_id = bodge_counter;
gNB->abstraction_flag = 0;
gNB->Mod_id = bodge_counter;
gNB->CC_id = bodge_counter;
RC.nb_nr_CC[bodge_counter] = 1;
if (gNB->if_inst==0) {
+1 -1
View File
@@ -31,7 +31,7 @@ PROJECT_NAME = @PACKAGE_NAME@
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = @PACKAGE_VERSION@
PROJECT_NUMBER = @GIT_COMMIT_HASH@
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer
+2 -4
View File
@@ -33,6 +33,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "common/oai_version.h"
#include "PHY/sse_intrin.h"
@@ -359,10 +360,7 @@ void init_encoder_sse (void) {
against main exec version. version mismatch no considered as fatal (interfaces not supposed to change)
*/
int coding_checkbuildver(char *mainexec_buildversion, char **shlib_buildversion) {
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "standalone built: " __DATE__ __TIME__
#endif
*shlib_buildversion = PACKAGE_VERSION;
*shlib_buildversion = OAI_PACKAGE_VERSION;
if (strcmp(mainexec_buildversion, *shlib_buildversion) != 0) {
fprintf(stderr,"[CODING] shared lib version %s, doesn't match main version %s, compatibility should be checked\n",
@@ -85,138 +85,119 @@
#include "ldpc_BG2_Zc80_byte.c"
#include "ldpc_BG2_Zc72_byte.c"
static void encode_parity_check_part_optim(uint8_t *cc,uint8_t *d, short BG,short Zc,short Kb, int simd_size, int ncols)
static void encode_parity_check_part_optim(uint8_t *cc, uint8_t *d, short BG,short Zc,short Kb, int simd_size, int ncols)
{
unsigned char c[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c
for (int i1=0; i1 < ncols; i1++) {
memcpy(&c[2*i1*Zc], &cc[i1*Zc], Zc*sizeof(unsigned char));
memcpy(&c[(2*i1+1)*Zc], &cc[i1*Zc], Zc*sizeof(unsigned char));
unsigned char c[2 * 22 * Zc * simd_size] __attribute__((aligned(32))); //double size matrix of c
for (int i1 = 0; i1 < ncols; i1++) {
memcpy(&c[2 * i1 * Zc], &cc[i1 * Zc], Zc * sizeof(unsigned char));
memcpy(&c[(2 * i1 + 1) * Zc], &cc[i1 * Zc], Zc * sizeof(unsigned char));
}
for (int i1=1;i1<simd_size;i1++) {
memcpy(&c[(2*ncols*Zc*i1)], &c[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
for (int i1 = 1; i1 < simd_size; i1++) {
memcpy(&c[(2 * ncols * Zc * i1)], &c[i1], (2 * ncols * Zc * sizeof(unsigned char)) - i1);
}
if (BG==1)
{
switch (Zc)
{
case 2: break;
case 3: break;
case 4: break;
case 5: break;
case 6: break;
case 7: break;
case 8: break;
case 9: break;
case 10: break;
case 11: break;
case 12: break;
case 13: break;
case 14: break;
case 15: break;
case 16: break;
case 18: break;
case 20: break;
case 22: break;
case 24: break;
case 26: break;
case 28: break;
case 30: break;
case 32: break;
case 36: break;
case 40: break;
case 44: break;
case 48: break;
case 52: break;
case 56: break;
case 60: break;
case 64: break;
case 72: break;
case 80: break;
case 88: break;
case 96: break;
case 104: break;
case 112: break;
case 120: break;
case 128: break;
case 144: break;
case 160: break;
case 176: ldpc176_byte(c,d); break;
case 192: ldpc192_byte(c,d); break;
case 208: ldpc208_byte(c,d); break;
case 224: ldpc224_byte(c,d); break;
case 240: ldpc240_byte(c,d); break;
case 256: ldpc256_byte(c,d); break;
case 288: ldpc288_byte(c,d); break;
case 320: ldpc320_byte(c,d); break;
case 352: ldpc352_byte(c,d); break;
case 384: ldpc384_byte(c,d); break;
default: AssertFatal(0,"BG %d Zc %d is not supported yet\n",BG,Zc); break;
if (BG == 1) {
switch (Zc) {
case 176:
ldpc176_byte(c, d);
break;
case 192:
ldpc192_byte(c, d);
break;
case 208:
ldpc208_byte(c, d);
break;
case 224:
ldpc224_byte(c, d);
break;
case 240:
ldpc240_byte(c, d);
break;
case 256:
ldpc256_byte(c, d);
break;
case 288:
ldpc288_byte(c, d);
break;
case 320:
ldpc320_byte(c, d);
break;
case 352:
ldpc352_byte(c, d);
break;
case 384:
ldpc384_byte(c, d);
break;
default:
AssertFatal(false, "BG %d Zc %d is not supported yet\n", BG, Zc);
}
}
else if (BG==2) {
switch (Zc)
{
case 2: break;
case 3: break;
case 4: break;
case 5: break;
case 6: break;
case 7: break;
case 8: break;
case 9: break;
case 10: break;
case 11: break;
case 12: break;
case 13: break;
case 14: break;
case 15: break;
case 16: break;
case 18: break;
case 20: break;
case 22: break;
case 24: break;
case 26: break;
case 28: break;
case 30: break;
case 32: break;
case 36: break;
case 40: break;
case 44: break;
case 48: break;
case 52: break;
case 56: break;
case 60: break;
case 64: break;
case 72: ldpc_BG2_Zc72_byte(c,d); break;
case 80: ldpc_BG2_Zc80_byte(c,d); break;
case 88: ldpc_BG2_Zc88_byte(c,d); break;
case 96: ldpc_BG2_Zc96_byte(c,d); break;
case 104: ldpc_BG2_Zc104_byte(c,d); break;
case 112: ldpc_BG2_Zc112_byte(c,d); break;
case 120: ldpc_BG2_Zc120_byte(c,d); break;
case 128: ldpc_BG2_Zc128_byte(c,d); break;
case 144: ldpc_BG2_Zc144_byte(c,d); break;
case 160: ldpc_BG2_Zc160_byte(c,d); break;
case 176: ldpc_BG2_Zc176_byte(c,d); break;
case 192: ldpc_BG2_Zc192_byte(c,d); break;
case 208: ldpc_BG2_Zc208_byte(c,d); break;
case 224: ldpc_BG2_Zc224_byte(c,d); break;
case 240: ldpc_BG2_Zc240_byte(c,d); break;
case 256: ldpc_BG2_Zc256_byte(c,d); break;
case 288: ldpc_BG2_Zc288_byte(c,d); break;
case 320: ldpc_BG2_Zc320_byte(c,d); break;
case 352: ldpc_BG2_Zc352_byte(c,d); break;
case 384: ldpc_BG2_Zc384_byte(c,d); break;
default: AssertFatal(0,"BG %d Zc %d is not supported yet\n",BG,Zc); break;
} else if (BG == 2) {
switch (Zc) {
case 72:
ldpc_BG2_Zc72_byte(c, d);
break;
case 80:
ldpc_BG2_Zc80_byte(c, d);
break;
case 88:
ldpc_BG2_Zc88_byte(c, d);
break;
case 96:
ldpc_BG2_Zc96_byte(c, d);
break;
case 104:
ldpc_BG2_Zc104_byte(c, d);
break;
case 112:
ldpc_BG2_Zc112_byte(c, d);
break;
case 120:
ldpc_BG2_Zc120_byte(c, d);
break;
case 128:
ldpc_BG2_Zc128_byte(c, d);
break;
case 144:
ldpc_BG2_Zc144_byte(c, d);
break;
case 160:
ldpc_BG2_Zc160_byte(c, d);
break;
case 176:
ldpc_BG2_Zc176_byte(c, d);
break;
case 192:
ldpc_BG2_Zc192_byte(c, d);
break;
case 208:
ldpc_BG2_Zc208_byte(c, d);
break;
case 224:
ldpc_BG2_Zc224_byte(c, d);
break;
case 240:
ldpc_BG2_Zc240_byte(c, d);
break;
case 256:
ldpc_BG2_Zc256_byte(c, d);
break;
case 288:
ldpc_BG2_Zc288_byte(c, d);
break;
case 320:
ldpc_BG2_Zc320_byte(c, d);
break;
case 352:
ldpc_BG2_Zc352_byte(c, d);
break;
case 384:
ldpc_BG2_Zc384_byte(c, d);
break;
default:
AssertFatal(false , "BG %d Zc %d is not supported yet\n", BG, Zc);
}
}
else {
AssertFatal(0,"BG %d is not supported yet\n",BG);
}
} else
AssertFatal(false, "BG %d is not supported\n", BG);
}
@@ -101,7 +101,7 @@ int LDPCencoder(uint8_t **test_input, uint8_t **channel_input, encoder_implempar
if(impp->tinput != NULL) stop_meas(impp->tinput);
if ((BG==1 && Zc>=176) || (BG==2 && Zc>=64)) {
if ((BG==1 && Zc>=176) || (BG==2 && Zc>=72)) {
// extend matrix
if(impp->tprep != NULL) start_meas(impp->tprep);
if(impp->tprep != NULL) stop_meas(impp->tprep);
@@ -143,7 +143,7 @@ int LDPCencoder(uint8_t **test_input, uint8_t **channel_input, encoder_implempar
if(impp->tinput != NULL) stop_meas(impp->tinput);
if ((BG==1 && Zc>=176) || (BG==2 && Zc>=64)) {
if ((BG==1 && Zc>=176) || (BG==2 && Zc>=72)) {
// extend matrix
if(impp->tprep != NULL) start_meas(impp->tprep);
if(impp->tprep != NULL) stop_meas(impp->tprep);
@@ -151,7 +151,7 @@ int LDPCencoder(uint8_t **input, uint8_t **output, encoder_implemparams_t *impp)
if(impp->tinput != NULL) stop_meas(impp->tinput);
if ((BG==1 && Zc>=176) || (BG==2 && Zc>=64)) {
if ((BG==1 && Zc>=176) || (BG==2 && Zc>=72)) {
// extend matrix
if(impp->tprep != NULL) start_meas(impp->tprep);
if(impp->tprep != NULL) stop_meas(impp->tprep);
-14
View File
@@ -190,7 +190,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
common_vars->debugBuff_sample_offset = 0;
// PRACH
prach_vars->prachF = (int16_t *)malloc16_clear( 1024*2*sizeof(int16_t) );
prach_vars->rxsigF = (int16_t **)malloc16_clear(Prx*sizeof(int16_t*));
prach_vars->prach_ifft = (int32_t *)malloc16_clear(1024*2*sizeof(int32_t));
@@ -205,19 +204,13 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
gNB->pusch_vars = (NR_gNB_PUSCH *)malloc16_clear(gNB->max_nb_pusch * sizeof(NR_gNB_PUSCH));
for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id];
pusch->rxdataF_ext = (int32_t **)malloc16(Prx * sizeof(int32_t *));
pusch->ul_ch_estimates = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pusch->ul_ch_estimates_ext = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pusch->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pusch->ul_ch_estimates_time = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pusch->rxdataF_comp = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pusch->llr_layers = (int16_t **)malloc16(max_ul_mimo_layers * sizeof(int32_t *));
for (i = 0; i < Prx; i++) {
pusch->rxdataF_ext[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot);
}
for (i = 0; i < n_buf; i++) {
pusch->ul_ch_estimates[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->ofdm_symbol_size * fp->symbols_per_slot);
pusch->ul_ch_estimates_ext[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot);
pusch->ul_ch_estimates_time[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->ofdm_symbol_size);
pusch->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->symbols_per_slot); // symbols per slot
pusch->rxdataF_comp[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot);
@@ -279,7 +272,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
free_and_zero(common_vars->debugBuff);
NR_gNB_PRACH* prach_vars = &gNB->prach_vars;
free_and_zero(prach_vars->prachF);
free_and_zero(prach_vars->rxsigF);
free_and_zero(prach_vars->prach_ifft);
@@ -287,20 +279,14 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id];
for (int i=0; i< max_ul_mimo_layers; i++)
free_and_zero(pusch_vars->llr_layers[i]);
for (int i = 0; i < Prx; i++) {
free_and_zero(pusch_vars->rxdataF_ext[i]);
}
for (int i = 0; i < n_buf; i++) {
free_and_zero(pusch_vars->ul_ch_estimates[i]);
free_and_zero(pusch_vars->ul_ch_estimates_ext[i]);
free_and_zero(pusch_vars->ul_ch_estimates_time[i]);
free_and_zero(pusch_vars->ptrs_phase_per_slot[i]);
free_and_zero(pusch_vars->rxdataF_comp[i]);
}
free_and_zero(pusch_vars->llr_layers);
free_and_zero(pusch_vars->rxdataF_ext);
free_and_zero(pusch_vars->ul_ch_estimates);
free_and_zero(pusch_vars->ul_ch_estimates_ext);
free_and_zero(pusch_vars->ptrs_phase_per_slot);
free_and_zero(pusch_vars->ul_ch_estimates_time);
free_and_zero(pusch_vars->ul_valid_re_per_slot);
+5 -5
View File
@@ -35,6 +35,7 @@
#include "PHY/NR_REFSIG/nr_mod_table.h"
#include "openair2/COMMON/prs_nr_paramdef.h"
#include "SCHED_NR_UE/harq_nr.h"
#include "nr-uesoftmodem.h"
void RCconfig_nrUE_prs(void *cfg)
{
@@ -277,15 +278,14 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
}
ue->init_averaging = 1;
// enable MIB/SIB decoding by default
ue->decode_MIB = 1;
ue->decode_SIB = 1;
init_nr_prach_tables(839);
init_symbol_rotation(fp);
init_timeshift_rotation(fp);
// initialize to false only for SA since in do-ra and phy-test it is already set to true before getting here
if (get_softmodem_params()->sa)
ue->received_config_request = false;
return 0;
}
+167 -134
View File
@@ -47,12 +47,13 @@ const uint8_t nr_pbch_payload_interleaving_pattern[32] = {16, 23, 18, 17, 8, 30,
9, 11, 12, 13, 14, 15, 19, 20, 21, 22, 25, 26, 27, 28, 29, 31
};
int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs,
c16_t *txdataF,
int16_t amp,
uint8_t ssb_start_symbol,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms) {
void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs,
c16_t *txdataF,
int16_t amp,
uint8_t ssb_start_symbol,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms)
{
int k,l;
//int16_t a;
int16_t mod_dmrs[NR_PBCH_DMRS_LENGTH<<1];
@@ -139,186 +140,220 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs,
#ifdef DEBUG_PBCH_DMRS
write_output("txdataF_pbch_dmrs.m", "txdataF_pbch_dmrs", txdataF[0], frame_parms->samples_per_frame_wCP>>1, 1, 1);
#endif
return 0;
}
static void nr_pbch_scrambling(NR_gNB_PBCH *pbch,
uint32_t Nid,
uint8_t nushift,
uint16_t M,
uint16_t length,
uint8_t encoded,
uint32_t unscrambling_mask)
{
uint32_t *pbch_e = pbch->pbch_e;
// x1 is set in lte_gold_generic
typedef struct {
int len;
int goldIdx;
int offset;
} NR_PBCH_scramb_info_t;
const int len = (nushift * M + 31) / 32 + (length + 31) / 32;
uint32_t *s = gold_cache(Nid, len);
static NR_PBCH_scramb_info_t get_scrambling_info(uint8_t nushift,
uint16_t M,
uint16_t length)
{
NR_PBCH_scramb_info_t info;
info.len = (nushift * M + 31) / 32 + (length + 31) / 32;
// The Gold sequence is shifted by nushift* M, so we skip (nushift*M /32) double words
int goldIdx = (nushift * M + 31) / 32 - 1;
info.goldIdx = (nushift * M + 31) / 32 - 1;
// Scrambling is now done with offset (nushift*M)%32
uint8_t offset = (nushift * M) & 0x1f;
info.offset = (nushift * M) & 0x1f;
return info;
}
static void nr_pbch_encoded_scrambling(uint32_t *pbch_e,
uint32_t Nid,
uint8_t nushift,
uint16_t M,
uint16_t length)
{
NR_PBCH_scramb_info_t info = get_scrambling_info(nushift, M, length);
uint32_t *s = gold_cache(Nid, info.len);
int goldIdx = info.goldIdx;
#ifdef DEBUG_PBCH_ENCODING
printf("Scrambling params: nushift %d M %d length %d encoded %d offset %d\n", nushift, M, length, encoded, offset);
printf("Scrambling params: nushift %d M %d length %d offset %d\n", nushift, M, length, info.offset);
#endif
#ifdef DEBUG_PBCH_ENCODING
printf("s: %04x\t", s);
#endif
int k = 0;
if (!encoded) {
/// 1st Scrambling
for (int i = 0; i < length; ++i) {
if ((unscrambling_mask>>i)&1)
pbch->pbch_a_prime ^= ((pbch->pbch_a_interleaved>>i)&1)<<i;
else {
if (((k + offset) & 0x1f) == 0)
goldIdx++;
pbch->pbch_a_prime ^= (((pbch->pbch_a_interleaved >> i) & 1) ^ ((s[goldIdx] >> ((k + offset) & 0x1f)) & 1)) << i;
k++; /// k increase only when payload bit is not special bit
}
}
} else {
/// 2nd Scrambling
for (int i = 0; i < length; ++i) {
if (((i + offset) & 0x1f) == 0)
goldIdx++;
pbch_e[i >> 5] ^= (((s[goldIdx] >> ((i + offset) & 0x1f)) & 1) << (i & 0x1f));
}
for (int i = 0; i < length; ++i) {
if (((i + info.offset) & 0x1f) == 0)
goldIdx++;
pbch_e[i >> 5] ^= (((s[goldIdx] >> ((i + info.offset) & 0x1f)) & 1) << (i & 0x1f));
}
}
void nr_init_pbch_interleaver(uint8_t *interleaver) {
uint8_t j_sfn=0, j_hrf=10, j_ssb=11, j_other=14;
memset((void *)interleaver,0, NR_POLAR_PBCH_PAYLOAD_BITS);
for (uint8_t i=0; i<NR_POLAR_PBCH_PAYLOAD_BITS; i++)
if (!i) // choice bit:1
*(interleaver+i) = *(nr_pbch_payload_interleaving_pattern+j_other++);
else if (i<7) //Sfn bits:6
*(interleaver+i) = *(nr_pbch_payload_interleaving_pattern+j_sfn++);
else if (i<24) // other:17
*(interleaver+i) = *(nr_pbch_payload_interleaving_pattern+j_other++);
else if (i<28) // Sfn:4
*(interleaver+i) = *(nr_pbch_payload_interleaving_pattern+j_sfn++);
else if (i==28) // Hrf bit:1
*(interleaver+i) = *(nr_pbch_payload_interleaving_pattern+j_hrf);
else // Ssb bits:3
*(interleaver+i) = *(nr_pbch_payload_interleaving_pattern+j_ssb++);
static uint32_t nr_pbch_scrambling(uint32_t pbch_a_interleaved,
uint32_t Nid,
uint8_t nushift,
uint16_t M,
uint16_t length,
uint32_t unscrambling_mask)
{
uint32_t pbch_a_prime = 0;
int k = 0;
NR_PBCH_scramb_info_t info = get_scrambling_info(nushift, M, length);
uint32_t *s = gold_cache(Nid, info.len);
#ifdef DEBUG_PBCH_ENCODING
printf("Scrambling params: nushift %d M %d length %d offset %d\n", nushift, M, length, info.offset);
#endif
#ifdef DEBUG_PBCH_ENCODING
printf("s: %04x\t", s);
#endif
int goldIdx = info.goldIdx;
for (int i = 0; i < length; ++i) {
if ((unscrambling_mask >> i) & 1)
pbch_a_prime ^= ((pbch_a_interleaved >> i) & 1) << i;
else {
if (((k + info.offset) & 0x1f) == 0)
goldIdx++;
pbch_a_prime ^= (((pbch_a_interleaved >> i) & 1) ^ ((s[goldIdx] >> ((k + info.offset) & 0x1f)) & 1)) << i;
k++; /// k increase only when payload bit is not special bit
}
}
return pbch_a_prime;
}
int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
uint8_t *interleaver,
c16_t *txdataF,
int16_t amp,
uint8_t ssb_start_symbol,
uint8_t n_hf,
int sfn,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms) {
int k,l,m;
//int16_t a;
int16_t mod_pbch_e[NR_POLAR_PBCH_E];
uint8_t idx=0;
uint16_t M;
uint8_t nushift;
uint32_t unscrambling_mask;
void nr_init_pbch_interleaver(uint8_t *interleaver)
{
uint8_t j_sfn = 0, j_hrf = 10, j_ssb = 11, j_other = 14;
memset((void *)interleaver,0, NR_POLAR_PBCH_PAYLOAD_BITS);
for (int i = 0; i < NR_POLAR_PBCH_PAYLOAD_BITS; i++)
if (!i) // choice bit:1
*(interleaver + i) = *(nr_pbch_payload_interleaving_pattern + j_other++);
else if (i < 7) //Sfn bits:6
*(interleaver + i) = *(nr_pbch_payload_interleaving_pattern + j_sfn++);
else if (i < 24) // other:17
*(interleaver + i) = *(nr_pbch_payload_interleaving_pattern + j_other++);
else if (i < 28) // Sfn:4
*(interleaver + i) = *(nr_pbch_payload_interleaving_pattern + j_sfn++);
else if (i == 28) // Hrf bit:1
*(interleaver + i) = *(nr_pbch_payload_interleaving_pattern + j_hrf);
else // Ssb bits:3
*(interleaver + i) = *(nr_pbch_payload_interleaving_pattern + j_ssb++);
}
uint32_t nr_pbch_extra_byte_generation(int sfn, int n_hf, int ssb_index, int ssb_sc_offset, int Lmax)
{
uint32_t extra_byte = 0;
// Extra byte generation
for (int i = 0; i < 4; i++)
extra_byte |= ((sfn >> (3 - i)) & 1) << i; // resp. 4th, 3rd, 2nd ans 1st lsb of sfn
extra_byte |= n_hf << 4; // half frame index bit
if (Lmax == 64)
for (int i = 0; i < 3; i++)
extra_byte |= (uint32_t)((ssb_index >> (5 - i)) & 1) << (5 + i); // resp. 6th, 5th and 4th bits of ssb_index
else
extra_byte |= ((ssb_sc_offset >> 4) & 1) << 5; //MSB of k_SSB (bit index 4)
return extra_byte;
}
void nr_generate_pbch(PHY_VARS_gNB *gNB,
const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
c16_t *txdataF,
uint8_t ssb_start_symbol,
uint8_t n_hf,
int sfn,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms)
{
LOG_D(PHY, "PBCH generation started\n");
///Payload generation
NR_gNB_PBCH m_pbch;
NR_gNB_PBCH *pbch = &m_pbch;
memset((void *)pbch, 0, sizeof(NR_gNB_PBCH));
pbch->pbch_a=0;
uint8_t ssb_index = ssb_pdu->ssb_pdu_rel15.SsbBlockIndex;
uint8_t *pbch_pdu = (uint8_t*)&ssb_pdu->ssb_pdu_rel15.bchPayload;
const uint8_t *pbch_pdu = (const uint8_t*)&ssb_pdu->ssb_pdu_rel15.bchPayload;
uint8_t Lmax = frame_parms->Lmax;
for (int i=0; i<NR_PBCH_PDU_BITS; i++)
pbch->pbch_a |= ((pbch_pdu[i>>3]>>(7-(i&7)))&1)<<i;
uint32_t pbch_a = 0;
for (int i = 0; i < NR_PBCH_PDU_BITS; i++)
pbch_a |= ((pbch_pdu[i >> 3] >> (7 - (i & 7))) & 1) << i;
// NSA to signal no coreset0
const int ssb_sc_offset = get_softmodem_params()->sa ? config->ssb_table.ssb_subcarrier_offset.value : 31;
#ifdef DEBUG_PBCH_ENCODING
for (int i=0; i<3; i++)
for (int i = 0; i < 3; i++)
printf("pbch_pdu[%d]: 0x%02x\n", i, pbch_pdu[i]);
printf("PBCH payload = 0x%08x\n",pbch->pbch_a);
printf("PBCH payload = 0x%08x\n", pbch_a);
#endif
// Extra byte generation
for (int i=0; i<4; i++)
pbch->pbch_a |= ((sfn>>(3-i))&1)<<(24+i); // resp. 4th, 3rd, 2nd ans 1st lsb of sfn
pbch->pbch_a |= n_hf<<28; // half frame index bit
if (Lmax == 64)
for (int i = 0; i < 3; i++)
pbch->pbch_a |= (uint32_t)((ssb_index >> (5 - i)) & 1) << (29 + i); // resp. 6th, 5th and 4th bits of ssb_index
else
pbch->pbch_a |= ((ssb_sc_offset >> 4) & 1) << 29; //MSB of k_SSB (bit index 4)
LOG_D(PHY,"After extra byte: pbch_a = 0x%08x\n",pbch->pbch_a);
uint32_t extra_byte = nr_pbch_extra_byte_generation(sfn, n_hf, ssb_index, ssb_sc_offset, Lmax);
pbch_a |= extra_byte << 24;
LOG_D(PHY,"After extra byte: pbch_a = 0x%08x\n", pbch_a);
// Payload interleaving
for (int i=0; i<NR_POLAR_PBCH_PAYLOAD_BITS; i++) {
pbch->pbch_a_interleaved |= ((pbch->pbch_a>>i)&1)<<(*(interleaver+i));
uint32_t pbch_a_interleaved = 0;
uint8_t *interleaver = gNB->nr_pbch_interleaver;
for (int i = 0; i < NR_POLAR_PBCH_PAYLOAD_BITS; i++) {
pbch_a_interleaved |= ((pbch_a >> i) & 1) << (*(interleaver + i));
#ifdef DEBUG_PBCH_ENCODING
printf("i %d out 0x%08x ilv %d (in>>i)&1) %d\n", i, pbch->pbch_a_interleaved, *(interleaver+i), (pbch->pbch_a>>i)&1);
printf("i %d out 0x%08x ilv %d (in>>i)&1) %d\n", i, pbch_a_interleaved, *(interleaver+i), (pbch_a >> i) & 1);
#endif
}
#ifdef DEBUG_PBCH_ENCODING
printf("Interleaving:\n");
printf("pbch_a_interleaved: 0x%08x\n", pbch->pbch_a_interleaved);
printf("pbch_a_interleaved: 0x%08x\n", pbch_a_interleaved);
#endif
// Scrambling
unscrambling_mask = (Lmax ==64)? 0x100006D:0x1000041;
M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3);
nushift = (((sfn>>2)&1)<<1) ^ ((sfn>>1)&1);
pbch->pbch_a_prime = 0;
nr_pbch_scrambling(pbch, (uint32_t)config->cell_config.phy_cell_id.value, nushift, M, NR_POLAR_PBCH_PAYLOAD_BITS, 0, unscrambling_mask);
uint32_t unscrambling_mask = (Lmax == 64) ? 0x100006D : 0x1000041;
uint16_t M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3);
uint8_t nushift = (((sfn >> 2) & 1) << 1) ^ ((sfn >> 1) & 1);
uint32_t pbch_a_prime = nr_pbch_scrambling(pbch_a_interleaved,
(uint32_t)config->cell_config.phy_cell_id.value,
nushift,
M,
NR_POLAR_PBCH_PAYLOAD_BITS,
unscrambling_mask);
#ifdef DEBUG_PBCH_ENCODING
printf("Payload scrambling: nushift %d M %d sfn3 %d sfn2 %d\n", nushift, M, (sfn>>2)&1, (sfn>>1)&1);
printf("pbch_a_prime: 0x%08x\n", pbch->pbch_a_prime);
printf("Payload scrambling: nushift %d M %d sfn3 %d sfn2 %d\n", nushift, M, (sfn >> 2) & 1, (sfn >> 1) & 1);
printf("pbch_a_prime: 0x%08x\n", pbch_a_prime);
#endif
// Encoder reversal
uint64_t a_reversed = reverse_bits((uint64_t)pbch->pbch_a_prime, NR_POLAR_PBCH_PAYLOAD_BITS);
uint64_t a_reversed = reverse_bits((uint64_t)pbch_a_prime, NR_POLAR_PBCH_PAYLOAD_BITS);
uint32_t pbch_e[NR_POLAR_PBCH_E_DWORD];
/// CRC, coding and rate matching
polar_encoder_fast (&a_reversed, (void*)pbch->pbch_e, 0, 0,
NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL);
polar_encoder_fast(&a_reversed,
pbch_e,
0,
0,
NR_POLAR_PBCH_MESSAGE_TYPE,
NR_POLAR_PBCH_PAYLOAD_BITS,
NR_POLAR_PBCH_AGGREGATION_LEVEL);
#ifdef DEBUG_PBCH_ENCODING
printf("Channel coding:\n");
for (int i=0; i<NR_POLAR_PBCH_E_DWORD; i++)
printf("pbch_e[%d]: 0x%08x\t", i, pbch->pbch_e[i]);
for (int i = 0; i < NR_POLAR_PBCH_E_DWORD; i++)
printf("pbch_e[%d]: 0x%08x\t", i, pbch_e[i]);
printf("\n");
#endif
/// Scrambling
M = NR_POLAR_PBCH_E;
nushift = (Lmax==4)? ssb_index&3 : ssb_index&7;
nr_pbch_scrambling(pbch, (uint32_t)config->cell_config.phy_cell_id.value, nushift, M, NR_POLAR_PBCH_E, 1, 0);
M = NR_POLAR_PBCH_E;
nushift = (Lmax == 4) ? ssb_index & 3 : ssb_index & 7;
nr_pbch_encoded_scrambling(pbch_e,
(uint32_t)config->cell_config.phy_cell_id.value,
nushift,
M,
NR_POLAR_PBCH_E);
#ifdef DEBUG_PBCH_ENCODING
printf("Scrambling:\n");
for (int i=0; i<NR_POLAR_PBCH_E_DWORD; i++)
printf("pbch_e[%d]: 0x%08x\t", i, pbch->pbch_e[i]);
for (int i = 0; i < NR_POLAR_PBCH_E_DWORD; i++)
printf("pbch_e[%d]: 0x%08x\t", i, pbch_e[i]);
printf("\n");
#endif
int16_t mod_pbch_e[NR_POLAR_PBCH_E];
/// QPSK modulation
for (int i=0; i<NR_POLAR_PBCH_E>>1; i++) {
idx = ((pbch->pbch_e[(i<<1)>>5]>>((i<<1)&0x1f))&3);
mod_pbch_e[i<<1] = nr_qpsk_mod_table[idx<<1];
mod_pbch_e[(i<<1)+1] = nr_qpsk_mod_table[(idx<<1)+1];
int idx = ((pbch_e[(i << 1) >> 5] >> ((i << 1) & 0x1f)) & 3);
mod_pbch_e[i<<1] = nr_qpsk_mod_table[idx << 1];
mod_pbch_e[(i<<1)+1] = nr_qpsk_mod_table[(idx << 1) + 1];
#ifdef DEBUG_PBCH
printf("i %d idx %d mod_pbch %d %d\n", i, idx, mod_pbch_e[2*i], mod_pbch_e[2*i+1]);
printf("i %d idx %d mod_pbch %d %d\n", i, idx, mod_pbch_e[2 * i], mod_pbch_e[2 * i + 1]);
#endif
}
@@ -326,9 +361,10 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
nushift = config->cell_config.phy_cell_id.value &3;
// PBCH modulated symbols are mapped within the SSB block on symbols 1, 2, 3 excluding the subcarriers used for the PBCH DMRS
///symbol 1 [0:239] -- 180 mod symbols
k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
l = ssb_start_symbol + 1;
m = 0;
int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
int l = ssb_start_symbol + 1;
int m = 0;
int16_t amp = gNB->TX_AMP;
for (int ssb_sc_idx = 0; ssb_sc_idx < 240; ssb_sc_idx++) {
if ((ssb_sc_idx&3) == nushift) { //skip DMRS
@@ -419,7 +455,4 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
if (k >= frame_parms->ofdm_symbol_size)
k-=frame_parms->ofdm_symbol_size;
}
return 0;
}
+102 -101
View File
@@ -432,21 +432,17 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
uint16_t *max_preamble_energy,
uint16_t *max_preamble_delay)
{
AssertFatal(gNB!=NULL,"Can only be called from gNB\n");
int i;
nfapi_nr_prach_config_t *cfg=&gNB->gNB_config.prach_config;
AssertFatal(gNB != NULL, "Can only be called from gNB\n");
nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config;
NR_DL_FRAME_PARMS *fp;
uint16_t rootSequenceIndex;
int numrootSequenceIndex;
uint8_t restricted_set;
uint8_t n_ra_prb=0xFF;
int16_t *prachF=NULL;
int nb_rx;
uint16_t rootSequenceIndex;
int numrootSequenceIndex;
uint8_t restricted_set;
uint8_t n_ra_prb=0xFF;
int nb_rx;
int16_t **rxsigF = gNB->prach_vars.rxsigF;
int16_t **rxsigF = gNB->prach_vars.rxsigF;
uint8_t preamble_index;
uint16_t NCS=99,NCS2;
@@ -460,10 +456,8 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
uint8_t not_found;
uint16_t u;
int16_t *Xu=0;
uint16_t offset;
uint16_t first_nonzero_root_idx=0;
uint8_t new_dft=0;
uint8_t aa;
int32_t lev;
int16_t levdB;
int log2_ifft_size=10;
@@ -473,23 +467,22 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
fp = &gNB->frame_parms;
nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value;
rootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].prach_root_sequence_index.value;
numrootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].num_root_sequences.value;
NCS = prach_pdu->num_cs;//cfg->num_prach_fd_occasions_list[0].prach_zero_corr_conf.value;
rootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].prach_root_sequence_index.value;
numrootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].num_root_sequences.value;
NCS = prach_pdu->num_cs;//cfg->num_prach_fd_occasions_list[0].prach_zero_corr_conf.value;
int prach_sequence_length = cfg->prach_sequence_length.value;
int msg1_frequencystart = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].k1.value;
int msg1_frequencystart = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].k1.value;
// int num_unused_root_sequences = cfg->num_prach_fd_occasions_list[0].num_unused_root_sequences.value;
// cfg->num_prach_fd_occasions_list[0].unused_root_sequences_list
restricted_set = cfg->restricted_set_config.value;
restricted_set = cfg->restricted_set_config.value;
uint8_t prach_fmt = prach_pdu->prach_format;
uint16_t N_ZC = (prach_sequence_length==0)?839:139;
LOG_D(PHY,"L1 PRACH RX: rooSequenceIndex %d, numRootSeqeuences %d, NCS %d, N_ZC %d, format %d \n",rootSequenceIndex,numrootSequenceIndex,NCS,N_ZC,prach_fmt);
prach_ifft = gNB->prach_vars.prach_ifft;
prachF = gNB->prach_vars.prachF;
prach_ifft = gNB->prach_vars.prach_ifft;
if (LOG_DEBUGFLAG(PRACH)){
if ((frame&1023) < 20) LOG_D(PHY,"PRACH (gNB) : running rx_prach for slot %d, msg1_frequencystart %d, rootSequenceIndex %d\n", slot, msg1_frequencystart, rootSequenceIndex);
}
@@ -508,10 +501,10 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
preamble_offset_old = 99;
*max_preamble_energy=0;
*max_preamble_delay=0;
*max_preamble=0;
*max_preamble_energy = 0;
*max_preamble_delay = 0;
*max_preamble = 0;
int16_t prachF[2 * 1024];
for (preamble_index=0 ; preamble_index<64 ; preamble_index++) {
if (LOG_DEBUGFLAG(PRACH)){
@@ -521,14 +514,14 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
if (restricted_set == 0) {
// This is the relative offset in the root sequence table (5.7.2-4 from 36.211) for the given preamble index
preamble_offset = ((NCS==0)? preamble_index : (preamble_index/(N_ZC/NCS)));
if (preamble_offset != preamble_offset_old) {
preamble_offset_old = preamble_offset;
new_dft = 1;
// This is the \nu corresponding to the preamble index
preamble_shift = 0;
}
else {
preamble_shift -= NCS;
@@ -551,33 +544,32 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
// current root depending on rootSequenceIndex
int index = (rootSequenceIndex + preamble_offset) % N_ZC;
u = prach_root_sequence_map[index];
u = prach_root_sequence_map[index];
uint16_t n_group_ra = 0;
uint16_t n_group_ra = 0;
if ( (nr_du[u]<(N_ZC/3)) && (nr_du[u]>=NCS) ) {
n_shift_ra = nr_du[u]/NCS;
d_start = (nr_du[u]<<1) + (n_shift_ra * NCS);
n_group_ra = N_ZC/d_start;
n_shift_ra_bar = max(0,(N_ZC-(nr_du[u]<<1)-(n_group_ra*d_start))/N_ZC);
} else if ( (nr_du[u]>=(N_ZC/3)) && (nr_du[u]<=((N_ZC - NCS)>>1)) ) {
n_shift_ra = (N_ZC - (nr_du[u]<<1))/NCS;
d_start = N_ZC - (nr_du[u]<<1) + (n_shift_ra * NCS);
n_group_ra = nr_du[u]/d_start;
n_shift_ra_bar = min(n_shift_ra,max(0,(nr_du[u]- (n_group_ra*d_start))/NCS));
} else {
n_shift_ra = 0;
n_shift_ra_bar = 0;
}
// This is the number of cyclic shifts for the current root u
numshift = (n_shift_ra*n_group_ra) + n_shift_ra_bar;
// skip to next root and recompute parameters if numshift==0
(numshift>0) ? (not_found = 0) : (preamble_offset++);
}
}
if ((nr_du[u] < (N_ZC / 3)) && (nr_du[u] >= NCS) ) {
n_shift_ra = nr_du[u] / NCS;
d_start = (nr_du[u] << 1) + (n_shift_ra * NCS);
n_group_ra = N_ZC / d_start;
n_shift_ra_bar = max(0, (N_ZC-(nr_du[u] << 1) - (n_group_ra * d_start)) / N_ZC);
} else if ((nr_du[u] >= (N_ZC / 3)) && (nr_du[u] <= ((N_ZC - NCS) >> 1))) {
n_shift_ra = (N_ZC - (nr_du[u] << 1)) / NCS;
d_start = N_ZC - (nr_du[u] << 1) + (n_shift_ra * NCS);
n_group_ra = nr_du[u] / d_start;
n_shift_ra_bar = min(n_shift_ra, max(0, (nr_du[u]- (n_group_ra * d_start)) / NCS));
} else {
n_shift_ra = 0;
n_shift_ra_bar = 0;
}
// This is the number of cyclic shifts for the current root u
numshift = (n_shift_ra * n_group_ra) + n_shift_ra_bar;
// skip to next root and recompute parameters if numshift==0
(numshift>0) ? (not_found = 0) : (preamble_offset++);
}
}
if (n_shift_ra>0)
preamble_shift = -((d_start * (preamble_index0/n_shift_ra)) + ((preamble_index0%n_shift_ra)*NCS)); // minus because the channel is h(t -\tau + Cv)
else
@@ -595,8 +587,17 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
// Compute DFT of RX signal (conjugate input, results in conjugate output) for each new rootSequenceIndex
if (LOG_DEBUGFLAG(PRACH)) {
int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840));
if (en>60) LOG_D(PHY,"frame %d, slot %d : preamble index %d, NCS %d, N_ZC/NCS %d: offset %d, preamble shift %d , en %d)\n",
frame,slot,preamble_index,NCS,N_ZC/NCS,preamble_offset,preamble_shift,en);
if (en>60)
LOG_D(PHY,
"frame %d, slot %d : preamble index %d, NCS %d, N_ZC/NCS %d: offset %d, preamble shift %d , en %d)\n",
frame,
slot,
preamble_index,
NCS,
N_ZC / NCS,
preamble_offset,
preamble_shift,
en);
}
LOG_D(PHY,"PRACH RX preamble_index %d, preamble_offset %d\n",preamble_index,preamble_offset);
@@ -605,57 +606,56 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
if (new_dft == 1) {
new_dft = 0;
Xu=(int16_t*)gNB->X_u[preamble_offset-first_nonzero_root_idx];
Xu = (int16_t*)gNB->X_u[preamble_offset-first_nonzero_root_idx];
LOG_D(PHY,"PRACH RX new dft preamble_offset-first_nonzero_root_idx %d\n",preamble_offset-first_nonzero_root_idx);
memset(prach_ifft,0,((N_ZC==839) ? 2048 : 256)*sizeof(int32_t));
memset(prachF, 0, sizeof(int16_t)*2*1024 );
if (LOG_DUMPFLAG(PRACH)) {
memset(prachF, 0, sizeof(int16_t) * 2 * 1024);
if (LOG_DUMPFLAG(PRACH)) {
LOG_M("prach_rxF0.m","prach_rxF0",rxsigF[0],N_ZC,1,1);
LOG_M("prach_rxF1.m","prach_rxF1",rxsigF[1],6144,1,1);
}
for (aa=0;aa<nb_rx; aa++) {
for (int aa = 0; aa < nb_rx; aa++) {
// Do componentwise product with Xu* on each antenna
for (offset=0; offset<(N_ZC<<1); offset+=2) {
prachF[offset] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset] + (int32_t)Xu[offset+1]*rxsigF[aa][offset+1])>>15);
prachF[offset+1] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset+1] - (int32_t)Xu[offset+1]*rxsigF[aa][offset])>>15);
}
for (int offset = 0; offset < (N_ZC << 1); offset += 2) {
prachF[offset] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset] + (int32_t)Xu[offset+1]*rxsigF[aa][offset+1])>>15);
prachF[offset+1] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset+1] - (int32_t)Xu[offset+1]*rxsigF[aa][offset])>>15);
}
// Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139)
if (N_ZC == 839) {
idft(IDFT_1024,prachF,prach_ifft_tmp,1);
// compute energy and accumulate over receive antennas
for (i=0;i<1024;i++)
prach_ifft[i] += (int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[i<<1] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)];
} else {
idft(IDFT_256,prachF,prach_ifft_tmp,1);
log2_ifft_size = 8;
// compute energy and accumulate over receive antennas and repetitions for BR
for (i=0;i<256;i++)
prach_ifft[i] += (int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[(i<<1)] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)];
}
if (LOG_DUMPFLAG(PRACH)) {
if (aa==0) LOG_M("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1);
if (aa==1) LOG_M("prach_rxF_comp1.m","prach_rxF_comp1",prachF,1024,1,1);
// Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139)
if (N_ZC == 839) {
idft(IDFT_1024, prachF, prach_ifft_tmp, 1);
// compute energy and accumulate over receive antennas
for (int i = 0; i < 1024; i++)
prach_ifft[i] += (int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[i<<1] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)];
} else {
idft(IDFT_256, prachF, prach_ifft_tmp, 1);
log2_ifft_size = 8;
// compute energy and accumulate over receive antennas and repetitions for BR
for (int i = 0; i < 256; i++)
prach_ifft[i] += (int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[(i<<1)] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)];
}
}// antennas_rx
if (LOG_DUMPFLAG(PRACH)) {
if (aa == 0)
LOG_M("prach_rxF_comp0.m","prach_rxF_comp0", prachF, 1024, 1, 1);
if (aa == 1)
LOG_M("prach_rxF_comp1.m","prach_rxF_comp1", prachF, 1024, 1, 1);
}
} // antennas_rx
// Normalization of energy over ifft and receive antennas
if (N_ZC == 839) {
log2_ifft_size = 10;
for (i=0;i<1024;i++)
for (int i = 0; i < 1024; i++)
prach_ifft[i] = (prach_ifft[i]>>log2_ifft_size)/nb_rx;
} else {
log2_ifft_size = 8;
for (i=0;i<256;i++)
for (int i = 0; i < 256; i++)
prach_ifft[i] = (prach_ifft[i]>>log2_ifft_size)/nb_rx;
}
@@ -665,14 +665,14 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<<log2_ifft_size)/N_ZC));
for (i=0; i<NCS2; i++) {
for (int i = 0; i < NCS2; i++) {
lev = (int32_t)prach_ifft[(preamble_shift2+i)];
levdB = dB_fixed_times10(lev);
if (levdB>*max_preamble_energy) {
LOG_D(PHY,"preamble_index %d, delay %d en %d dB > %d dB\n",preamble_index,i,levdB,*max_preamble_energy);
*max_preamble_energy = levdB;
*max_preamble_delay = i; // Note: This has to be normalized to the 30.72 Ms/s sampling rate
*max_preamble = preamble_index;
*max_preamble_energy = levdB;
*max_preamble_delay = i; // Note: This has to be normalized to the 30.72 Ms/s sampling rate
*max_preamble = preamble_index;
}
}
}// preamble_index
@@ -695,9 +695,11 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
// max_preamble_delay * ( (2048/2^mu*(fs/30.72M)) / 256 ) / fs = TA * 16 * 64 / 2^mu * Tc
uint16_t *TA = max_preamble_delay;
int mu = fp->numerology_index;
if (cfg->prach_sequence_length.value==0) {
if (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2) *TA = *TA*3*(1<<mu)/2;
else if (prach_fmt == 3) *TA = *TA*3*(1<<mu)/8;
if (cfg->prach_sequence_length.value == 0) {
if (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2)
*TA = *TA * 3 * (1 << mu) / 2;
else if (prach_fmt == 3)
*TA = *TA * 3 * (1 << mu) / 8;
}
else *TA = *TA/2;
@@ -705,19 +707,18 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
if (LOG_DUMPFLAG(PRACH)) {
//int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840));
// if (en>60) {
int k = (12*n_ra_prb) - 6*fp->N_RB_UL;
if (k<0) k+=fp->ofdm_symbol_size;
int k = (12 * n_ra_prb) - 6 * fp->N_RB_UL;
if (k < 0)
k += fp->ofdm_symbol_size;
k*=12;
k+=13;
k*=2;
LOG_M("rxsigF.m","prach_rxF",&rxsigF[0][0],12288,1,1);
LOG_M("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1);
LOG_M("Xu.m","xu",Xu,N_ZC,1,1);
LOG_M("prach_ifft0.m","prach_t0",prach_ifft,1024,1,1);
LOG_M("rxsigF.m","prach_rxF", &rxsigF[0][0], 12288, 1, 1);
LOG_M("prach_rxF_comp0.m","prach_rxF_comp0", prachF, 1024, 1, 1);
LOG_M("Xu.m","xu", Xu, N_ZC, 1, 1);
LOG_M("prach_ifft0.m","prach_t0", prach_ifft, 1024, 1, 1);
// }
} /* LOG_DUMPFLAG(PRACH) */
stop_meas(&gNB->rx_prach);
+17 -19
View File
@@ -72,33 +72,30 @@ int nr_generate_sss(c16_t *txdataF,
NR_DL_FRAME_PARMS *frame_parms);
/*!
\fn int nr_generate_pbch_dmrs
\fn void nr_generate_pbch_dmrs
\brief Generation of the DMRS for the PBCH
@param
@returns 0 on success
*/
int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs,
c16_t *txdataF,
int16_t amp,
uint8_t ssb_start_symbol,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms);
void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs,
c16_t *txdataF,
int16_t amp,
uint8_t ssb_start_symbol,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms);
/*!
\fn int nr_generate_pbch
\fn void nr_generate_pbch
\brief Generation of the PBCH
@param
@returns 0 on success
*/
int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
uint8_t *interleaver,
c16_t *txdataF,
int16_t amp,
uint8_t ssb_start_symbol,
uint8_t n_hf,
int sfn,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms);
void nr_generate_pbch(PHY_VARS_gNB *gNB,
const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
c16_t *txdataF,
uint8_t ssb_start_symbol,
uint8_t n_hf,
int sfn,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms);
/*!
\fn int nr_generate_pbch
@@ -107,6 +104,7 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
@returns the bit index of the output
*/
void nr_init_pbch_interleaver(uint8_t *interleaver);
uint32_t nr_pbch_extra_byte_generation(int sfn, int n_hf, int ssb_index, int ssb_sc_offset, int Lmax);
NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB);
@@ -288,14 +288,11 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF,
NR_DL_FRAME_PARMS *frame_parms)
{
uint8_t delta = 0;
int start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size;
int nb_re_pusch = NR_NB_SC_PER_RB * pusch_pdu->rb_size;
c16_t *rxF = &rxdataF[rxoffset];
c16_t *rxF_ext = &rxFext[0];
c16_t *ul_ch0 = &chF[choffset];
c16_t *rxF = &rxdataF[rxoffset];
c16_t *rxF_ext = &rxFext[0];
c16_t *ul_ch0 = &chF[choffset];
c16_t *ul_ch0_ext = &chFext[0];
if (is_dmrs_symbol == 0) {
@@ -307,11 +304,11 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF,
memcpy(rxF_ext, &rxF[start_re], neg_length * sizeof(c16_t));
memcpy(&rxF_ext[neg_length], rxF, pos_length * sizeof(c16_t));
}
memcpy(ul_ch0_ext, ul_ch0, nb_re_pusch * sizeof(c16_t));
memcpy(ul_ch0_ext, ul_ch0, nb_re_pusch * sizeof(c16_t));
}
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) { // 6 REs / PRB
AssertFatal(delta == 0 || delta == 1, "Illegal delta %d\n",delta);
c16_t *rxF32 = &rxF[start_re];
c16_t *rxF32 = &rxF[start_re];
if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) {
for (int idx = 1 - delta; idx < nb_re_pusch; idx += 2) {
*rxF_ext++ = rxF32[idx];
@@ -367,7 +364,8 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF,
}
}
static void nr_ulsch_scale_channel(int **ul_ch_estimates_ext,
static void nr_ulsch_scale_channel(int size_est,
int ul_ch_estimates_ext[][size_est],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t symbol,
uint8_t is_dmrs_symbol,
@@ -419,7 +417,8 @@ static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t
}
// compute average channel_level on each (TX,RX) antenna pair
static void nr_ulsch_channel_level(int **ul_ch_estimates_ext,
static void nr_ulsch_channel_level(int size_est,
int ul_ch_estimates_ext[][size_est],
NR_DL_FRAME_PARMS *frame_parms,
int32_t *avg,
uint8_t symbol,
@@ -436,7 +435,7 @@ static void nr_ulsch_channel_level(int **ul_ch_estimates_ext,
//clear average level
avg128U = simde_mm_setzero_si128();
ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol * len];
ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx + aarx][symbol * len];
for (int i = 0; i < len >> 2; i++) {
avg128U = simde_mm_add_epi32(avg128U, simde_mm_srai_epi32(simde_mm_madd_epi16(ul_ch128[i], ul_ch128[i]), x));
@@ -1445,6 +1444,28 @@ static void nr_pusch_symbol_processing(void *arg)
}
}
static uint32_t average_u32(const uint32_t *x, uint16_t size)
{
AssertFatal(size > 0 && x != NULL, "x is NULL or size is 0\n");
uint64_t sum_x = 0;
simde__m256i vec_sum = simde_mm256_setzero_si256();
int i = 0;
for (; i + 8 <= size; i += 8) {
simde__m256i vec_data = simde_mm256_loadu_si256((simde__m256i *)&x[i]);
vec_sum = simde_mm256_add_epi32(vec_sum, vec_data);
}
uint32_t *vec_sum32 = (uint32_t *)&vec_sum;
for (int k = 0; k < 8; k++) {
sum_x += vec_sum32[k];
}
for (; i < size; i++) {
sum_x += x[i];
}
return (uint32_t)(sum_x / size);
}
int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
uint8_t ulsch_id,
@@ -1505,14 +1526,38 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
pusch_vars->ulsch_power[aarx] = 0;
pusch_vars->ulsch_noise_power[aarx] = 0;
}
for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) {
pusch_vars->ulsch_power[aarx] += signal_energy_nodc(
(c16_t*)&pusch_vars->ul_ch_estimates[aatx * gNB->frame_parms.nb_antennas_rx + aarx][symbol * frame_parms->ofdm_symbol_size],
rel15_ul->rb_size * 12);
int64_t symb_energy = 0;
int start_sc = (rel15_ul->bwp_start + rel15_ul->rb_start) * NR_NB_SC_PER_RB;
int middle_sc = frame_parms->ofdm_symbol_size - frame_parms->first_carrier_offset;
int end_sc = (start_sc + rel15_ul->rb_size * NR_NB_SC_PER_RB - 1) % frame_parms->ofdm_symbol_size;
for (int s = rel15_ul->start_symbol_index; s < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); s++) {
int offset0 = ((slot & 3) * frame_parms->symbols_per_slot + s) * frame_parms->ofdm_symbol_size;
int offset = offset0 + (frame_parms->first_carrier_offset + start_sc) % frame_parms->ofdm_symbol_size;
c16_t *ul_ch = &gNB->common_vars.rxdataF[aarx][offset];
if (end_sc < start_sc) {
int64_t symb_energy_aux = signal_energy_nodc(ul_ch, middle_sc - start_sc) * (middle_sc - start_sc);
ul_ch = &gNB->common_vars.rxdataF[aarx][offset0];
symb_energy_aux += (signal_energy_nodc(ul_ch, end_sc + 1) * (end_sc + 1));
symb_energy += symb_energy_aux / (rel15_ul->rb_size * NR_NB_SC_PER_RB);
} else {
symb_energy += signal_energy_nodc(ul_ch, rel15_ul->rb_size * NR_NB_SC_PER_RB);
}
}
for (int rb = 0; rb < rel15_ul->rb_size; rb++)
pusch_vars->ulsch_noise_power[aarx] +=
n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start + rb] / rel15_ul->rb_size;
pusch_vars->ulsch_power[aarx] += (symb_energy / rel15_ul->nr_of_symbols);
pusch_vars->ulsch_noise_power[aarx] +=
average_u32(&n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start], rel15_ul->rb_size);
LOG_D(PHY,
"aa %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n",
aarx,
rel15_ul->bwp_start,
rel15_ul->rb_start,
rel15_ul->rb_size,
pusch_vars->ulsch_power[aarx],
pusch_vars->ulsch_noise_power[aarx]);
}
}
}
@@ -1592,17 +1637,21 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
dmrs_symbol = get_valid_dmrs_idx_for_channel_est(rel15_ul->ul_dmrs_symb_pos, meas_symbol);
else // average of channel estimates stored in first symbol
dmrs_symbol = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, end_symbol);
int size_est = nb_re_pusch * frame_parms->symbols_per_slot;
__attribute__((aligned(32))) int ul_ch_estimates_ext[rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx][size_est];
memset(ul_ch_estimates_ext, 0, sizeof(ul_ch_estimates_ext));
int buffer_length = rel15_ul->rb_size * NR_NB_SC_PER_RB;
c16_t temp_rxFext[frame_parms->nb_antennas_rx][buffer_length] __attribute__((aligned(32)));
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++)
for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++)
for (int nl = 0; nl < rel15_ul->nrOfLayers; nl++)
nr_ulsch_extract_rbs(gNB->common_vars.rxdataF[aarx],
(c16_t*)pusch_vars->ul_ch_estimates[aatx * frame_parms->nb_antennas_rx + aarx],
(c16_t*)&pusch_vars->rxdataF_ext[aarx][meas_symbol * nb_re_pusch],
(c16_t*)&pusch_vars->ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx+aarx][meas_symbol * nb_re_pusch],
(c16_t *)pusch_vars->ul_ch_estimates[nl * frame_parms->nb_antennas_rx + aarx],
temp_rxFext[aarx],
(c16_t*)&ul_ch_estimates_ext[nl * frame_parms->nb_antennas_rx + aarx][meas_symbol * nb_re_pusch],
soffset + meas_symbol * frame_parms->ofdm_symbol_size,
dmrs_symbol * frame_parms->ofdm_symbol_size,
aarx,
(rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01,
(rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01,
rel15_ul,
frame_parms);
@@ -1613,7 +1662,8 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
//----------------------------------------------------------
//--------------------- Channel Scaling --------------------
//----------------------------------------------------------
nr_ulsch_scale_channel(pusch_vars->ul_ch_estimates_ext,
nr_ulsch_scale_channel(size_est,
ul_ch_estimates_ext,
frame_parms,
meas_symbol,
(rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01,
@@ -1622,16 +1672,17 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
rel15_ul->rb_size,
shift_ch_ext);
nr_ulsch_channel_level(pusch_vars->ul_ch_estimates_ext,
nr_ulsch_channel_level(size_est,
ul_ch_estimates_ext,
frame_parms,
avg,
meas_symbol, // index of the start symbol
nb_re_pusch, // number of the re in pusch
rel15_ul->nrOfLayers);
for (int aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++)
for (int nl = 0; nl < rel15_ul->nrOfLayers; nl++)
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++)
avgs = cmax(avgs, avg[aatx*frame_parms->nb_antennas_rx+aarx]);
avgs = cmax(avgs, avg[nl * frame_parms->nb_antennas_rx + aarx]);
pusch_vars->log2_maxh = (log2_approx(avgs) >> 1);
+1 -69
View File
@@ -56,18 +56,9 @@ void exit_function(const char *file, const char *function, const int line, const
#include "common/utils/LOG/log.h"
#include <cstdlib>
#include <memory>
#include "openair1/PHY/TOOLS/phy_test_tools.hpp"
#include <random>
constexpr bool is_power_of_two(uint64_t n)
{
return n > 0 && (n & (n - 1)) == 0;
}
size_t align_up(size_t a, size_t b)
{
return (a + b - 1) / b * b;
}
int16_t saturating_sub(int16_t a, int16_t b)
{
int32_t result = (int32_t)a - (int32_t)b;
@@ -81,44 +72,6 @@ int16_t saturating_sub(int16_t a, int16_t b)
}
}
// Template adaptations for std::vector. This is needed because the avx functions expect 256 bit alignment.
template <typename T, size_t alignment>
class AlignedAllocator {
public:
static_assert(is_power_of_two(alignment), "Alignment should be power of 2");
static_assert(alignment >= 8, "Alignment must be at least 8 bits");
using value_type = T;
AlignedAllocator() = default;
AlignedAllocator(const AlignedAllocator &) = default;
AlignedAllocator &operator=(const AlignedAllocator &) = default;
template <typename U>
struct rebind {
using other = AlignedAllocator<U, alignment>;
};
T *allocate(size_t n)
{
size_t alignment_bytes = alignment / 8;
void *ptr = ::aligned_alloc(alignment_bytes, align_up(n * sizeof(T), alignment_bytes));
return static_cast<T *>(ptr);
}
void deallocate(T *p, size_t n)
{
::free(p);
}
};
// Using 512-aligned vector in case some functions use avx-512
template <typename T>
using AlignedAllocator512 = AlignedAllocator<T, 512>;
template <typename T>
using AlignedVector512 = std::vector<T, AlignedAllocator512<T>>;
void nr_ulsch_16qam_llr_ref(c16_t *rxdataF_comp, int32_t *ul_ch_mag, int16_t *ulsch_llr, uint32_t nb_re, uint8_t symbol)
{
int16_t *ul_ch_mag_i16 = (int16_t *)ul_ch_mag;
@@ -190,27 +143,6 @@ void nr_ulsch_256qam_llr_ref(c16_t *rxdataF_comp,
}
}
AlignedVector512<c16_t> generate_random_c16(size_t num)
{
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int16_t> dist(INT16_MIN, INT16_MAX);
AlignedVector512<c16_t> vec;
vec.resize(num);
auto gen = [&]() { return (c16_t){dist(rng), dist(rng)}; };
std::generate(vec.begin(), vec.end(), gen);
return vec;
}
AlignedVector512<uint16_t> generate_random_uint16(size_t num)
{
AlignedVector512<uint16_t> vec;
vec.resize(num);
auto gen = [&]() { return static_cast<uint16_t>(std::rand()); };
std::generate(vec.begin(), vec.end(), gen);
return vec;
}
void test_function_16_qam(AlignedVector512<uint32_t> nb_res)
{
for (auto i = 0U; i < nb_res.size(); i++) {
@@ -24,7 +24,7 @@
#include "PHY/defs_nr_UE.h"
//#include "PHY/defs_gNB.h"
/** @addtogroup _PHY_PARAMETER_ESTIMATION_BLOCKS_
* @{
*/
@@ -417,7 +417,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
//printf("start rx segment %d\n",r);
uint32_t E = nr_get_E(G, harq_process->C, dlsch->dlsch_config.qamModOrder, dlsch->Nl, r);
decParams.R = nr_get_R_ldpc_decoder(dlsch->dlsch_config.rv, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->DLround);
union ldpcReqUnion id = {.s={dlsch->rnti,frame,nr_slot_rx,0,0}};
union ldpcReqUnion id = {.s = {dlsch->rnti, frame, nr_slot_rx, 0, 0}};
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_ue_t), id.p, &nf, &nr_processDLSegment);
ldpcDecode_ue_t * rdata=(ldpcDecode_ue_t *) NotifiedFifoData(req);
+101
View File
@@ -0,0 +1,101 @@
/*
* 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
*/
#ifndef __PHY_TEST_TOOLS_HPP__
#define __PHY_TEST_TOOLS_HPP__
#include <vector>
#include <random>
#include <algorithm>
extern "C" {
#include "openair1/PHY/TOOLS/tools_defs.h"
}
constexpr bool is_power_of_two(uint64_t n)
{
return n != 0 && (n & (n - 1)) == 0;
}
size_t align_up(size_t a, size_t b)
{
return (a + b - 1) / b * b;
}
// Template adaptations for std::vector. This is needed because the avx functions expect 256 bit alignment.
template <typename T, size_t alignment>
class AlignedAllocator {
public:
static_assert(is_power_of_two(alignment), "Alignment should be power of 2");
static_assert(alignment >= 8, "Alignment must be at least 8 bits");
using value_type = T;
AlignedAllocator() = default;
AlignedAllocator(const AlignedAllocator &) = default;
AlignedAllocator &operator=(const AlignedAllocator &) = default;
template <typename U>
struct rebind {
using other = AlignedAllocator<U, alignment>;
};
T *allocate(size_t n)
{
size_t alignment_bytes = alignment / 8;
void *ptr = ::aligned_alloc(alignment_bytes, align_up(n * sizeof(T), alignment_bytes));
return static_cast<T *>(ptr);
}
void deallocate(T *p, size_t n)
{
::free(p);
}
};
// Using 512-aligned vector in case some functions use avx-512
template <typename T>
using AlignedAllocator512 = AlignedAllocator<T, 512>;
template <typename T>
using AlignedVector512 = std::vector<T, AlignedAllocator512<T>>;
AlignedVector512<c16_t> generate_random_c16(size_t num)
{
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int16_t> dist(INT16_MIN, INT16_MAX);
AlignedVector512<c16_t> vec;
vec.resize(num);
auto gen = [&]() { return (c16_t){dist(rng), dist(rng)}; };
std::generate(vec.begin(), vec.end(), gen);
return vec;
}
AlignedVector512<uint16_t> generate_random_uint16(size_t num)
{
AlignedVector512<uint16_t> vec;
vec.resize(num);
auto gen = [&]() { return static_cast<uint16_t>(std::rand()); };
std::generate(vec.begin(), vec.end(), gen);
return vec;
}
#endif
+6
View File
@@ -3,3 +3,9 @@ target_link_libraries(test_signal_energy PRIVATE GTest::gtest UTIL)
add_dependencies(tests test_signal_energy)
add_test(NAME test_signal_energy
COMMAND ./test_signal_energy)
add_executable(benchmark_rotate_vector benchmark_rotate_vector.cpp)
target_link_libraries(benchmark_rotate_vector PRIVATE benchmark::benchmark UTIL PHY_NR)
add_dependencies(tests benchmark_rotate_vector)
add_test(NAME benchmark_rotate_vector
COMMAND ./benchmark_rotate_vector)
@@ -0,0 +1,59 @@
/*
* 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
*/
#include <stdint.h>
#include <vector>
#include <algorithm>
#include <numeric>
extern "C" {
#include "openair1/PHY/TOOLS/tools_defs.h"
struct configmodule_interface_s;
struct configmodule_interface_s *uniqCfg = NULL;
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
{
if (assert) {
abort();
} else {
exit(EXIT_SUCCESS);
}
}
}
#include <cstdio>
#include "common/utils/LOG/log.h"
#include "benchmark/benchmark.h"
#include "openair1/PHY/TOOLS/phy_test_tools.hpp"
static void BM_rotate_cpx_vector(benchmark::State &state)
{
int vector_size = state.range(0);
auto input_complex_16 = generate_random_c16(vector_size);
auto input_alpha = generate_random_c16(vector_size);
AlignedVector512<c16_t> output;
output.resize(vector_size);
int shift = 2;
for (auto _ : state) {
rotate_cpx_vector(input_complex_16.data(), input_alpha.data(), output.data(), vector_size, shift);
}
}
BENCHMARK(BM_rotate_cpx_vector)->RangeMultiplier(4)->Range(100, 20000);
BENCHMARK_MAIN();
-3
View File
@@ -52,9 +52,6 @@
extern "C" {
#endif
#define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
typedef struct complexd {
double r;
double i;
+29 -171
View File
@@ -53,23 +53,6 @@ typedef struct {
int lut[MAX_PUCCH0_NID][160][14];
} NR_gNB_PUCCH0_LUT_t;
typedef struct {
uint32_t pbch_a;
uint32_t pbch_a_interleaved;
uint32_t pbch_a_prime;
uint32_t pbch_e[NR_POLAR_PBCH_E_DWORD];
} NR_gNB_PBCH;
typedef enum {
NR_SCH_IDLE,
NR_ACTIVE,
NR_CBA_ACTIVE,
NR_DISABLED
} NR_SCH_status_t;
typedef struct {
/// Nfapi DLSCH PDU
nfapi_nr_dl_tti_pdsch_pdu pdsch_pdu;
@@ -81,8 +64,6 @@ typedef struct {
uint8_t **c;
/// Frame where current HARQ round was sent
uint32_t frame;
/// Subframe where current HARQ round was sent
uint32_t subframe;
/// Interleaver outputs
uint8_t *f;
/// LDPC lifting size
@@ -164,9 +145,6 @@ typedef struct {
#define NUMBER_OF_NR_PRACH_MAX 8
typedef struct {
/// \brief ?.
/// first index: ? [0..1023] (hard coded)
int16_t *prachF;
/// \brief ?.
/// second index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
/// third index: frequency-domain sample [0..ofdm_symbol_size*12[
@@ -221,6 +199,7 @@ typedef struct {
int llrLen;
//////////////////////////////////////////////////////////////
} NR_UL_gNB_HARQ_t;
static inline int lenWithCrc(int nbSeg, int len)
{
if (nbSeg > 1)
@@ -237,24 +216,8 @@ static inline int crcType(int nbSeg, int len)
typedef struct {
//! estimated rssi (dBm)
int rx_rssi_dBm;
//! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation)
int rx_correlation[2];
//! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation)
int rx_correlation_dB[2];
/// Wideband CQI (= SINR)
int wideband_cqi[MAX_NUM_RU_PER_gNB];
/// Wideband CQI in dB (= SINR dB)
int wideband_cqi_dB[MAX_NUM_RU_PER_gNB];
/// Wideband CQI (sum of all RX antennas, in dB)
char wideband_cqi_tot;
/// Subband CQI per RX antenna and RB (= SINR)
int subband_cqi[MAX_NUM_RU_PER_gNB][275];
/// Total Subband CQI and RB (= SINR)
int subband_cqi_tot[275];
/// Subband CQI in dB and RB (= SINR dB)
int subband_cqi_dB[MAX_NUM_RU_PER_gNB][275];
/// Total Subband CQI and RB
int subband_cqi_tot_dB[275];
} ulsch_measurements_gNB;
typedef struct {
@@ -320,10 +283,6 @@ typedef struct {
typedef struct {
/// \brief Holds the received data in the frequency domain for the allocated RBs in repeated format.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..2*ofdm_symbol_size[
int32_t **rxdataF_ext;
/// \brief Hold the channel estimates in time domain based on DRS.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..4*ofdm_symbol_size[
@@ -332,10 +291,6 @@ typedef struct {
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t **ul_ch_estimates;
/// \brief Uplink channel estimates extracted in PRBS.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t **ul_ch_estimates_ext;
/// \brief Holds the compensated signal.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
@@ -347,7 +302,7 @@ typedef struct {
/// total signal over antennas
uint32_t ulsch_power_tot;
/// measured RX noise power
int ulsch_noise_power[8];
uint32_t ulsch_noise_power[8];
/// total noise over antennas
uint32_t ulsch_noise_power_tot;
/// \brief llr values.
@@ -379,7 +334,7 @@ typedef struct {
/// Context data structure for RX/TX portion of slot processing
typedef struct {
/// Component Carrier index
uint8_t CC_id;
uint8_t CC_id;
/// timestamp transmitted to HW
openair0_timestamp timestamp_tx;
/// slot to act upon for transmission
@@ -393,111 +348,32 @@ typedef struct {
/// \brief Instance count for RXn-TXnp4 processing thread.
/// \internal This variable is protected by \ref mutex_rxtx.
int instance_cnt;
/// pthread structure for RXn-TXnp4 processing thread
pthread_t pthread;
/// pthread attributes for RXn-TXnp4 processing thread
pthread_attr_t attr;
/// condition variable for tx processing thread
pthread_cond_t cond;
/// mutex for RXn-TXnp4 processing thread
pthread_mutex_t mutex;
/// scheduling parameters for RXn-TXnp4 thread
struct sched_param sched_param_rxtx;
/// \internal This variable is protected by \ref mutex_RUs_tx.
int instance_cnt_RUs;
/// condition variable for tx processing thread
pthread_cond_t cond_RUs;
/// mutex for L1 RXTX processing thread
pthread_mutex_t mutex_RUs;
/// mutex for L1 TX FH synchronization
pthread_mutex_t mutex_RUs_tx;
} gNB_L1_rxtx_proc_t;
/// Context data structure for eNB slot processing
typedef struct gNB_L1_proc_t_s {
/// Component Carrier index
uint8_t CC_id;
/// thread index
int thread_index;
uint8_t CC_id;
/// timestamp received from HW
openair0_timestamp timestamp_rx;
/// timestamp to send to "slave rru"
openair0_timestamp timestamp_tx;
/// slot to act upon for reception
int slot_rx;
/// slot to act upon for PRACH
int slot_prach;
/// frame to act upon for reception
int frame_rx;
/// frame to act upon for transmission
int frame_tx;
/// frame to act upon for PRACH
int frame_prach;
/// \internal This variable is protected by \ref mutex_td.
int instance_cnt_td;
/// \internal This variable is protected by \ref mutex_te.
int instance_cnt_te;
/// \internal This variable is protected by \ref mutex_prach.
int instance_cnt_prach;
/// \internal This variable is protected by \ref mutex_asynch_rxtx.
int instance_cnt_asynch_rxtx;
/// pthread structure for eNB single processing thread
pthread_t pthread_single;
/// pthread structure for asychronous RX/TX processing thread
pthread_t pthread_asynch_rxtx;
/// pthread structure for dumping L1 stats
pthread_t L1_stats_thread;
/// pthread structure for printing time meas
pthread_t process_stats_thread;
/// pthread structure for reordering L1 tx thread messages
pthread_t pthread_tx_reorder;
/// flag to indicate first RX acquisition
int first_rx;
/// flag to indicate first TX transmission
int first_tx;
/// pthread attributes for single gNB processing thread
pthread_attr_t attr_single;
/// pthread attributes for prach processing thread
pthread_attr_t attr_prach;
/// pthread attributes for asynchronous RX thread
pthread_attr_t attr_asynch_rxtx;
/// scheduling parameters for parallel turbo-decoder thread
struct sched_param sched_param_td;
/// scheduling parameters for parallel turbo-encoder thread
struct sched_param sched_param_te;
/// scheduling parameters for single eNB thread
struct sched_param sched_param_single;
/// scheduling parameters for prach thread
struct sched_param sched_param_prach;
/// scheduling parameters for asynch_rxtx thread
struct sched_param sched_param_asynch_rxtx;
pthread_cond_t cond_prach;
/// condition variable for asynch RX/TX thread
pthread_cond_t cond_asynch_rxtx;
/// mutex for parallel turbo-decoder thread
pthread_mutex_t mutex_td;
/// mutex for parallel turbo-encoder thread
pthread_mutex_t mutex_te;
/// mutex for PRACH thread
pthread_mutex_t mutex_prach;
/// mutex for asynch RX/TX thread
pthread_mutex_t mutex_asynch_rxtx;
/// mutex for RU access to eNB processing (PDSCH/PUSCH)
pthread_mutex_t mutex_RU;
/// mutex for RU_tx access to eNB_tx processing (PDSCH/PUSCH)
pthread_mutex_t mutex_RU_tx;
/// mutex for RU access to eNB processing (PRACH)
pthread_mutex_t mutex_RU_PRACH;
/// mutex for RU access to eNB processing (PRACH BR)
pthread_mutex_t mutex_RU_PRACH_br;
/// mask for RUs serving eNB (PDSCH/PUSCH)
int RU_mask, RU_mask_tx;
/// mask for RUs serving eNB (PRACH)
int RU_mask_prach;
/// set of scheduling variables RXn-TXnp4 threads
gNB_L1_rxtx_proc_t L1_proc, L1_proc_tx;
gNB_L1_rxtx_proc_t L1_proc;
gNB_L1_rxtx_proc_t L1_proc_tx;
} gNB_L1_proc_t;
typedef struct {
@@ -523,8 +399,7 @@ typedef struct {
//! estimated avg noise power per RB (dBm)
int n0_subband_power_tot_dBm[275];
/// PRACH background noise level
int prach_I0;
int prach_I0;
} PHY_MEASUREMENTS_gNB;
@@ -539,25 +414,23 @@ typedef struct {
/// Top-level PHY Data Structure for gNB
typedef struct PHY_VARS_gNB_s {
/// Module ID indicator for this instance
module_id_t Mod_id;
uint8_t CC_id;
uint8_t configured;
gNB_L1_proc_t proc;
int abstraction_flag;
int num_RU;
RU_t *RU_list[MAX_NUM_RU_PER_gNB];
module_id_t Mod_id;
uint8_t CC_id;
uint8_t configured;
gNB_L1_proc_t proc;
int num_RU;
RU_t *RU_list[MAX_NUM_RU_PER_gNB];
/// Ethernet parameters for northbound midhaul interface
eth_params_t eth_params_n;
eth_params_t eth_params_n;
/// Ethernet parameters for fronthaul interface
eth_params_t eth_params;
int rx_total_gain_dB;
int (*nr_start_if)(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB);
uint8_t local_flag;
nfapi_nr_config_request_scf_t gNB_config;
NR_DL_FRAME_PARMS frame_parms;
eth_params_t eth_params;
int rx_total_gain_dB;
int (*nr_start_if)(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB);
nfapi_nr_config_request_scf_t gNB_config;
NR_DL_FRAME_PARMS frame_parms;
PHY_MEASUREMENTS_gNB measurements;
NR_IF_Module_t *if_inst;
NR_UL_IND_t UL_INFO;
NR_IF_Module_t *if_inst;
NR_UL_IND_t UL_INFO;
/// NFAPI RX ULSCH information
nfapi_nr_rx_data_pdu_t rx_pdu_list[MAX_UL_PDUS_PER_SLOT];
@@ -570,7 +443,7 @@ typedef struct PHY_VARS_gNB_s {
/// NFAPI PRACH information
nfapi_nr_prach_indication_pdu_t prach_pdu_indication_list[MAX_NUM_NR_RX_RACH_PDUS];
nfapi_nr_ul_tti_request_t UL_tti_req;
nfapi_nr_ul_tti_request_t UL_tti_req;
nfapi_nr_uci_indication_t uci_indication;
int max_nb_pucch;
@@ -578,16 +451,15 @@ typedef struct PHY_VARS_gNB_s {
int max_nb_pdsch;
int max_nb_pusch;
NR_gNB_PBCH pbch;
NR_gNB_COMMON common_vars;
NR_gNB_PRACH prach_vars;
NR_gNB_PRS prs_vars;
NR_gNB_COMMON common_vars;
NR_gNB_PRACH prach_vars;
NR_gNB_PRS prs_vars;
NR_gNB_PUSCH *pusch_vars;
NR_gNB_PUCCH_t *pucch;
NR_gNB_SRS_t *srs;
NR_gNB_ULSCH_t *ulsch;
NR_gNB_PHY_STATS_t phy_stats[MAX_MOBILES_PER_GNB];
t_nrPolar_params **polarParams;
t_nrPolar_params **polarParams;
/// SRS variables
nr_srs_info_t **nr_srs_info;
@@ -635,15 +507,11 @@ typedef struct PHY_VARS_gNB_s {
uint64_t bad_pucch;
int num_ulprbbl;
int ulprbbl[275];
/*
time_stats_t phy_proc;
*/
time_stats_t phy_proc_tx;
time_stats_t phy_proc_rx;
time_stats_t rx_prach;
/*
time_stats_t ofdm_mod_stats;
*/
time_stats_t dlsch_encoding_stats;
time_stats_t dlsch_modulation_stats;
time_stats_t dlsch_scrambling_stats;
@@ -678,10 +546,6 @@ typedef struct PHY_VARS_gNB_s {
time_stats_t srs_beam_report_stats;
time_stats_t srs_iq_matrix_stats;
/*
time_stats_t rx_dft_stats;
time_stats_t ulsch_freq_offset_estimation_stats;
*/
notifiedFIFO_t respPuschSymb;
notifiedFIFO_t respDecode;
notifiedFIFO_t resp_L1;
@@ -739,7 +603,7 @@ typedef struct LDPCDecode_s {
struct ldpcReqId {
uint16_t rnti;
uint16_t frame;
uint8_t subframe;
uint8_t slot;
uint8_t codeblock;
uint16_t spare;
} __attribute__((packed));
@@ -756,12 +620,6 @@ typedef struct processingData_L1 {
PHY_VARS_gNB *gNB;
} processingData_L1_t;
typedef enum {
FILLED,
FILLING,
NOT_FILLED
} msgStatus_t;
typedef struct processingData_L1tx {
int frame;
int slot;
+3 -5
View File
@@ -384,7 +384,7 @@ typedef struct PHY_VARS_NR_UE_s {
NR_UE_COMMON common_vars;
nr_ue_if_module_t *if_inst;
bool received_config_request;
fapi_nr_config_request_t nrUE_config;
nr_synch_request_t synch_request;
@@ -450,11 +450,9 @@ typedef struct PHY_VARS_NR_UE_s {
int dlsch_mtch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX];
int dlsch_mcch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX];
int dlsch_mtch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX];
uint8_t decode_SIB;
uint8_t decode_MIB;
uint8_t init_sync_frame;
uint8_t init_sync_frame;
/// temporary offset during cell search prior to MIB decoding
int ssb_offset;
int ssb_offset;
uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync
int64_t max_pos_iir; /// Timing offset IIR filter
int max_pos_acc; /// Timing offset accumuluated error for PI filter
+5 -12
View File
@@ -45,7 +45,7 @@
extern uint8_t nfapi_mode;
void nr_common_signal_procedures(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_dl_tti_ssb_pdu ssb_pdu)
void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame,int slot, nfapi_nr_dl_tti_ssb_pdu ssb_pdu)
{
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
@@ -135,10 +135,9 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_
gNB->common_vars.beam_id[0][slot*fp->symbols_per_slot+j] = cfg->ssb_table.ssb_beam_id_list[ssb_index].beam_id.value;
}
nr_generate_pbch(&ssb_pdu,
gNB->nr_pbch_interleaver,
nr_generate_pbch(gNB,
&ssb_pdu,
&txdataF[0][txdataF_offset],
gNB->TX_AMP,
ssb_start_symbol,
n_hf,
frame,
@@ -346,10 +345,7 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF0.m","chF0",
&gNB->pusch_vars[0].ul_ch_estimates[0][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1);
LOG_M("chestF0_ext.m","chF0_ext",
&gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size))], (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_comp.m","rxsF0_comp",
LOG_M("rxsigF0_comp.m","rxsF0_comp",
&gNB->pusch_vars[0].rxdataF_comp[0][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_llr.m","rxsF0_llr",
@@ -361,10 +357,7 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF1.m","chF1",
&gNB->pusch_vars[0].ul_ch_estimates[1][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1);
LOG_M("chestF1_ext.m","chF1_ext",
&gNB->pusch_vars[0].ul_ch_estimates_ext[1][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size))], (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF1_comp.m","rxsF1_comp",
LOG_M("rxsigF1_comp.m","rxsF1_comp",
&gNB->pusch_vars[0].rxdataF_comp[1][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
ulsch_harq->ulsch_pdu.rb_size)),1,1);
+7 -4
View File
@@ -549,13 +549,14 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response)
return 0;
}
int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config)
void nr_ue_phy_config_request(nr_phy_config_t *phy_config)
{
fapi_nr_config_request_t *nrUE_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config;
PHY_VARS_NR_UE *phy = PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id];
fapi_nr_config_request_t *nrUE_config = &phy->nrUE_config;
if(phy_config != NULL) {
phy->received_config_request = true;
memcpy(nrUE_config, &phy_config->config_req, sizeof(fapi_nr_config_request_t));
}
return 0;
}
void nr_ue_synch_request(nr_synch_request_t *synch_request)
@@ -567,8 +568,10 @@ void nr_ue_synch_request(nr_synch_request_t *synch_request)
void nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config)
{
sl_nr_phy_config_request_t *sl_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->SL_UE_PHY_PARAMS.sl_config;
PHY_VARS_NR_UE *phy = PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id];
sl_nr_phy_config_request_t *sl_config = &phy->SL_UE_PHY_PARAMS.sl_config;
if (phy_config != NULL) {
phy->received_config_request = true;
memcpy(sl_config, &phy_config->sl_config_req, sizeof(sl_nr_phy_config_request_t));
}
}
+1 -1
View File
@@ -46,7 +46,7 @@ int8_t nr_ue_scheduled_response_stub(nr_scheduled_response_t *scheduled_response
/**\brief NR UE FAPI-like P5 message, physical configuration from L2 to configure L1
\param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/
int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config);
void nr_ue_phy_config_request(nr_phy_config_t *phy_config);
void nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config);
/**\brief NR UE FAPI message to schedule a synchronization with target gNB
+11 -12
View File
@@ -204,6 +204,7 @@ int main(int argc, char **argv)
channel_desc_t *gNB2UE;
get_softmodem_params()->sa = 1;
get_softmodem_params()->usim_test = 1;
//uint8_t extended_prefix_flag=0;
//int8_t interf1=-21,interf2=-21;
@@ -230,7 +231,7 @@ int main(int argc, char **argv)
int frame_length_complex_samples_no_prefix;
NR_DL_FRAME_PARMS *frame_parms;
int ret, payload_ret=0;
int ret;
int run_initial_sync=0;
int loglvl=OAILOG_WARNING;
@@ -835,17 +836,15 @@ int main(int argc, char **argv)
rxdataF);
if (ret == 0) {
// UE->rx_ind.rx_indication_body->mib_pdu.ssb_index; //not yet detected automatically
// UE->rx_ind.rx_indication_body->mib_pdu.ssb_length; //Lmax, not yet detected automatically
uint8_t gNB_xtra_byte = 0;
for (int i = 0; i < 8; i++)
gNB_xtra_byte |= ((gNB->pbch.pbch_a >> (31 - i)) & 1) << (7 - i);
payload_ret = (result.xtra_byte == gNB_xtra_byte);
for (i = 0; i < 3; i++) {
payload_ret +=
(result.decoded_output[i] == ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload >> (8 * i)) & 0xff));
}
uint32_t xtra_byte = nr_pbch_extra_byte_generation(frame,
n_hf,
ssb_index,
gNB->gNB_config.ssb_table.ssb_subcarrier_offset.value,
frame_parms->Lmax);
int payload_ret = (result.xtra_byte == xtra_byte);
nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15;
for (int i = 0; i < 3; i++)
payload_ret += (result.decoded_output[i] == ((pdu->bchPayload >> (8 * i)) & 0xff));
// printf("ret %d\n", payload_ret);
if (payload_ret != 4)
n_errors_payload++;
+10 -16
View File
@@ -135,11 +135,6 @@ int main(int argc, char **argv){
int prachOccasion = 0;
double DS_TDL = .03;
// int8_t interf1=-19,interf2=-19;
// uint8_t abstraction_flag=0,calibration_flag=0;
// double prach_sinr;
// uint32_t nsymb;
// uint16_t preamble_max, preamble_energy_max;
FILE *input_fd=NULL;
char* input_file=NULL;
int n_bytes=0;
@@ -784,22 +779,21 @@ int main(int argc, char **argv){
if (n_frames==1) {
printf("preamble %d (tx %d) : energy %d, delay %d\n",preamble_rx,preamble_tx,preamble_energy,preamble_delay);
#ifdef NR_PRACH_DEBUG
LOG_M("prach0.m","prach0", &txdata[0][prach_start], frame_parms->samples_per_subframe, 1, 1);
LOG_M("prachF0.m","prachF0", &gNB->prach_vars.prachF[0], N_ZC, 1, 1);
LOG_M("rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
LOG_M("ru_rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
LOG_M("ru_rxsigF0.m","rxsF0", ru->common.rxdataF[0], frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot, 1, 1);
LOG_M("ru_prach_rxsigF0.m","rxsF0", ru->prach_rxsigF[0][0], N_ZC, 1, 1);
LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1);
LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1);
#endif
#ifdef NR_PRACH_DEBUG
LOG_M("prach0.m","prach0", &txdata[0][prach_start], frame_parms->samples_per_subframe, 1, 1);
LOG_M("rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
LOG_M("ru_rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
LOG_M("ru_rxsigF0.m","rxsF0", ru->common.rxdataF[0], frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot, 1, 1);
LOG_M("ru_prach_rxsigF0.m","rxsF0", ru->prach_rxsigF[0][0], N_ZC, 1, 1);
LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1);
LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1);
#endif
}
}
printf("SNR %f dB, UE Speed %f km/h: errors %u/%d (delay %f)\n", SNR, ue_speed, prach_errors, n_frames, delay_avg/(double)(n_frames-prach_errors));
if (input_fd)
break;
break;
if (prach_errors)
break;
+2 -62
View File
@@ -1266,30 +1266,20 @@ int main(int argc, char *argv[])
if (n_trials == 1 && round == 0) {
__attribute__((unused)) int off = ((nb_rb & 1) == 1) ? 4 : 0;
LOG_M("rxsigF0_ext.m",
"rxsF0_ext",
&pusch_vars->rxdataF_ext[0][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("chestF0.m",
"chF0",
&pusch_vars->ul_ch_estimates[0][start_symbol * frame_parms->ofdm_symbol_size],
frame_parms->ofdm_symbol_size,
1,
1);
LOG_M("chestF0_ext.m",
"chF0_ext",
&pusch_vars->ul_ch_estimates_ext[0][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
(nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("rxsigF0_comp.m",
"rxsF0_comp",
&pusch_vars->rxdataF_comp[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("rxsigF0_llrlayers0.m",
"rxsF0_llrlayers0",
&pusch_vars->llr_layers[0][0],
@@ -1298,12 +1288,6 @@ int main(int argc, char *argv[])
0);
if (precod_nbr_layers == 2) {
LOG_M("rxsigF1_ext.m",
"rxsF1_ext",
&pusch_vars->rxdataF_ext[1][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("chestF3.m",
"chF3",
@@ -1312,13 +1296,6 @@ int main(int argc, char *argv[])
1,
1);
LOG_M("chestF3_ext.m",
"chF3_ext",
&pusch_vars->ul_ch_estimates_ext[3][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
(nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("rxsigF2_comp.m",
"rxsF2_comp",
&pusch_vars->rxdataF_comp[2][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
@@ -1335,24 +1312,6 @@ int main(int argc, char *argv[])
}
if (precod_nbr_layers == 4) {
LOG_M("rxsigF1_ext.m",
"rxsF1_ext",
&pusch_vars->rxdataF_ext[1][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("rxsigF2_ext.m",
"rxsF2_ext",
&pusch_vars->rxdataF_ext[2][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("rxsigF3_ext.m",
"rxsF3_ext",
&pusch_vars->rxdataF_ext[3][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("chestF5.m",
"chF5",
@@ -1373,25 +1332,6 @@ int main(int argc, char *argv[])
1,
1);
LOG_M("chestF5_ext.m",
"chF5_ext",
&pusch_vars->ul_ch_estimates_ext[5][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
(nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("chestF10_ext.m",
"chF10_ext",
&pusch_vars->ul_ch_estimates_ext[10][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
(nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("chestF15_ext.m",
"chF15_ext",
&pusch_vars->ul_ch_estimates_ext[15][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
(nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
LOG_M("rxsigF4_comp.m",
"rxsF4_comp",
&pusch_vars->rxdataF_comp[4][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
-2
View File
@@ -1620,7 +1620,6 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
if (!get_softmodem_params()->emulate_l1)
mac->if_module->phy_config_request(&mac->phy_config);
mac->phy_config_request_sent = true;
}
void nr_rrc_mac_config_req_sib19_r17(module_id_t module_id,
@@ -1676,7 +1675,6 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
mac->synch_request.synch_req.target_Nid_cell = mac->physCellId;
mac->if_module->synch_request(&mac->synch_request);
mac->if_module->phy_config_request(&mac->phy_config);
mac->phy_config_request_sent = true;
}
}
-2
View File
@@ -541,8 +541,6 @@ typedef struct NR_UE_MAC_INST_s {
NR_UL_TIME_ALIGNMENT_t ul_time_alignment;
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon;
bool phy_config_request_sent;
frame_type_t frame_type;
/* Random Access */
-1
View File
@@ -59,7 +59,6 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
nr_ue_reset_sync_state(mac);
mac->get_sib1 = false;
mac->get_otherSI = false;
mac->phy_config_request_sent = false;
memset(&mac->phy_config, 0, sizeof(mac->phy_config));
mac->si_window_start = -1;
mac->servCellIndex = 0;
+2 -2
View File
@@ -346,7 +346,7 @@ static bool is_my_dci(NR_UE_MAC_INST_t *mac, nfapi_nr_dl_dci_pdu_t *received_pdu
if (get_softmodem_params()->sa) {
if (mac->state == UE_NOT_SYNC)
return false;
if (received_pdu->RNTI == 0xFFFF && mac->phy_config_request_sent)
if (received_pdu->RNTI == 0xFFFF)
return false;
if (received_pdu->RNTI != mac->crnti && mac->ra.ra_state == nrRA_SUCCEEDED)
return false;
@@ -1149,7 +1149,7 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info)
LOG_T(NR_MAC, "Not calling scheduler mac->ra.ra_state = %d\n", mac->ra.ra_state);
if (mac->phy_config_request_sent && is_nr_UL_slot(mac->tdd_UL_DL_ConfigurationCommon, ul_info->slot, mac->frame_type))
if (is_nr_UL_slot(mac->tdd_UL_DL_ConfigurationCommon, ul_info->slot, mac->frame_type))
nr_ue_ul_scheduler(mac, ul_info);
pthread_mutex_unlock(&mac_IF_mutex);
+1 -7
View File
@@ -227,18 +227,12 @@ typedef void (nr_sl_ue_scheduled_response_f)(nr_scheduled_response_t *sl_schedul
/*
* Generic type of an application-defined callback to return various
* types of data to the application.
* EXPECTED RETURN VALUES:
* -1: Failed to consume bytes. Abort the mission.
* Non-negative return values indicate success, and ignored.
*/
typedef int8_t (nr_ue_phy_config_request_f)(nr_phy_config_t *phy_config);
typedef void (nr_ue_phy_config_request_f)(nr_phy_config_t *phy_config);
/*
* Generic type of an application-defined callback to return various
* types of data to the application.
* EXPECTED RETURN VALUES:
* -1: Failed to consume bytes. Abort the mission.
* Non-negative return values indicate success, and ignored.
*/
typedef void(nr_ue_sl_phy_config_request_f)(nr_sl_phy_config_t *sl_phy_config);
+3 -2
View File
@@ -30,6 +30,7 @@
# include "nas_parser.h"
# include "nas_proc.h"
#include "common/utils/mem/oai_memory.h"
#include "common/oai_version.h"
#include "nas_user.h"
#include "common/ran_context.h"
@@ -134,7 +135,7 @@ void *nas_ue_task(void *args_p)
user->at_response = calloc_or_fail(1, sizeof(at_response_t));
user->lowerlayer_data = calloc_or_fail(1, sizeof(lowerlayer_data_t));
/* Initialize NAS user */
nas_user_initialize(user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION);
nas_user_initialize(user, &user_api_emm_callback, &user_api_esm_callback, OAI_FIRMWARE_VERSION);
}
}
else
@@ -174,7 +175,7 @@ void *nas_ue_task(void *args_p)
user->at_response = calloc_or_fail(1, sizeof(at_response_t));
user->lowerlayer_data = calloc_or_fail(1, sizeof(lowerlayer_data_t));
/* Initialize NAS user */
nas_user_initialize(user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION);
nas_user_initialize(user, &user_api_emm_callback, &user_api_esm_callback, OAI_FIRMWARE_VERSION);
user->ueid = 0;
}
+10 -1
View File
@@ -92,10 +92,19 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
rx_sym = callback_tag->symbol;
uint32_t ru_id = callback_tag->oXuId;
LOG_D(NR_PHY,
"rx_callback frame %d, subframe %d, slot %d, second %lld, rx_sym %d ru_id %d\n",
frame,
subframe,
slot,
(unsigned long long)second,
rx_sym,
ru_id);
if (rx_sym == 7) {
if (first_call_set) {
if (!first_rx_set) {
LOG_I(NR_PHY, "first_rx is set (num_ports %d)\n", num_ports);
LOG_I(NR_PHY, "first_rx is set (num_ports %d), first_read_set %d\n", num_ports, first_read_set);
}
first_rx_set = 1;
if (first_read_set == 1) {
+6 -2
View File
@@ -392,8 +392,8 @@ static void oran_allocate_buffers(void *handle,
}
}
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->RxCbTag[0][0]);
xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->PrachCbTag[0][0]);
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);
}
int *oai_oran_initialize(const openair0_config_t *openair0_cfg)
@@ -432,7 +432,11 @@ int *oai_oran_initialize(const openair0_config_t *openair0_cfg)
}
int sector = 0;
printf("Initialize ORAN port instance %d (%d) sector %d\n", o_xu_id, init.xran_ports, sector);
oran_port_instance_t *pi = &gPortInst[o_xu_id][sector];
struct xran_cb_tag tag = {.cellId = sector, .oXuId = o_xu_id};
pi->prach_tag = tag;
pi->pusch_tag = tag;
oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, &xran_fh_config[o_xu_id]);
if ((xret = xran_reg_physide_cb(gxran_handle, oai_physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI)) != XRAN_STATUS_SUCCESS) {
+2 -2
View File
@@ -50,8 +50,8 @@ typedef struct oran_port_instance_t {
void *instanceHandle;
//uint32_t dpdkPoolIndex[MAX_SW_XRAN_INTERFACE_NUM];
struct xran_cb_tag RxCbTag[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR];
struct xran_cb_tag PrachCbTag[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR];
struct xran_cb_tag prach_tag;
struct xran_cb_tag pusch_tag;
} oran_port_instance_t;
extern struct xran_fh_config gxran_fh_config[XRAN_PORTS_NUM];
+11 -2
View File
@@ -182,6 +182,8 @@ typedef struct {
static int allocCirBuf(rfsimulator_state_t *bridge, int sock)
{
/* TODO: cleanup code so that this AssertFatal becomes useless */
AssertFatal(sock >= 0 && sock < sizeofArray(bridge->buf), "socket %d is not in range\n", sock);
buffer_t *ptr=&bridge->buf[sock];
ptr->circularBuf = calloc(1, sampleToByte(CirSize, 1));
if (ptr->circularBuf == NULL) {
@@ -302,7 +304,12 @@ static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t)
while (count) {
l = write(fd, buf, count);
if (l <= 0) {
if (l == 0) {
LOG_E(HW, "write() failed, returned 0\n");
return;
}
if (l < 0) {
if (errno==EINTR)
continue;
@@ -310,8 +317,10 @@ static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t)
LOG_D(HW, "write() failed, errno(%d)\n", errno);
usleep(250);
continue;
} else
} else {
LOG_E(HW, "write() failed, errno(%d)\n", errno);
return;
}
}
count -= l;
@@ -0,0 +1,289 @@
Active_gNBs = ( "gNB-OAI-DU");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_DU_ID = 0xe00;
gNB_name = "gNB-OAI-DU";
// 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;
pusch_AntennaPorts = 8;
do_CSIRS = 1;
do_SRS = 0 ;
sib1_tda = 15;
# force_UL256qam_off = 1;
maxMIMO_layers = 2;
pdcch_ConfigSIB1 = (
{
controlResourceSetZero = 11;
searchSpaceZero = 0;
}
);
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# n_TimingAdvanceOffset = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 3430.56 MHz (center frequency)
absoluteFrequencySSB = 628704;
dl_frequencyBand = 78;
# this is 3411.48 MHz
dl_absoluteFrequencyPointA = 627432;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 1;
dl_carrierBandwidth = 106;
#initialDownlinkBWP
#genericParameters
initialDLBWPlocationAndBandwidth = 28875; #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 = 106;
pMax = 23;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 28875;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 1;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 154;
#prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 0;
preambleReceivedTargetPower = -100;
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
preambleTransMax = 8;
#powerRampingStep
# 0=dB0,1=dB2,2=dB4,3=dB6
powerRampingStep = 3;
#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_PositionsInBurs_BitmapPR
# 1=short, 2=medium, 3=long
ssb_PositionsInBurst_PR = 2;
ssb_PositionsInBurst_Bitmap = 0x10001L;
# 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
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 8=ms3 9=ms4
referenceSubcarrierSpacing = 1;
dl_UL_TransmissionPeriodicity = 8;
nrofDownlinkSlots = 3;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 2;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 10;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "f1";
local_n_if_name = "enp193s0f0";
local_n_address = "172.21.16.51";
remote_n_address = "172.21.6.90";
local_n_portc = 500;
local_n_portd = 2153;
remote_n_portc = 501;
remote_n_portd = 2153;
pusch_TargetSNRx10 = 230;
pucch_TargetSNRx10 = 270;
dl_bler_target_upper = .35;
dl_bler_target_lower = .15;
ul_bler_target_upper = .35;
ul_bler_target_lower = .15;
pusch_FailureThres = 100;
ul_max_mcs = 28;
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 100;
pucch0_dtx_threshold = 80;
pusch_dtx_threshold = 10;
max_ldpc_iterations = 10;
tx_amp_backoff_dB = 12; # needs to match O-RU configuration
L1_rx_thread_core = 8;
L1_tx_thread_core = 10; # relevant after merge of l1_tx_thread
phase_compensation = 0; # needs to match O-RU configuration
}
);
RUs = (
{
local_rf = "no";
nb_tx = 8;
nb_rx = 8;
att_tx = 0
att_rx = 0;
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
sf_extension = 0;
eNB_instances = [0];
ru_thread_core = 9;
sl_ahead = 10;
clock_src = "internal";
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";
f1ap_log_level = "info";
};
fhi_72 = {
dpdk_devices = ("0000:01:01.0", "0000:01:01.1", "0000:01:01.2", "0000:01:01.3");
system_core = 0;
io_core = 1;
worker_cores = (2);
du_addr = ("00:11:22:33:44:66","00:11:22:33:44:67","00:11:22:33:44:68","00:11:22:33:44:69");
ru_addr = ("70:b3:d5:e1:5b:ff","70:b3:d5:e1:5b:ff","70:b3:d5:e1:5b:81", "70:b3:d5:e1:5b:81");
mtu = 9216;
file_prefix = "fhi_72";
fh_config = (
# RAN650
{
Tadv_cp_dl = 125;
T2a_cp_dl = (259, 500);
T2a_cp_ul = (25, 500);
T2a_up = (134, 375);
Ta3 = (152, 160);
T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336);
T1a_up = (294, 345);
Ta4 = (0, 200);
ru_config = {
iq_width = 9;
iq_width_prach = 9;
};
prach_config = {
eAxC_offset = 4;
};
},
# RAN550
{
Tadv_cp_dl = 125;
T2a_cp_dl = (259, 500);
T2a_cp_ul = (25, 500);
T2a_up = (134, 375);
Ta3 = (152, 160);
T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336);
T1a_up = (294, 345);
Ta4 = (0, 200);
ru_config = {
iq_width = 9;
iq_width_prach = 9;
};
prach_config = {
eAxC_offset = 4;
};
});
};