Merge branch 'integration_2024_w51' into 'develop'
Integration: `2024.w51` Closes #879 See merge request oai/openairinterface5g!3180 * !3155 UL BLER vs SNR plot * !3170 Replace AssertFatal with static_assert for cmdline arguments check * !3172 A script to run CI tests locally. * !3151 Optimize PHY_ofdm_mod CYCLIC_PREFIX in case of incidentally aligned pointers * !3164 Fix and refactor channel average * !3154 Fix TPMI for UL retransmissions
This commit is contained in:
@@ -47,6 +47,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER):
|
||||
py_param_file_present = False
|
||||
py_params={}
|
||||
|
||||
force_local = False
|
||||
while len(argvs) > 1:
|
||||
myArgv = argvs.pop(1) # 0th is this file's name
|
||||
|
||||
@@ -54,6 +55,9 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER):
|
||||
if re.match('^\-\-help$', myArgv, re.IGNORECASE):
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit(0)
|
||||
if re.match('^\-\-local$', myArgv, re.IGNORECASE):
|
||||
force_local = True
|
||||
|
||||
|
||||
#--apply=<filename> as parameters file, to replace inline parameters
|
||||
elif re.match('^\-\-Apply=(.+)$', myArgv, re.IGNORECASE):
|
||||
@@ -271,4 +275,4 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER):
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('Invalid Parameter: ' + myArgv)
|
||||
|
||||
return py_param_file_present, py_params, mode
|
||||
return py_param_file_present, py_params, mode, force_local
|
||||
|
||||
@@ -217,6 +217,8 @@ class RemoteCmd(Cmd):
|
||||
return client
|
||||
|
||||
def _lookup_ssh_config(hostname):
|
||||
if is_local(hostname):
|
||||
raise ValueError("Using localhost as SSH target is not allowed: use LocalCmd instead.")
|
||||
ssh_config = paramiko.SSHConfig()
|
||||
user_config_file = os.path.expanduser("~/.ssh/config")
|
||||
if os.path.exists(user_config_file):
|
||||
|
||||
@@ -43,6 +43,8 @@ def GenericHelp(vers):
|
||||
print(' InitiateHtml, FinalizeHtml')
|
||||
print(' TerminateeNB, TerminateHSS, TerminateMME, TerminateSPGW')
|
||||
print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf')
|
||||
print(' --local Force local execution: rewrites the test xml script before running to always execute on localhost. Assumes')
|
||||
print(' images are available locally, will not remove any images and will run inside the current repo directory')
|
||||
|
||||
def GitSrvHelp(repository,branch,commit,mergeallow,targetbranch):
|
||||
print(' --ranRepository=[OAI RAN Repository URL] -- ' + repository)
|
||||
|
||||
+40
-20
@@ -212,13 +212,17 @@ def ExecuteActionWithParam(action):
|
||||
|
||||
elif action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Terminate_UE' or action == 'CheckStatusUE' or action == 'DataEnable_UE' or action == 'DataDisable_UE':
|
||||
CiTestObj.ue_ids = test.findtext('id').split(' ')
|
||||
if test.findtext('nodes'):
|
||||
CiTestObj.nodes = test.findtext('nodes').split(' ')
|
||||
if len(CiTestObj.ue_ids) != len(CiTestObj.nodes):
|
||||
logging.error('Number of Nodes are not equal to the total number of UEs')
|
||||
sys.exit("Mismatch in number of Nodes and UIs")
|
||||
if force_local:
|
||||
# Change all execution targets to localhost
|
||||
CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids)
|
||||
else:
|
||||
CiTestObj.nodes = [None] * len(CiTestObj.ue_ids)
|
||||
if test.findtext('nodes'):
|
||||
CiTestObj.nodes = test.findtext('nodes').split(' ')
|
||||
if len(CiTestObj.ue_ids) != len(CiTestObj.nodes):
|
||||
logging.error('Number of Nodes are not equal to the total number of UEs')
|
||||
sys.exit("Mismatch in number of Nodes and UIs")
|
||||
else:
|
||||
CiTestObj.nodes = [None] * len(CiTestObj.ue_ids)
|
||||
if action == 'Initialize_UE':
|
||||
success = CiTestObj.InitializeUE(HTML)
|
||||
elif action == 'Attach_UE':
|
||||
@@ -238,13 +242,17 @@ def ExecuteActionWithParam(action):
|
||||
CiTestObj.ping_args = test.findtext('ping_args')
|
||||
CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold')
|
||||
CiTestObj.ue_ids = test.findtext('id').split(' ')
|
||||
if test.findtext('nodes'):
|
||||
CiTestObj.nodes = test.findtext('nodes').split(' ')
|
||||
if len(CiTestObj.ue_ids) != len(CiTestObj.nodes):
|
||||
logging.error('Number of Nodes are not equal to the total number of UEs')
|
||||
sys.exit("Mismatch in number of Nodes and UIs")
|
||||
if force_local:
|
||||
# Change all execution targets to localhost
|
||||
CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids)
|
||||
else:
|
||||
CiTestObj.nodes = [None] * len(CiTestObj.ue_ids)
|
||||
if test.findtext('nodes'):
|
||||
CiTestObj.nodes = test.findtext('nodes').split(' ')
|
||||
if len(CiTestObj.ue_ids) != len(CiTestObj.nodes):
|
||||
logging.error('Number of Nodes are not equal to the total number of UEs')
|
||||
sys.exit("Mismatch in number of Nodes and UIs")
|
||||
else:
|
||||
CiTestObj.nodes = [None] * len(CiTestObj.ue_ids)
|
||||
ping_rttavg_threshold = test.findtext('ping_rttavg_threshold') or ''
|
||||
success = CiTestObj.Ping(HTML,EPC,CONTAINERS)
|
||||
|
||||
@@ -252,15 +260,19 @@ def ExecuteActionWithParam(action):
|
||||
CiTestObj.iperf_args = test.findtext('iperf_args')
|
||||
CiTestObj.ue_ids = test.findtext('id').split(' ')
|
||||
CiTestObj.svr_id = test.findtext('svr_id') or None
|
||||
if test.findtext('nodes'):
|
||||
CiTestObj.nodes = test.findtext('nodes').split(' ')
|
||||
if len(CiTestObj.ue_ids) != len(CiTestObj.nodes):
|
||||
logging.error('Number of Nodes are not equal to the total number of UEs')
|
||||
sys.exit("Mismatch in number of Nodes and UIs")
|
||||
if force_local:
|
||||
# Change all execution targets to localhost
|
||||
CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids)
|
||||
else:
|
||||
CiTestObj.nodes = [None] * len(CiTestObj.ue_ids)
|
||||
if test.findtext('nodes'):
|
||||
CiTestObj.nodes = test.findtext('nodes').split(' ')
|
||||
if len(CiTestObj.ue_ids) != len(CiTestObj.nodes):
|
||||
logging.error('Number of Nodes are not equal to the total number of UEs')
|
||||
sys.exit("Mismatch in number of Nodes and UIs")
|
||||
else:
|
||||
CiTestObj.nodes = [None] * len(CiTestObj.ue_ids)
|
||||
if test.findtext('svr_node'):
|
||||
CiTestObj.svr_node = test.findtext('svr_node')
|
||||
CiTestObj.svr_node = test.findtext('svr_node') if not force_local else 'localhost'
|
||||
CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold')
|
||||
CiTestObj.iperf_bitrate_threshold = test.findtext('iperf_bitrate_threshold') or '90'
|
||||
CiTestObj.iperf_profile = test.findtext('iperf_profile') or 'balanced'
|
||||
@@ -356,6 +368,9 @@ def ExecuteActionWithParam(action):
|
||||
elif action == 'Undeploy_Object':
|
||||
success = CONTAINERS.UndeployObject(HTML, RAN)
|
||||
elif action == 'Create_Workspace':
|
||||
if force_local:
|
||||
# Do not create a working directory when running locally. Current repo directory will be used
|
||||
return True
|
||||
success = CONTAINERS.Create_Workspace(HTML)
|
||||
|
||||
elif action == 'Run_Physim':
|
||||
@@ -375,6 +390,9 @@ def ExecuteActionWithParam(action):
|
||||
success = CONTAINERS.Push_Image_to_Local_Registry(HTML, svr_id)
|
||||
|
||||
elif action == 'Pull_Local_Registry' or action == 'Clean_Test_Server_Images':
|
||||
if force_local:
|
||||
# Do not pull or remove images when running locally. User is supposed to handle image creation & cleanup
|
||||
return True
|
||||
svr_id = test.findtext('svr_id')
|
||||
images = test.findtext('images').split()
|
||||
# hack: for FlexRIC, we need to overwrite the tag to use
|
||||
@@ -463,7 +481,9 @@ CLUSTER = cls_cluster.Cluster()
|
||||
#-----------------------------------------------------------
|
||||
|
||||
import args_parse
|
||||
py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER)
|
||||
# Force local execution, move all execution targets to localhost
|
||||
force_local = False
|
||||
py_param_file_present, py_params, mode, force_local = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER)
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
SHORT_COMMIT_SHA=$(git rev-parse --short=8 HEAD)
|
||||
COMMIT_SHA=$(git rev-parse HEAD)
|
||||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
REPO_PATH=$(dirname $(realpath $0))/../
|
||||
TESTCASE=$1
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
echo "Provide a testcase as an argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The script assumes you've build the following images:
|
||||
#
|
||||
# docker build . -f docker/Dockerfile.gNB.ubuntu22 -t oai-gnb
|
||||
# docker build . -f docker/Dockerfile.nrUE.ubuntu22 -t oai-nr-ue
|
||||
#
|
||||
# The images above depend on the following images:
|
||||
#
|
||||
# docker build . -f docker/Dockerfile.build.ubuntu22 -t ran-build
|
||||
# dokcer build . -f docker/Dockerfile.base.ubuntu22 -t ran-base
|
||||
|
||||
docker tag oai-nr-ue oai-ci/oai-nr-ue:develop-${SHORT_COMMIT_SHA}
|
||||
docker tag oai-gnb oai-ci/oai-gnb:develop-${SHORT_COMMIT_SHA}
|
||||
|
||||
python3 main.py --mode=TesteNB --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \
|
||||
--ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \
|
||||
--ranTargetBranch=NONE --eNBIPAddress=NONE --eNBUserName=NONE --eNBPassword=NONE \
|
||||
--eNBSourceCodePath=NONE --EPCIPAddress=NONE --EPCType=OAI --eNBPassword=NONE \
|
||||
--eNBSourceCodePath=${REPO_PATH} --EPCIPAddress=NONE \
|
||||
--EPCUserName=NONE --EPCPassword=NONE --EPCSourceCodePath=NONE \
|
||||
--XMLTestFile=xml_files/${TESTCASE} --local
|
||||
@@ -3,7 +3,7 @@ add_subdirectory(config/yaml)
|
||||
|
||||
configure_file(oai_version.h.in oai_version.h @ONLY)
|
||||
|
||||
add_library(instrumentation INTERFACE instrumentation.h)
|
||||
add_library(instrumentation INTERFACE)
|
||||
target_include_directories(instrumentation INTERFACE .)
|
||||
if (TRACY_ENABLE)
|
||||
target_link_libraries(instrumentation INTERFACE Tracy::TracyClient)
|
||||
|
||||
@@ -105,8 +105,9 @@ void get_common_options(configmodule_interface_t *cfg, uint32_t execmask)
|
||||
|
||||
paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC;
|
||||
checkedparam_t cmdline_CheckParams[] = CMDLINE_PARAMS_CHECK_DESC;
|
||||
static_assert(sizeofArray(cmdline_params) == sizeofArray(cmdline_CheckParams),
|
||||
"cmdline_params and cmdline_CheckParams should have the same size");
|
||||
int numparams = sizeofArray(cmdline_params);
|
||||
AssertFatal(numparams == sizeofArray(cmdline_CheckParams), "Error in arrays size (%d!=%lu)\n", numparams, sizeofArray(cmdline_CheckParams));
|
||||
config_set_checkfunctions(cmdline_params, cmdline_CheckParams, numparams);
|
||||
config_get(cfg, cmdline_params, numparams, NULL);
|
||||
nfapi_index = config_paramidx_fromname(cmdline_params, numparams, "nfapi");
|
||||
@@ -115,9 +116,10 @@ void get_common_options(configmodule_interface_t *cfg, uint32_t execmask)
|
||||
|
||||
paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
|
||||
checkedparam_t cmdline_log_CheckParams[] = CMDLINE_LOGPARAMS_CHECK_DESC;
|
||||
int numlogparams = sizeofArray(cmdline_logparams);
|
||||
AssertFatal(numlogparams == sizeofArray(cmdline_log_CheckParams), "Error in arrays size (%d!=%lu)\n", numlogparams, sizeofArray(cmdline_log_CheckParams));
|
||||
static_assert(sizeofArray(cmdline_logparams) == sizeofArray(cmdline_log_CheckParams),
|
||||
"cmdline_logparams and cmdline_log_CheckParams should have the same size");
|
||||
|
||||
int numlogparams = sizeofArray(cmdline_logparams);
|
||||
config_set_checkfunctions(cmdline_logparams, cmdline_log_CheckParams, numlogparams);
|
||||
config_get(cfg, cmdline_logparams, numlogparams, NULL);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
@param nb_prefix_samples The number of prefix/suffix/zero samples
|
||||
@param etype Type of extension (CYCLIC_PREFIX,CYCLIC_SUFFIX,ZEROS)
|
||||
*/
|
||||
void PHY_ofdm_mod(int *input,
|
||||
void PHY_ofdm_mod(const int *input,
|
||||
int *output,
|
||||
int fftsize,
|
||||
unsigned char nb_symbols,
|
||||
|
||||
@@ -40,6 +40,9 @@ This section deals with basic functions for OFDM Modulation.
|
||||
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
|
||||
//#define DEBUG_OFDM_MOD
|
||||
|
||||
// Use 64-byte alignment for IDFT output buffer to ensure no
|
||||
// runtime error in case IDFT implementation uses AVX-512.
|
||||
#define IDFT_OUTPUT_BUFFER_ALIGNMENT 64
|
||||
|
||||
void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
@@ -122,109 +125,90 @@ void nr_normal_prefix_mod(c16_t *txdataF, c16_t *txdata, uint8_t nsymb, const NR
|
||||
|
||||
}
|
||||
|
||||
void PHY_ofdm_mod(int *input, /// pointer to complex input
|
||||
int *output, /// pointer to complex output
|
||||
int fftsize, /// FFT_SIZE
|
||||
unsigned char nb_symbols, /// number of OFDM symbols
|
||||
unsigned short nb_prefix_samples, /// cyclic prefix length
|
||||
Extension_t etype /// type of extension
|
||||
)
|
||||
void PHY_ofdm_mod(const int *input, /// pointer to complex input
|
||||
int *output, /// pointer to complex output
|
||||
int fftsize, /// FFT_SIZE
|
||||
unsigned char nb_symbols, /// number of OFDM symbols
|
||||
unsigned short nb_prefix_samples, /// cyclic prefix length
|
||||
Extension_t etype /// type of extension
|
||||
)
|
||||
{
|
||||
if (nb_symbols == 0)
|
||||
return;
|
||||
|
||||
if(nb_symbols == 0) return;
|
||||
|
||||
int16_t temp[2*2*6144*4] __attribute__((aligned(32)));
|
||||
int i,j;
|
||||
|
||||
volatile int *output_ptr=(int*)0;
|
||||
|
||||
int *temp_ptr=(int*)0;
|
||||
idft_size_idx_t idft_size = get_idft(fftsize);
|
||||
|
||||
#ifdef DEBUG_OFDM_MOD
|
||||
printf("[PHY] OFDM mod (size %d,prefix %d) Symbols %d, input %p, output %p\n",
|
||||
fftsize,nb_prefix_samples,nb_symbols,input,output);
|
||||
fftsize,
|
||||
nb_prefix_samples,
|
||||
nb_symbols,
|
||||
input,
|
||||
output);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
for (i=0; i<nb_symbols; i++) {
|
||||
|
||||
for (int i = 0; i < nb_symbols; i++) {
|
||||
#ifdef DEBUG_OFDM_MOD
|
||||
printf("[PHY] symbol %d/%d offset %d (%p,%p -> %p)\n",i,nb_symbols,i*fftsize+(i*nb_prefix_samples),input,&input[i*fftsize],&output[(i*fftsize) + ((i)*nb_prefix_samples)]);
|
||||
printf("[PHY] symbol %d/%d offset %d (%p,%p -> %p)\n",
|
||||
i,
|
||||
nb_symbols,
|
||||
i * fftsize + (i * nb_prefix_samples),
|
||||
input,
|
||||
&input[i * fftsize],
|
||||
&output[(i * fftsize) + ((i)*nb_prefix_samples)]);
|
||||
#endif
|
||||
|
||||
// on AVX2 need 256-bit alignment
|
||||
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)temp, 1);
|
||||
|
||||
// Copy to frame buffer with Cyclic Extension
|
||||
// Note: will have to adjust for synchronization offset!
|
||||
|
||||
switch (etype) {
|
||||
case CYCLIC_PREFIX:
|
||||
output_ptr = &output[(i*fftsize) + ((1+i)*nb_prefix_samples)];
|
||||
temp_ptr = (int *)temp;
|
||||
|
||||
|
||||
// msg("Doing cyclic prefix method\n");
|
||||
|
||||
{
|
||||
memcpy((void*)output_ptr,(void*)temp_ptr,fftsize<<2);
|
||||
}
|
||||
memcpy((void*)&output_ptr[-nb_prefix_samples],(void*)&output_ptr[fftsize-nb_prefix_samples],nb_prefix_samples<<2);
|
||||
break;
|
||||
|
||||
case CYCLIC_SUFFIX:
|
||||
|
||||
|
||||
output_ptr = &output[(i*fftsize)+ (i*nb_prefix_samples)];
|
||||
|
||||
temp_ptr = (int *)temp;
|
||||
|
||||
// msg("Doing cyclic suffix method\n");
|
||||
|
||||
for (j=0; j<fftsize ; j++) {
|
||||
output_ptr[j] = temp_ptr[2*j];
|
||||
case CYCLIC_PREFIX: {
|
||||
int *output_ptr = &output[(i * fftsize) + ((1 + i) * nb_prefix_samples)];
|
||||
// Current idft implementation uses AVX-256: Check if buffer is already aligned to 256 bits (32 bytes)
|
||||
if ((uintptr_t)output_ptr % 32 == 0) {
|
||||
// output ptr is aligned, do ifft inplace
|
||||
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)output_ptr, 1);
|
||||
} else {
|
||||
// output ptr is not aligned, needs an extra memcpy
|
||||
c16_t temp[fftsize] __attribute__((aligned(IDFT_OUTPUT_BUFFER_ALIGNMENT)));
|
||||
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)temp, 1);
|
||||
memcpy((void *)output_ptr, (void *)temp, sizeof(temp));
|
||||
}
|
||||
// perform cyclic prefix insertion
|
||||
memcpy((void *)&output_ptr[-nb_prefix_samples], (void *)&output_ptr[fftsize - nb_prefix_samples], nb_prefix_samples * sizeof(c16_t));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
for (j=0; j<nb_prefix_samples; j++)
|
||||
output_ptr[fftsize+j] = output_ptr[j];
|
||||
|
||||
break;
|
||||
|
||||
case ZEROS:
|
||||
|
||||
break;
|
||||
|
||||
case NONE:
|
||||
|
||||
// msg("NO EXTENSION!\n");
|
||||
output_ptr = &output[fftsize];
|
||||
|
||||
temp_ptr = (int *)temp;
|
||||
|
||||
for (j=0; j<fftsize ; j++) {
|
||||
output_ptr[j] = temp_ptr[2*j];
|
||||
|
||||
|
||||
case CYCLIC_SUFFIX: {
|
||||
// Use alignment of 64 bytes
|
||||
c16_t temp[fftsize] __attribute__((aligned(IDFT_OUTPUT_BUFFER_ALIGNMENT)));
|
||||
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)temp, 1);
|
||||
int *output_ptr = &output[(i * fftsize) + (i * nb_prefix_samples)];
|
||||
memcpy(output_ptr, temp, sizeof(temp));
|
||||
memcpy(&output_ptr[fftsize], temp, nb_prefix_samples * sizeof(c16_t));
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case ZEROS:
|
||||
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
|
||||
case NONE: {
|
||||
c16_t temp[fftsize] __attribute__((aligned(IDFT_OUTPUT_BUFFER_ALIGNMENT)));
|
||||
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)temp, 1);
|
||||
int *output_ptr = &output[i * fftsize];
|
||||
memcpy(output_ptr, temp, sizeof(temp));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void do_OFDM_mod(c16_t **txdataF, c16_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
|
||||
|
||||
@@ -209,25 +209,17 @@ static void nr_ulsch_channel_level(int size_est,
|
||||
uint32_t len,
|
||||
uint8_t nrOfLayers)
|
||||
{
|
||||
simde__m128i *ul_ch128, avg128U;
|
||||
|
||||
int16_t x = factor2(len);
|
||||
int16_t y = (len)>>x;
|
||||
|
||||
for (int aatx = 0; aatx < nrOfLayers; aatx++) {
|
||||
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
//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];
|
||||
simde__m128i *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));
|
||||
}
|
||||
|
||||
int32_t *avg32i = (int32_t *)&avg128U;
|
||||
int64_t avg64 = (int64_t)avg32i[0] + avg32i[1] + avg32i[2] + avg32i[3];
|
||||
avg[aatx * frame_parms->nb_antennas_rx + aarx] = avg64 / y;
|
||||
//compute average level
|
||||
avg[aatx * frame_parms->nb_antennas_rx + aarx] = simde_mm_average(ul_ch128, len, x, y);
|
||||
//LOG_D(PHY, "Channel level: %d\n", avg[aatx * frame_parms->nb_antennas_rx + aarx]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -226,30 +226,12 @@ void nr_pdcch_channel_level(int32_t rx_size,
|
||||
int nb_rb)
|
||||
{
|
||||
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
//clear average level
|
||||
simde__m128i avg128P = simde_mm_setzero_si128();
|
||||
|
||||
simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx][symbol * nb_rb * 12];
|
||||
|
||||
for (int rb = 0; rb < (nb_rb * 3) >> 2; rb++) {
|
||||
avg128P = simde_mm_add_epi32(avg128P,simde_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
|
||||
avg128P = simde_mm_add_epi32(avg128P,simde_mm_madd_epi16(dl_ch128[1],dl_ch128[1]));
|
||||
avg128P = simde_mm_add_epi32(avg128P,simde_mm_madd_epi16(dl_ch128[2],dl_ch128[2]));
|
||||
// for (int i=0;i<24;i+=2) printf("pdcch channel re %d (%d,%d)\n",(rb*12)+(i>>1),((int16_t*)dl_ch128)[i],((int16_t*)dl_ch128)[i+1]);
|
||||
dl_ch128+=3;
|
||||
/*
|
||||
if (rb==0) {
|
||||
print_shorts("dl_ch128",&dl_ch128[0]);
|
||||
print_shorts("dl_ch128",&dl_ch128[1]);
|
||||
print_shorts("dl_ch128",&dl_ch128[2]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
DevAssert(nb_rb);
|
||||
avg[aarx] = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
avg[aarx] += ((int32_t *)&avg128P)[i] / (nb_rb * 9);
|
||||
LOG_DDD("Channel level : %d\n",avg[aarx]);
|
||||
//compute average level
|
||||
avg[aarx] = simde_mm_average(dl_ch128, nb_rb * 12, 0, nb_rb * 12);
|
||||
//LOG_DDD("Channel level : %d\n", avg[aarx]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1098,28 +1098,20 @@ void nr_dlsch_channel_level(uint32_t rx_size_symbol,
|
||||
int32_t avg[MAX_ANT][MAX_ANT],
|
||||
uint32_t len)
|
||||
{
|
||||
simde__m128i *dl_ch128, avg128D;
|
||||
//nb_rb*nre = y * 2^x
|
||||
int16_t x = factor2(len);
|
||||
int16_t y = (len) >> x;
|
||||
|
||||
uint32_t nb_rb_0 = len / NR_NB_SC_PER_RB + ((len % NR_NB_SC_PER_RB) ? 1 : 0);
|
||||
LOG_D(NR_PHY, "nb_rb_0 %d len %d = %d * 2^(%d)\n", nb_rb_0, len, y, x);
|
||||
|
||||
for (int aatx = 0; aatx < n_tx; aatx++) {
|
||||
for (int aarx = 0; aarx < n_rx; aarx++) {
|
||||
//clear average level
|
||||
avg128D = simde_mm_setzero_si128();
|
||||
|
||||
dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[(aatx * n_rx) + aarx];
|
||||
simde__m128i *dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[(aatx * n_rx) + aarx];
|
||||
|
||||
for (int rb = 0; rb < nb_rb_0; rb++) {
|
||||
avg128D = simde_mm_add_epi32(avg128D,simde_mm_srai_epi32(simde_mm_madd_epi16(dl_ch128[0],dl_ch128[0]),x));
|
||||
avg128D = simde_mm_add_epi32(avg128D,simde_mm_srai_epi32(simde_mm_madd_epi16(dl_ch128[1],dl_ch128[1]),x));
|
||||
avg128D = simde_mm_add_epi32(avg128D,simde_mm_srai_epi32(simde_mm_madd_epi16(dl_ch128[2],dl_ch128[2]),x));
|
||||
dl_ch128+=3;
|
||||
}
|
||||
int32_t *tmp = (int32_t *)&avg128D;
|
||||
avg[aatx][aarx] = ((int64_t)tmp[0] + tmp[1] + tmp[2] + tmp[3]) / y;
|
||||
LOG_D(PHY, "Channel level: %d\n", avg[aatx][aarx]);
|
||||
//compute average level
|
||||
avg[aatx][aarx] = simde_mm_average(dl_ch128, nb_rb_0 * 12, x, y);
|
||||
//LOG_D(PHY, "Channel level: %d\n", avg[aatx][aarx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,31 +208,14 @@ int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
int nb_re)
|
||||
{
|
||||
int16_t nb_rb=nb_re/12;
|
||||
simde__m128i avg128;
|
||||
simde__m128i *dl_ch128;
|
||||
int avg1=0,avg2=0;
|
||||
int32_t avg2 = 0;
|
||||
|
||||
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
//clear average level
|
||||
avg128 = simde_mm_setzero_si128();
|
||||
dl_ch128=(simde__m128i *)dl_ch_estimates_ext[aarx];
|
||||
|
||||
for (int rb=0; rb<nb_rb; rb++) {
|
||||
avg128 = simde_mm_add_epi32(avg128, simde_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
|
||||
avg128 = simde_mm_add_epi32(avg128, simde_mm_madd_epi16(dl_ch128[1],dl_ch128[1]));
|
||||
avg128 = simde_mm_add_epi32(avg128, simde_mm_madd_epi16(dl_ch128[2],dl_ch128[2]));
|
||||
dl_ch128+=3;
|
||||
/*
|
||||
if (rb==0) {
|
||||
print_shorts("dl_ch128",&dl_ch128[0]);
|
||||
print_shorts("dl_ch128",&dl_ch128[1]);
|
||||
print_shorts("dl_ch128",&dl_ch128[2]);
|
||||
}*/
|
||||
}
|
||||
simde__m128i *dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[aarx];
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
avg1 += ((int *)&avg128)[i] / (nb_rb * 12);
|
||||
//compute average level
|
||||
int32_t avg1 = simde_mm_average(dl_ch128, nb_re, 0, nb_re);
|
||||
|
||||
if (avg1>avg2)
|
||||
avg2 = avg1;
|
||||
|
||||
+94
-31
@@ -49,13 +49,6 @@
|
||||
#define SSE_INTRIN_H
|
||||
|
||||
|
||||
#include <simde/x86/mmx.h>
|
||||
#include <simde/x86/sse.h>
|
||||
#include <simde/x86/sse2.h>
|
||||
#include <simde/x86/sse3.h>
|
||||
#include <simde/x86/ssse3.h>
|
||||
#include <simde/x86/sse4.1.h>
|
||||
#include <simde/x86/sse4.2.h>
|
||||
#include <simde/x86/avx2.h>
|
||||
#include <simde/x86/fma.h>
|
||||
#if defined(__x86_64) || defined(__i386__)
|
||||
@@ -81,31 +74,101 @@
|
||||
* OAI specific
|
||||
*/
|
||||
|
||||
static const short minusConjug128[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1};
|
||||
static inline simde__m128i mulByConjugate128(simde__m128i *a, simde__m128i *b, int8_t output_shift) {
|
||||
|
||||
simde__m128i realPart = simde_mm_madd_epi16(*a,*b);
|
||||
realPart = simde_mm_srai_epi32(realPart,output_shift);
|
||||
simde__m128i imagPart = simde_mm_shufflelo_epi16(*b, SIMDE_MM_SHUFFLE(2,3,0,1));
|
||||
imagPart = simde_mm_shufflehi_epi16(imagPart, SIMDE_MM_SHUFFLE(2,3,0,1));
|
||||
imagPart = simde_mm_sign_epi16(imagPart,*(simde__m128i *)minusConjug128);
|
||||
imagPart = simde_mm_madd_epi16(imagPart,*a);
|
||||
imagPart = simde_mm_srai_epi32(imagPart,output_shift);
|
||||
simde__m128i lowPart = simde_mm_unpacklo_epi32(realPart,imagPart);
|
||||
simde__m128i highPart = simde_mm_unpackhi_epi32(realPart,imagPart);
|
||||
return ( simde_mm_packs_epi32(lowPart,highPart));
|
||||
static const short minusConjug128[8] __attribute__((aligned(16))) = {-1, 1, -1, 1, -1, 1, -1, 1};
|
||||
static inline simde__m128i mulByConjugate128(simde__m128i *a, simde__m128i *b, int8_t output_shift)
|
||||
{
|
||||
simde__m128i realPart = simde_mm_madd_epi16(*a, *b);
|
||||
realPart = simde_mm_srai_epi32(realPart, output_shift);
|
||||
simde__m128i imagPart = simde_mm_shufflelo_epi16(*b, SIMDE_MM_SHUFFLE(2, 3, 0, 1));
|
||||
imagPart = simde_mm_shufflehi_epi16(imagPart, SIMDE_MM_SHUFFLE(2, 3, 0, 1));
|
||||
imagPart = simde_mm_sign_epi16(imagPart, *(simde__m128i *)minusConjug128);
|
||||
imagPart = simde_mm_madd_epi16(imagPart, *a);
|
||||
imagPart = simde_mm_srai_epi32(imagPart, output_shift);
|
||||
simde__m128i lowPart = simde_mm_unpacklo_epi32(realPart, imagPart);
|
||||
simde__m128i highPart = simde_mm_unpackhi_epi32(realPart, imagPart);
|
||||
return (simde_mm_packs_epi32(lowPart, highPart));
|
||||
}
|
||||
|
||||
#define displaySamples128(vect) {\
|
||||
simde__m128i x=vect; \
|
||||
printf("vector: %s = (%hd,%hd) (%hd,%hd) (%hd,%hd) (%hd,%hd)\n", #vect, \
|
||||
simde_mm_extract_epi16(x,0), \
|
||||
simde_mm_extract_epi16(x,1),\
|
||||
simde_mm_extract_epi16(x,2),\
|
||||
simde_mm_extract_epi16(x,3),\
|
||||
simde_mm_extract_epi16(x,4),\
|
||||
simde_mm_extract_epi16(x,5),\
|
||||
simde_mm_extract_epi16(x,6),\
|
||||
simde_mm_extract_epi16(x,7));\
|
||||
#define displaySamples128(vect) \
|
||||
{ \
|
||||
simde__m128i x = vect; \
|
||||
printf("vector: %s = (%hd,%hd) (%hd,%hd) (%hd,%hd) (%hd,%hd)\n", \
|
||||
#vect, \
|
||||
simde_mm_extract_epi16(x, 0), \
|
||||
simde_mm_extract_epi16(x, 1), \
|
||||
simde_mm_extract_epi16(x, 2), \
|
||||
simde_mm_extract_epi16(x, 3), \
|
||||
simde_mm_extract_epi16(x, 4), \
|
||||
simde_mm_extract_epi16(x, 5), \
|
||||
simde_mm_extract_epi16(x, 6), \
|
||||
simde_mm_extract_epi16(x, 7)); \
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int64_t simde_mm_average_sse(simde__m128i *a, int length, int shift)
|
||||
{
|
||||
// compute average level with shift (64-bit verstion)
|
||||
simde__m128i avg128 = simde_mm_setzero_si128();
|
||||
for (int i = 0; i < length >> 2; i++) {
|
||||
const simde__m128i in1 = a[i];
|
||||
avg128 = simde_mm_add_epi32(avg128, simde_mm_srai_epi32(simde_mm_madd_epi16(in1, in1), shift));
|
||||
}
|
||||
|
||||
// Horizontally add pairs
|
||||
// 1st [A + C, B + D]
|
||||
simde__m128i sum_pairs = simde_mm_add_epi64(simde_mm_unpacklo_epi32(avg128, simde_mm_setzero_si128()), // [A, B] → [A, 0, B, 0]
|
||||
simde_mm_unpackhi_epi32(avg128, simde_mm_setzero_si128()) // [C, D] → [C, 0, D, 0]
|
||||
);
|
||||
|
||||
// 2nd [A + B + C + D, ...]
|
||||
simde__m128i total_sum = simde_mm_add_epi64(sum_pairs, simde_mm_shuffle_epi32(sum_pairs, SIMDE_MM_SHUFFLE(1, 0, 3, 2)));
|
||||
|
||||
// Extract horizontal sum as a scalar int64_t result
|
||||
return simde_mm_cvtsi128_si64(total_sum);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int64_t simde_mm_average_avx2(simde__m256i *a, int length, int shift)
|
||||
{
|
||||
simde__m256i avg256 = simde_mm256_setzero_si256();
|
||||
for (int i = 0; i < length >> 3; i++) {
|
||||
const simde__m256i in1 = simde_mm256_loadu_si256(&a[i]); // unaligned load
|
||||
avg256 = simde_mm256_add_epi32(avg256, simde_mm256_srai_epi32(simde_mm256_madd_epi16(in1, in1), shift));
|
||||
}
|
||||
|
||||
// Split the 256-bit vector into two 128-bit halves and convert to 64-bit
|
||||
// [A + E, B + F, C + G, D + H]
|
||||
simde__m256i sum_pairs = simde_mm256_add_epi64(
|
||||
simde_mm256_cvtepi32_epi64(simde_mm256_castsi256_si128(avg256)), // [A, B, C, D] → [A, 0, B, 0, C, 0, D, 0]
|
||||
simde_mm256_cvtepi32_epi64(simde_mm256_extracti128_si256(avg256, 1)) // [E, F, G, H] → [E, 0, F, 0, G, 0, H, 0]
|
||||
);
|
||||
|
||||
// Horizontal sum within the 256-bit vector
|
||||
// [A + E + B + F, C + G + D + H]
|
||||
simde__m128i total_sum = simde_mm_add_epi64(simde_mm256_castsi256_si128(sum_pairs), simde_mm256_extracti128_si256(sum_pairs, 1));
|
||||
|
||||
// [A + E + B + F + C + G + D + H, ...]
|
||||
total_sum = simde_mm_add_epi64(total_sum, simde_mm_shuffle_epi32(total_sum, SIMDE_MM_SHUFFLE(1, 0, 3, 2)));
|
||||
|
||||
// Extract horizontal sum as a scalar int64_t result
|
||||
return simde_mm_cvtsi128_si64(total_sum);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int32_t simde_mm_average(simde__m128i *a, int length, int shift, int16_t scale)
|
||||
{
|
||||
int64_t avg = 0;
|
||||
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
if (__builtin_cpu_supports("avx2")) {
|
||||
avg += simde_mm_average_avx2((simde__m256i *)a, length, shift);
|
||||
|
||||
// tail processing by SSE
|
||||
a += ((length & ~7) >> 2);
|
||||
length -= (length & ~7);
|
||||
}
|
||||
#endif
|
||||
|
||||
avg += simde_mm_average_sse(a, length, shift);
|
||||
|
||||
return (uint32_t)(avg / scale);
|
||||
}
|
||||
|
||||
#endif // SSE_INTRIN_H
|
||||
|
||||
@@ -94,6 +94,8 @@ MessageDef *RCconfig_NR_CU_E1(const E1_t *entity)
|
||||
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_PLMNParams[] = PLMNPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_PLMNParams) == sizeofArray(PLMNParams),
|
||||
"config_check_PLMNParams and PLMNParams should have the same size");
|
||||
|
||||
for (int I = 0; I < sizeofArray(PLMNParams); ++I)
|
||||
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
|
||||
|
||||
@@ -266,9 +266,13 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc) {
|
||||
paramlist_def_t ENBParamList = {ENB_CONFIG_STRING_ENB_LIST,NULL,0};
|
||||
checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK;
|
||||
paramdef_t CCsParams[] = CCPARAMS_DESC(ccparams_lte);
|
||||
static_assert(sizeofArray(config_check_CCparams) == sizeofArray(CCsParams),
|
||||
"config_check_CCparams and CCsParams should have the same size");
|
||||
paramlist_def_t CCsParamList = {ENB_CONFIG_STRING_COMPONENT_CARRIERS,NULL,0};
|
||||
paramdef_t eMTCParams[] = EMTCPARAMS_DESC((&eMTCconfig));
|
||||
checkedparam_t config_check_eMTCparams[] = EMTCPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_eMTCparams) == sizeofArray(eMTCParams),
|
||||
"config_check_eMTCparams and eMTCParamsCCsParams should have the same size");
|
||||
srb1_params_t srb1_params;
|
||||
memset((void *)&srb1_params,0,sizeof(srb1_params_t));
|
||||
paramdef_t SRB1Params[] = SRB1PARAMS_DESC(srb1_params);
|
||||
@@ -320,6 +324,8 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc) {
|
||||
paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_PLMNParams) == sizeofArray(PLMNParams),
|
||||
"config_check_PLMNParams and PLMNParams should have the same size");
|
||||
|
||||
for (int I = 0; I < sizeofArray(PLMNParams); ++I)
|
||||
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
|
||||
@@ -1910,6 +1916,8 @@ int RCconfig_M2(MessageDef *msg_p, uint32_t i) {
|
||||
paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_PLMNParams) == sizeofArray(PLMNParams),
|
||||
"config_check_PLMNParams and PLMNParams should have the same size");
|
||||
|
||||
for (int I = 0; I < sizeofArray(PLMNParams); ++I)
|
||||
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
|
||||
@@ -2159,6 +2167,8 @@ int RCconfig_S1(
|
||||
paramdef_t CCsParams[] = CCPARAMS_DESC(ccparams_lte);
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_CCparams) == sizeofArray(CCsParams),
|
||||
"config_check_CCparams and CCsParams should have the same size");
|
||||
|
||||
for (int I = 0; I < sizeofArray(CCsParams); I++) {
|
||||
CCsParams[I].chkPptr = &(config_check_CCparams[I]);
|
||||
@@ -2166,6 +2176,8 @@ int RCconfig_S1(
|
||||
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_PLMNParams) == sizeofArray(PLMNParams),
|
||||
"config_check_PLMNParams and PLMNParams should have the same size");
|
||||
|
||||
for (int I = 0; I < sizeofArray(PLMNParams); ++I) {
|
||||
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
|
||||
@@ -2413,6 +2425,8 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
|
||||
config_get(config_get_if(), ENBSParams, sizeofArray(ENBSParams), NULL);
|
||||
checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK;
|
||||
paramdef_t CCsParams[] = CCPARAMS_DESC(ccparams_lte);
|
||||
static_assert(sizeofArray(config_check_CCparams) == sizeofArray(CCsParams),
|
||||
"config_check_CCparams and CCsParams should have the same size");
|
||||
paramlist_def_t CCsParamList = {ENB_CONFIG_STRING_COMPONENT_CARRIERS, NULL, 0};
|
||||
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
@@ -2450,6 +2464,8 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
|
||||
paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_PLMNParams) == sizeofArray(PLMNParams),
|
||||
"config_check_PLMNParams and PLMNParams should have the same size");
|
||||
|
||||
for (int I = 0; I < sizeofArray(PLMNParams); ++I)
|
||||
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
|
||||
|
||||
@@ -749,43 +749,6 @@ typedef struct ccparams_lte_s {
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } , \
|
||||
{ { NULL } } \
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -351,6 +351,7 @@ typedef struct ccparams_eMTC_s {
|
||||
{ {NULL}} , \
|
||||
{ {NULL}} , \
|
||||
{ {NULL}} , \
|
||||
{ {NULL}} , \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -1118,6 +1118,8 @@ static int read_du_cell_info(configmodule_interface_t *cfg,
|
||||
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_PLMNParams[] = PLMNPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_PLMNParams) == sizeofArray(PLMNParams),
|
||||
"config_check_PLMNParams and PLMNParams should have the same size");
|
||||
for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
|
||||
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
|
||||
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
@@ -1151,6 +1153,8 @@ static int read_du_cell_info(configmodule_interface_t *cfg,
|
||||
paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC;
|
||||
paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0};
|
||||
checkedparam_t config_check_SNSSAIParams[] = SNSSAIPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_SNSSAIParams) == sizeofArray(SNSSAIParams),
|
||||
"config_check_SNSSAIParams and SNSSAIParams should have the same size");
|
||||
for (int J = 0; J < sizeofArray(SNSSAIParams); ++J)
|
||||
SNSSAIParams[J].chkPptr = &(config_check_SNSSAIParams[J]);
|
||||
char snssaistr[MAX_OPTNAME_SIZE * 2 + 8];
|
||||
@@ -1288,6 +1292,8 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_GNBParams[] = GNBPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_GNBParams) == sizeofArray(GNBParams),
|
||||
"config_check_GNBParams and GNBParams should have the same size");
|
||||
for (int i = 0; i < sizeofArray(GNBParams); ++i)
|
||||
GNBParams[i].chkPptr = &(config_check_GNBParams[i]);
|
||||
config_getlist(cfg, &GNBParamList, GNBParams, sizeofArray(GNBParams), NULL);
|
||||
@@ -1296,6 +1302,8 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_MacRLCParams[] = MACRLCPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_MacRLCParams) == sizeofArray(MacRLC_Params),
|
||||
"config_check_MacRLCParams and MacRLC_Params should have the same size");
|
||||
for (int i = 0; i < sizeofArray(MacRLC_Params); ++i)
|
||||
MacRLC_Params[i].chkPptr = &(config_check_MacRLCParams[i]);
|
||||
config_getlist(config_get_if(), &MacRLC_ParamList, MacRLC_Params, sizeofArray(MacRLC_Params), NULL);
|
||||
@@ -1906,6 +1914,8 @@ gNB_RRC_INST *RCconfig_NRRRC()
|
||||
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_PLMNParams) == sizeofArray(PLMNParams),
|
||||
"config_check_PLMNParams and PLMNParams should have the same size");
|
||||
|
||||
for (int I = 0; I < sizeofArray(PLMNParams); ++I)
|
||||
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
|
||||
@@ -2013,7 +2023,11 @@ int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i) {
|
||||
paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_PLMNParams) == sizeofArray(PLMNParams),
|
||||
"config_check_PLMNParams and PLMNParams should have the same size");
|
||||
checkedparam_t config_check_SNSSAIParams [] = SNSSAIPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_SNSSAIParams) == sizeofArray(SNSSAIParams),
|
||||
"config_check_SNSSAIParams and SNSSAIParams should have the same size");
|
||||
|
||||
for (int I = 0; I < sizeofArray(PLMNParams); ++I)
|
||||
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
|
||||
@@ -2277,6 +2291,8 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) {
|
||||
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
|
||||
static_assert(sizeofArray(config_check_PLMNParams) == sizeofArray(PLMNParams),
|
||||
"config_check_PLMNParams and PLMNParams should have the same size");
|
||||
|
||||
for (int I = 0; I < sizeofArray(PLMNParams); ++I)
|
||||
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
|
||||
|
||||
@@ -2822,6 +2822,7 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
|
||||
dci_field_t srs_resource_indicator,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
const uint8_t *nrOfLayers,
|
||||
int *tpmi,
|
||||
uint32_t *val)
|
||||
{
|
||||
// It is only applicable to codebook based transmission. This field occupies 0 bits for non-codebook based
|
||||
@@ -2841,6 +2842,7 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
|
||||
long max_rank = *pusch_Config->maxRank;
|
||||
long *ul_FullPowerTransmission = pusch_Config->ext1 ? pusch_Config->ext1->ul_FullPowerTransmission_r16 : NULL;
|
||||
long *codebookSubset = pusch_Config->codebookSubset;
|
||||
int ul_tpmi = tpmi ? *tpmi : srs_feedback ? srs_feedback->tpmi : -1;
|
||||
|
||||
if (pusch_antenna_ports == 2) {
|
||||
|
||||
@@ -2854,21 +2856,21 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
nbits = 2;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 2,"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = srs_feedback->tpmi;
|
||||
AssertFatal(ul_tpmi <= 2,"TPMI %d is invalid!\n", ul_tpmi);
|
||||
*val = ul_tpmi;
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 1;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 1,"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = srs_feedback->tpmi;
|
||||
AssertFatal(ul_tpmi <= 1,"TPMI %d is invalid!\n", ul_tpmi);
|
||||
*val = ul_tpmi;
|
||||
}
|
||||
} else {
|
||||
nbits = 3;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 5,"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = srs_feedback->tpmi;
|
||||
AssertFatal(ul_tpmi <= 5,"TPMI %d is invalid!\n", ul_tpmi);
|
||||
*val = ul_tpmi;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2881,25 +2883,25 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
|
||||
if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) {
|
||||
nbits = 2;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 2) || (*nrOfLayers==2 && srs_feedback->tpmi == 0),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = *nrOfLayers==1 ? table_7_3_1_1_2_4A_1layer[srs_feedback->tpmi] : 2;
|
||||
AssertFatal((*nrOfLayers==1 && ul_tpmi <= 2) || (*nrOfLayers==2 && ul_tpmi == 0),
|
||||
"TPMI %d is invalid!\n", ul_tpmi);
|
||||
*val = *nrOfLayers==1 ? table_7_3_1_1_2_4A_1layer[ul_tpmi] : 2;
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 2;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 1) || (*nrOfLayers==2 && srs_feedback->tpmi == 0),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = *nrOfLayers==1 ? srs_feedback->tpmi : 2;
|
||||
AssertFatal((*nrOfLayers==1 && ul_tpmi <= 1) || (*nrOfLayers==2 && ul_tpmi == 0),
|
||||
"TPMI %d is invalid!\n", ul_tpmi);
|
||||
*val = *nrOfLayers==1 ? ul_tpmi : 2;
|
||||
}
|
||||
} else {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 5) || (*nrOfLayers==2 && srs_feedback->tpmi <= 2),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
*val = *nrOfLayers==1 ? table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[srs_feedback->tpmi] :
|
||||
table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[srs_feedback->tpmi];
|
||||
AssertFatal((*nrOfLayers==1 && ul_tpmi <= 5) || (*nrOfLayers==2 && ul_tpmi <= 2),
|
||||
"TPMI %d is invalid!\n", ul_tpmi);
|
||||
*val = *nrOfLayers==1 ? table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[ul_tpmi] :
|
||||
table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[ul_tpmi];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2918,36 +2920,36 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 3;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 3 || srs_feedback->tpmi == 13, "TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal(ul_tpmi <= 3 || ul_tpmi == 13, "TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
} else {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 15, "TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal(ul_tpmi <= 15, "TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
}
|
||||
if (val && srs_feedback) {
|
||||
*val = table_7_3_1_1_2_3A[srs_feedback->tpmi];
|
||||
*val = table_7_3_1_1_2_3A[ul_tpmi];
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 2;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 3, "TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal(ul_tpmi <= 3, "TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
} else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 11, "TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal(ul_tpmi <= 11, "TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
} else {
|
||||
nbits = 5;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal(srs_feedback->tpmi <= 27, "TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal(ul_tpmi <= 27, "TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
}
|
||||
if (val && srs_feedback) {
|
||||
*val = srs_feedback->tpmi;
|
||||
*val = ul_tpmi;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -2965,48 +2967,48 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && (srs_feedback->tpmi <= 3 || srs_feedback->tpmi==13)) || (*nrOfLayers==2 && srs_feedback->tpmi <= 6),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal((*nrOfLayers==1 && (ul_tpmi <= 3 || ul_tpmi==13)) || (*nrOfLayers==2 && ul_tpmi <= 6),
|
||||
"TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
} else {
|
||||
nbits = 5;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 15) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal((*nrOfLayers==1 && ul_tpmi <= 15) || (*nrOfLayers==2 && ul_tpmi <= 13),
|
||||
"TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
}
|
||||
if (val && srs_feedback) {
|
||||
*val = *nrOfLayers==1 ? table_7_3_1_1_2_2A_1layer[srs_feedback->tpmi] : table_7_3_1_1_2_2A_2layers[srs_feedback->tpmi];
|
||||
*val = *nrOfLayers==1 ? table_7_3_1_1_2_2A_1layer[ul_tpmi] : table_7_3_1_1_2_2A_2layers[ul_tpmi];
|
||||
}
|
||||
} else {
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && (srs_feedback->tpmi <= 3 || srs_feedback->tpmi == 13)) || (*nrOfLayers==2 && srs_feedback->tpmi <= 6) ||
|
||||
(*nrOfLayers==3 && srs_feedback->tpmi <= 1) || (*nrOfLayers==4 && srs_feedback->tpmi == 0),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal((*nrOfLayers==1 && (ul_tpmi <= 3 || ul_tpmi == 13)) || (*nrOfLayers==2 && ul_tpmi <= 6) ||
|
||||
(*nrOfLayers==3 && ul_tpmi <= 1) || (*nrOfLayers==4 && ul_tpmi == 0),
|
||||
"TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
} else {
|
||||
nbits = 6;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 15) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13) ||
|
||||
(*nrOfLayers==3 && srs_feedback->tpmi <= 2) || (*nrOfLayers==4 && srs_feedback->tpmi <= 2),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal((*nrOfLayers==1 && ul_tpmi <= 15) || (*nrOfLayers==2 && ul_tpmi <= 13) ||
|
||||
(*nrOfLayers==3 && ul_tpmi <= 2) || (*nrOfLayers==4 && ul_tpmi <= 2),
|
||||
"TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
}
|
||||
if (val && srs_feedback) {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
*val = table_7_3_1_1_2_2B_1layer[srs_feedback->tpmi];
|
||||
*val = table_7_3_1_1_2_2B_1layer[ul_tpmi];
|
||||
break;
|
||||
case 2:
|
||||
*val = table_7_3_1_1_2_2B_2layers[srs_feedback->tpmi];
|
||||
*val = table_7_3_1_1_2_2B_2layers[ul_tpmi];
|
||||
break;
|
||||
case 3:
|
||||
*val = table_7_3_1_1_2_2B_3layers[srs_feedback->tpmi];
|
||||
*val = table_7_3_1_1_2_2B_3layers[ul_tpmi];
|
||||
break;
|
||||
case 4:
|
||||
*val = table_7_3_1_1_2_2B_4layers[srs_feedback->tpmi];
|
||||
*val = table_7_3_1_1_2_2B_4layers[ul_tpmi];
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
@@ -3017,38 +3019,38 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
|
||||
if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) {
|
||||
nbits = 4;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 3) || (*nrOfLayers==2 && srs_feedback->tpmi <= 5) ||
|
||||
(*nrOfLayers==3 && srs_feedback->tpmi == 0) || (*nrOfLayers==4 && srs_feedback->tpmi == 0),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal((*nrOfLayers==1 && ul_tpmi <= 3) || (*nrOfLayers==2 && ul_tpmi <= 5) ||
|
||||
(*nrOfLayers==3 && ul_tpmi == 0) || (*nrOfLayers==4 && ul_tpmi == 0),
|
||||
"TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
} else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) {
|
||||
nbits = 5;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 11) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13) ||
|
||||
(*nrOfLayers==3 && srs_feedback->tpmi <= 2) || (*nrOfLayers==4 && srs_feedback->tpmi <= 2),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal((*nrOfLayers==1 && ul_tpmi <= 11) || (*nrOfLayers==2 && ul_tpmi <= 13) ||
|
||||
(*nrOfLayers==3 && ul_tpmi <= 2) || (*nrOfLayers==4 && ul_tpmi <= 2),
|
||||
"TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
} else {
|
||||
nbits = 6;
|
||||
if (val && srs_feedback) {
|
||||
AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 28) || (*nrOfLayers==2 && srs_feedback->tpmi <= 22) ||
|
||||
(*nrOfLayers==3 && srs_feedback->tpmi <= 7) || (*nrOfLayers==4 && srs_feedback->tpmi <= 5),
|
||||
"TPMI %d is invalid!\n", srs_feedback->tpmi);
|
||||
AssertFatal((*nrOfLayers==1 && ul_tpmi <= 28) || (*nrOfLayers==2 && ul_tpmi <= 22) ||
|
||||
(*nrOfLayers==3 && ul_tpmi <= 7) || (*nrOfLayers==4 && ul_tpmi <= 5),
|
||||
"TPMI %d is invalid!\n", ul_tpmi);
|
||||
}
|
||||
}
|
||||
if (val && srs_feedback) {
|
||||
switch (*nrOfLayers) {
|
||||
case 1:
|
||||
*val = table_7_3_1_1_2_2_1layer[srs_feedback->tpmi];
|
||||
*val = table_7_3_1_1_2_2_1layer[ul_tpmi];
|
||||
break;
|
||||
case 2:
|
||||
*val = table_7_3_1_1_2_2_2layers[srs_feedback->tpmi];
|
||||
*val = table_7_3_1_1_2_2_2layers[ul_tpmi];
|
||||
break;
|
||||
case 3:
|
||||
*val = table_7_3_1_1_2_2_3layers[srs_feedback->tpmi];
|
||||
*val = table_7_3_1_1_2_2_3layers[ul_tpmi];
|
||||
break;
|
||||
case 4:
|
||||
*val = table_7_3_1_1_2_2_4layers[srs_feedback->tpmi];
|
||||
*val = table_7_3_1_1_2_2_4layers[ul_tpmi];
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers);
|
||||
@@ -3299,7 +3301,8 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP,
|
||||
size += dci_pdu->srs_resource_indicator.nbits;
|
||||
LOG_D(NR_MAC, "dci_pdu->srs_resource_indicator.nbits %d\n", dci_pdu->srs_resource_indicator.nbits);
|
||||
// Precoding info and number of layers
|
||||
dci_pdu->precoding_information.nbits = compute_precoding_information(pusch_Config, srs_config, dci_pdu->srs_resource_indicator, NULL, NULL, NULL);
|
||||
dci_pdu->precoding_information.nbits =
|
||||
compute_precoding_information(pusch_Config, srs_config, dci_pdu->srs_resource_indicator, NULL, NULL, NULL, NULL);
|
||||
size += dci_pdu->precoding_information.nbits;
|
||||
LOG_D(NR_MAC, "dci_pdu->precoding_informaiton.nbits=%d\n", dci_pdu->precoding_information.nbits);
|
||||
// Antenna ports
|
||||
|
||||
@@ -79,6 +79,7 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config,
|
||||
dci_field_t srs_resource_indicator,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
const uint8_t *nrOfLayers,
|
||||
int *tpmi,
|
||||
uint32_t *val);
|
||||
|
||||
NR_PDSCH_TimeDomainResourceAllocationList_t *get_dl_tdalist(const NR_UE_DL_BWP_t *DL_BWP,
|
||||
|
||||
@@ -894,6 +894,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
pusch_pdu,
|
||||
&uldci_payload,
|
||||
NULL,
|
||||
NULL,
|
||||
ra->Msg3_tda_id,
|
||||
ra->msg3_TPC,
|
||||
1, // Not toggling NDI in msg3 retransmissions
|
||||
|
||||
@@ -782,6 +782,7 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info,
|
||||
const nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
int *tpmi,
|
||||
int time_domain_assignment,
|
||||
uint8_t tpc,
|
||||
uint8_t ndi,
|
||||
@@ -830,6 +831,7 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info,
|
||||
dci_pdu_rel15->srs_resource_indicator,
|
||||
srs_feedback,
|
||||
&pusch_pdu->nrOfLayers,
|
||||
tpmi,
|
||||
&dci_pdu_rel15->precoding_information.val);
|
||||
|
||||
// antenna_ports.val = 0 for transform precoder is disabled, dmrs-Type=1, maxLength=1, Rank=1/2/3/4
|
||||
|
||||
@@ -2256,6 +2256,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n
|
||||
|
||||
uint16_t rnti = UE->rnti;
|
||||
sched_ctrl->SR = false;
|
||||
int *tpmi = NULL;
|
||||
|
||||
int8_t harq_id = sched_pusch->ul_harq_pid;
|
||||
if (harq_id < 0) {
|
||||
@@ -2297,6 +2298,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n
|
||||
* retransmissions */
|
||||
cur_harq->sched_pusch.time_domain_allocation = sched_pusch->time_domain_allocation;
|
||||
cur_harq->sched_pusch.nrOfLayers = sched_pusch->nrOfLayers;
|
||||
cur_harq->sched_pusch.tpmi = sched_pusch->tpmi;
|
||||
sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
|
||||
UE->mac_stats.ul.total_rbs += sched_pusch->rbSize;
|
||||
|
||||
@@ -2397,6 +2399,10 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n
|
||||
else
|
||||
pusch_pdu->data_scrambling_id = *scc->physCellId;
|
||||
pusch_pdu->nrOfLayers = sched_pusch->nrOfLayers;
|
||||
// If nrOfLayers is the same as in srs_feedback, we use the best TPMI, i.e. the one in srs_feedback.
|
||||
// Otherwise, we use the valid TPMI that we saved in the first transmission.
|
||||
if (pusch_pdu->nrOfLayers != (sched_ctrl->srs_feedback.ul_ri + 1))
|
||||
tpmi = &sched_pusch->tpmi;
|
||||
pusch_pdu->num_dmrs_cdm_grps_no_data = sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data;
|
||||
|
||||
/* FAPI: DMRS */
|
||||
@@ -2572,6 +2578,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n
|
||||
pusch_pdu,
|
||||
&uldci_payload,
|
||||
&sched_ctrl->srs_feedback,
|
||||
tpmi,
|
||||
sched_pusch->time_domain_allocation,
|
||||
UE->UE_sched_ctrl.tpc0,
|
||||
cur_harq->ndi,
|
||||
|
||||
@@ -163,6 +163,7 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info,
|
||||
const nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
nr_srs_feedback_t *srs_feedback,
|
||||
int *tpmi,
|
||||
int time_domain_assignment,
|
||||
uint8_t tpc,
|
||||
uint8_t ndi,
|
||||
|
||||
@@ -422,6 +422,8 @@ typedef struct NR_sched_pusch {
|
||||
int8_t ul_harq_pid;
|
||||
|
||||
uint8_t nrOfLayers;
|
||||
int tpmi;
|
||||
|
||||
// time_domain_allocation is the index of a list of tda
|
||||
int time_domain_allocation;
|
||||
NR_tda_info_t tda_info;
|
||||
|
||||
@@ -529,8 +529,9 @@ void trace_pdu_implementation(ws_trace_t *t)
|
||||
int init_opt(void) {
|
||||
paramdef_t opt_params[] = OPT_PARAMS_DESC ;
|
||||
checkedparam_t opt_checkParams[] = OPTPARAMS_CHECK_DESC;
|
||||
static_assert(sizeofArray(opt_params) == sizeofArray(opt_checkParams),
|
||||
"opt_params and opt_checkParams should have the same size");
|
||||
int sz=sizeofArray(opt_params);
|
||||
AssertFatal(sz == sizeofArray(opt_checkParams), "Error in arrays size (%d!=%lu)\n", sz, sizeofArray(opt_checkParams));
|
||||
config_set_checkfunctions(opt_params, opt_checkParams, sz);
|
||||
config_get(config_get_if(), opt_params, sz, OPT_CONFIGPREFIX);
|
||||
subframesSinceCaptureStart = 0;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Plotting tools
|
||||
|
||||
## `ul_bler_vs_snr_graph.py`
|
||||
|
||||
This generates UL BLER vs SNR plots using nr_ulsim. It uses cache so subsequent runs are faster.
|
||||
Assumes your nr_ulsim is in `../../cmake_targets/ran_build/build`. Run with -h flag to see options
|
||||
|
||||
Example graph:
|
||||
|
||||

|
||||
|
||||
### Cache usage and modifting `nr_ulsim` command
|
||||
|
||||
Modify the script call to `nr_ulsim` if you want a different channel model or other flags in the `nr_ulsim` command.
|
||||
Remember to clear the cache (remove `cache.pkl` from this folder) so that the results from a different run are not
|
||||
taken from the cache.
|
||||
|
||||
Same goes for any software modifications of `nr_ulsim` - the cache is not aware of the software version used to generate
|
||||
the data - remember to clear your cache manually if you are comparing different `nr_ulsim` versions.
|
||||
|
||||
The script also allows to skip usage of the cache with `--rerun` option.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,2 @@
|
||||
matplotlib==3.8.3
|
||||
numpy==1.21.5
|
||||
Executable
+128
@@ -0,0 +1,128 @@
|
||||
#!/bin/python3
|
||||
import os
|
||||
import subprocess
|
||||
import numpy as np
|
||||
import re
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.cm as cm
|
||||
import pickle
|
||||
import argparse
|
||||
import concurrent.futures
|
||||
import traceback
|
||||
import multiprocessing
|
||||
|
||||
default_ulsim_cmd = "../../cmake_targets/ran_build/build/nr_ulsim -i 1,0 -t 100 -R 273"
|
||||
ulsim_args = "-n {} -s {} -S {} -m {} -r {}"
|
||||
|
||||
def find_throughput(line):
|
||||
### Example line
|
||||
### SNR 10.000000: Channel BLER (0.000000e+00,-nan,-nan,-nan Channel BER (1.548551e-03,-nan,-nan,-nan) Avg round 1.00, Eff Rate 1672.0000 bits/slot, Eff Throughput 100.00, TBS 1672 bits/slot
|
||||
### SNR -0.000000: Channel BLER (0.000000e+00,-nan,-nan,-nan Channel BER (1.888043e-01,-nan,-nan,-nan) Avg round 1.00, Eff Rate 2152.0000 bits/slot, Eff Throughput 100.00, TBS 2152 bits/slot
|
||||
pattern = r"SNR (-?\d+.\d+).*BLER \((-?\d+\.\d*(?:[eE][+-]\d+)?),.*Eff Throughput (\d+.\d+)"
|
||||
match = re.search(pattern, line)
|
||||
if match:
|
||||
snr, bler, thp = match.groups()
|
||||
return float(snr), float(bler), float(thp)
|
||||
return None, None, None
|
||||
|
||||
def generate_mcs_thps(ulsim_cmd_with_args, snr, mcs, num_runs = 10, num_rbs = 50, cache = {}):
|
||||
thp = 0
|
||||
bler = 0
|
||||
num_runs_cached = 0
|
||||
cache_string = "{},{},{}".format(snr, mcs, num_rbs)
|
||||
if cache_string in cache:
|
||||
thp, bler, num_runs_cached = cache[cache_string]
|
||||
if num_runs_cached >= num_runs:
|
||||
return bler, thp
|
||||
|
||||
num_runs_left = num_runs - num_runs_cached
|
||||
|
||||
ulsim_cmd_formatted = ulsim_cmd_with_args.format(num_runs_left, snr, snr+0.01, mcs, num_rbs)
|
||||
print(ulsim_cmd_formatted, "result insufficient in cache, running")
|
||||
process = subprocess.Popen(ulsim_cmd_formatted.split(" "), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout_data = process.communicate()[0]
|
||||
output = ""
|
||||
if stdout_data is not None:
|
||||
output = stdout_data.decode()
|
||||
for line in output.splitlines():
|
||||
_snr, _bler, _thp = find_throughput(line)
|
||||
if _snr is not None:
|
||||
bler = (bler * num_runs_cached + _bler * num_runs_left) / num_runs
|
||||
thp = (thp * num_runs_cached + _thp * num_runs_left) / num_runs
|
||||
cache[cache_string] = thp, bler, num_runs
|
||||
return bler, thp
|
||||
print("error processing "+ ulsim_cmd_with_args)
|
||||
print(output)
|
||||
print(process.communicate()[1].decode())
|
||||
return None, None
|
||||
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="UL SNR/BLER plot generator")
|
||||
parser.add_argument("--snr-start", help="Starting SNR value")
|
||||
parser.add_argument("--snr-stop", help="Final SNR value")
|
||||
parser.add_argument("--snr-step", help="SNR step value")
|
||||
parser.add_argument("--mcs-start", help="First MCS to test")
|
||||
parser.add_argument("--mcs-stop", help="Last MCS to test")
|
||||
parser.add_argument("--num-runs", help="Number of simulations per SNR/MCS value")
|
||||
parser.add_argument("--rerun", help="Do not use cache to read data, run from scrach", action="store_true")
|
||||
parser.add_argument("--num-rbs", help="Number of RBs")
|
||||
parser.add_argument("--ulsim-cmd", help="ULSIM command to run. Do not use `sSrnm` flags, as these are used by the script", default=default_ulsim_cmd)
|
||||
|
||||
cpu_count = multiprocessing.cpu_count()
|
||||
cpu_to_use = max(1, cpu_count - 2)
|
||||
|
||||
parser.add_argument("--num-threads", help="Number of threads to run", default=cpu_to_use)
|
||||
args = parser.parse_args()
|
||||
|
||||
_snr_start = float(args.snr_start)
|
||||
_snr_step = float(args.snr_step)
|
||||
_snr_end = float(args.snr_stop) + _snr_step/2
|
||||
_mcs_start = int(args.mcs_start)
|
||||
_mcs_stop = int(args.mcs_stop)
|
||||
_num_runs = int(args.num_runs)
|
||||
_num_rbs = int(args.num_rbs)
|
||||
ulsim_cmd = args.ulsim_cmd + " " + ulsim_args
|
||||
num_threads = int(args.num_threads)
|
||||
|
||||
cmap = cm.viridis
|
||||
plt.figure()
|
||||
plt.ylim(-0.1, 1.1)
|
||||
plt.title("BLER vs SNR for MCS{} to MCS{}, nRB={} (num_runs = {})".format(_mcs_start, _mcs_stop, _num_rbs, _num_runs))
|
||||
plt.xlabel("SNR [dB]")
|
||||
plt.ylabel("BLER")
|
||||
|
||||
cache = {}
|
||||
if not args.rerun:
|
||||
try:
|
||||
with open("cache.pkl", "rb+") as f:
|
||||
cache = pickle.load(f)
|
||||
except FileNotFoundError:
|
||||
pass # no cache found
|
||||
|
||||
snrs_list = np.arange(_snr_start, _snr_end, _snr_step)
|
||||
mcss_list = np.arange(_mcs_start, _mcs_stop + 1, 1)
|
||||
plot_index = 0
|
||||
for mcs in mcss_list:
|
||||
results = {}
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
|
||||
result_to_snr_index = {executor.submit(generate_mcs_thps, ulsim_cmd, snrs_list[snr_index], mcs, _num_runs, _num_rbs, cache): snr_index for (snr_index, _) in enumerate(snrs_list)}
|
||||
for future in concurrent.futures.as_completed(result_to_snr_index):
|
||||
snr_index = result_to_snr_index[future]
|
||||
bler, thp = future.result()
|
||||
results[snr_index] = bler
|
||||
blers = np.zeros_like(snrs_list)
|
||||
for snr_index in results:
|
||||
blers[snr_index] = results[snr_index]
|
||||
|
||||
num_plots = len(mcss_list)
|
||||
percentage = float(plot_index) / max(1, (num_plots - 1))
|
||||
color = cmap(percentage)
|
||||
plot_index += 1
|
||||
plt.plot(snrs_list, blers, label="MCS{}".format(mcs), color = color)
|
||||
plt.legend()
|
||||
plt.savefig('MCS={}-{},SNR={}-{},RBs={}graph.png'.format(_mcs_start, _mcs_stop, _snr_start, _snr_end, _num_rbs))
|
||||
if not args.rerun:
|
||||
with open("cache.pkl", "wb+") as f:
|
||||
pickle.dump(cache, f)
|
||||
|
||||
Reference in New Issue
Block a user