Compare commits

...

10 Commits

Author SHA1 Message Date
Romain Beurdouche
6ef8b69c99 fix(nrL1_stats): smaller timers in encoder/decoder
Try to fix the stack overflow with encoder/decoder timers by having
smaller timers.
This MR offers to disable the sorted list on these timers.
It remains to find how to remove the array of the sorted list.
2026-02-04 15:09:50 +00:00
Romain Beurdouche
0bac5035f1 alternative(nrL1_stats): Store sorted list on stack
TODO: In order that this MR turns functional,
some timers need to be removed or shall not use the sorted list
otherwise these timers have a huge memory footprint which drives to a stack overflow.
2026-02-04 14:46:50 +00:00
Romain Beurdouche
8edca4ab93 feat(phytest): Add DL PMI setting with option -p 2026-02-04 14:45:31 +00:00
Romain Beurdouche
29770b1618 feat(nr-softmodem): Enable option for advanced statistics
Option `-q` of the NR softmodem can now take an argument to choose the
NR L1 statistics to display:
* no `-q` show no statistics
* `-q` or `-q 1` shows the usual statistics with averaging from gNB start
* `-q 2` shows the advanced statistics with distribution with a reset every second
2026-02-04 14:45:31 +00:00
Romain Beurdouche
67b1f7372b fix(nrL1_stats): Do not start/stop/merge timers on mixed slots
When timers are started/stopped/merged on mixed slot,
the measured times are not homogeneous as the mixed slots are much
lighter than full UL/DL slots.
Then, to make the analysis of results easier,
we do not measure the mixed slots.
2026-02-04 14:45:31 +00:00
Romain Beurdouche
ddb50ac4e7 fix(nrLDPC_coding): Rework encoding timers
Changed tinput, tprep, tparity and toutput timers
from pointers at the slot to parts of the struct at the segment.
They can then be merged like the other timers of the encoder.
This solution enables an easier usage.
2026-02-04 14:45:31 +00:00
Romain Beurdouche
e0bb703456 feat(nrL1_stats): Add min, d1, q1, median, q3 and d9 for nrL1_stats 2026-02-04 14:45:31 +00:00
Romain Beurdouche
7a49ac6cf3 feat(time_meas): Use posix clock instead of cpu tick
Timers were relying on rdtsc which gives a number of ticks which should
be proportionated by the clock frequency.
But the clock frequency can vary.
Then this way of calculating time is not reliable.
This commit offers to use the posix clock monotonic raw instead.
2026-02-04 14:45:24 +00:00
Romain Beurdouche
6dc37b6ebe feat(time_meas): dichotomy to insert new values in sorted list
The insertion in the sorted list for computing the distribution was done
with a naive sequential search.
From this commit, it uses dichotomy instead.
2026-02-02 08:09:52 +01:00
Romain Beurdouche
b46b6aa4b3 feat(time_meas): Add more stats
* Standard Deviation
* Optional Sorted list enabling:
  * min
  * median
  * q1
  * q3
  * d1
  * d9

The sorted list is optional.
It is enabled by initializing the sorted list which allocates the list.
The size of the list that is allocated is an argument of the initialization.
2026-02-02 08:09:52 +01:00
23 changed files with 769 additions and 129 deletions

View File

@@ -24,6 +24,7 @@ It is defined in include file [ common/config/config_paramdesc.h ](https://gitla
| `PARAMFLAG_NOFREE` | The end_configmodule API won't free the memory which has been possibly allocated to store the value of the parameter.| I |
| `PARAMFLAG_BOOL` | Parameter is a boolean, it can be specified without a value to set it to true | I |
| `PARAMFLAG_CMDLINE_NOPREFIXENABLED` | parameter can be specified without the prefix on the command line. Must be used with care, carefuly checking unicity, especially for short parameter names | I |
| `PARAMFLAG_VALUE_OPTIONAL` | Parameter can be specified with a value or without a value to set it to 1 | I |
| `PARAMFLAG_MALLOCINCONFIG` | Memory for the parameter value has been allocated by the configuration module |O |
| `PARAMFLAG_PARAMSET` | Parameter value has been explicitely set, as the parameter was specified either on the command line or the config source | O |
| `PARAMFLAG_PARAMSETDEF` | Parameter value has been set to it's default | O |

View File

@@ -80,7 +80,7 @@ static int processoption(configmodule_interface_t *cfg, paramdef_t *cfgoptions,
char defbool[2]="1";
if ( value == NULL) {
if( (cfgoptions->paramflags &PARAMFLAG_BOOL) == 0 ) { /* not a boolean, argument required */
if( (cfgoptions->paramflags & (PARAMFLAG_BOOL | PARAMFLAG_VALUE_OPTIONAL)) == 0 ) { /* not a boolean, argument required */
CONFIG_PRINTF_ERROR("[CONFIG] command line, option %s requires an argument\n",cfgoptions->optname);
AssertFatal(false, "[CONFIG] command line, requires an argument\n");
} else { /* boolean value option without argument, set value to true*/

View File

@@ -45,7 +45,8 @@
#define PARAMFLAG_NOFREE (1 << 3) // don't free parameter in end function
#define PARAMFLAG_BOOL (1 << 4) // integer param can be 0 or 1
#define PARAMFLAG_CMDLINE_NOPREFIXENABLED (1 << 5) // on the command line, allow a parameter to be specified without the prefix
#define PARAMFLAG_CMDLINEONLY (1 << 6) // this parameter cannot be specified in config file
#define PARAMFLAG_CMDLINEONLY (1 << 6) // this parameter cannot be specified in config file
#define PARAMFLAG_VALUE_OPTIONAL (1 << 7) // integer param is 1 if no value provided
/* Flags used by config modules to return info to calling modules and/or to for internal usage*/
#define PARAMFLAG_MALLOCINCONFIG (1 << 15) // parameter allocated in config module

View File

@@ -19,6 +19,7 @@
* contact@openairinterface.org
*/
#define _GNU_SOURCE
#define DICHOTOMY
#include <stdio.h>
#include "time_meas.h"
#include <math.h>
@@ -51,6 +52,11 @@ double get_cpu_freq_GHz(void)
}
static double StdDev(time_stats_t *ptr)
{
return sqrt((double)ptr->diff_square * 1e-6 / ptr->trials - pow((double)ptr->diff / ptr->trials / 1000, 2));
}
void print_meas_now(time_stats_t *ts,
const char *name,
@@ -110,6 +116,45 @@ void print_meas(time_stats_t *ts,
}
}
size_t print_meas_log_header(time_stats_t *total_exec_time,
time_stats_t *sf_exec_time,
char *output,
size_t outputlen)
{
const char *begin = output;
const char *end = output + outputlen;
if ((total_exec_time == NULL) || (sf_exec_time== NULL))
output += snprintf(output,
end - output,
"%25s %18s %18s %18s %15s %18s %18s %18s %18s %18s %18s %9s %6f\n",
"Name",
"Total",
"Max",
"Std",
"Num Trials",
"min",
"d1",
"q1",
"median",
"q3",
"d9",
"CPU_F_GHz",
cpu_freq_GHz);
else
output += snprintf(output,
end - output,
"%25s %18s %18s %15s %9s %6f\n",
"Name",
"Total",
"Average/Frame",
"Trials",
"CPU_F_GHz",
cpu_freq_GHz);
return output - begin;
}
size_t print_meas_log(time_stats_t *ts,
const char *name,
time_stats_t *total_exec_time,
@@ -119,46 +164,38 @@ size_t print_meas_log(time_stats_t *ts,
{
const char *begin = output;
const char *end = output + outputlen;
static int first_time = 0;
static double cpu_freq_GHz = 0.0;
if (cpu_freq_GHz == 0.0)
cpu_freq_GHz = get_cpu_freq_GHz();
if (first_time == 0) {
first_time=1;
if ((total_exec_time == NULL) || (sf_exec_time== NULL))
output += snprintf(output,
end - output,
"%25s %25s %25s %25s %25s %6f\n",
"Name",
"Total",
"Per Trials",
"Num Trials",
"CPU_F_GHz",
cpu_freq_GHz);
else
output += snprintf(output,
end - output,
"%25s %25s %25s %20s %15s %6f\n",
"Name",
"Total",
"Average/Frame",
"Trials",
"CPU_F_GHz",
cpu_freq_GHz);
}
if (ts->trials>0) {
if ((total_exec_time == NULL) || (sf_exec_time== NULL)) {
output += snprintf(output,
end - output,
"%25s: %15.3f us; %15d; %15.3f us;\n",
name,
ts->diff / ts->trials / cpu_freq_GHz / 1000.0,
ts->trials,
ts->max / cpu_freq_GHz / 1000.0);
if (is_enabled_time_stats_sorted_list(&ts->time_stats_sorted_list)) {
output += snprintf(output,
end - output,
"%25s: %15.3f us; %15.3f us; %15.3f us; %15d; %15.3f us; %15.3f us; %15.3f us; %15.3f us; %15.3f us; %15.3f us;\n",
name,
ts->diff / ts->trials / 1000.0,
ts->max / 1000.0,
StdDev(ts),
ts->trials,
get_min(&ts->time_stats_sorted_list) / 1000.0,
get_d1(&ts->time_stats_sorted_list) / 1000.0,
get_q1(&ts->time_stats_sorted_list) / 1000.0,
get_median(&ts->time_stats_sorted_list) / 1000.0,
get_q3(&ts->time_stats_sorted_list) / 1000.0,
get_d9(&ts->time_stats_sorted_list) / 1000.0);
} else {
output += snprintf(output,
end - output,
"%25s: %15.3f us; %15.3f us; %15.3f us; %15d;\n",
name,
ts->diff / ts->trials / 1000.0,
ts->max / 1000.0,
StdDev(ts),
ts->trials);
}
} else {
output += snprintf(output,
end - output,
@@ -302,3 +339,209 @@ void end_meas(void) {
msg->msgid = TIMESTAT_MSGID_END ;
pushNotifiedFIFO(&measur_fifo, nfe);
}
/**
* \brief enables sorted list
* if the list is already enabled then empties it
* \param time_stats_sorted_list sorted list to be enabled
* \param size size of the sorted list
*/
void enable_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list)
{
if (time_stats_sorted_list->size == 0) {
time_stats_sorted_list->size = SORTED_LIST_ALLOC_SIZE;
}
time_stats_sorted_list->nb_elm = 0;
}
/**
* \brief disable sorted list
* \param time_stats_sorted_list sorted list to be freed
*/
void disable_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list)
{
time_stats_sorted_list->size = 0;
}
/**
* \brief returns true if the sorted list is enabled and false otherwise
* \param time_stats_sorted_list sorted list to be tested
*/
int is_enabled_time_stats_sorted_list(const time_stats_sorted_list_t *time_stats_sorted_list)
{
return (time_stats_sorted_list->size > 0);
}
/**
* \brief empties sorted list
* if dst is not enabled then does nothing
* \param time_stats_sorted_list sorted list to be emptied
*/
void reset_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list)
{
if (time_stats_sorted_list->size > 0) {
time_stats_sorted_list->nb_elm = 0;
}
}
/**
* \brief inserts value sorted list
* if dst is not enabled then does nothing
* if dst is full then does nothing
* \param time_stats_sorted_list sorted list to insert in
* \param time time value to insert
*/
void insert_in_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list, const oai_cputime_t time)
{
if (time_stats_sorted_list->size > 0) {
if (time_stats_sorted_list->nb_elm < time_stats_sorted_list->size) {
unsigned int i = 0;
#ifdef DICHOTOMY
unsigned int low = 0;
unsigned int high = time_stats_sorted_list->nb_elm;
bool converged = false;
while (!converged) {
i = (high + low) / 2;
if (i > 0 && time_stats_sorted_list->list[i - 1] > time) {
high = i - 1;
} else if (i < time_stats_sorted_list->nb_elm && time_stats_sorted_list->list[i] < time) {
low = i + 1;
} else {
converged = true;
}
}
#else
for (; i < time_stats_sorted_list->nb_elm && time_stats_sorted_list->list[i] < time; i++);
#endif
memcpy(&time_stats_sorted_list->list[i+1], &time_stats_sorted_list->list[i], (time_stats_sorted_list->nb_elm - i) * sizeof(oai_cputime_t));
time_stats_sorted_list->list[i] = time;
time_stats_sorted_list->nb_elm++;
}
}
}
/**
* \brief copy sorted list src into dst, freeing and replacing dst
* dst and src should be enabled, otherwise does nothing
* \param dst destination sorted list
* should be enabled to make sure that copying the list there is expected by the caller
* \param src source sorted list
*/
void copy_time_stats_sorted_list(time_stats_sorted_list_t *dst, const time_stats_sorted_list_t *src)
{
if (dst->size > 0 && src->size > 0) {
memcpy(dst->list, src->list, src->nb_elm * sizeof(oai_cputime_t));
dst->nb_elm = src->nb_elm;
}
}
/**
* \brief inserts the content of sorted list src into dst
* dst and src should be enabled, otherwise does nothing
* if dst is not large enough to copy src then does nothing
* \param dst destination sorted list
* \param src source sorted list
*/
void merge_time_stats_sorted_list(time_stats_sorted_list_t *dst, const time_stats_sorted_list_t *src)
{
if (dst->size > 0 && src->size > 0) {
if ((dst->size - dst->nb_elm) >= src->nb_elm) {
unsigned int j = 0;
for (unsigned int i = 0; i < src->nb_elm; i++) {
#ifdef DICHOTOMY
unsigned int low = j + 1;
unsigned int high = dst->nb_elm;
bool converged = false;
while (!converged) {
j = (high + low) / 2;
if (j > 0 && dst->list[j - 1] > src->list[i]) {
high = j - 1;
} else if (j < dst->nb_elm && dst->list[j] < src->list[i]) {
low = j + 1;
} else {
converged = true;
}
}
#else
for (; j < dst->nb_elm && dst->list[j] < src->list[i]; j++);
#endif
memcpy(&dst->list[j+1], &dst->list[j], (dst->nb_elm - j) * sizeof(oai_cputime_t));
dst->list[j] = src->list[i];
dst->nb_elm++;
j++;
}
}
}
}
/**
* \brief get the minimum from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_min(time_stats_sorted_list_t *time_stats_sorted_list)
{
if (time_stats_sorted_list->size > 0 && time_stats_sorted_list->nb_elm > 0) {
return time_stats_sorted_list->list[0];
} else {
return -1;
}
}
/**
* \brief get the median from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_median(time_stats_sorted_list_t *time_stats_sorted_list)
{
if (time_stats_sorted_list->size > 0 && time_stats_sorted_list->nb_elm > 0) {
return time_stats_sorted_list->list[time_stats_sorted_list->nb_elm / 2];
} else {
return -1;
}
}
/**
* \brief get the first quartile from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_q1(time_stats_sorted_list_t *time_stats_sorted_list)
{
if (time_stats_sorted_list->size > 0 && time_stats_sorted_list->nb_elm > 0) {
return time_stats_sorted_list->list[time_stats_sorted_list->nb_elm / 4];
} else {
return -1;
}
}
/**
* \brief get the third quartile from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_q3(time_stats_sorted_list_t *time_stats_sorted_list)
{
if (time_stats_sorted_list->size > 0 && time_stats_sorted_list->nb_elm > 0) {
return time_stats_sorted_list->list[3 * time_stats_sorted_list->nb_elm / 4];
} else {
return -1;
}
}
/**
* \brief get the first decile from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_d1(time_stats_sorted_list_t *time_stats_sorted_list)
{
if (time_stats_sorted_list->size > 0 && time_stats_sorted_list->nb_elm > 0) {
return time_stats_sorted_list->list[time_stats_sorted_list->nb_elm / 10];
} else {
return -1;
}
}
/**
* \brief get the nineth decile from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_d9(time_stats_sorted_list_t *time_stats_sorted_list)
{
if (time_stats_sorted_list->size > 0 && time_stats_sorted_list->nb_elm > 0) {
return time_stats_sorted_list->list[9 * time_stats_sorted_list->nb_elm / 10];
} else {
return -1;
}
}

View File

@@ -55,20 +55,121 @@ typedef struct {
meas_printfunc_t displayFunc; /*!< \brief function to call when DISPLAY message is received*/
} time_stats_msg_t;
#define SORTED_LIST_ALLOC_SIZE 2048
/**
* \typedef time_stats_sorted_list_t
* \brief sorted list of time stats to get med, q1, q2
* it can be left disabled by leaving size equal to 0
* \var size size of the list
* 0 is the sorted list is disabled
* \var nb_elm number of elements in the list
* \var list array holding the sorted list
*/
typedef struct {
unsigned int size;
unsigned int nb_elm;
oai_cputime_t list[SORTED_LIST_ALLOC_SIZE];
} time_stats_sorted_list_t;
/**
* \brief enables sorted list
* if the list is already enabled then empties it
* \param time_stats_sorted_list sorted list to be enabled
* \param size size of the sorted list
*/
void enable_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list);
/**
* \brief disable sorted list
* \param time_stats_sorted_list sorted list to be freed
*/
void disable_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list);
/**
* \brief returns true if the sorted list is enabled and false otherwise
* \param time_stats_sorted_list sorted list to be tested
*/
int is_enabled_time_stats_sorted_list(const time_stats_sorted_list_t *time_stats_sorted_list);
/**
* \brief empties sorted list
* if the list is not enabled then does nothing
* \param time_stats_sorted_list sorted list to be emptied
*/
void reset_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list);
/**
* \brief inserts value sorted list
* if dst is not enabled then does nothing
* if dst is full then does nothing
* \param time_stats_sorted_list sorted list to insert in
* \param time time value to insert
*/
void insert_in_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list, const oai_cputime_t time);
/**
* \brief copy sorted list src into dst, freeing and replacing dst
* dst and src should be enabled, otherwise does nothing
* \param dst destination sorted list
* should be enableed to make sure that copying the list there is expected by the caller
* \param src source sorted list
*/
void copy_time_stats_sorted_list(time_stats_sorted_list_t *dst, const time_stats_sorted_list_t *src);
/**
* \brief inserts the content of sorted list src into dst
* dst and src should be enabled, otherwise does nothing
* if dst is not large enough to copy src then does nothing
* \param dst destination sorted list
* \param src source sorted list
*/
void merge_time_stats_sorted_list(time_stats_sorted_list_t *dst, const time_stats_sorted_list_t *src);
/**
* \brief get the minimum from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_min(time_stats_sorted_list_t *time_stats_sorted_list);
/**
* \brief get the median from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_median(time_stats_sorted_list_t *time_stats_sorted_list);
/**
* \brief get the first quartile from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_q1(time_stats_sorted_list_t *time_stats_sorted_list);
/**
* \brief get the third quartile from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_q3(time_stats_sorted_list_t *time_stats_sorted_list);
/**
* \brief get the first decile from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_d1(time_stats_sorted_list_t *time_stats_sorted_list);
/**
* \brief get the nineth decile from a sorted list
* if the sorted list is not enabled or empty then returns -1
* \param time_stats_sorted_list sorted list to query
*/
oai_cputime_t get_d9(time_stats_sorted_list_t *time_stats_sorted_list);
struct notifiedFIFO_elt_s;
typedef struct time_stats {
oai_cputime_t in; /*!< \brief time at measure starting point */
oai_cputime_t diff; /*!< \brief average difference between time at starting point and time at endpoint*/
oai_cputime_t p_time; /*!< \brief absolute process duration */
double diff_square; /*!< \brief process duration square */
oai_cputime_t max; /*!< \brief maximum difference between time at starting point and time at endpoint*/
int trials; /*!< \brief number of start point - end point iterations */
int meas_flag; /*!< \brief 1: stop_meas not called (consecutive calls of start_meas) */
char *meas_name; /*!< \brief name to use when printing the measure (not used for PHY simulators)*/
int meas_index; /*!< \brief index of this measure in the measure array (not used for PHY simulators)*/
int meas_enabled; /*!< \brief per measure enablement flag. send_meas tests this flag, unused today in start_meas and stop_meas*/
struct notifiedFIFO_elt_s *tpoolmsg; /*!< \brief message pushed to the cpu measurment queue to report a measure START or STOP */
time_stats_msg_t *tstatptr; /*!< \brief pointer to the time_stats_msg_t data in the tpoolmsg, stored here for perf considerations*/
oai_cputime_t in; /*!< \brief time at measure starting point */
oai_cputime_t diff; /*!< \brief average difference between time at starting point and time at endpoint*/
oai_cputime_t p_time; /*!< \brief absolute process duration */
double diff_square; /*!< \brief process duration square */
oai_cputime_t max; /*!< \brief maximum difference between time at starting point and time at endpoint*/
int trials; /*!< \brief number of start point - end point iterations */
int meas_flag; /*!< \brief 1: stop_meas not called (consecutive calls of start_meas) */
char *meas_name; /*!< \brief name to use when printing the measure (not used for PHY simulators)*/
int meas_index; /*!< \brief index of this measure in the measure array (not used for PHY simulators)*/
int meas_enabled; /*!< \brief per measure enablement flag. send_meas tests this flag, unused today in start_meas and stop_meas*/
struct notifiedFIFO_elt_s *tpoolmsg; /*!< \brief message pushed to the cpu measurment queue to report a measure START or STOP */
time_stats_msg_t *tstatptr; /*!< \brief pointer to the time_stats_msg_t data in the tpoolmsg, stored here for perf considerations */
time_stats_sorted_list_t time_stats_sorted_list; /*!< \brief optional sorted list to get med, q1, q2 */
} time_stats_t;
#define MEASURE_ENABLED(X) (X->meas_enabled)
@@ -77,6 +178,10 @@ static inline void stop_meas(time_stats_t *ts) __attribute__((always_inline));
void print_meas_now(time_stats_t *ts, const char *name, FILE *file_name);
void print_meas(time_stats_t *ts, const char *name, time_stats_t *total_exec_time, time_stats_t *sf_exec_time);
size_t print_meas_log_header(time_stats_t *total_exec_time,
time_stats_t *sf_exec_time,
char *output,
size_t outputlen);
size_t print_meas_log(time_stats_t *ts,
const char *name,
time_stats_t *total_exec_time,
@@ -118,6 +223,19 @@ static inline uint32_t rdtsc_oai(void) {
}
#endif
static inline long long clock_gettime_oai()
{
struct timespec time;
#ifdef CLOCK_MONOTONIC_RAW
// CLOCK_MONOTONIC_RAW only on linux
// See clock_getres(2)
clock_gettime(CLOCK_MONOTONIC_RAW, &time);
#else
clock_gettime(CLOCK_REALTIME, &time);
#endif
return 1e+9 * time.tv_sec + time.tv_nsec;
}
#define CPUMEAS_DISABLE 0
#define CPUMEAS_ENABLE 1
#define CPUMEAS_GETSTATE 2
@@ -143,10 +261,10 @@ static inline void start_meas(time_stats_t *ts) {
if (cpu_meas_enabled) {
if (ts->meas_flag==0) {
ts->trials++;
ts->in = rdtsc_oai();
ts->in = clock_gettime_oai();
ts->meas_flag=1;
} else {
ts->in = rdtsc_oai();
ts->in = clock_gettime_oai();
}
if ((ts->trials&16383)<10) ts->max=0;
}
@@ -154,7 +272,7 @@ static inline void start_meas(time_stats_t *ts) {
static inline void stop_meas(time_stats_t *ts) {
if (cpu_meas_enabled) {
long long out = rdtsc_oai();
long long out = clock_gettime_oai();
if (ts->in) {
ts->diff += (out - ts->in);
/// process duration is the difference between two clock points
@@ -164,6 +282,7 @@ static inline void stop_meas(time_stats_t *ts) {
if ((out - ts->in) > ts->max)
ts->max = out - ts->in;
insert_in_time_stats_sorted_list(&ts->time_stats_sorted_list, (out - ts->in));
ts->meas_flag = 0;
}
}
@@ -177,6 +296,7 @@ static inline void reset_meas(time_stats_t *ts) {
ts->max=0;
ts->trials=0;
ts->meas_flag=0;
reset_time_stats_sorted_list(&ts->time_stats_sorted_list);
}
static inline void copy_meas(time_stats_t *dst_ts,time_stats_t *src_ts) {
@@ -184,6 +304,7 @@ static inline void copy_meas(time_stats_t *dst_ts,time_stats_t *src_ts) {
dst_ts->trials=src_ts->trials;
dst_ts->diff=src_ts->diff;
dst_ts->max=src_ts->max;
copy_time_stats_sorted_list(&dst_ts->time_stats_sorted_list, &src_ts->time_stats_sorted_list);
}
}
@@ -196,6 +317,23 @@ static inline void merge_meas(time_stats_t *dst_ts, const time_stats_t *src_ts)
dst_ts->diff_square += src_ts->diff_square;
if (src_ts->max > dst_ts->max)
dst_ts->max = src_ts->max;
if (is_enabled_time_stats_sorted_list(&src_ts->time_stats_sorted_list)) {
merge_time_stats_sorted_list(&dst_ts->time_stats_sorted_list, &src_ts->time_stats_sorted_list);
} else {
insert_in_time_stats_sorted_list(&dst_ts->time_stats_sorted_list, src_ts->diff / src_ts->trials);
}
}
#define TIME_STATS_ADVANCED_MODE 2
static inline void enable_sorted_list_meas(time_stats_t *ts)
{
enable_time_stats_sorted_list(&ts->time_stats_sorted_list);
}
static inline void disable_sorted_list_meas(time_stats_t *ts)
{
disable_time_stats_sorted_list(&ts->time_stats_sorted_list);
}
#define CPUMEASUR_SECTION "cpumeasur"

View File

@@ -120,7 +120,9 @@ static void tx_func(processingData_L1tx_t *info)
// TODO check for analog_bf_vendor_ext set to 1 is a workaround while no beam API for beam selection is implemented
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx
|| IS_SOFTMODEM_RFSIM || cfg->analog_beamforming_ve.analog_bf_vendor_ext.value) {
start_meas(&info->gNB->phy_proc_tx);
if (tx_slot_type == NR_DOWNLINK_SLOT) {
start_meas(&info->gNB->phy_proc_tx);
}
phy_procedures_gNB_TX(info->gNB,
&sched_response.DL_req,
&sched_response.TX_req,
@@ -137,7 +139,9 @@ static void tx_func(processingData_L1tx_t *info)
syncMsgRU.timestamp_tx = info->timestamp_tx;
LOG_D(PHY, "gNB: %d.%d : calling RU TX function\n", syncMsgRU.frame_tx, syncMsgRU.slot_tx);
ru_tx_func((void *)&syncMsgRU);
stop_meas(&info->gNB->phy_proc_tx);
if (tx_slot_type == NR_DOWNLINK_SLOT) {
stop_meas(&info->gNB->phy_proc_tx);
}
}
}
@@ -150,9 +154,14 @@ void *L1_rx_thread(void *arg)
if (res == NULL)
break;
processingData_L1_t *info = (processingData_L1_t *)NotifiedFifoData(res);
start_meas(&gNB->l1_rx_proc);
int slot_type = nr_slot_select(&gNB->gNB_config, info->frame_rx, info->slot_rx);
if (slot_type == NR_UPLINK_SLOT) {
start_meas(&gNB->l1_rx_proc);
}
rx_func(info);
stop_meas(&gNB->l1_rx_proc);
if (slot_type == NR_UPLINK_SLOT) {
stop_meas(&gNB->l1_rx_proc);
}
delNotifiedFIFO_elt(res);
}
return NULL;
@@ -166,9 +175,14 @@ void *L1_tx_thread(void *arg) {
if (res == NULL) // stopping condition, happens only when queue is freed
break;
processingData_L1tx_t *info = (processingData_L1tx_t *)NotifiedFifoData(res);
start_meas(&gNB->l1_tx_proc);
int slot_type = nr_slot_select(&gNB->gNB_config, info->frame, info->slot);
if (slot_type == NR_DOWNLINK_SLOT) {
start_meas(&gNB->l1_tx_proc);
}
tx_func(info);
stop_meas(&gNB->l1_tx_proc);
if (slot_type == NR_DOWNLINK_SLOT) {
stop_meas(&gNB->l1_tx_proc);
}
delNotifiedFIFO_elt(res);
}
return NULL;
@@ -214,9 +228,13 @@ static void rx_func(processingData_L1_t *info)
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx, &UL_INFO);
// Call the scheduler
start_meas(&gNB->ul_indication_stats);
if (rx_slot_type == NR_UPLINK_SLOT) {
start_meas(&gNB->ul_indication_stats);
}
gNB->if_inst->NR_UL_indication(&UL_INFO);
stop_meas(&gNB->ul_indication_stats);
if (rx_slot_type == NR_UPLINK_SLOT) {
stop_meas(&gNB->ul_indication_stats);
}
notifiedFIFO_elt_t *res = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->L1_rx_out, NULL);
processingData_L1_t *syncMsg = NotifiedFifoData(res);
@@ -233,15 +251,24 @@ static void rx_func(processingData_L1_t *info)
static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size_t outputlen) {
const char *begin = output;
const char *end = output + outputlen;
output += print_meas_log_header(NULL, NULL, output, end - output);
output += print_meas_log(&gNB->l1_tx_proc, "L1 Tx job", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->l1_rx_proc, "L1 Rx job", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->phy_proc_tx, "L1 Tx processing", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->dlsch_encoding_stats, "DLSCH encoding", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->dlsch_segmentation_stats, "DL segment segmentation", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->tinput, "DL encoding input", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->tprep, "DL encoding preparation", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->tparity, "DL encoding parity", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->toutput, "DL encoding output", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->dlsch_rate_matching_stats, "DL rate matching", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->dlsch_interleaving_stats, "DL interleaving", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->dlsch_scrambling_stats, "DLSCH scrambling", NULL, NULL, output, end-output);
output += print_meas_log(&gNB->dlsch_modulation_stats, "DLSCH modulation", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->dlsch_resource_mapping_stats, "DLSCH resource mapping", NULL, NULL, output,end-output);
output += print_meas_log(&gNB->dlsch_precoding_stats, "DLSCH precoding", NULL, NULL, output,end-output);
output += print_meas_log(&gNB->dlsch_pdsch_generation_stats, "DLSCH generation", NULL, NULL, output,end-output);
output += print_meas_log(&gNB->phy_proc_rx, "L1 Rx processing", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->ulsch_decoding_stats, "ULSCH decoding", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->ts_deinterleave, "UL segment deinterleaving", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->ts_rate_unmatch, "UL segment rate recovery", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->ts_ldpc_decode, "UL segments decoding", NULL, NULL, output, end - output);
@@ -249,8 +276,9 @@ static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size
output += print_meas_log(&gNB->slot_indication_stats, "Slot Indication", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL, output, end - output);
output += print_meas_log(&gNB->rx_prach, "PRACH RX", NULL, NULL, output, end - output);
if (ru->feprx)
if (ru->feprx) {
output += print_meas_log(&ru->ofdm_demod_stats, "feprx", NULL, NULL, output, end - output);
}
bool full_slot = ru->half_slot_parallelization == 0;
if (ru->feptx_prec) {
@@ -274,8 +302,9 @@ static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size
output += print_meas_log(&ru->txdataF_copy_stats, "txdataF_copy", NULL, NULL, output, end - output);
}
if (ru->fh_north_asynch_in)
if (ru->fh_north_asynch_in) {
output += print_meas_log(&ru->rx_fhaul,"rx_fhaul",NULL,NULL, output, end - output);
}
output += print_meas_log(&ru->tx_fhaul,"tx_fhaul",NULL,NULL, output, end - output);
@@ -283,6 +312,58 @@ static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size
output += print_meas_log(&ru->compression,"compression",NULL,NULL, output, end - output);
output += print_meas_log(&ru->transport,"transport",NULL,NULL, output, end - output);
}
if (cpu_meas_enabled == TIME_STATS_ADVANCED_MODE) {
reset_meas(&gNB->l1_tx_proc);
reset_meas(&gNB->l1_rx_proc);
reset_meas(&gNB->phy_proc_tx);
reset_meas(&gNB->dlsch_encoding_stats);
reset_meas(&gNB->dlsch_segmentation_stats);
reset_meas(&gNB->tinput);
reset_meas(&gNB->tprep);
reset_meas(&gNB->tparity);
reset_meas(&gNB->toutput);
reset_meas(&gNB->dlsch_rate_matching_stats);
reset_meas(&gNB->dlsch_interleaving_stats);
reset_meas(&gNB->dlsch_scrambling_stats);
reset_meas(&gNB->dlsch_modulation_stats);
reset_meas(&gNB->dlsch_resource_mapping_stats);
reset_meas(&gNB->dlsch_pdsch_generation_stats);
reset_meas(&gNB->phy_proc_rx);
reset_meas(&gNB->ulsch_decoding_stats);
reset_meas(&gNB->ts_deinterleave);
reset_meas(&gNB->ts_rate_unmatch);
reset_meas(&gNB->ts_ldpc_decode);
reset_meas(&gNB->ul_indication_stats);
reset_meas(&gNB->slot_indication_stats);
reset_meas(&gNB->rx_pusch_stats);
reset_meas(&gNB->rx_prach);
if (ru->feprx) {
reset_meas(&ru->ofdm_demod_stats);
}
if (ru->feptx_prec) {
reset_meas(&ru->precoding_stats);
}
if (ru->feptx_ofdm) {
reset_meas(&ru->txdataF_copy_stats);
reset_meas(&ru->ofdm_mod_stats);
reset_meas(&ru->ofdm_total_stats);
reset_meas(&ru->txdataF_copy_stats);
}
if (ru->fh_north_asynch_in) {
reset_meas(&ru->rx_fhaul);
}
reset_meas(&ru->tx_fhaul);
if (ru->fh_north_out) {
reset_meas(&ru->compression);
reset_meas(&ru->transport);
}
}
return output - begin;
}
@@ -298,21 +379,95 @@ void *nrL1_stats_thread(void *param) {
return NULL;
}
if (cpu_meas_enabled == TIME_STATS_ADVANCED_MODE) {
enable_sorted_list_meas(&gNB->l1_tx_proc);
enable_sorted_list_meas(&gNB->l1_rx_proc);
enable_sorted_list_meas(&gNB->phy_proc_tx);
enable_sorted_list_meas(&gNB->dlsch_encoding_stats);
enable_sorted_list_meas(&gNB->tinput);
enable_sorted_list_meas(&gNB->tprep);
enable_sorted_list_meas(&gNB->tparity);
enable_sorted_list_meas(&gNB->toutput);
enable_sorted_list_meas(&gNB->dlsch_segmentation_stats);
enable_sorted_list_meas(&gNB->dlsch_rate_matching_stats);
enable_sorted_list_meas(&gNB->dlsch_interleaving_stats);
enable_sorted_list_meas(&gNB->dlsch_scrambling_stats);
enable_sorted_list_meas(&gNB->dlsch_modulation_stats);
enable_sorted_list_meas(&gNB->dlsch_pdsch_generation_stats);
enable_sorted_list_meas(&gNB->phy_proc_rx);
enable_sorted_list_meas(&gNB->ulsch_decoding_stats);
enable_sorted_list_meas(&gNB->ts_deinterleave);
enable_sorted_list_meas(&gNB->ts_rate_unmatch);
enable_sorted_list_meas(&gNB->ts_ldpc_decode);
enable_sorted_list_meas(&gNB->ul_indication_stats);
enable_sorted_list_meas(&gNB->slot_indication_stats);
enable_sorted_list_meas(&gNB->rx_pusch_stats);
enable_sorted_list_meas(&gNB->rx_prach);
if (ru->feprx) {
enable_sorted_list_meas(&ru->ofdm_demod_stats);
}
if (ru->feptx_prec) {
enable_sorted_list_meas(&ru->precoding_stats);
}
if (ru->feptx_ofdm) {
enable_sorted_list_meas(&ru->txdataF_copy_stats);
enable_sorted_list_meas(&ru->ofdm_mod_stats);
enable_sorted_list_meas(&ru->ofdm_total_stats);
}
if (ru->fh_north_asynch_in) {
enable_sorted_list_meas(&ru->rx_fhaul);
}
enable_sorted_list_meas(&ru->tx_fhaul);
if (ru->fh_north_out) {
enable_sorted_list_meas(&ru->compression);
enable_sorted_list_meas(&ru->transport);
}
}
reset_meas(&gNB->l1_tx_proc);
reset_meas(&gNB->l1_rx_proc);
reset_meas(&gNB->phy_proc_tx);
reset_meas(&gNB->dlsch_encoding_stats);
reset_meas(&gNB->dlsch_segmentation_stats);
reset_meas(&gNB->tinput);
reset_meas(&gNB->tprep);
reset_meas(&gNB->tparity);
reset_meas(&gNB->toutput);
reset_meas(&gNB->dlsch_rate_matching_stats);
reset_meas(&gNB->dlsch_interleaving_stats);
reset_meas(&gNB->dlsch_scrambling_stats);
reset_meas(&gNB->dlsch_modulation_stats);
reset_meas(&gNB->dlsch_pdsch_generation_stats);
reset_meas(&gNB->phy_proc_rx);
reset_meas(&gNB->ulsch_decoding_stats);
reset_meas(&gNB->ts_deinterleave);
reset_meas(&gNB->ts_rate_unmatch);
reset_meas(&gNB->ts_ldpc_decode);
reset_meas(&gNB->ul_indication_stats);
reset_meas(&gNB->slot_indication_stats);
reset_meas(&gNB->rx_pusch_stats);
reset_meas(&gNB->dlsch_scrambling_stats);
reset_meas(&gNB->dlsch_modulation_stats);
reset_meas(&gNB->dlsch_resource_mapping_stats);
reset_meas(&gNB->dlsch_precoding_stats);
reset_meas(&gNB->rx_prach);
if (ru->feprx) {
reset_meas(&ru->ofdm_demod_stats);
}
if (ru->feptx_prec) {
reset_meas(&ru->precoding_stats);
}
if (ru->feptx_ofdm) {
reset_meas(&ru->txdataF_copy_stats);
reset_meas(&ru->ofdm_mod_stats);
reset_meas(&ru->ofdm_total_stats);
}
if (ru->fh_north_asynch_in) {
reset_meas(&ru->rx_fhaul);
}
reset_meas(&ru->tx_fhaul);
if (ru->fh_north_out) {
reset_meas(&ru->compression);
reset_meas(&ru->transport);
}
while (!oai_exit) {
sleep(1);
if (ftruncate(fileno(fd), 0) != 0 || fseek(fd, 0, SEEK_SET) != 0) {
@@ -326,6 +481,54 @@ void *nrL1_stats_thread(void *param) {
fprintf(fd,"%s\n",output);
fflush(fd);
}
if (cpu_meas_enabled == TIME_STATS_ADVANCED_MODE) {
disable_sorted_list_meas(&gNB->l1_tx_proc);
disable_sorted_list_meas(&gNB->l1_rx_proc);
disable_sorted_list_meas(&gNB->phy_proc_tx);
disable_sorted_list_meas(&gNB->dlsch_encoding_stats);
disable_sorted_list_meas(&gNB->dlsch_segmentation_stats);
disable_sorted_list_meas(&gNB->tinput);
disable_sorted_list_meas(&gNB->tprep);
disable_sorted_list_meas(&gNB->tparity);
disable_sorted_list_meas(&gNB->toutput);
disable_sorted_list_meas(&gNB->dlsch_rate_matching_stats);
disable_sorted_list_meas(&gNB->dlsch_interleaving_stats);
disable_sorted_list_meas(&gNB->dlsch_scrambling_stats);
disable_sorted_list_meas(&gNB->dlsch_modulation_stats);
disable_sorted_list_meas(&gNB->dlsch_pdsch_generation_stats);
disable_sorted_list_meas(&gNB->phy_proc_rx);
disable_sorted_list_meas(&gNB->ulsch_decoding_stats);
disable_sorted_list_meas(&gNB->ts_deinterleave);
disable_sorted_list_meas(&gNB->ts_rate_unmatch);
disable_sorted_list_meas(&gNB->ts_ldpc_decode);
disable_sorted_list_meas(&gNB->ul_indication_stats);
disable_sorted_list_meas(&gNB->slot_indication_stats);
disable_sorted_list_meas(&gNB->rx_pusch_stats);
disable_sorted_list_meas(&gNB->rx_prach);
if (ru->feprx) {
disable_sorted_list_meas(&ru->ofdm_demod_stats);
}
if (ru->feptx_prec) {
disable_sorted_list_meas(&ru->precoding_stats);
}
if (ru->feptx_ofdm) {
disable_sorted_list_meas(&ru->txdataF_copy_stats);
disable_sorted_list_meas(&ru->ofdm_mod_stats);
disable_sorted_list_meas(&ru->ofdm_total_stats);
disable_sorted_list_meas(&ru->txdataF_copy_stats);
}
if (ru->fh_north_asynch_in) {
disable_sorted_list_meas(&ru->rx_fhaul);
}
disable_sorted_list_meas(&ru->tx_fhaul);
if (ru->fh_north_out) {
disable_sorted_list_meas(&ru->compression);
disable_sorted_list_meas(&ru->transport);
}
}
fclose(fd);
return(NULL);
}

View File

@@ -31,6 +31,7 @@
/* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
#define CONFIG_HLP_DLMCS_PHYTEST "Set the downlink MCS for PHYTEST mode\n"
#define CONFIG_HLP_DLNL_PHYTEST "Set the downlink nrOfLayers for PHYTEST mode\n"
#define CONFIG_HLP_DLPMI_PHYTEST "Set the downlink Precoding Matrix Index for PHYTEST mode\n"
#define CONFIG_HLP_ULNL_PHYTEST "Set the uplink nrOfLayers for PHYTEST mode\n"
#define CONFIG_HLP_DLBW_PHYTEST "Set the number of PRBs used for DLSCH in PHYTEST mode\n"
#define CONFIG_HLP_ULBW_PHYTEST "Set the number of PRBs used for ULSCH in PHYTEST mode\n"

View File

@@ -17,9 +17,10 @@
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
// clang-format off
#define CMDLINE_PARAMS_DESC_GNB { \
{"m" , CONFIG_HLP_DLMCS_PHYTEST, 0, .uptr=&target_dl_mcs, .defintval=0, TYPE_UINT, 0}, \
{"l" , CONFIG_HLP_DLNL_PHYTEST, 0, .uptr=&target_dl_Nl, .defintval=0, TYPE_UINT, 0}, \
{"L" , CONFIG_HLP_ULNL_PHYTEST, 0, .uptr=&target_ul_Nl, .defintval=0, TYPE_UINT, 0}, \
{"p" , CONFIG_HLP_DLPMI_PHYTEST, 0, .uptr=&target_dl_pmi, .defintval=0, TYPE_UINT, 0}, \
{"m" , CONFIG_HLP_DLMCS_PHYTEST, 0, .uptr=&target_dl_mcs, .defintval=0, TYPE_UINT, 0}, \
{"t" , CONFIG_HLP_ULMCS_PHYTEST, 0, .uptr=&target_ul_mcs, .defintval=0, TYPE_UINT, 0}, \
{"M" , CONFIG_HLP_DLBW_PHYTEST, 0, .uptr=&target_dl_bw, .defintval=0, TYPE_UINT, 0}, \
{"T" , CONFIG_HLP_ULBW_PHYTEST, 0, .uptr=&target_ul_bw, .defintval=0, TYPE_UINT, 0}, \
@@ -30,9 +31,10 @@
}
// clang-format on
extern uint32_t target_dl_mcs;
extern uint32_t target_dl_Nl;
extern uint32_t target_ul_Nl;
extern uint32_t target_dl_pmi;
extern uint32_t target_dl_mcs;
extern uint32_t target_ul_mcs;
extern uint32_t target_dl_bw;
extern uint32_t target_ul_bw;

View File

@@ -142,7 +142,7 @@ extern int usrp_tx_thread;
{"CO" , CONFIG_HLP_ULF, 0, .iptr=&(uplink_frequency_offset[0][0]), .defintval=0, TYPE_INT, 0}, \
{"a" , CONFIG_HLP_CHOFF, 0, .iptr=&CHAIN_OFFSET, .defintval=0, TYPE_INT, 0}, \
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, .uptr=&do_forms, .defintval=0, TYPE_UINT, 0}, \
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, .iptr=&cpu_meas_enabled, .defintval=0, TYPE_INT, 0}, \
{"q" , CONFIG_HLP_STMON, PARAMFLAG_VALUE_OPTIONAL, .iptr=&cpu_meas_enabled, .defintval=0, TYPE_INT, 0}, \
{"numerology" , CONFIG_HLP_NUMEROLOGY, 0, .iptr=&NUMEROLOGY, .defintval=1, TYPE_INT, 0}, \
{"band" , CONFIG_HLP_BAND, 0, .iptr=&BAND, .defintval=78, TYPE_INT, 0}, \
{"parallel-config", CONFIG_HLP_PARALLEL_CMD, 0, .strptr=&parallel_config, .defstrval=NULL, TYPE_STRING, 0}, \

View File

@@ -121,7 +121,8 @@ int main(int argc, char *argv[])
}
}
// Initiate timing. (Results depend on CPU Frequency. Therefore, might change due to performance variances during simulation.)
time_stats_t timeEncoder, timeDecoder;
time_stats_t timeEncoder = {0};
time_stats_t timeDecoder = {0};
cpu_meas_enabled = 1;
reset_meas(&timeEncoder);
reset_meas(&timeDecoder);

View File

@@ -9,7 +9,8 @@
configmodule_interface_t *uniqCfg = NULL;
int main(int argc, char *argv[])
{
time_stats_t timeEncoder, timeDecoder;
time_stats_t timeEncoder = {0};
time_stats_t timeDecoder = {0};
cpu_meas_enabled = 1;
reset_meas(&timeEncoder);
reset_meas(&timeDecoder);

View File

@@ -893,10 +893,8 @@ static int pmd_lcore_ldpc_enc(void *arg)
AssertFatal(ret == 0, "Allocation failed for %d ops", num_segments);
set_ldpc_enc_op(ops_enq, bufs->inputs, bufs->hard_outputs, nrLDPC_slot_encoding_parameters);
if (nrLDPC_slot_encoding_parameters->tprep != NULL)
stop_meas(nrLDPC_slot_encoding_parameters->tprep);
if (nrLDPC_slot_encoding_parameters->tparity != NULL)
start_meas(nrLDPC_slot_encoding_parameters->tparity);
stop_meas(&nrLDPC_slot_encoding_parameters->TBs[0].segments[0].tprep);
start_meas(&nrLDPC_slot_encoding_parameters->TBs[0].segments[0].tparity);
uint16_t enq = 0, deq = 0;
while (enq < num_segments) {
@@ -910,14 +908,11 @@ static int pmd_lcore_ldpc_enc(void *arg)
time_out++;
DevAssert(time_out <= TIME_OUT_POLL);
}
if (nrLDPC_slot_encoding_parameters->tparity != NULL)
stop_meas(nrLDPC_slot_encoding_parameters->tparity);
if (nrLDPC_slot_encoding_parameters->toutput != NULL)
start_meas(nrLDPC_slot_encoding_parameters->toutput);
stop_meas(&nrLDPC_slot_encoding_parameters->TBs[0].segments[0].tparity);
start_meas(&nrLDPC_slot_encoding_parameters->TBs[0].segments[0].toutput);
ret = retrieve_ldpc_enc_op(ops_deq, nrLDPC_slot_encoding_parameters);
AssertFatal(ret == 0, "Failed to retrieve LDPC encoding op!");
if (nrLDPC_slot_encoding_parameters->toutput != NULL)
stop_meas(nrLDPC_slot_encoding_parameters->toutput);
stop_meas(&nrLDPC_slot_encoding_parameters->TBs[0].segments[0].toutput);
rte_bbdev_enc_op_free_bulk(ops_enq, num_segments);
return ret;
}
@@ -1332,8 +1327,7 @@ int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_dec
int32_t nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters)
{
pthread_mutex_lock(&encode_mutex);
if (nrLDPC_slot_encoding_parameters->tprep != NULL)
start_meas(nrLDPC_slot_encoding_parameters->tprep);
start_meas(&nrLDPC_slot_encoding_parameters->TBs[0].segments[0].tprep);
const uint16_t num_segments = nb_segments_encoding(nrLDPC_slot_encoding_parameters);

View File

@@ -152,6 +152,10 @@ typedef struct nrLDPC_segment_encoding_parameters_s{
time_stats_t ts_interleave;
time_stats_t ts_rate_match;
time_stats_t ts_ldpc_encode;
time_stats_t tinput;
time_stats_t tprep;
time_stats_t tparity;
time_stats_t toutput;
} nrLDPC_segment_encoding_parameters_t;
/**
@@ -225,10 +229,6 @@ typedef struct nrLDPC_slot_encoding_parameters_s{
int slot;
int nb_TBs;
tpool_t *threadPool;
time_stats_t *tinput;
time_stats_t *tprep;
time_stats_t *tparity;
time_stats_t *toutput;
nrLDPC_TB_encoding_parameters_t *TBs;
} nrLDPC_slot_encoding_parameters_t;

View File

@@ -366,10 +366,6 @@ static int nrLDPC_launch_TB_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_s
encoder_implemparams_t common_segment_params = {
.n_segments = nrLDPC_TB_encoding_parameters->C,
.tinput = nrLDPC_slot_encoding_parameters->tinput,
.tprep = nrLDPC_slot_encoding_parameters->tprep,
.tparity = nrLDPC_slot_encoding_parameters->tparity,
.toutput = nrLDPC_slot_encoding_parameters->toutput,
.Kb = nrLDPC_TB_encoding_parameters->Kb,
.Zc = nrLDPC_TB_encoding_parameters->Z,
.BG = nrLDPC_TB_encoding_parameters->BG,
@@ -458,8 +454,6 @@ int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encodin
uint32_t C = nrLDPC_TB_encoding_parameters->C;
size_t n_seg = (C / 8 + ((C & 7) == 0 ? 0 : 1));
time_stats_t *toutput = nrLDPC_slot_encoding_parameters->toutput;
for (int j = 0; j < n_seg; j++) {
unsigned int macro_segment = j * 8;
unsigned int macro_segment_end = (C > macro_segment + 8) ? macro_segment + 8 : C;
@@ -478,7 +472,8 @@ int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encodin
}
}
if(toutput != NULL) start_meas(toutput);
time_stats_t *toutput = &nrLDPC_TB_encoding_parameters->segments[macro_segment].toutput;
start_meas(toutput);
uint32_t Eoffset=0;
for (int s=0; s<macro_segment; s++)
@@ -494,7 +489,7 @@ int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encodin
nrLDPC_TB_encoding_parameters->output,
Eoffset);
if(toutput != NULL) stop_meas(toutput);
stop_meas(toutput);
}
nbTasks += n_seg;
}

View File

@@ -548,7 +548,7 @@ static inline void do_txdataF(c16_t **txdataF,
rb += rb_step;
} // RB loop: while(rb < rel15->rbSize)
}
static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSCH_t *dlsch, int slot)
static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSCH_t *dlsch, int frame, int slot)
{
const int16_t amp = gNB->TX_AMP;
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
@@ -608,9 +608,12 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
memcpy(dlsch->f, input_ptr, (encoded_length + 7) >> 3);
c16_t mod_symbs[rel15->NrOfCodewords][encoded_length] __attribute__((aligned(64)));
int slot_type = nr_slot_select(&gNB->gNB_config, frame, slot);
for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) {
/// scrambling
start_meas(dlsch_scrambling_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
start_meas(dlsch_scrambling_stats);
}
uint32_t scrambled_output[(encoded_length >> 5) + 4]; // modulator acces by 4 bytes in some cases
memset(scrambled_output, 0, sizeof(scrambled_output));
nr_pdsch_codeword_scrambling(input_ptr, encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output);
@@ -624,12 +627,18 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
}
#endif
stop_meas(dlsch_scrambling_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
stop_meas(dlsch_scrambling_stats);
}
/// Modulation
start_meas(dlsch_modulation_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
start_meas(dlsch_modulation_stats);
}
nr_modulation(scrambled_output, encoded_length, Qm, (int16_t *)mod_symbs[codeWord]);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_MODULATION, 0);
stop_meas(dlsch_modulation_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
stop_meas(dlsch_modulation_stats);
}
#ifdef DEBUG_DLSCH
printf("PDSCH Modulation: Qm %d(%d)\n", Qm, nb_re);
for (int i = 0; i < nb_re; i += 8) {
@@ -641,7 +650,9 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
#endif
}
start_meas(&gNB->dlsch_pdsch_generation_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
start_meas(&gNB->dlsch_pdsch_generation_stats);
}
/// Resource mapping
// Non interleaved VRB to PRB mapping
uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart + rel15->BWPStart) * NR_NB_SC_PER_RB;
@@ -663,7 +674,9 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
c16_t mod_dmrs[(n_dmrs+63)&~63] __attribute__((aligned(64)));
unsigned int re_beginning_of_symbol = 0;
start_meas(&gNB->dlsch_layer_mapping_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
start_meas(&gNB->dlsch_layer_mapping_stats);
}
int layerSz2 = (layerSz + 63) & ~63;
c16_t tx_layers[rel15->nrOfLayers][layerSz2] __attribute__((aligned(64)));
memset(tx_layers, 0, sizeof(tx_layers));
@@ -687,7 +700,9 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
bitmap);
c16_t **txdataF = gNB->common_vars.txdataF[beam_nb];
stop_meas(&gNB->dlsch_layer_mapping_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
stop_meas(&gNB->dlsch_layer_mapping_stats);
}
// Loop Over OFDM symbols:
for (int l_symbol = rel15->StartSymbolIndex; l_symbol < rel15->StartSymbolIndex + rel15->NrOfSymbols; l_symbol++) {
start_meas(&gNB->dlsch_resource_mapping_stats);
@@ -764,7 +779,9 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
}
stop_meas(&gNB->dlsch_precoding_stats);
}
stop_meas(&gNB->dlsch_pdsch_generation_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
stop_meas(&gNB->dlsch_pdsch_generation_stats);
}
/* output and its parts for each dlsch should be aligned on 64 bytes (or 8 * 64 bits)
* should remain a multiple of 8 * 64 with enough offset to fit each dlsch
*/
@@ -827,7 +844,10 @@ void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_arr
unsigned char output[size_output >> 3] __attribute__((aligned(64)));
bzero(output, sizeof(output));
start_meas(dlsch_encoding_stats);
int slot_type = nr_slot_select(&gNB->gNB_config, frame, slot);
if (slot_type == NR_DOWNLINK_SLOT) {
start_meas(dlsch_encoding_stats);
}
if (nr_dlsch_encoding(gNB,
n_dlsch,
dlsch_array,
@@ -845,11 +865,13 @@ void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_arr
== -1) {
return;
}
stop_meas(dlsch_encoding_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
stop_meas(dlsch_encoding_stats);
}
unsigned char *output_ptr = output;
for (int i = 0; i < n_dlsch; i++) {
output_ptr += do_one_dlsch(output_ptr, gNB, &dlsch_array[i], slot);
output_ptr += do_one_dlsch(output_ptr, gNB, &dlsch_array[i], frame, slot);
}
}

View File

@@ -125,6 +125,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
int num_segments = 0;
int slot_type = nr_slot_select(&gNB->gNB_config, frame, slot);
for (int i = 0; i < n_dlsch; i++) {
NR_gNB_DLSCH_t *dlsch = &dlsch_array[i];
@@ -190,7 +191,9 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
TB_parameters->harq_unique_pid = i;
TB_parameters->BG = rel15->maintenance_parms_v3.ldpcBaseGraph;
TB_parameters->A = A;
start_meas(dlsch_segmentation_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
start_meas(dlsch_segmentation_stats);
}
TB_parameters->Kb = nr_segmentation(dlsch->b,
dlsch->c,
B,
@@ -199,7 +202,9 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
&TB_parameters->Z,
&TB_parameters->F,
TB_parameters->BG);
stop_meas(dlsch_segmentation_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
stop_meas(dlsch_segmentation_stats);
}
if (TB_parameters->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * rel15->nrOfLayers) {
LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", TB_parameters->C, B);
@@ -260,6 +265,10 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
reset_meas(&segment_parameters->ts_interleave);
reset_meas(&segment_parameters->ts_rate_match);
reset_meas(&segment_parameters->ts_ldpc_encode);
reset_meas(&segment_parameters->tinput);
reset_meas(&segment_parameters->tprep);
reset_meas(&segment_parameters->tparity);
reset_meas(&segment_parameters->toutput);
}
segments_offset += TB_parameters->C;
@@ -275,10 +284,6 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
.slot = slot,
.nb_TBs = n_dlsch,
.threadPool = &gNB->threadPool,
.tinput = tinput,
.tprep = tprep,
.tparity = tparity,
.toutput = toutput,
.TBs = TBs};
gNB->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters);
@@ -286,9 +291,15 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[i];
for (int r = 0; r < TB_parameters->C; r++) {
nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
merge_meas(dlsch_interleaving_stats, &segment_parameters->ts_interleave);
merge_meas(dlsch_rate_matching_stats, &segment_parameters->ts_rate_match);
// merge_meas(, &segment_parameters->ts_ldpc_encode);
if (slot_type == NR_DOWNLINK_SLOT) {
merge_meas(dlsch_interleaving_stats, &segment_parameters->ts_interleave);
merge_meas(dlsch_rate_matching_stats, &segment_parameters->ts_rate_match);
// merge_meas(, &segment_parameters->ts_ldpc_encode);
merge_meas(tinput, &segment_parameters->tinput);
merge_meas(tprep, &segment_parameters->tprep);
merge_meas(tparity, &segment_parameters->tparity);
merge_meas(toutput, &segment_parameters->toutput);
}
}
}

View File

@@ -279,7 +279,14 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
}
}
int slot_type = nr_slot_select(&phy_vars_gNB->gNB_config, frame, nr_tti_rx);
if (slot_type == NR_UPLINK_SLOT) {
start_meas(&phy_vars_gNB->ulsch_decoding_stats);
}
int ret_decoder = phy_vars_gNB->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
if (slot_type == NR_UPLINK_SLOT) {
stop_meas(&phy_vars_gNB->ulsch_decoding_stats);
}
// post decode
for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
@@ -303,9 +310,11 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
}
offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
merge_meas(&phy_vars_gNB->ts_deinterleave, &nrLDPC_segment_decoding_parameters.ts_deinterleave);
merge_meas(&phy_vars_gNB->ts_rate_unmatch, &nrLDPC_segment_decoding_parameters.ts_rate_unmatch);
merge_meas(&phy_vars_gNB->ts_ldpc_decode, &nrLDPC_segment_decoding_parameters.ts_ldpc_decode);
if (slot_type == NR_UPLINK_SLOT) {
merge_meas(&phy_vars_gNB->ts_deinterleave, &nrLDPC_segment_decoding_parameters.ts_deinterleave);
merge_meas(&phy_vars_gNB->ts_rate_unmatch, &nrLDPC_segment_decoding_parameters.ts_rate_unmatch);
merge_meas(&phy_vars_gNB->ts_ldpc_decode, &nrLDPC_segment_decoding_parameters.ts_ldpc_decode);
}
}
}

View File

@@ -175,10 +175,6 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
.slot = slot,
.nb_TBs = nb_ulsch,
.threadPool = &get_nrUE_params()->Tpool,
.tinput = NULL,
.tprep = NULL,
.tparity = NULL,
.toutput = NULL,
.TBs = TBs};
int max_num_segments = 0;
@@ -232,6 +228,10 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
reset_meas(&segment_parameters->ts_interleave);
reset_meas(&segment_parameters->ts_rate_match);
reset_meas(&segment_parameters->ts_ldpc_encode);
reset_meas(&segment_parameters->tinput);
reset_meas(&segment_parameters->tprep);
reset_meas(&segment_parameters->tparity);
reset_meas(&segment_parameters->toutput);
} // TB_parameters->C
} // pusch_id
@@ -249,6 +249,10 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_INTERLEAVING_STATS], &segment_parameters->ts_interleave);
merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_RATE_MATCHING_STATS], &segment_parameters->ts_rate_match);
merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_LDPC_ENCODING_STATS], &segment_parameters->ts_ldpc_encode);
merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_LDPC_INPUT_STATS], &segment_parameters->tinput);
merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_LDPC_PREP_STATS], &segment_parameters->tprep);
merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_LDPC_PARITY_STATS], &segment_parameters->tparity);
merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_LDPC_OUTPUT_STATS], &segment_parameters->toutput);
}
}

View File

@@ -16,6 +16,7 @@ int cpu_meas_enabled;
THREAD_STRUCT thread_struct;
uint32_t target_ul_mcs = 9;
uint32_t target_dl_mcs = 9;
uint32_t target_dl_pmi = 0;
uint64_t dlsch_slot_bitmap = (1<<1);
uint64_t ulsch_slot_bitmap = (1<<8);
uint32_t target_ul_bw = 50;

View File

@@ -744,8 +744,6 @@ typedef struct RRU_config_s {
int RU_mask[10];
/// time measurements for RU arrivals
struct timespec t[10];
/// Timing statistics (RU_arrivals)
time_stats_t ru_arrival_time;
/// mask for RUs serving eNB (PRACH)
int RU_mask_prach;
/// embms mbsfn sf config

View File

@@ -52,6 +52,10 @@
FN(ULSCH_LDPC_ENCODING_STATS),\
FN(ULSCH_RATE_MATCHING_STATS),\
FN(ULSCH_INTERLEAVING_STATS),\
FN(ULSCH_LDPC_INPUT_STATS),\
FN(ULSCH_LDPC_PREP_STATS),\
FN(ULSCH_LDPC_PARITY_STATS),\
FN(ULSCH_LDPC_OUTPUT_STATS),\
FN(ULSCH_ENCODING_STATS),\
FN(OFDM_MOD_STATS),\
FN(PRACH_GEN_STATS)

View File

@@ -333,7 +333,10 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
}
//apply the OFDM symbol rotation here
start_meas(&gNB->phase_comp_stats);
int slot_type = nr_slot_select(&gNB->gNB_config, frame, slot);
if (slot_type == NR_DOWNLINK_SLOT) {
start_meas(&gNB->phase_comp_stats);
}
for (int i = 0; i < gNB->common_vars.num_beams_period; ++i) {
for (int aa = 0; aa < cfg->carrier_config.num_tx_ant.value; aa++) {
if (gNB->phase_comp) {
@@ -353,7 +356,9 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
T_BUFFER(&gNB->common_vars.txdataF[i][aa][txdataF_offset], fp->samples_per_slot_wCP * sizeof(int32_t)));
}
}
stop_meas(&gNB->phase_comp_stats);
if (slot_type == NR_DOWNLINK_SLOT) {
stop_meas(&gNB->phase_comp_stats);
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX + gNB->CC_id, 0);
}
@@ -1027,7 +1032,10 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
}
const int soffset = (slot_rx & 3) * nb_symb * ofdm_symbol_size;
start_meas(&gNB->phy_proc_rx);
int slot_type = nr_slot_select(&gNB->gNB_config, frame_rx, slot_rx);
if (slot_type == NR_UPLINK_SLOT) {
start_meas(&gNB->phy_proc_rx);
}
for (int i = 0; i < gNB->max_nb_pucch; i++) {
NR_gNB_PUCCH_t *pucch = &gNB->pucch[i];
@@ -1389,7 +1397,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
stop_meas(&gNB->rx_srs_stats);
}
stop_meas(&gNB->phy_proc_rx);
if (slot_type == NR_UPLINK_SLOT) {
stop_meas(&gNB->phy_proc_rx);
}
if (pucch_decode_done || pusch_decode_done) {
T(T_GNB_PHY_PUCCH_PUSCH_IQ,

View File

@@ -51,6 +51,7 @@ static bool is_xlsch_in_slot(uint64_t bitmap, slot_t slot)
uint32_t target_dl_mcs = 9;
uint32_t target_dl_Nl = 1;
uint32_t target_dl_pmi = 0;
uint32_t target_dl_bw = 50;
uint64_t dlsch_slot_bitmap = (1<<1);
@@ -189,7 +190,7 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch)
// tbSize further below
.dl_harq_pid = sched_ctrl->retrans_dl_harq.head, // PID of HARQ awaiting retransmission, or -1 otherwise
.pucch_allocation = alloc,
.pm_index = 0,
.pm_index = target_dl_pmi,
.nrOfLayers = target_dl_Nl,
.bwp_info = get_pdsch_bwp_start_size(mac, UE),
.dmrs_parms = get_dl_dmrs_params(scc, dl_bwp, &tda_info, target_dl_Nl),