Compare commits

...

9 Commits

Author SHA1 Message Date
Romain Beurdouche
c89dee6382 feat(nrL1_stats): Reduce overhead
* less sorted lists
2026-05-06 08:49:24 +00:00
Romain Beurdouche
0b97ef2057 fix(time_meas): Avoid many short sorted lists in LDPC encoder/decoder 2026-05-06 08:49:21 +00:00
Romain Beurdouche
f6ee85a014 feat(phytest): Add DL PMI setting with option -p 2026-05-06 06:47:21 +00:00
Romain Beurdouche
cb1d707f87 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-05-06 06:47:21 +00:00
Romain Beurdouche
362445a058 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-04-27 14:28:09 +00:00
Romain Beurdouche
e1f477e1f9 feat(nrL1_stats): Add min, d1, q1, median, q3 and d9 for nrL1_stats 2026-04-27 14:28:00 +00:00
Romain Beurdouche
10bb591f29 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-04-27 13:07:02 +00:00
Romain Beurdouche
84e3a647c6 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-04-27 13:07:02 +00:00
Romain Beurdouche
56c6fcdd1c 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-04-27 13:07:02 +00:00
21 changed files with 592 additions and 93 deletions

View File

@@ -26,6 +26,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

@@ -57,7 +57,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

@@ -22,7 +22,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

@@ -2,6 +2,7 @@
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#define _GNU_SOURCE
#define DICHOTOMY
#include <stdio.h>
#include "time_meas.h"
#include <math.h>
@@ -34,6 +35,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, FILE *file_name)
{
@@ -92,6 +98,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,
@@ -101,46 +146,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,
@@ -284,3 +321,222 @@ void end_meas(void) {
msg->msgid = TIMESTAT_MSGID_END ;
pushNotifiedFIFO(&measur_fifo, nfe);
}
/**
* \brief initializes sorted list
* if dst is already initialized then asserts
* \param time_stats_sorted_list sorted list to be initialized
* \param size size of the sorted list
*/
void init_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list, unsigned int size)
{
if (time_stats_sorted_list->size == 0) {
time_stats_sorted_list->list = calloc(size, sizeof(oai_cputime_t));
time_stats_sorted_list->size = size;
time_stats_sorted_list->nb_elm = 0;
} else {
AssertFatal(time_stats_sorted_list->size == 0, "Calling init_time_stats_sorted_list on initialized sorted list\n");
}
}
/**
* \brief free sorted list
* if dst is already free then does nothing
* \param time_stats_sorted_list sorted list to be freed
*/
void free_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list)
{
if (time_stats_sorted_list->size > 0) {
free(time_stats_sorted_list->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 initialized 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 initialized 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, 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
// dst and src may overlap => use memmove rather than memcpy
memmove(&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 initialized, otherwise does nothing
* \param dst destination sorted list
* should be intitialized even with a dummy size 1 buffer 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) {
if (dst->size != src->size) {
free_time_stats_sorted_list(dst);
init_time_stats_sorted_list(dst, src->size);
}
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 initialized, 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
// dst and src may overlap => use memmove rather than memcpy
memmove(&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 initialized 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 initialized 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 initialized 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 initialized 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 initialized 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 initialized 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

@@ -38,20 +38,121 @@ typedef struct {
meas_printfunc_t displayFunc; /*!< \brief function to call when DISPLAY message is received*/
} time_stats_msg_t;
/**
* \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 allocated size of the list
* 0 is the sorted list is disabled
* \var nb_elm number of elements in the list
* \var list pointer to the list
*/
typedef struct {
unsigned int size;
unsigned int nb_elm;
oai_cputime_t *list;
} time_stats_sorted_list_t;
/**
* \brief initializes sorted list
* if dst is already initialized then asserts
* \param time_stats_sorted_list sorted list to be initialized
* \param size size of the sorted list
*/
void init_time_stats_sorted_list(time_stats_sorted_list_t *time_stats_sorted_list, unsigned int size);
/**
* \brief free sorted list
* if dst is already free then does nothing
* \param time_stats_sorted_list sorted list to be freed
*/
void free_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 dst is not initialized 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 initialized 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, oai_cputime_t time);
/**
* \brief copy sorted list src into dst, freeing and replacing dst
* dst and src should be initialized, otherwise does nothing
* \param dst destination sorted list
* should be intitialized even with a dummy size 1 buffer 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 initialized, 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 initialized 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 initialized 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 initialized 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 initialized 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 initialized 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 initialized 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)
@@ -60,6 +161,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,
@@ -101,6 +206,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
@@ -126,10 +244,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;
}
@@ -137,7 +255,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
@@ -147,6 +265,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;
}
}
@@ -160,6 +279,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) {
@@ -167,6 +287,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);
}
}
@@ -179,6 +300,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 if (src_ts->trials == 1) {
insert_in_time_stats_sorted_list(&dst_ts->time_stats_sorted_list, src_ts->max);
}
}
#define TIME_STATS_ADVANCED_MODE 2
static inline void init_sorted_list_meas(time_stats_t *ts, unsigned int size)
{
init_time_stats_sorted_list(&ts->time_stats_sorted_list, size);
}
static inline void free_sorted_list_meas(time_stats_t *ts)
{
free_time_stats_sorted_list(&ts->time_stats_sorted_list);
}
#define CPUMEASUR_SECTION "cpumeasur"

View File

@@ -207,14 +207,23 @@ 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_pdsch_generation_stats, "PDSCH 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);
@@ -222,8 +231,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) {
@@ -247,8 +257,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);
@@ -256,9 +267,26 @@ 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_pdsch_generation_stats);
reset_meas(&gNB->phy_proc_rx);
reset_meas(&gNB->ulsch_decoding_stats);
reset_meas(&gNB->rx_pusch_stats);
reset_meas(&gNB->rx_prach);
if (ru->fh_north_asynch_in) {
reset_meas(&ru->rx_fhaul);
}
reset_meas(&ru->tx_fhaul);
}
return output - begin;
}
#define SORTED_LIST_SIZE 2048
void *nrL1_stats_thread(void *param) {
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
RU_t *ru = RC.ru[0];
@@ -271,20 +299,66 @@ void *nrL1_stats_thread(void *param) {
return NULL;
}
if (cpu_meas_enabled == TIME_STATS_ADVANCED_MODE) {
init_sorted_list_meas(&gNB->l1_tx_proc, SORTED_LIST_SIZE);
init_sorted_list_meas(&gNB->l1_rx_proc, SORTED_LIST_SIZE);
init_sorted_list_meas(&gNB->phy_proc_tx, SORTED_LIST_SIZE);
init_sorted_list_meas(&gNB->dlsch_encoding_stats, SORTED_LIST_SIZE);
init_sorted_list_meas(&gNB->dlsch_pdsch_generation_stats, SORTED_LIST_SIZE);
init_sorted_list_meas(&gNB->phy_proc_rx, SORTED_LIST_SIZE);
init_sorted_list_meas(&gNB->ulsch_decoding_stats, SORTED_LIST_SIZE);
init_sorted_list_meas(&gNB->rx_pusch_stats, SORTED_LIST_SIZE);
init_sorted_list_meas(&gNB->rx_prach, SORTED_LIST_SIZE);
if (ru->fh_north_asynch_in) {
init_sorted_list_meas(&ru->rx_fhaul, SORTED_LIST_SIZE);
}
init_sorted_list_meas(&ru->tx_fhaul, SORTED_LIST_SIZE);
}
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_pdsch_generation_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) {
@@ -298,6 +372,23 @@ void *nrL1_stats_thread(void *param) {
fprintf(fd,"%s\n",output);
fflush(fd);
}
if (cpu_meas_enabled == TIME_STATS_ADVANCED_MODE) {
free_sorted_list_meas(&gNB->l1_tx_proc);
free_sorted_list_meas(&gNB->l1_rx_proc);
free_sorted_list_meas(&gNB->phy_proc_tx);
free_sorted_list_meas(&gNB->dlsch_encoding_stats);
free_sorted_list_meas(&gNB->dlsch_pdsch_generation_stats);
free_sorted_list_meas(&gNB->phy_proc_rx);
free_sorted_list_meas(&gNB->ulsch_decoding_stats);
free_sorted_list_meas(&gNB->rx_pusch_stats);
free_sorted_list_meas(&gNB->rx_prach);
if (ru->fh_north_asynch_in) {
free_sorted_list_meas(&ru->rx_fhaul);
}
free_sorted_list_meas(&ru->tx_fhaul);
}
fclose(fd);
return(NULL);
}

View File

@@ -34,6 +34,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

@@ -21,9 +21,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}, \
@@ -36,9 +37,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

@@ -118,7 +118,7 @@ extern int usrp_tx_thread;
{"CO" , CONFIG_HLP_ULF, 0, .i64ptr=&(uplink_frequency_offset[0][0]), .defintval=0, TYPE_INT64, 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

@@ -125,7 +125,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

@@ -13,7 +13,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

@@ -899,10 +899,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) {
@@ -916,14 +914,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;
}
@@ -1338,8 +1333,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

@@ -137,6 +137,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;
/**
@@ -210,10 +214,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

@@ -342,10 +342,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,
@@ -434,8 +430,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;
@@ -454,7 +448,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++)
@@ -470,7 +465,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

@@ -713,7 +713,9 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
re_beginning_of_symbol -= n_dmrs;
}
}
memset(&rdata->dlsch_resource_mapping_stats, 0, sizeof(rdata->dlsch_resource_mapping_stats));
reset_meas(&rdata->dlsch_resource_mapping_stats);
memset(&rdata->dlsch_precoding_stats, 0, sizeof(rdata->dlsch_precoding_stats));
reset_meas(&rdata->dlsch_precoding_stats);
for (int l = 0; l < rel15->nrOfLayers; l++)
rdata->tx_layers[l] = tx_layers[l];

View File

@@ -238,6 +238,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;
@@ -253,10 +257,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);
@@ -267,6 +267,10 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
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);
}
}
return 0;

View File

@@ -269,7 +269,9 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
}
}
start_meas(&phy_vars_gNB->ulsch_decoding_stats);
int ret_decoder = phy_vars_gNB->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
stop_meas(&phy_vars_gNB->ulsch_decoding_stats);
// post decode
for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {

View File

@@ -151,10 +151,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;
@@ -208,6 +204,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
@@ -222,6 +222,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

@@ -21,6 +21,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

@@ -35,6 +35,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

@@ -35,6 +35,7 @@ static bool is_xlsch_in_slot(uint64_t bitmap, uint32_t modval, 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);
uint32_t dlsch_slot_modval = 0;
@@ -158,7 +159,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),