Compare commits

...

44 Commits

Author SHA1 Message Date
mir
653f32d3ca RAN-PhySim tests 2023-12-22 12:17:28 +01:00
Eurecom
1b8c81a345 a label can only be a part of a statement 2023-12-21 15:51:24 +01:00
Eurecom
6a1704f0d2 C and C++ 2023-12-21 14:09:05 +01:00
Eurecom
d17d22c1b4 remove unnecessary debug info 2023-12-21 13:29:18 +01:00
Eurecom
7794f72088 Merge branch 'tp_poc_5' into tp_poc 2023-12-21 13:28:37 +01:00
Eurecom
e222a86244 TASK_MANAGER_LTE 2023-12-20 19:35:00 +01:00
Eurecom
86013d7038 cache line for the task_t 2023-12-20 18:04:23 +01:00
Eurecom
9ff74080a6 TASK_MANAGER_SIM 2023-12-20 17:53:46 +01:00
Eurecom
e1bea49b00 gNB working 2023-12-20 17:21:41 +01:00
Eurecom
3af9a372fd task manager RU working 2023-12-20 14:53:45 +01:00
Eurecom
a795079573 Demodulation Added 2023-12-20 13:56:22 +01:00
Eurecom
aaa9584636 working solution 2023-12-20 12:43:54 +01:00
Eurecom
a8ea220797 conditional variables added 2023-12-19 17:01:08 +01:00
Eurecom
98fdcb61b4 working false sharing added 2023-12-19 14:01:11 +01:00
Eurecom
8b9b8595e7 working 2023-12-19 13:41:56 +01:00
Eurecom
e1304a77ab Not working solution 2023-12-19 13:22:42 +01:00
Eurecom
9e0a3549c5 Working no ULLL 2023-12-19 13:05:02 +01:00
Laurent
f049fe295a Bug in memset 2023-12-18 14:28:42 +01:00
Laurent
6a0c6da2bf Data race in futex. Back to cond_var to test correctness 2023-12-18 11:32:18 +01:00
mir
028625077c Wrong var renamed 2023-12-15 14:45:46 +01:00
mir
a09ae006bf Change the amount of threads added in the RU TP 2023-12-15 13:05:30 +01:00
mir
aa94266f3c quick BugFix 2023-12-14 17:54:47 +01:00
mir
aa44c423c8 comment RU to see if test passes 2023-12-14 17:26:13 +01:00
mir
4bb2014159 reduce function calls for taks manager 2023-12-12 10:45:01 +01:00
mir
473b4167c7 remove printf for passing the tests 2023-12-12 09:48:45 +01:00
mir
ef81690d77 _Atomic and c++ 2023-12-12 09:03:24 +01:00
mir
16bd57ae1d Avoid Flase Sharing in task complete 2023-12-11 16:31:43 +01:00
mir
cdabdd06d5 Demodulation added 2023-12-11 10:41:56 +01:00
mir
ef340749e3 Printf added for debugging tasks in tasks out 2023-12-11 10:40:18 +01:00
mir
738ca2d23c 4G Simulator 2023-12-11 10:40:18 +01:00
mir
e976c66b46 4G compiling 2023-12-11 10:40:18 +01:00
mir
0cec575dc4 Added some debugging information 2023-12-11 10:40:18 +01:00
mir
1916498903 char* not valid input 2023-12-11 10:40:18 +01:00
mir
026926265c Memory leak + bug at nr_dlsch_decoding.c 2023-12-11 10:40:18 +01:00
mir
d406eb0332 Free the task_manager to avoid memory leak. 2023-12-11 10:40:18 +01:00
mir
3597ac63cd Priority and scheduling policy removed 2023-12-11 10:40:18 +01:00
mir
3c056f5f6b number of threads = 0 passed to the init_task_manager. nproc not working on containers? 2023-12-11 10:40:18 +01:00
mir
dba9017edc Trigger the CI again 2023-12-11 10:40:18 +01:00
mir
f9a9a368d5 Threads clamped to 8 2023-12-11 10:40:18 +01:00
mir
8054dba74d Unused time_now_us 2023-12-11 10:40:18 +01:00
mir
f6dc244361 Atomic in cpp 2023-12-11 10:40:18 +01:00
mir
6f8b4f2055 _Atomic and c++ .. 2023-12-11 10:40:18 +01:00
Mikel Irazabal
9cc244787d Warning pin_thread_to_core unused treatead as error. Commenting the code 2023-12-11 10:40:18 +01:00
mir
37a03a2212 RFSim working. Decoding working 2023-12-11 10:40:16 +01:00
40 changed files with 2301 additions and 138 deletions

View File

@@ -685,6 +685,7 @@ set(SCHED_SRC
${OPENAIR1_DIR}/SCHED/fapi_l1.c
${OPENAIR1_DIR}/SCHED/phy_procedures_lte_eNb.c
${OPENAIR1_DIR}/SCHED/phy_procedures_lte_common.c
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
)
add_library(SCHED_LIB ${SCHED_SRC})
target_link_libraries(SCHED_LIB PRIVATE asn1_lte_rrc_hdrs)
@@ -934,6 +935,7 @@ set(PHY_SRC_COMMON
${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c
${OPENAIR1_DIR}/PHY/TOOLS/lut.c
${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
)
set(PHY_SRC
@@ -961,6 +963,7 @@ set(PHY_SRC
# ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_eNB_measurements.c
${OPENAIR1_DIR}/PHY/INIT/lte_init.c
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
)
set(PHY_SRC_RU
@@ -2053,6 +2056,7 @@ add_executable(nr-softmodem
${nr_rrc_h}
${s1ap_h}
# ${OPENAIR_BIN_DIR}/messages_xml.h
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR_DIR}/executables/nr-gnb.c
${OPENAIR_DIR}/executables/nr-ru.c
${OPENAIR_DIR}/executables/nr-softmodem.c
@@ -2132,6 +2136,7 @@ add_executable(nr-uesoftmodem
${OPENAIR2_DIR}/RRC/NAS/rb_config.c
${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c
)
@@ -2219,6 +2224,7 @@ target_link_libraries(ldpctest PRIVATE
)
add_executable(nr_dlschsim
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
@@ -2230,6 +2236,7 @@ target_link_libraries(nr_dlschsim PRIVATE
target_link_libraries(nr_dlschsim PRIVATE asn1_nr_rrc_hdrs)
add_executable(nr_pbchsim
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
@@ -2243,6 +2250,7 @@ target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
#PUCCH ---> Prashanth
add_executable(nr_pucchsim
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/pucchsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
@@ -2254,6 +2262,7 @@ target_link_libraries(nr_pucchsim PRIVATE
target_link_libraries(nr_pucchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_dlsim
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
@@ -2271,6 +2280,7 @@ target_link_libraries(nr_dlsim PRIVATE
target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_prachsim
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/prachsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
@@ -2281,6 +2291,7 @@ target_link_libraries(nr_prachsim PRIVATE
target_link_libraries(nr_prachsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_ulschsim
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulschsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
@@ -2293,6 +2304,7 @@ target_link_libraries(nr_ulschsim PRIVATE
target_link_libraries(nr_ulschsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_ulsim
${OPENAIR_DIR}/common/utils/thread_pool/task_manager.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c

View File

@@ -137,9 +137,26 @@ void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates
#define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
#define cmax(a,b) ((a>b) ? (a) : (b))
// How many cmin/cmax, min/max are defined in OAI? Clean in separate MR
#ifndef cmax
#define cmax(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#endif
#define cmax3(a,b,c) ((cmax(a,b)>c) ? (cmax(a,b)) : (c))
#define cmin(a,b) ((a<b) ? (a) : (b))
#ifndef cmin
#define cmin(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
#endif
#ifdef __cplusplus
#ifdef min

View File

@@ -0,0 +1,2 @@
Thread Pool implemented in C following the talk of Sean Parent "Better Code: Concurrency" from 2016

View File

@@ -0,0 +1,106 @@
#include <assert.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "task_manager.h"
#define NUM_THREADS 4
#define NUM_JOBS 1024
int64_t time_now_us(void)
{
struct timespec tms;
/* The C11 way */
/* if (! timespec_get(&tms, TIME_UTC)) */
/* POSIX.1-2008 way */
if (clock_gettime(CLOCK_MONOTONIC_RAW,&tms)) {
return -1;
}
/* seconds, multiplied with 1 million */
int64_t micros = tms.tv_sec * 1000000;
/* Add full microseconds */
int64_t const tv_nsec = tms.tv_nsec;
micros += tv_nsec/1000;
/* round up if necessary */
if (tv_nsec % 1000 >= 500) {
++micros;
}
return micros;
}
typedef struct{
int64_t a;
int64_t time;
} pair_t;
static inline
int64_t naive_fibonnacci(int64_t a)
{
assert(a < 1000);
if(a < 2)
return a;
return naive_fibonnacci(a-1) + naive_fibonnacci(a-2);
}
//static _Thread_local int64_t counter = 0;
static
int marker_fd;
void do_work(void* arg)
{
int64_t now = time_now_us();
pair_t* a = (pair_t*)arg;
naive_fibonnacci(23 + a->a);
int64_t stop = time_now_us();
char buffer[100] = {0};
int ret = snprintf(buffer, 100, "ID %lu Fib elapsed %ld start-stop %ld - %ld \n", pthread_self(), stop - now, now, stop);
assert(ret > 0 && ret < 100);
// write_marker_ft_mir(marker_fd, buffer);
// puts(buffer);
}
int main()
{
task_manager_t man = {0};
init_task_manager(&man, NUM_THREADS);
usleep(100);
pair_t* arr = calloc(NUM_JOBS, sizeof(pair_t));
assert(arr != NULL);
int64_t now = time_now_us();
for(int k = 0; k < NUM_JOBS/8; ++k){
for(int i = 0; i < 8; ++i){
pair_t* pa = &arr[i];
pa->a = 0; //i%10;
pa->time = 0;
task_t t = {.args = pa, t.func = do_work};
async_task_manager(&man, t);
}
printf("Waiting %ld \n", time_now_us());
trigger_and_wait_all_task_manager(&man);
printf("Done %ld \n", time_now_us());
//usleep(1024);
}
free_task_manager(&man, NULL);
printf("Total elapsed %ld \n", time_now_us() - now);
free(arr);
return EXIT_SUCCESS;
}

63
common/utils/thread_pool/run Executable file
View File

@@ -0,0 +1,63 @@
#!/bin/bash
# Full dyntick CPU on which we'll run the user loop,
# it must be part of nohz_full kernel parameter
TARGET=4
# Migrate all possible tasks to CPU 0
for P in $(ls /proc)
do
if [ -x "/proc/$P/task/" ]
then
echo $P
taskset -acp 0 $P
fi
done
# Migrate irqs to CPU 0
for D in $(ls /proc/irq)
do
if [[ -x "/proc/irq/$D" && $D != "0" ]]
then
echo $D
echo 1 > /proc/irq/$D/smp_affinity
fi
done
# Delay the annoying vmstat timer far away
sysctl vm.stat_interval=120
# Shutdown nmi watchdog as it uses perf events
sysctl -w kernel.watchdog=0
# Remove -rt task runtime limit
echo -1 > /proc/sys/kernel/sched_rt_runtime_us
# Pin the writeback workqueue to CPU0
echo 1 > /sys/bus/workqueue/devices/writeback/cpumask
DIR=/sys/kernel/debug/tracing
echo > $DIR/trace
echo 0 > $DIR/tracing_on
# Uncomment the below for more details on what disturbs the CPU
echo 0 > $DIR/events/irq/enable
echo 1 > $DIR/events/sched/sched_switch/enable
echo 1 > $DIR/events/workqueue/workqueue_queue_work/enable
echo 1 > $DIR/events/workqueue/workqueue_execute_start/enable
echo 1 > $DIR/events/timer/hrtimer_expire_entry/enable
echo 1 > $DIR/events/timer/tick_stop/enable
echo nop > $DIR/current_tracer
echo 1 > $DIR/tracing_on
# Run a 10 secs user loop on target
taskset -c 3-7 ./a.out
#sleep 20
#killall a.out
# Checkout the trace in trace.* file
cat /sys/kernel/debug/tracing/per_cpu/cpu4/trace > trace.4
cat /sys/kernel/debug/tracing/per_cpu/cpu5/trace > trace.5
cat /sys/kernel/debug/tracing/per_cpu/cpu6/trace > trace.6
cat /sys/kernel/debug/tracing/per_cpu/cpu7/trace > trace.7

View File

@@ -0,0 +1,29 @@
#ifndef TASK_WORK_STEALING_THREAD_POOL_H
#define TASK_WORK_STEALING_THREAD_POOL_H
#ifndef __cplusplus
#include <stdalign.h>
#else
#define _Alignas(X) alignas(X)
#endif
#if defined (__i386__) || defined(__x86_64__)
#define LEVEL1_DCACHE_LINESIZE 64
#elif __aarch64__
// This is not true for ARM in the general case
// in linux, you can obtain the size at runtime using sysconf (_SC_LEVEL1_DCACHE_LINESIZE)
// in c++ using std::hardware_destructive_interference_size
#define LEVEL1_DCACHE_LINESIZE 64
#else
static_assert(0!=0, "Unknown CPU architecture");
#endif
typedef struct{
// Avoid false sharing. Doing it in the first member
_Alignas(LEVEL1_DCACHE_LINESIZE) void* args;
void (*func)(void* args);
} task_t;
#endif

View File

@@ -0,0 +1,698 @@
#define _GNU_SOURCE
#include <unistd.h>
#include "task_manager.h"
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdatomic.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <fcntl.h>
#include <linux/futex.h> /* Definition of FUTEX_* constants */
#include <sys/syscall.h> /* Definition of SYS_* constants */
#include <unistd.h>
/*
static
int64_t time_now_us(void)
{
struct timespec tms;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &tms)) {
return -1;
}
int64_t micros = tms.tv_sec * 1000000;
int64_t const tv_nsec = tms.tv_nsec;
micros += tv_nsec/1000;
if (tv_nsec % 1000 >= 500) {
++micros;
}
return micros;
}
static
void pin_thread_to_core(int core_num)
{
cpu_set_t set = {0};
CPU_ZERO(&set);
CPU_SET(core_num, &set);
int ret = sched_setaffinity(gettid(), sizeof(set), &set);
assert(ret != -1);
printf("Pining into core %d id %ld \n", core_num, pthread_self());
}
*/
//////////////////////////////
//////////////////////////////
////////// RING //
//////////////////////////////
//////////////////////////////
//////////////////////////////
typedef struct seq_ring_buf_s
{
// const size_t elt_size;
task_t* array;
size_t cap;
uint32_t head;
uint32_t tail;
_Atomic uint64_t sz;
} seq_ring_task_t;
typedef void (*seq_free_func)(task_t*);
// For working correctly, maintain the default elements to a multiple of 2
#define DEFAULT_ELM 32
static
size_t size_seq_ring_task(seq_ring_task_t* r)
{
assert(r != NULL);
return r->head - r->tail;
}
inline static
uint32_t mask(uint32_t cap, uint32_t val)
{
return val & (cap-1);
}
static
bool full(seq_ring_task_t* r)
{
return size_seq_ring_task(r) == r->cap -1;
}
static
void enlarge_buffer(seq_ring_task_t* r)
{
assert(r != NULL);
assert(full(r));
const uint32_t factor = 2;
task_t* tmp_buffer = calloc(r->cap * factor, sizeof(task_t) );
assert(tmp_buffer != NULL);
const uint32_t head_pos = mask(r->cap, r->head);
const uint32_t tail_pos = mask(r->cap, r->tail);
if(head_pos > tail_pos){
memcpy(tmp_buffer, r->array + tail_pos , (head_pos-tail_pos)*sizeof(task_t) );
} else {
memcpy(tmp_buffer, r->array + tail_pos, (r->cap-tail_pos)*sizeof(task_t));
memcpy(tmp_buffer + (r->cap-tail_pos), r->array, head_pos*sizeof(task_t));
}
r->cap *= factor;
free(r->array);
r->array = tmp_buffer;
r->tail = 0;
r->head = r->cap/2 - 1;
}
static
void init_seq_ring_task(seq_ring_task_t* r)
{
assert(r != NULL);
task_t* tmp_buffer = calloc(DEFAULT_ELM, sizeof(task_t));
assert(tmp_buffer != NULL);
seq_ring_task_t tmp = {.array = tmp_buffer, .head = 0, .tail = 0, .cap = DEFAULT_ELM};
memcpy(r, &tmp, sizeof(seq_ring_task_t));
r->sz = 0;
}
static
void free_seq_ring_task(seq_ring_task_t* r, seq_free_func fp)
{
assert(r != NULL);
assert(fp == NULL);
free(r->array);
}
static
void push_back_seq_ring_task(seq_ring_task_t* r, task_t t)
{
assert(r != NULL);
if(full(r))
enlarge_buffer(r);
const uint32_t pos = mask(r->cap, r->head);
r->array[pos] = t;
r->head += 1;
r->sz += 1;
}
static
task_t pop_seq_ring_task(seq_ring_task_t* r )
{
assert(r != NULL);
assert(size_seq_ring_task(r) > 0);
const uint32_t pos = mask(r->cap, r->tail);
task_t t = r->array[pos];
r->tail += 1;
r->sz -= 1;
return t;
}
//////////////////////////////
//////////////////////////////
////////// END RING //
//////////////////////////////
//////////////////////////////
//////////////////////////////
//////////////////////////////
//////////////////////////////
////////// Start Notification Queue //
//////////////////////////////
//////////////////////////////
//////////////////////////////
typedef struct {
pthread_mutex_t mtx;
pthread_cond_t cv;
seq_ring_task_t r;
// _Atomic int32_t* futex;
// _Atomic bool* waiting;
_Atomic int done;
} not_q_t;
typedef struct{
task_t t;
bool success;
} ret_try_t;
static
void init_not_q(not_q_t* q/*, _Atomic int32_t* futex, _Atomic bool* waiting*/)
{
assert(q != NULL);
q->done = 0;
//q->waiting = waiting;
init_seq_ring_task(&q->r);
pthread_mutexattr_t attr = {0};
#ifdef _DEBUG
int const rc_mtx = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
assert(rc_mtx == 0);
#endif
int rc = pthread_mutex_init(&q->mtx, &attr);
assert(rc == 0 && "Error while creating the mtx");
pthread_condattr_t* c_attr = NULL;
rc = pthread_cond_init(&q->cv, c_attr);
assert(rc == 0);
//q->futex = futex;
}
static
void free_not_q(not_q_t* q, void (*clean)(task_t*) )
{
assert(q != NULL);
assert(q->done == 1);
free_seq_ring_task(&q->r, clean);
int rc = pthread_mutex_destroy(&q->mtx);
assert(rc == 0);
rc = pthread_cond_destroy(&q->cv);
assert(rc == 0);
}
static
bool try_push_not_q(not_q_t* q, task_t t)
{
assert(q != NULL);
assert(q->done == 0 || q->done ==1);
assert(t.func != NULL);
assert(t.args != NULL);
if(pthread_mutex_trylock(&q->mtx ) != 0)
return false;
push_back_seq_ring_task(&q->r, t);
pthread_cond_signal(&q->cv);
int const rc = pthread_mutex_unlock(&q->mtx);
assert(rc == 0);
return true;
}
static
void push_not_q(not_q_t* q, task_t t)
{
assert(q != NULL);
assert(q->done == 0 || q->done ==1);
assert(t.func != NULL);
int const rc = pthread_mutex_lock(&q->mtx);
assert(rc == 0);
push_back_seq_ring_task(&q->r, t);
pthread_cond_signal(&q->cv);
pthread_mutex_unlock(&q->mtx);
}
static
ret_try_t try_pop_not_q(not_q_t* q)
{
assert(q != NULL);
ret_try_t ret = {.success = false};
int rc = pthread_mutex_trylock(&q->mtx);
assert(rc == 0 || rc == EBUSY);
if(rc == EBUSY)
return ret;
assert(q->done == 0 || q->done ==1);
size_t sz = size_seq_ring_task(&q->r);
if(sz == 0){
rc = pthread_mutex_unlock(&q->mtx);
assert(rc == 0);
return ret;
}
assert(sz > 0);
ret.t = pop_seq_ring_task(&q->r);
rc = pthread_mutex_unlock(&q->mtx);
assert(rc == 0);
ret.success = true;
return ret;
}
static
bool pop_not_q(not_q_t* q, ret_try_t* out)
{
assert(q != NULL);
assert(out != NULL);
assert(q->done == 0 || q->done ==1);
//label:
// Let's be conservative and not use memory_order_relaxed
// while (atomic_load_explicit(q->waiting, memory_order_seq_cst) == true){ //
// Issue X86 PAUSE or ARM YIELD instruction to reduce contention between
// hyper-threads
// pause_or_yield();
// }
pthread_mutex_lock(&q->mtx);
while(size_seq_ring_task(&q->r) == 0 && q->done == 0)
pthread_cond_wait(&q->cv , &q->mtx);
// if(size_seq_ring_task(&q->r) == 0 && q->done == 0){
// int rc = pthread_mutex_unlock(&q->mtx);
// assert(rc == 0);
//
// int val = *q->futex; // atomic_load_explicit(q->futex, memory_order_acquire);
// long r = syscall(SYS_futex, q->futex, FUTEX_WAIT_PRIVATE, val, NULL, 0);
// assert(r != -1);
// goto label;
// }
//
//printf("Waking %ld id %ld \n", time_now_us(), pthread_self());
assert(q->done == 0 || q->done ==1);
if(q->done == 1){
//printf("Done, returning \n");
int rc = pthread_mutex_unlock(&q->mtx);
assert(rc == 0);
return false;
}
out->t = pop_seq_ring_task(&q->r);
int rc = pthread_mutex_unlock(&q->mtx);
assert(rc == 0);
return true;
}
static
void done_not_q(not_q_t* q)
{
assert(q != NULL);
int rc = pthread_mutex_lock(&q->mtx);
assert(rc == 0);
q->done = 1;
//long r = syscall(SYS_futex, q->futex, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0);
//assert(r != -1);
rc = pthread_cond_signal(&q->cv);
assert(rc == 0);
rc = pthread_mutex_unlock(&q->mtx);
assert(rc == 0);
// rc = pthread_cond_signal(&q->cv);
// assert(rc == 0);
// q->futex++;
}
//////////////////////////////
//////////////////////////////
////////// END Notification Queue //
//////////////////////////////
//////////////////////////////
//////////////////////////////
//static int marker_fd;
typedef struct{
task_manager_t* man;
int idx;
} task_thread_args_t;
// Just for debugging purposes, it is very slow!!!!
//static
//_Atomic int cnt_out = 0;
//static
//_Atomic int cnt_in = 0;
static
void* worker_thread(void* arg)
{
assert(arg != NULL);
task_thread_args_t* args = (task_thread_args_t*)arg;
int const idx = args->idx;
//int const log_cores = get_nprocs_conf();
//assert(log_cores > 0);
// Assuming: 2 x Physical cores = Logical cores
//pin_thread_to_core(idx+log_cores/2);
task_manager_t* man = args->man;
uint32_t const len = man->len_thr;
uint32_t const num_it = 2*(man->len_thr + idx);
not_q_t* q_arr = (not_q_t*)man->q_arr;
int acc_num_task = 0;
for(;;){
ret_try_t ret = {.success = false};
for(uint32_t i = idx; i < num_it; ++i){
ret = try_pop_not_q(&q_arr[i%len]);
if(ret.success == true){
break;
}
}
if(ret.success == false){
man->num_task -= acc_num_task;
acc_num_task = 0;
if(pop_not_q(&q_arr[idx], &ret) == false)
break;
}
//int64_t now = time_now_us();
//printf("Calling fuinc \n");
ret.t.func(ret.t.args);
//printf("Returning from func \n");
//int64_t stop = time_now_us();
//cnt_out++;
//printf("Tasks out %d %ld \n", cnt_out, time_now_us());
acc_num_task +=1;
}
free(args);
return NULL;
}
void init_task_manager(task_manager_t* man, uint32_t num_threads)
{
assert(man != NULL);
assert(num_threads > 0 && num_threads < 33 && "Do you have zero or more than 32 processors??");
man->q_arr = calloc(num_threads, sizeof(not_q_t));
assert(man->q_arr != NULL && "Memory exhausted");
//man->futex = 0;
//man->waiting = false;
not_q_t* q_arr = (not_q_t*)man->q_arr;
for(uint32_t i = 0; i < num_threads; ++i){
init_not_q(&q_arr[i] /*, &man->futex, &man->waiting*/);
}
man->t_arr = calloc(num_threads, sizeof(pthread_t));
assert(man->t_arr != NULL && "Memory exhausted" );
man->len_thr = num_threads;
for(uint32_t i = 0; i < num_threads; ++i){
task_thread_args_t* args = malloc(sizeof(task_thread_args_t) );
args->idx = i;
args->man = man;
pthread_attr_t attr = {0};
int ret=pthread_attr_init(&attr);
assert(ret == 0);
ret=pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
assert(ret == 0);
ret=pthread_attr_setschedpolicy(&attr, SCHED_RR);
assert(ret == 0);
struct sched_param sparam={0};
sparam.sched_priority = 94;
ret=pthread_attr_setschedparam(&attr, &sparam);
int rc = pthread_create(&man->t_arr[i], &attr, worker_thread, args);
assert(rc == 0 && "Error creating a thread");
}
man->index = 0;
//
// pthread_mutexattr_t attr = {0};
//#ifdef _DEBUG
// int const rc_mtx = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
// assert(rc_mtx == 0);
//#endif
// int rc = pthread_mutex_init(&man->wait_mtx, &attr);
// assert(rc == 0 && "Error while creating the mtx");
//
// pthread_condattr_t* c_attr = NULL;
// rc = pthread_cond_init(&man->wait_cv, c_attr);
// assert(rc == 0);
//
//pin_thread_to_core(3);
}
void free_task_manager(task_manager_t* man, void (*clean)(task_t*))
{
not_q_t* q_arr = (not_q_t*)man->q_arr;
//atomic_store(&man->waiting, false);
for(uint32_t i = 0; i < man->len_thr; ++i){
done_not_q(&q_arr[i]);
}
for(uint32_t i = 0; i < man->len_thr; ++i){
int rc = pthread_join(man->t_arr[i], NULL);
assert(rc == 0);
}
for(uint32_t i = 0; i < man->len_thr; ++i){
free_not_q(&q_arr[i], clean);
}
free(man->q_arr);
free(man->t_arr);
// int rc = pthread_mutex_destroy(&man->wait_mtx);
// assert(rc == 0);
//
// rc = pthread_cond_destroy(&man->wait_cv);
// assert(rc == 0);
}
void async_task_manager(task_manager_t* man, task_t t)
{
assert(man != NULL);
assert(man->len_thr > 0);
assert(t.func != NULL);
//assert(t.args != NULL);
uint64_t const index = man->index++;
const uint32_t len_thr = man->len_thr;
not_q_t* q_arr = (not_q_t*)man->q_arr;
for(uint32_t i = 0; i < len_thr ; ++i){
if(try_push_not_q(&q_arr[(i+index) % len_thr], t)){
man->num_task +=1;
// Debbugging purposes
//cnt_in++;
//printf("Tasks in %d %ld \n", cnt_in, time_now_us());
return;
}
}
push_not_q(&q_arr[index%len_thr], t);
man->num_task +=1;
// Debbugging purposes
//cnt_in++;
//printf("Tasks in %d %ld \n", cnt_in, time_now_us());
}
/*
void trigger_and_spin_task_manager(task_manager_t* man)
{
assert(man != NULL);
atomic_store(&man->waiting, true);
trigger_all_task_manager(man);
}
void stop_spining_task_manager(task_manager_t* man)
{
assert(man != NULL);
atomic_store(&man->waiting, false);
}
void trigger_and_wait_all_task_manager(task_manager_t* man)
{
assert(man != NULL);
trigger_and_spin_task_manager(man);
stop_spining_task_manager(man);
// atomic_store(&man->waiting, false);
// GCC thread sanitizer complains, while Clang does not. Let's be conservative and pay some cycles
// memory_order_relaxed
//printf("Main func waiting \n");
while (atomic_load_explicit(&man->num_task, memory_order_relaxed)){
// Issue X86 PAUSE or ARM YIELD instruction to reduce contention between
// hyper-threads
pause_or_yield();
}
//printf("Main func returnning \n");
atomic_store(&man->waiting, true);
}
*/
/*
void trigger_all_task_manager(task_manager_t* man)
{
assert(man != NULL);
// FUTEX_WAKE_PRIVATE
atomic_store_explicit(&man->futex, 0, memory_order_seq_cst);
long r = syscall(SYS_futex, &man->futex, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0);
//printf("Number of threads woken %ld \n", r);
if(r == -1){
printf("%d errno \n", errno);
}
assert(r != -1);
}
*/
/*
void wait_all_task_manager(task_manager_t* man)
{
assert(man != NULL);
while (atomic_load_explicit(&man->num_task, memory_order_relaxed)){
// Issue X86 PAUSE or ARM YIELD instruction to reduce contention between
// hyper-threads
pause_or_yield();
}
}
*/
/*
// This function does not belong here logically
void wait_task_status_completed(size_t len, task_status_t* arr)
{
assert(len > 0);
assert(arr != NULL);
// We are believing Fedor
const struct timespec ns = {0,1};
int i = 0;
for(int j = len -1; j != -1 ; i++){
for(; j != -1; --j){
int const task_completed = 1;
if(atomic_load_explicit(&arr[j].completed, memory_order_seq_cst) != task_completed) // memory_order_acquire
break;
}
if(i == 16){
i = 0;
nanosleep(&ns, NULL);
}
}
}
*/
// This function does not belong here logically
void wait_task_status_completed(size_t len, task_status_t* arr)
{
assert(len > 0);
assert(arr != NULL);
// We are believing Fedor
const struct timespec ns = {0,1};
uint64_t i = 0;
for(int j = len -1; j != -1 ; i++){
for(; j != -1; --j){
int const task_completed = 1;
if(atomic_load_explicit(&arr[j].completed, memory_order_acquire) != task_completed) // memory_order_acquire
break;
}
if(i % 16 == 0){
nanosleep(&ns, NULL);
}
//sched_yield();
// pause_or_yield();
}
}
#undef pause_or_yield

View File

@@ -0,0 +1,91 @@
#ifndef TASK_MANAGER_WORKING_STEALING_H
#define TASK_MANAGER_WORKING_STEALING_H
// Comment for deactivating ws tpool
#define TASK_MANAGER
#define TASK_MANAGER_DEMODULATION
#define TASK_MANAGER_CODING
#define TASK_MANAGER_RU
#define TASK_MANAGER_UE
#define TASK_MANAGER_UE_DECODING
#define TASK_MANAGER_SIM
#define TASK_MANAGER_LTE
#include "task.h"
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#ifndef __cplusplus
#include <stdalign.h>
#include <stdatomic.h>
#else
#include <atomic>
#define _Atomic(X) std::atomic< X >
#define _Alignas(X) alignas(X)
#endif
#if defined (__i386__) || defined(__x86_64__)
#define pause_or_yield __builtin_ia32_pause
#elif __aarch64__
#define pause_or_yield() asm volatile("yield" ::: "memory")
#else
static_assert(0!=0, "Unknown CPU architecture");
#endif
typedef struct{
// Avoid false sharing
_Alignas(LEVEL1_DCACHE_LINESIZE) _Atomic(int) completed;
} task_status_t;
typedef struct{
uint8_t* buf;
size_t len;
task_status_t* tasks_remaining;
} thread_info_tm_t;
typedef struct{
pthread_t* t_arr;
size_t len_thr;
_Atomic(uint64_t) index;
void* q_arr;
_Atomic(uint64_t) num_task;
// pthread_cond_t wait_cv;
// pthread_mutex_t wait_mtx;
// _Atomic int32_t futex;
// _Atomic bool waiting;
} task_manager_t;
void init_task_manager(task_manager_t* man, uint32_t num_threads);
void free_task_manager(task_manager_t* man, void (*clean)(task_t* args) );
void async_task_manager(task_manager_t* man, task_t t);
//void trigger_all_task_manager(task_manager_t* man);
//
////void trigger_and_spin_task_manager(task_manager_t* man);
//
//void stop_spining_task_manager(task_manager_t* man);
//
////void trigger_and_wait_all_task_manager(task_manager_t* man);
//
//void wait_all_task_manager(task_manager_t* man);
//
// This function does not belong here.
// It should be in an algorithm file
//void wait_spin_all_atomics_one(size_t len, _Atomic int arr[len]);
void wait_task_status_completed(size_t len, task_status_t* arr);
#endif

View File

@@ -27,7 +27,7 @@
#include "assertions.h"
#include <pthread.h>
#include "common/config/config_userapi.h"
#include <common/utils/threadPool/thread-pool.h>
#include "common/utils/threadPool/thread-pool.h"
// global var for openair performance profiler
int opp_enabled = 0;
double cpu_freq_GHz __attribute__ ((aligned(32)));

View File

@@ -33,7 +33,7 @@
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sched.h>
#include <ctype.h>
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#include "assertions.h"
@@ -434,6 +434,37 @@ static void wait_nfapi_init(char *thread_name) {
pthread_mutex_unlock(&nfapi_sync_mutex);
printf( "NFAPI: got sync (%s)\n", thread_name);
}
#ifdef TASK_MANAGER_LTE
static int num_threads(char* params)
{
char *saveptr, * curptr;
char *parms_cpy=strdup(params);
int nbThreads=0;
curptr=strtok_r(parms_cpy,",",&saveptr);
while ( curptr!=NULL ) {
int c=toupper(curptr[0]);
switch (c) {
case 'N':
//pool->activated=false;
break;
default: ;
int core_id = atoi(curptr);
printf("create a thread for core %d\n", core_id);
// set the thread name for debugging
nbThreads++;
}
curptr=strtok_r(NULL,",",&saveptr);
}
free(parms_cpy);
return nbThreads;
}
#endif
configmodule_interface_t *uniqCfg = NULL;
int main ( int argc, char **argv )
{
@@ -545,18 +576,34 @@ int main ( int argc, char **argv )
printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
init_eNB(get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
}
#ifdef TASK_MANAGER_LTE
assert(strlen(get_softmodem_params()->threadPoolConfig) > 0);
int const n_threads = max(num_threads(get_softmodem_params()->threadPoolConfig), 1);
task_manager_t man = {0};
init_task_manager(&man, n_threads);
#endif
for (int x=0; x < RC.nb_L1_inst; x++)
for (int CC_id=0; CC_id<RC.nb_L1_CC[x]; CC_id++) {
L1_rxtx_proc_t *L1proc= &RC.eNB[x][CC_id]->proc.L1_proc;
L1_rxtx_proc_t *L1proctx= &RC.eNB[x][CC_id]->proc.L1_proc_tx;
L1proc->threadPool = (tpool_t *)malloc(sizeof(tpool_t));
#ifdef TASK_MANAGER_LTE
L1proc->man = &man;
L1proctx->man = &man;
#else
L1proc->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
// Most likely a bug. Do you want a thread pool per CC ?
L1proc->threadPool = (tpool_t *)malloc(sizeof(tpool_t));
if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 )
initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true);
else
initTpool("n", L1proc->threadPool, true);
initNotifiedFIFO(L1proc->respDecode);
}
else{
assert(0!=0 && "Bug");
initTpool("n", L1proc->threadPool, true);
}
L1proctx->threadPool = L1proc->threadPool;
#endif
initNotifiedFIFO(L1proc->respDecode);
}
printf("wait_eNBs()\n");

View File

@@ -32,6 +32,7 @@
#define _GNU_SOURCE
#include <pthread.h>
#include <ctype.h>
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
@@ -52,6 +53,7 @@
#include "PHY/MODULATION/nr_modulation.h"
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h"
#include "common/utils/thread_pool/task_manager.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
@@ -269,30 +271,48 @@ void rx_func(void *param)
int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx);
if ((tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) && NFAPI_MODE != NFAPI_MODE_PNF) {
notifiedFIFO_elt_t *res;
processingData_L1tx_t *syncMsg;
// notifiedFIFO_elt_t *res;
// processingData_L1tx_t *syncMsg;
// Its a FIFO so it maitains the order in which the MAC fills the messages
// so no need for checking for right slot
if (get_softmodem_params()->reorder_thread_disable) {
// call the TX function directly from this thread
syncMsg = gNB->msgDataTx;
processingData_L1tx_t *syncMsg = gNB->msgDataTx;
syncMsg->gNB = gNB;
syncMsg->timestamp_tx = info->timestamp_tx;
tx_func(syncMsg);
} else {
res = pullTpool(&gNB->L1_tx_filled, &gNB->threadPool);
if (res == NULL)
return; // Tpool has been stopped
syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
//notifiedFIFO_elt_t * res = pullTpool(&gNB->L1_tx_filled, &gNB->threadPool);
notifiedFIFO_elt_t* res = pullNotifiedFIFO(&gNB->L1_tx_filled);
if (res == NULL){
#ifdef TASK_MANAGER_RU
if(info->elm != NULL)
pushNotifiedFIFO(info->elm->reponseFifo, info->elm);
#endif
return; // Queue aborted
}
processingData_L1tx_t* syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
syncMsg->gNB = gNB;
syncMsg->timestamp_tx = info->timestamp_tx;
res->key = slot_tx;
pushTpool(&gNB->threadPool, res);
//#ifdef TASK_MANAGER
assert(res->processingFunc != NULL);
res->processingFunc(NotifiedFifoData(res));
if (res->reponseFifo)
pushNotifiedFIFO(res->reponseFifo, res);
//#else
// pushTpool(&gNB->threadPool, res);
//#endif
}
} else if (get_softmodem_params()->continuous_tx) {
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&gNB->L1_tx_free);
if (res == NULL)
return; // Tpool has been stopped
if (res == NULL){
#ifdef TASK_MANAGER_RU
if(info->elm != NULL)
pushNotifiedFIFO(info->elm->reponseFifo, info->elm);
#endif
return; // Queue aborted
}
processingData_L1tx_t *syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
syncMsg->gNB = gNB;
syncMsg->timestamp_tx = info->timestamp_tx;
@@ -301,6 +321,11 @@ void rx_func(void *param)
res->key = slot_tx;
pushNotifiedFIFO(&gNB->L1_tx_out, res);
}
#ifdef TASK_MANAGER_RU
// I can also write bad code
if(info->elm != NULL)
pushNotifiedFIFO(info->elm->reponseFifo, info->elm);
#endif
#if 0
LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
@@ -415,12 +440,11 @@ void *nrL1_stats_thread(void *param) {
return(NULL);
}
// This thread reads the finished L1 tx jobs from threaPool
// This thread reads the finished L1 tx jobs from threadPool
// and pushes RU tx thread in the right order. It works only
// two parallel L1 tx threads.
void *tx_reorder_thread(void* param) {
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
notifiedFIFO_elt_t *resL1Reserve = pullNotifiedFIFO(&gNB->L1_tx_out);
AssertFatal(resL1Reserve != NULL, "pullTpool() did not return start message in %s\n", __func__);
int next_tx_slot=((processingData_L1tx_t *)NotifiedFifoData(resL1Reserve))->slot;
@@ -469,15 +493,54 @@ void *tx_reorder_thread(void* param) {
return(NULL);
}
static
int num_threads(char* params)
{
char *saveptr, * curptr;
int nbThreads=0;
curptr=strtok_r( params,",",&saveptr);
while ( curptr!=NULL ) {
int c=toupper(curptr[0]);
switch (c) {
case 'N': {
//pool->activated=false;
break;
}
default:{
int core_id = atoi(curptr);
printf("create a thread for core %d\n", core_id);
nbThreads++;
}
}
curptr=strtok_r(NULL,",",&saveptr);
}
return nbThreads;
}
void init_gNB_Tpool(int inst) {
PHY_VARS_gNB *gNB;
gNB = RC.gNB[inst];
gNB_L1_proc_t *proc = &gNB->proc;
// PUSCH symbols per thread need to be calculated by how many threads we have
gNB->num_pusch_symbols_per_thread = 1;
#if defined(TASK_MANAGER) && defined(TASK_MANAGER_CODING) && defined(TASK_MANAGER_DEMODULATION) && defined(TASK_MANAGER_RU)
int n_threads = num_threads(get_softmodem_params()->threadPoolConfig);
init_task_manager(&gNB->man, n_threads); //log_cores/2);
#elif !defined(TASK_MANAGER) || !defined(TASK_MANAGER_CODING) || !defined(TASK_MANAGER_DEMODULATION) || !defined(TASK_MANAGER_RU)
int n_threads = num_threads(get_softmodem_params()->threadPoolConfig);
init_task_manager(&gNB->man, n_threads ); //log_cores/2);
// ULSCH decoding threadpool
initTpool(get_softmodem_params()->threadPoolConfig, &gNB->threadPool, cpumeas(CPUMEAS_GETSTATE));
// ULSCH decoder result FIFO
#else
// ULSCH decoding threadpool
initTpool(get_softmodem_params()->threadPoolConfig, &gNB->threadPool, cpumeas(CPUMEAS_GETSTATE));
#endif
// ULSCH decoder result FIFO
initNotifiedFIFO(&gNB->respPuschSymb);
initNotifiedFIFO(&gNB->respDecode);
@@ -531,7 +594,13 @@ void init_gNB_Tpool(int inst) {
void term_gNB_Tpool(int inst) {
PHY_VARS_gNB *gNB = RC.gNB[inst];
#ifdef TASK_MANAGER
void (*clean)(task_t*) = NULL;
free_task_manager(&gNB->man , clean);
#else
abortTpool(&gNB->threadPool);
#endif
abortNotifiedFIFO(&gNB->respDecode);
abortNotifiedFIFO(&gNB->resp_L1);
abortNotifiedFIFO(&gNB->L1_tx_free);

View File

@@ -54,6 +54,8 @@
#include <executables/softmodem-common.h>
#include "common/utils/thread_pool/task_manager.h"
#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
@@ -1189,9 +1191,6 @@ void *ru_thread( void *param ) {
pthread_mutex_unlock(&RC.ru_mutex);
wait_sync("ru_thread");
processingData_L1_t *syncMsg;
notifiedFIFO_elt_t *res;
if(!emulate_rf) {
// Start RF device if any
if (ru->start_rf) {
@@ -1339,14 +1338,19 @@ void *ru_thread( void *param ) {
}
} // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
notifiedFIFO_elt_t *res = NULL;
// At this point, all information for subframe has been received on FH interface
if (!get_softmodem_params()->reorder_thread_disable) {
res = pullTpool(&gNB->resp_L1, &gNB->threadPool);
res = pullNotifiedFIFO(&gNB->resp_L1);
if (res == NULL)
break; // Tpool has been stopped
} else {
res=newNotifiedFIFO_elt(sizeof(processingData_L1_t),0, &gNB->resp_L1,NULL);
} else {
res = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->resp_L1, NULL);
}
processingData_L1_t *syncMsg = NULL;
syncMsg = (processingData_L1_t *)NotifiedFifoData(res);
syncMsg->gNB = gNB;
syncMsg->frame_rx = proc->frame_rx;
@@ -1355,8 +1359,18 @@ void *ru_thread( void *param ) {
syncMsg->slot_tx = proc->tti_tx;
syncMsg->timestamp_tx = proc->timestamp_tx;
res->key = proc->tti_rx;
#ifdef TASK_MANAGER // No TASK_MANAGER_RU
if (!get_softmodem_params()->reorder_thread_disable) {
assert(res->processingFunc == rx_func);
assert(res->reponseFifo != NULL);
syncMsg->elm = res;
task_t t = {.func = rx_func, .args = syncMsg};
async_task_manager(&gNB->man, t);
}
#else
if (!get_softmodem_params()->reorder_thread_disable)
pushTpool(&gNB->threadPool, res);
#endif
else
pushNotifiedFIFO(&gNB->resp_L1, res);
}
@@ -1862,8 +1876,12 @@ void init_NR_RU(configmodule_interface_t *cfg, char *rf_config_file)
s_offset+=sprintf(pool+s_offset,",%d",ru->tpcores[icpu]);
}
LOG_I(PHY,"RU thread-pool core string %s\n",pool);
#ifdef TASK_MANAGER_RU
init_task_manager(&ru->man, ru->num_tpcores);
#else
ru->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
initTpool(pool, ru->threadPool, cpumeas(CPUMEAS_GETSTATE));
#endif
// FEP RX result FIFO
ru->respfeprx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
initNotifiedFIFO(ru->respfeprx);

View File

@@ -36,6 +36,7 @@
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "RRC/NR/MESSAGES/asn1_msg.h"
#include "common/utils/thread_pool/task_manager.h"
/*
* NR SLOT PROCESSING SEQUENCE
@@ -363,7 +364,9 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
typedef nr_rxtx_thread_data_t syncData_t;
static void UE_synch(void *arg) {
static
void UE_synch(void *arg)
{
syncData_t *syncD=(syncData_t *) arg;
int i, hw_slot_offset;
PHY_VARS_NR_UE *UE = syncD->UE;
@@ -538,8 +541,8 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
}
void processSlotTX(void *arg) {
void processSlotTX(void *arg)
{
nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg;
UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
PHY_VARS_NR_UE *UE = rxtxD->UE;
@@ -773,10 +776,8 @@ void *UE_thread(void *arg)
}
while (!oai_exit) {
if (syncRunning) {
notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool));
notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf);
if (res) {
syncRunning=false;
if (UE->is_synchronized) {
@@ -789,18 +790,18 @@ void *UE_thread(void *arg)
decoded_frame_rx = (decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER;
}
delNotifiedFIFO_elt(res);
start_rx_stream=0;
start_rx_stream = 0;
} else {
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
// For IQ recorder/player we force synchronization to happen in 280 ms
while (trashed_frames != 28) {
readFrame(UE, &timestamp, true);
trashed_frames+=2;
}
} else {
readFrame(UE, &timestamp, true);
trashed_frames+=2;
}
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
// For IQ recorder/player we force synchronization to happen in 280 ms
while (trashed_frames != 28) {
readFrame(UE, &timestamp, true);
trashed_frames += 2;
}
} else {
readFrame(UE, &timestamp, true);
trashed_frames += 2;
}
continue;
}
}
@@ -813,24 +814,34 @@ void *UE_thread(void *arg)
syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg);
syncMsg->UE = UE;
memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
pushTpool(&(get_nrUE_params()->Tpool), Msg);
#ifdef TASK_MANAGER_UE
assert(Msg->processingFunc != NULL);
Msg->processingFunc(NotifiedFifoData(Msg));
if (Msg->reponseFifo)
pushNotifiedFIFO(Msg->reponseFifo,Msg);
else
delNotifiedFIFO_elt(Msg);
#else
pushTpool(&(get_nrUE_params()->Tpool), Msg);
#endif
trashed_frames = 0;
syncRunning = true;
continue;
}
if (start_rx_stream == 0) {
start_rx_stream=1;
start_rx_stream = 1;
syncInFrame(UE, &timestamp);
UE->rx_offset=0;
UE->time_sync_cell=0;
UE->rx_offset = 0;
UE->time_sync_cell = 0;
// read in first symbol
AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 ==
UE->rfdevice.trx_read_func(&UE->rfdevice,
&timestamp,
(void **)UE->common_vars.rxdata,
UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
UE->frame_parms.nb_antennas_rx),"");
AssertFatal(UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0
== UE->rfdevice.trx_read_func(&UE->rfdevice,
&timestamp,
(void **)UE->common_vars.rxdata,
UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0,
UE->frame_parms.nb_antennas_rx),
"");
// we have the decoded frame index in the return of the synch process
// and we shifted above to the first slot of next frame
decoded_frame_rx++;
@@ -839,12 +850,11 @@ void *UE_thread(void *arg)
continue;
}
absolute_slot++;
int slot_nr = absolute_slot % nb_slot_frame;
nr_rxtx_thread_data_t curMsg = {0};
curMsg.UE=UE;
curMsg.UE = UE;
// update thread index for received subframe
curMsg.proc.nr_slot_rx = slot_nr;
curMsg.proc.nr_slot_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
@@ -860,9 +870,9 @@ void *UE_thread(void *arg)
}
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms);
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp+
UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,0)];
for (int i = 0; i < UE->frame_parms.nb_antennas_rx; i++)
rxp[i] = (void *)&UE->common_vars
.rxdata[i][firstSymSamp + UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, 0)];
int readBlockSize, writeBlockSize;
@@ -875,12 +885,9 @@ void *UE_thread(void *arg)
UE->apply_timing_offset = false;
}
AssertFatal(readBlockSize ==
UE->rfdevice.trx_read_func(&UE->rfdevice,
&timestamp,
rxp,
readBlockSize,
UE->frame_parms.nb_antennas_rx),"");
AssertFatal(
readBlockSize == UE->rfdevice.trx_read_func(&UE->rfdevice, &timestamp, rxp, readBlockSize, UE->frame_parms.nb_antennas_rx),
"");
if(slot_nr == (nb_slot_frame - 1)) {
// read in first symbol of next frame and adjust for timing drift
@@ -888,14 +895,15 @@ void *UE_thread(void *arg)
if (first_symbols > 0) {
openair0_timestamp ignore_timestamp;
AssertFatal(first_symbols ==
UE->rfdevice.trx_read_func(&UE->rfdevice,
&ignore_timestamp,
(void **)UE->common_vars.rxdata,
first_symbols,
UE->frame_parms.nb_antennas_rx),"");
AssertFatal(first_symbols
== UE->rfdevice.trx_read_func(&UE->rfdevice,
&ignore_timestamp,
(void **)UE->common_vars.rxdata,
first_symbols,
UE->frame_parms.nb_antennas_rx),
"");
} else
LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols);
LOG_E(PHY, "can't compensate: diff =%d\n", first_symbols);
}
// use previous timing_advance value to compute writeTimestamp
@@ -915,30 +923,60 @@ void *UE_thread(void *arg)
// Start TX slot processing here. It runs in parallel with RX slot processing
notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_tx, &txFifo, processSlotTX);
nr_rxtx_thread_data_t *curMsgTx = (nr_rxtx_thread_data_t *) NotifiedFifoData(newElt);
nr_rxtx_thread_data_t *curMsgTx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newElt);
curMsgTx->proc = curMsg.proc;
curMsgTx->writeBlockSize = writeBlockSize;
curMsgTx->proc.timestamp_tx = writeTimestamp;
curMsgTx->UE = UE;
curMsgTx->tx_wait_for_dlsch = UE->tx_wait_for_dlsch[curMsgTx->proc.nr_slot_tx];
UE->tx_wait_for_dlsch[curMsgTx->proc.nr_slot_tx] = 0;
pushTpool(&(get_nrUE_params()->Tpool), newElt);
#ifdef TASK_MANAGER_UE
assert(newElt->processingFunc != NULL);
newElt->processingFunc(NotifiedFifoData(newElt));
if (newElt->reponseFifo)
pushNotifiedFIFO(newElt->reponseFifo, newElt);
else
delNotifiedFIFO_elt(newElt);
#else
pushTpool(&(get_nrUE_params()->Tpool), newElt);
#endif
// RX slot processing. We launch and forget.
newElt = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_rx, NULL, UE_dl_processing);
nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *) NotifiedFifoData(newElt);
nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newElt);
curMsgRx->proc = curMsg.proc;
curMsgRx->UE = UE;
curMsgRx->phy_data = UE_dl_preprocessing(UE, &curMsg.proc);
#ifdef TASK_MANAGER_UE
assert(newElt->processingFunc != NULL);
newElt->processingFunc(NotifiedFifoData(newElt));
if (newElt->reponseFifo)
pushNotifiedFIFO(newElt->reponseFifo, newElt);
else
delNotifiedFIFO_elt(newElt);
#else
pushTpool(&(get_nrUE_params()->Tpool), newElt);
#endif
/*
if (curMsg.proc.decoded_frame_rx != -1)
decoded_frame_rx =
(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused) << 4) | curMsg.proc.decoded_frame_rx);
else
decoded_frame_rx = -1;
// Wait for TX slot processing to finish
notifiedFIFO_elt_t *res;
res = pullTpool(&txFifo, &(get_nrUE_params()->Tpool));
if (decoded_frame_rx > 0 && decoded_frame_rx != curMsg.proc.frame_rx)
LOG_E(PHY,
"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n",
decoded_frame_rx,
curMsg.proc.frame_rx);
*/
// Wait for TX slot processing to finish
notifiedFIFO_elt_t* res = pullNotifiedFIFO(&txFifo);
if (res == NULL)
LOG_E(PHY, "Tpool has been aborted\n");
else
delNotifiedFIFO_elt(res);
} // while !oai_exit
return NULL;
@@ -981,15 +1019,16 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf
}
}
void init_NR_UE_threads(int nb_inst) {
void init_NR_UE_threads(int nb_inst)
{
int inst;
pthread_t threads[nb_inst];
for (inst=0; inst < nb_inst; inst++) {
for (inst = 0; inst < nb_inst; inst++) {
PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0];
LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
LOG_I(PHY, "Intializing UE Threads for instance %d (%p,%p)...\n", inst, PHY_vars_UE_g[inst], PHY_vars_UE_g[inst][0]);
threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
if (!IS_SOFTMODEM_NOSTATS_BIT) {
pthread_t stat_pthread;
@@ -997,3 +1036,16 @@ void init_NR_UE_threads(int nb_inst) {
}
}
}
/* HACK: this function is needed to compile the UE
* fix it somehow
*/
int find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB, find_type_t type)
{
printf("you cannot read this\n");
abort();
}
void multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP)
{
}

View File

@@ -32,7 +32,11 @@
#include "SCHED_NR_UE/defs.h"
#include "common/ran_context.h"
#include "common/config/config_userapi.h"
//#include "common/utils/threadPool/thread-pool.h"
#include "common/utils/threadPool/thread-pool.h"
#include "common/utils/thread_pool/task_manager.h"
#include <sys/sysinfo.h>
#include "common/utils/load_module_shlib.h"
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "common/utils/nr/nr_common.h"
@@ -89,6 +93,8 @@ unsigned short config_frames[4] = {2,9,11,13};
extern const char *duplex_mode[];
THREAD_STRUCT thread_struct;
static
nrUE_params_t nrUE_params;
// Thread variables
@@ -460,7 +466,14 @@ int main( int argc, char **argv ) {
#if T_TRACER
T_Config_Init();
#endif
#if defined TASK_MANAGER_UE || defined TASK_MANAGER_UE_DECODING
int const log_cores = get_nprocs_conf();
assert(log_cores > 0);
init_task_manager(&nrUE_params.man, log_cores);
#else
initTpool(get_softmodem_params()->threadPoolConfig, &(nrUE_params.Tpool), cpumeas(CPUMEAS_GETSTATE));
#endif
//randominit (0);
set_taus_seed (0);

View File

@@ -4,8 +4,7 @@
#include <executables/softmodem-common.h>
#include "PHY/defs_nr_UE.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
#include "common/utils/thread_pool/task_manager.h"
#define CONFIG_HLP_IF_FREQ "IF frequency for RF, if needed\n"
#define CONFIG_HLP_IF_FREQ_OFF "UL IF frequency offset for RF, if needed\n"
@@ -70,7 +69,14 @@ typedef struct {
uint64_t optmask; //mask to store boolean config options
uint32_t ofdm_offset_divisor; // Divisor for sample offset computation for each OFDM symbol
int max_ldpc_iterations; // number of maximum LDPC iterations
#if defined (TASK_MANAGER_UE) && defined (TASK_MANAGER_UE_DECODING) && defined(TASK_MANAGER_SIM)
task_manager_t man;
#elif !defined (TASK_MANAGER_UE) || !defined(TASK_MANAGER_UE_DECODING) || !defined(TASK_MANAGER_SIM)
task_manager_t man;
tpool_t Tpool; // thread pool
#else
tpool_t Tpool; // thread pool
#endif
int UE_scan_carrier;
int UE_fo_compensation;
int timing_advance;

View File

@@ -205,6 +205,8 @@ void signal_handler(int sig) {
//void *array[10];
//size_t size;
printf("[MIR]: Here we are!\n");
if (sig==SIGSEGV) {
// get void*'s for all entries on the stack
/* backtrace uses malloc, that is not good in signal handlers

View File

@@ -0,0 +1,269 @@
Active_gNBs = ( "gNB-OAI");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_name = "gNB-OAI";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
nr_cellid = 12345678L;
min_rxtxtime=6;
////////// Physical parameters:
do_CSIRS = 1;
do_SRS = 1;
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
absoluteFrequencySSB = 641280;
dl_frequencyBand = 78;
# this is 3600 MHz
dl_absoluteFrequencyPointA = 640008;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 1;
dl_carrierBandwidth = 106;
#initialDownlinkBWP
#genericParameters
# this is RBstart=27,L=48 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 1;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 12;
initialDLBWPsearchSpaceZero = 0;
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 78;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 1;
ul_carrierBandwidth = 106;
pMax = 20;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 28875;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 1;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 98;
#prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 13;
preambleReceivedTargetPower = -96;
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
preambleTransMax = 6;
#powerRampingStep
# 0=dB0,1=dB2,2=dB4,3=dB6
powerRampingStep = 1;
#ra_ReponseWindow
#1,2,4,8,10,20,40,80
ra_ResponseWindow = 4;
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
#oneHalf (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
#ra_ContentionResolutionTimer
#(0..7) 8,16,24,32,40,48,56,64
ra_ContentionResolutionTimer = 7;
rsrp_ThresholdSSB = 19;
#prach-RootSequenceIndex_PR
#1 = 839, 2 = 139
prach_RootSequenceIndex_PR = 2;
prach_RootSequenceIndex = 1;
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
#
msg1_SubcarrierSpacing = 1,
# restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0,
msg3_DeltaPreamble = 1;
p0_NominalWithGrant =-90;
# pucch-ConfigCommon setup :
# pucchGroupHopping
# 0 = neither, 1= group hopping, 2=sequence hopping
pucchGroupHopping = 0;
hoppingId = 40;
p0_nominal = -90;
# ssb_PositionsInBurs_BitmapPR
# 1=short, 2=medium, 3=long
ssb_PositionsInBurst_PR = 2;
ssb_PositionsInBurst_Bitmap = 1;
# ssb_periodicityServingCell
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
ssb_periodicityServingCell = 2;
# dmrs_TypeA_position
# 0 = pos2, 1 = pos3
dmrs_TypeA_Position = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
subcarrierSpacing = 1;
#tdd-UL-DL-ConfigurationCommon
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
referenceSubcarrierSpacing = 1;
# pattern1
# dl_UL_TransmissionPeriodicity
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
dl_UL_TransmissionPeriodicity = 6;
nrofDownlinkSlots = 7;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 2;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -25;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ( { ipv4 = "192.168.70.132";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24";
GNB_INTERFACE_NAME_FOR_NGU = "demo-oai";
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 150;
pucch_TargetSNRx10 = 200;
ulsch_max_frame_inactivity = 0;
ul_max_mcs = 28;
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 120;
pucch0_dtx_threshold = 100;
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
}
);
RUs = (
{
local_rf = "yes"
nb_tx = 1
nb_rx = 1
att_tx = 12;
att_rx = 12;
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 114;
eNB_instances = [0];
#beamforming 1x4 matrix:
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
clock_src = "internal";
}
);
THREAD_STRUCT = (
{
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
parallel_config = "PARALLEL_SINGLE_THREAD";
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
worker_config = "WORKER_ENABLE";
}
);
rfsimulator :
{
serveraddr = "server";
serverport = "4043";
options = (); #("saviq"); or/and "chanmod"
modelname = "AWGN";
IQfile = "/tmp/rfsimulator.iqs";
};
security = {
# preferred ciphering algorithms
# the first one of the list that an UE supports in chosen
# valid values: nea0, nea1, nea2, nea3
ciphering_algorithms = ( "nea0" );
# preferred integrity algorithms
# the first one of the list that an UE supports in chosen
# valid values: nia0, nia1, nia2, nia3
integrity_algorithms = ( "nia2", "nia0" );
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
drb_ciphering = "yes";
drb_integrity = "no";
};
log_config :
{
global_log_level ="info";
hw_log_level ="info";
phy_log_level ="info";
mac_log_level ="info";
rlc_log_level ="info";
pdcp_log_level ="info";
rrc_log_level ="info";
ngap_log_level ="debug";
f1ap_log_level ="debug";
};

View File

@@ -24,6 +24,7 @@
#define __NRLDPC_DEFS__H__
#include <openair1/PHY/defs_nr_common.h>
#include "openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
#include "common/utils/thread_pool/task_manager.h"
/**
\brief LDPC encoder
@@ -63,6 +64,11 @@ typedef struct {
unsigned int G;
// Redundancy version index
uint8_t rv;
/// LDPC-code outputs
uint8_t *d[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS];
#ifdef TASK_MANAGER_CODING
task_status_t* task_done;
#endif
} encoder_implemparams_t;
typedef int32_t(LDPC_initfunc_t)(void);

View File

@@ -43,6 +43,7 @@
#include "executables/lte-softmodem.h"
#include <syscall.h>
#include <common/utils/threadPool/thread-pool.h>
#include <stdatomic.h>
//#define DEBUG_DLSCH_CODING
//#define DEBUG_DLSCH_FREE 1
@@ -280,6 +281,12 @@ static void TPencode(void * arg) {
rdata->r,
hadlsch->nb_rb);
stop_meas(rdata->rm_stats);
#ifdef TASK_MANAGER_LTE
//assert(atomic_load(rdata->tasks_remaining) == 0);
atomic_store_explicit(&rdata->tasks_remaining->completed,1, memory_order_seq_cst);
#endif
}
int dlsch_encoding(PHY_VARS_eNB *eNB,
@@ -318,7 +325,6 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
frame,subframe,beamforming_mode);
int nbEncode = 0;
// if (hadlsch->Ndi == 1) { // this is a new packet
if (hadlsch->round == 0) { // this is a new packet
// Add 24-bit crc (polynomial A) to payload
@@ -345,13 +351,25 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
return(-1);
}
#ifdef TASK_MANAGER_LTE
turboEncode_t arr[hadlsch->C];
task_status_t tasks_remaining[hadlsch->C];
memset(arr, 0, sizeof(turboEncode_t)*hadlsch->C); // Let's waste some CPU cycles...
memset(tasks_remaining, 0, sizeof(task_status_t)*hadlsch->C);
#else
notifiedFIFO_t respEncode;
initNotifiedFIFO(&respEncode);
#endif
for (int r=0, r_offset=0; r<hadlsch->C; r++) {
#ifdef TASK_MANAGER_LTE
turboEncode_t* rdata = &arr[r];
rdata->tasks_remaining = &tasks_remaining[r];
#else
union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}};
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, &respEncode, TPencode);
turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req);
#endif
rdata->input=hadlsch->c[r];
rdata->Kr_bytes= ( r<hadlsch->Cminus ? hadlsch->Kminus : hadlsch->Kplus) >>3;
rdata->filler=(r==0) ? hadlsch->F : 0;
@@ -365,9 +383,13 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
rdata->r_offset=r_offset;
rdata->G=G;
pushTpool(proc->threadPool, req);
#ifdef TASK_MANAGER_LTE
task_t t = {.func = TPencode, .args = rdata};
async_task_manager(proc->man, t);
#else
pushTpool(proc->threadPool, req);
#endif
nbEncode++;
int Qm=hadlsch->Qm;
int C=hadlsch->C;
int Nl=hadlsch->Nl;
@@ -378,6 +400,12 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
else
r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C));
}
#ifdef TASK_MANAGER_LTE
if(nbEncode > 0){
wait_task_status_completed(hadlsch->C, tasks_remaining);
}
#else
// Wait all other threads finish to process
while (nbEncode) {
notifiedFIFO_elt_t *res = pullTpool(&respEncode, proc->threadPool);
@@ -386,6 +414,7 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
delNotifiedFIFO_elt(res);
nbEncode--;
}
#endif
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return(0);
}
@@ -450,14 +479,26 @@ int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB,
&hadlsch->F)<0)
return(-1);
}
int nbEncode = 0;
#ifdef TASK_MANAGER_LTE
turboEncode_t arr[hadlsch->C];
task_status_t tasks_remaining[hadlsch->C];
memset(arr, 0, sizeof(turboEncode_t)*hadlsch->C); // Let's waste some CPU cycles...
memset(tasks_remaining, 0, sizeof(task_status_t)*hadlsch->C);
#else
notifiedFIFO_t respEncode;
initNotifiedFIFO(&respEncode);
#endif
for (int r=0, r_offset=0; r<hadlsch->C; r++) {
#ifdef TASK_MANAGER_LTE
turboEncode_t* rdata = &arr[r];
rdata->tasks_remaining = &tasks_remaining[r];
#else
union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}};
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, &respEncode, TPencode);
turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req);
#endif
rdata->input=hadlsch->c[r];
rdata->Kr_bytes= ( r<hadlsch->Cminus ? hadlsch->Kminus : hadlsch->Kplus) >>3;
rdata->filler=(r==0) ? hadlsch->F : 0;
@@ -471,7 +512,12 @@ int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB,
rdata->r_offset=r_offset;
rdata->G=G;
#ifdef TASK_MANAGER_LTE
task_t t = {.func = TPencode, .args = rdata};
async_task_manager(proc->man, t);
#else
pushTpool(proc->threadPool, req);
#endif
nbEncode++;
int Qm=hadlsch->Qm;
@@ -484,6 +530,12 @@ int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB,
else
r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C));
}
#ifdef TASK_MANAGER_LTE
if(nbEncode > 0){
wait_task_status_completed(hadlsch->C, tasks_remaining);
}
#else
// Wait all other threads finish to process
while (nbEncode) {
notifiedFIFO_elt_t *res = pullTpool(&respEncode, proc->threadPool);
@@ -492,6 +544,7 @@ int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB,
delNotifiedFIFO_elt(res);
nbEncode--;
}
#endif
return(0);
}

View File

@@ -525,7 +525,12 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB,
uint8_t UE_id,
uint8_t control_only_flag,
uint8_t Nbundled,
uint8_t llr8_flag);
uint8_t llr8_flag
#ifdef TASK_MANAGER_LTE
// This is a broken idea. But so is the code arquitecture
,thread_info_tm_t* t_info
#endif
);
void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB,
L1_rxtx_proc_t *proc,

View File

@@ -33,6 +33,7 @@
//#define DEBUG_ULSCH_DECODING
#include <syscall.h>
#include <stdatomic.h>
#include "PHY/defs_eNB.h"
#include "PHY/phy_extern.h"
#include "PHY/CODING/coding_extern.h"
@@ -41,6 +42,7 @@
#include "RRC/LTE/rrc_extern.h"
#include "PHY_INTERFACE/phy_interface.h"
#include "transport_proto.h"
#include "common/utils/thread_pool/task_manager.h"
extern int oai_exit;
@@ -209,7 +211,7 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) {
return(crc);
}
void processULSegment(void * arg) {
static void processULSegment(void * arg) {
turboDecode_t* rdata=(turboDecode_t*) arg;
PHY_VARS_eNB *eNB=rdata->eNB;
LTE_UL_eNB_HARQ_t *ulsch_harq=rdata->ulsch_harq;
@@ -239,8 +241,12 @@ void processULSegment(void * arg) {
1,
r,
&E)==-1) {
LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
return;
#ifdef TASK_MANAGER_LTE
// assert(rdata->task_status != NULL);
atomic_store_explicit(&rdata->tasks_remaining->completed, 1, memory_order_seq_cst);
#endif
LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
return;
}
stop_meas(&eNB->ulsch_rate_unmatching_stats);
int max_Ncb = 3*ulsch_harq->RTC[r]*32 ;
@@ -278,12 +284,18 @@ void processULSegment(void * arg) {
rdata->Fbits,
&eNB->ulsch_tc_init_stats,
&eNB->ulsch_tc_alpha_stats,
&eNB->ulsch_tc_beta_stats,
&eNB->ulsch_tc_gamma_stats,
&eNB->ulsch_tc_ext_stats,
&eNB->ulsch_tc_intl1_stats,
&eNB->ulsch_tc_intl2_stats,
&ulsch_harq->abort_decode);
#ifdef TASK_MANAGER_LTE
assert(rdata->tasks_remaining != NULL);
atomic_store_explicit(&rdata->tasks_remaining->completed, 1, memory_order_seq_cst);
#endif
}
/*!
@@ -295,7 +307,11 @@ void processULSegment(void * arg) {
@returns 0 on success
*/
#ifdef TASK_MANAGER_LTE
static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_id, int harq_pid, int llr8_flag, thread_info_tm_t* t_info)
#else
static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_id, int harq_pid, int llr8_flag)
#endif
{
unsigned int r_offset=0;
int offset = 0;
@@ -330,14 +346,20 @@ static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_i
E = ulsch_harq->Qm * (Gp/ulsch_harq->C);
else
E = ulsch_harq->Qm * ((GpmodC==0?0:1) + (Gp/ulsch_harq->C));
#ifdef TASK_MANAGER_LTE
turboDecode_t* rdata = &((turboDecode_t*)t_info->buf)[t_info->len];
assert(t_info->len < 64);
rdata->tasks_remaining = &t_info->tasks_remaining[t_info->len];
t_info->len += 1;
#else
union turboReqUnion id= {.s={ulsch->rnti,proc->frame_rx,proc->subframe_rx,0,0}};
notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboDecode_t),
id.p,
proc->respDecode,
processULSegment);
turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req);
#endif
rdata->eNB=eNB;
rdata->frame=proc->frame_rx;
rdata->subframe=proc->subframe_rx;
@@ -355,7 +377,12 @@ static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_i
rdata->function=td;
int Fbytes=(r==0) ? rdata->Fbits>>3 : 0;
int sz=Kr_bytes - Fbytes - ((ulsch_harq->C>1)?3:0);
#ifdef TASK_MANAGER_LTE
task_t t = { .args = rdata, .func = &processULSegment };
async_task_manager(proc->man, t);
#else
pushTpool(proc->threadPool,req);
#endif
proc->nbDecode++;
LOG_D(PHY,"Added a block to decode, in pipe: %d\n",proc->nbDecode);
r_offset+=E;
@@ -390,12 +417,17 @@ static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2,
// printf("n=%d : c %x\n",n,x1^x2);
}
unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,
unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc,
uint8_t UE_id,
uint8_t control_only_flag,
uint8_t Nbundled,
uint8_t llr8_flag)
uint8_t llr8_flag
#ifdef TASK_MANAGER_LTE
// This is a broken idea. But so is the code arquitecture
,thread_info_tm_t* t_info
#endif
)
{
int16_t *ulsch_llr = eNB->pusch_vars[UE_id]->llr;
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
@@ -1082,7 +1114,11 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,
LOG_D(PHY,"frame %d subframe %d O_ACK:%d o_ACK[]=%d:%d:%d:%d\n",frame,subframe,ulsch_harq->O_ACK,ulsch_harq->o_ACK[0],ulsch_harq->o_ACK[1],ulsch_harq->o_ACK[2],ulsch_harq->o_ACK[3]);
// Do ULSCH Decoding for data portion
#ifdef TASK_MANAGER_LTE
ret = ulsch_decoding_data(eNB, proc, UE_id, harq_pid, llr8_flag, t_info);
#else
ret = ulsch_decoding_data(eNB, proc, UE_id, harq_pid, llr8_flag);
#endif
return(ret);
}

View File

@@ -42,8 +42,10 @@
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "common/utils/LOG/log.h"
#include "common/utils/nr/nr_common.h"
#include <stdatomic.h>
#include <syscall.h>
#include <openair2/UTIL/OPT/opt.h>
#include "common/utils/thread_pool/task_manager.h"
//#define DEBUG_DLSCH_CODING
//#define DEBUG_DLSCH_FREE 1
@@ -159,7 +161,7 @@ void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch) {
dlsch->active = 0;
}
void ldpc8blocks(void *p)
static void ldpc8blocks(void *p)
{
encoder_implemparams_t *impp=(encoder_implemparams_t *) p;
NR_DL_gNB_HARQ_t *harq = (NR_DL_gNB_HARQ_t *)impp->harq;
@@ -274,6 +276,10 @@ void ldpc8blocks(void *p)
#endif
r_offset += E;
}
#ifdef TASK_MANAGER_CODING
atomic_store_explicit(&impp->task_done->completed, 1, memory_order_release);
#endif
}
int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
@@ -418,14 +424,38 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
notifiedFIFO_t nf;
initNotifiedFIFO(&nf);
int nbJobs = 0;
#ifdef TASK_MANAGER_CODING
size_t const sz = (impp.n_segments/8+((impp.n_segments&7)==0 ? 0 : 1));
encoder_implemparams_t arr[sz];
task_status_t task_status[sz];
memset(task_status, 0, sz * sizeof(task_status_t));
#endif
for (int j = 0; j < (impp.n_segments / 8 + ((impp.n_segments & 7) == 0 ? 0 : 1)); j++) {
#ifdef TASK_MANAGER_CODING
assert(nbJobs < sz);
encoder_implemparams_t* perJobImpp = &arr[nbJobs];
#else
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(impp), j, &nf, ldpc8blocks);
encoder_implemparams_t *perJobImpp = (encoder_implemparams_t *)NotifiedFifoData(req);
#endif
*perJobImpp = impp;
perJobImpp->macro_num = j;
#ifdef TASK_MANAGER_CODING
perJobImpp->task_done = &task_status[nbJobs];
task_t t = {.args = perJobImpp, .func = ldpc8blocks};
//assert(atomic_load(&perJobImpp->task_status->completed) == 0);
async_task_manager(&gNB->man, t);
#else
pushTpool(&gNB->threadPool, req);
#endif
nbJobs++;
}
#ifdef TASK_MANAGER_CODING
if(nbJobs > 0) {
wait_task_status_completed(nbJobs, task_status);
}
#else
while (nbJobs) {
notifiedFIFO_elt_t *req = pullTpool(&nf, &gNB->threadPool);
if (req == NULL)
@@ -433,6 +463,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
delNotifiedFIFO_elt(req);
nbJobs--;
}
#endif
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return 0;

View File

@@ -57,7 +57,11 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G);
uint32_t G
#ifdef TASK_MANAGER
, thread_info_tm_t* t_info
#endif
);
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
@param llr, Pointer to llr bits

View File

@@ -50,6 +50,12 @@
//#define DEBUG_ULSCH_DECODING
//#define gNB_DEBUG_TRACE
#include "common/utils/thread_pool/task_manager.h"
#include <stdatomic.h>
#include <stdint.h>
#include <time.h>
#include <stdalign.h>
#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
//#define DEBUG_CRC
#ifdef DEBUG_CRC
@@ -60,6 +66,10 @@
//extern double cpuf;
void nr_postDecode(PHY_VARS_gNB *gNB, ldpcDecode_t *rdata);
void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL)
{
@@ -180,6 +190,10 @@ static void nr_processULSegment(void *arg)
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
rdata->decodeIterations = max_ldpc_iterations + 1;
#ifdef TASK_MANAGER
//assert(rdata->task_status != NULL && atomic_load(&rdata->task_status->completed) == 0);
atomic_store_explicit(&rdata->tasks_remaining->completed, 1, memory_order_release); // memory_order order );
#endif
return;
}
@@ -220,6 +234,11 @@ static void nr_processULSegment(void *arg)
if (rdata->decodeIterations <= p_decoderParms->numMaxIter)
memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3);
#ifdef TASK_MANAGER
assert(rdata->tasks_remaining != NULL);
atomic_store_explicit(&rdata->tasks_remaining->completed, 1, memory_order_release); // memory_order order );
#endif
}
int decode_offload(PHY_VARS_gNB *phy_vars_gNB,
@@ -318,19 +337,23 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB,
}
int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint8_t ULSCH_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *pusch_pdu,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G)
{
if (!ulsch_llr) {
LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n");
return -1;
}
uint8_t ULSCH_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *pusch_pdu,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G
#ifdef TASK_MANAGER
, thread_info_tm_t* t_info
#endif
)
{
if (!ulsch_llr) {
LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n");
return -1;
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1);
@@ -434,9 +457,16 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
set_abort(&harq_process->abort_decode, false);
for (int r = 0; r < harq_process->C; r++) {
int E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
#ifdef TASK_MANAGER
ldpcDecode_t* rdata = &((ldpcDecode_t*)t_info->buf)[t_info->len];
assert(t_info->len < 16);
rdata->tasks_remaining = &t_info->tasks_remaining[t_info->len];
t_info->len += 1;
#else
union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}};
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, &phy_vars_gNB->respDecode, &nr_processULSegment);
ldpcDecode_t *rdata = (ldpcDecode_t *)NotifiedFifoData(req);
#endif
decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index,
E,
decParams.BG,
@@ -461,10 +491,17 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
rdata->ulsch = ulsch;
rdata->ulsch_id = ULSCH_id;
rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
pushTpool(&phy_vars_gNB->threadPool, req);
#ifdef TASK_MANAGER
task_t t = { .args = rdata, .func = &nr_processULSegment };
async_task_manager(&phy_vars_gNB->man, t);
#else
pushTpool(&phy_vars_gNB->threadPool, req);
#endif
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
r_offset += E;
offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
}
return harq_process->C;
}

View File

@@ -11,6 +11,8 @@
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
#include "PHY/sse_intrin.h"
#include <stdatomic.h>
#define INVALID_VALUE 255
void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
@@ -1440,6 +1442,10 @@ static void nr_pusch_symbol_processing(void *arg)
for (int i = 0; i < (nb_re_pusch * rel15_ul->qam_mod_order * rel15_ul->nrOfLayers); i++)
llr16[i] = llr_ptr[i] * rdata->s[i];
}
#ifdef TASK_MANAGER_DEMODULATION
atomic_store_explicit(&rdata->task_finished->completed, 1, memory_order_seq_cst); // memory_order order );
#endif
}
@@ -1650,6 +1656,17 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
start_meas(&gNB->rx_pusch_symbol_processing_stats);
int numSymbols = gNB->num_pusch_symbols_per_thread;
#ifdef TASK_MANAGER_DEMODULATION
int const loop_iter = rel15_ul->nr_of_symbols/numSymbols;
puschSymbolProc_t arr[loop_iter];
task_status_t arr_tf[loop_iter];
memset(arr, 0, loop_iter*sizeof(puschSymbolProc_t));
memset(arr_tf, 0, loop_iter*sizeof(task_status_t));
int sz_arr = 0;
#endif
for(uint8_t symbol = rel15_ul->start_symbol_index;
symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols);
symbol += numSymbols)
@@ -1663,11 +1680,16 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
total_res+=pusch_vars->ul_valid_re_per_slot[symbol+s];
}
if (total_res > 0) {
#ifdef TASK_MANAGER_DEMODULATION
puschSymbolProc_t *rdata = &arr[sz_arr];
rdata->task_finished = &arr_tf[sz_arr];
++sz_arr;
#else
union puschSymbolReqUnion id = {.s={ulsch_id,frame,slot,0}};
id.p=1+symbol;
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschSymbolProc_t), id.p, &gNB->respPuschSymb, &nr_pusch_symbol_processing); // create a job for Tpool
puschSymbolProc_t *rdata = (puschSymbolProc_t*)NotifiedFifoData(req); // data for the job
#endif
rdata->gNB = gNB;
rdata->frame_parms = frame_parms;
rdata->rel15_ul = rel15_ul;
@@ -1681,9 +1703,15 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
rdata->nvar = nvar;
if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
// Obvious memory leak when TASK_MANAGER not defined
nr_pusch_symbol_processing(rdata);
} else {
#ifdef TASK_MANAGER_DEMODULATION
task_t t = { .args = rdata, .func = &nr_pusch_symbol_processing };
async_task_manager(&gNB->man , t);
#else
pushTpool(&gNB->threadPool, req);
#endif
gNB->nbSymb++;
}
@@ -1691,12 +1719,18 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
}
} // symbol loop
#ifdef TASK_MANAGER_DEMODULATION
if(gNB->nbSymb > 0){
wait_task_status_completed(sz_arr, arr_tf);
gNB->nbSymb = 0;
}
#else
while (gNB->nbSymb > 0) {
notifiedFIFO_elt_t *req = pullTpool(&gNB->respPuschSymb, &gNB->threadPool);
gNB->nbSymb--;
delNotifiedFIFO_elt(req);
}
#endif
stop_meas(&gNB->rx_pusch_symbol_processing_stats);
return 0;
}

View File

@@ -46,6 +46,9 @@
#include "common/utils/nr/nr_common.h"
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
#include "openair1/PHY/TOOLS/phy_scope_interface.h"
#include "common/utils/thread_pool/task_manager.h"
#include <stdatomic.h>
//#define ENABLE_PHY_PAYLOAD_DEBUG 1
@@ -71,6 +74,18 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid,
nr_codeword_unscrambling(llr, size, q, Nid, n_RNTI);
}
#ifdef TASK_MANAGER_UE_DECODING
static bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue,
ldpcDecode_ue_t *rdata,
bool last,
int b_size,
uint8_t b[b_size],
int *num_seg_ok,
UE_nr_rxtx_proc_t *proc)
{
#else
static bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue,
notifiedFIFO_elt_t *req,
notifiedFIFO_t *nf_p,
@@ -81,6 +96,7 @@ static bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue,
UE_nr_rxtx_proc_t *proc)
{
ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) NotifiedFifoData(req);
#endif
NR_DL_UE_HARQ_t *harq_process = rdata->harq_process;
NR_UE_DLSCH_t *dlsch = (NR_UE_DLSCH_t *) rdata->dlsch;
int r = rdata->segment_r;
@@ -221,6 +237,11 @@ static void nr_processDLSegment(void *arg)
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_OUT);
stop_meas(&rdata->ts_rate_unmatch);
LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n");
#ifdef TASK_MANAGER_UE_DECODING
//assert(atomic_load(rdata->task_done) == 0);
atomic_store_explicit(&rdata->task_done->completed, 1, memory_order_release);
#endif
return;
}
stop_meas(&rdata->ts_rate_unmatch);
@@ -262,6 +283,9 @@ static void nr_processDLSegment(void *arg)
memcpy(harq_process->c[r], LDPCoutput, Kr >> 3);
stop_meas(&rdata->ts_ldpc_decode);
}
#ifdef TASK_MANAGER_UE_DECODING
atomic_store_explicit(&rdata->task_done->completed, 1, memory_order_release);
#endif
}
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
@@ -400,14 +424,25 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
notifiedFIFO_t nf;
initNotifiedFIFO(&nf);
set_abort(&harq_process->abort_decode, false);
#ifdef TASK_MANAGER_UE_DECODING
ldpcDecode_ue_t arr[harq_process->C];
task_status_t task_done[harq_process->C];
memset(task_done, 0, harq_process->C*sizeof(task_status_t));
#endif
for (r=0; r<harq_process->C; r++) {
//printf("start rx segment %d\n",r);
uint32_t E = nr_get_E(G, harq_process->C, dlsch->dlsch_config.qamModOrder, dlsch->Nl, r);
decParams.R = nr_get_R_ldpc_decoder(dlsch->dlsch_config.rv, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->DLround);
#ifdef TASK_MANAGER_UE_DECODING
ldpcDecode_ue_t* rdata = &arr[r];
rdata->task_done = &task_done[r];
#else
union ldpcReqUnion id = {.s={dlsch->rnti,frame,nr_slot_rx,0,0}};
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_ue_t), id.p, &nf, &nr_processDLSegment);
ldpcDecode_ue_t * rdata=(ldpcDecode_ue_t *) NotifiedFifoData(req);
#endif
rdata->phy_vars_ue = phy_vars_ue;
rdata->harq_process = harq_process;
rdata->decoderParms = decParams;
@@ -430,7 +465,12 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
reset_meas(&rdata->ts_deinterleave);
reset_meas(&rdata->ts_rate_unmatch);
reset_meas(&rdata->ts_ldpc_decode);
#ifdef TASK_MANAGER_UE_DECODING
task_t t = {.args = rdata, .func = nr_processDLSegment };
async_task_manager(&get_nrUE_params()->man, t);
#else
pushTpool(&get_nrUE_params()->Tpool,req);
#endif
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
r_offset += E;
offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0));
@@ -438,6 +478,15 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
}
int num_seg_ok = 0;
int nbDecode = harq_process->C;
#ifdef TASK_MANAGER_UE_DECODING
if(nbDecode > 0) {
wait_task_status_completed(nbDecode, task_done);
for(size_t i = 0; i < harq_process->C; ++i){
nr_ue_postDecode(phy_vars_ue, &arr[i], nbDecode == 1, b_size, b, &num_seg_ok, proc);
nbDecode--;
}
}
#else
while (nbDecode) {
notifiedFIFO_elt_t *req=pullTpool(&nf, &get_nrUE_params()->Tpool);
if (req == NULL)
@@ -446,6 +495,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
delNotifiedFIFO_elt(req);
nbDecode--;
}
#endif
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_COMBINE_SEG, VCD_FUNCTION_OUT);
ret = dlsch->last_iteration_cnt;

View File

@@ -41,6 +41,8 @@
#include "nfapi_nr_interface_scf.h"
#include <common/utils/threadPool/thread-pool.h>
#include <executables/rt_profiling.h>
#include "common/utils/thread_pool/task_manager.h"
#define MAX_BANDS_PER_RRU 4
#define MAX_RRU_CONFIG_SIZE 1024
@@ -176,6 +178,9 @@ typedef struct {
int startSymbol;
int endSymbol;
int slot;
#ifdef TASK_MANAGER_RU
task_status_t* task_done;
#endif
} feprx_cmd_t;
typedef struct {
@@ -184,6 +189,9 @@ typedef struct {
int slot;
int startSymbol;
int numSymbols;
#ifdef TASK_MANAGER_RU
task_status_t* task_done;
#endif
} feptx_cmd_t;
typedef struct {
@@ -426,8 +434,12 @@ typedef enum {
typedef struct RU_t_s {
#ifdef TASK_MANAGER_RU
task_manager_t man;
#else
/// ThreadPool for RU
tpool_t *threadPool;
#endif
/// index of this ru
uint32_t idx;
/// pointer to first RU

View File

@@ -66,7 +66,7 @@
#include "PHY/LTE_TRANSPORT/transport_eNB.h"
#include "openair2/PHY_INTERFACE/IF_Module.h"
#include "common/openairinterface5g_limits.h"
#include "common/utils/thread_pool/task_manager.h"
#define PBCH_A 24
#define MAX_NUM_RU_PER_eNB 64
@@ -252,7 +252,11 @@ typedef struct {
pthread_cond_t cond_RUs;
/// mutex for RXn-TXnp4 processing thread
pthread_mutex_t mutex_RUs;
#ifdef TASK_MANAGER_LTE
task_manager_t* man; // non-owning ptr
#else
tpool_t *threadPool;
#endif
int nbDecode;
notifiedFIFO_t *respDecode;
pthread_mutex_t mutex_emulateRF;
@@ -793,6 +797,9 @@ typedef struct TurboDecode_s {
int offset;
int maxIterations;
int decodeIterations;
#ifdef TASK_MANAGER_LTE
task_status_t* tasks_remaining;
#endif
} turboDecode_t;
#define TURBO_SIMD_SOFTBITS 96+12+3+3*6144
@@ -809,6 +816,9 @@ typedef struct turboEncode_s {
time_stats_t *rm_stats;
time_stats_t *te_stats;
time_stats_t *i_stats;
#ifdef TASK_MANAGER_LTE
task_status_t* tasks_remaining;
#endif
} turboEncode_t;

View File

@@ -43,6 +43,7 @@
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
#include "executables/rt_profiling.h"
#include "nfapi_nr_interface_scf.h"
#include "common/utils/thread_pool/task_manager.h"
#define MAX_NUM_RU_PER_gNB 8
#define MAX_PUCCH0_NID 8
@@ -727,7 +728,6 @@ typedef struct PHY_VARS_gNB_s {
notifiedFIFO_t L1_tx_filled;
notifiedFIFO_t L1_tx_out;
notifiedFIFO_t resp_RU_tx;
tpool_t threadPool;
int nbSymb;
int num_pusch_symbols_per_thread;
pthread_t L1_rx_thread;
@@ -738,6 +738,15 @@ typedef struct PHY_VARS_gNB_s {
void *scopeData;
/// structure for analyzing high-level RT measurements
rt_L1_profiling_t rt_L1_profiling;
#if defined(TASK_MANAGER) && defined(TASK_MANAGER_CODING) && defined(TASK_MANAGER_DEMODULATION) && defined(TASK_MANAGER_RU) && defined(TASK_MANAGER_SIM)
task_manager_t man;
#elif !defined(TASK_MANAGER) || !defined(TASK_MANAGER_CODING) || !defined(TASK_MANAGER_DEMODULATION) || !defined(TASK_MANAGER_RU) || !defined(TASK_MANAGER_SIM)
task_manager_t man;
tpool_t threadPool;
#else
tpool_t threadPool;
#endif
} PHY_VARS_gNB;
typedef struct puschSymbolProc_s {
@@ -752,6 +761,9 @@ typedef struct puschSymbolProc_s {
int16_t **llr_layers;
int16_t *s;
uint32_t nvar;
#ifdef TASK_MANAGER_DEMODULATION
task_status_t* task_finished;
#endif
} puschSymbolProc_t;
struct puschSymbolReqId {
@@ -786,6 +798,9 @@ typedef struct LDPCDecode_s {
int offset;
int decodeIterations;
uint32_t tbslbrm;
#ifdef TASK_MANAGER
task_status_t* tasks_remaining;
#endif
} ldpcDecode_t;
struct ldpcReqId {
@@ -808,6 +823,9 @@ typedef struct processingData_L1 {
int slot_tx;
openair0_timestamp timestamp_tx;
PHY_VARS_gNB *gNB;
#ifdef TASK_MANAGER_RU
notifiedFIFO_elt_t* elm;
#endif
} processingData_L1_t;
typedef enum {

View File

@@ -37,8 +37,10 @@
#define _Atomic(X) std::atomic< X >
#endif
#include "defs_nr_common.h"
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
#include "common/utils/thread_pool/task_manager.h"
#include <stdio.h>
#include <stdlib.h>
@@ -684,6 +686,9 @@ typedef struct nr_rxtx_thread_data_s {
notifiedFIFO_t txFifo;
nr_phy_data_t phy_data;
int tx_wait_for_dlsch;
#ifdef TASK_MANAGER_UE_DECODING
task_status_t* task_done;
#endif
} nr_rxtx_thread_data_t;
typedef struct LDPCDecode_ue_s {
@@ -710,6 +715,9 @@ typedef struct LDPCDecode_ue_s {
time_stats_t ts_rate_unmatch;
time_stats_t ts_ldpc_decode;
UE_nr_rxtx_proc_t *proc;
#ifdef TASK_MANAGER_UE_DECODING
task_status_t* task_done;
#endif
} ldpcDecode_ue_t;
#include "SIMULATION/ETH_TRANSPORT/defs.h"

View File

@@ -1232,10 +1232,13 @@ uci_procedures(PHY_VARS_eNB *eNB,
} // end loop for (int i = 0; i < NUMBER_OF_UCI_MAX; i++) {
}
#ifdef TASK_MANAGER_LTE
void postDecode(L1_rxtx_proc_t *proc, turboDecode_t* rdata){
#else
void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req)
{
turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req);
#endif
LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid];
LTE_UL_eNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
PHY_VARS_eNB *eNB=rdata->eNB;
@@ -1330,6 +1333,12 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
const int frame = proc->frame_rx;
uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe);
#ifdef TASK_MANAGER_LTE
turboDecode_t arr[64] = {0};
task_status_t tasks_remaining[64] = {0};
thread_info_tm_t t_info = { .tasks_remaining = tasks_remaining, .buf = (uint8_t*)arr };
#endif
for (i = 0; i < NUMBER_OF_ULSCH_MAX; i++) {
ulsch = eNB->ulsch[i];
if (!ulsch) continue;
@@ -1387,7 +1396,11 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
i,
0, // control_only_flag
ulsch_harq->V_UL_DAI,
ulsch_harq->nb_rb > 20 ? 1 : 0);
ulsch_harq->nb_rb > 20 ? 1 : 0
#ifdef TASK_MANAGER_LTE
,&t_info
#endif
);
}
else if ((ulsch) &&
(ulsch->rnti>0) &&
@@ -1404,6 +1417,15 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
} // for (i=0; i<NUMBER_OF_ULSCH_MAX; i++)
const bool decode = proc->nbDecode;
#ifdef TASK_MANAGER_LTE
assert(t_info.len == proc->nbDecode);
if (proc->nbDecode > 0) {
wait_task_status_completed(t_info.len, t_info.tasks_remaining);
for(size_t i = 0; i < t_info.len; ++i){
postDecode(proc, &arr[i]);
}
}
#else
while (proc->nbDecode > 0) {
notifiedFIFO_elt_t *req=pullTpool(proc->respDecode, proc->threadPool);
if (req == NULL)
@@ -1413,6 +1435,7 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
merge_meas(&eNB->ulsch_turbo_decoding_stats, &ts);
delNotifiedFIFO_elt(req);
}
#endif
if (decode)
stop_meas(&eNB->ulsch_decoding_stats);
}

View File

@@ -34,10 +34,13 @@
#include "sched_nr.h"
#include "PHY/MODULATION/modulation_common.h"
#include "PHY/MODULATION/nr_modulation.h"
#include <stdatomic.h>
#include "common/utils/LOG/log.h"
#include "common/utils/system.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "common/utils/thread_pool/task_manager.h"
#include "T.h"
@@ -323,6 +326,11 @@ void nr_feptx(void *arg) {
////////////FEPTX////////////
nr_feptx0(ru,slot,startSymbol,numSymbols,aa);
#ifdef TASK_MANAGER_RU
//assert(atomic_load(&feptx->task_done->completed) == 0);
atomic_store_explicit(&feptx->task_done->completed, 1, memory_order_release);
#endif
}
// RU FEP TX using thread-pool
@@ -335,33 +343,69 @@ void nr_feptx_tp(RU_t *ru, int frame_tx, int slot) {
if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM, 1 );
start_meas(&ru->ofdm_total_stats);
#ifdef TASK_MANAGER_RU
size_t const sz = ru->nb_tx + (ru->half_slot_parallelization>0)*ru->nb_tx;
feptx_cmd_t arr[sz];
task_status_t tasks_done[sz];
memset(&tasks_done, 0, sizeof(task_status_t) * sz);
#endif
for (int aid=0;aid<ru->nb_tx;aid++) {
#ifdef TASK_MANAGER_RU
feptx_cmd_t *feptx_cmd = &arr[nbfeptx];
feptx_cmd->task_done = &tasks_done[nbfeptx];
#else
notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(feptx_cmd_t), 2000 + aid,ru->respfeptx,nr_feptx);
feptx_cmd_t *feptx_cmd=(feptx_cmd_t*)NotifiedFifoData(req);
#endif
feptx_cmd->aid = aid;
feptx_cmd->ru = ru;
feptx_cmd->slot = slot;
feptx_cmd->startSymbol = 0;
feptx_cmd->numSymbols = (ru->half_slot_parallelization>0)?ru->nr_frame_parms->symbols_per_slot>>1:ru->nr_frame_parms->symbols_per_slot;
#ifdef TASK_MANAGER_RU
task_t t = {.func = nr_feptx, .args = feptx_cmd};
async_task_manager(&ru->man, t);
#else
pushTpool(ru->threadPool,req);
#endif
nbfeptx++;
if (ru->half_slot_parallelization>0) {
notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(feptx_cmd_t), 2000 + aid + ru->nb_tx,ru->respfeptx,nr_feptx);
#ifdef TASK_MANAGER_RU
feptx_cmd_t *feptx_cmd = &arr[nbfeptx];
feptx_cmd->task_done = &tasks_done[nbfeptx];
#else
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(feptx_cmd_t), 2000 + aid + ru->nb_tx,ru->respfeptx,nr_feptx);
feptx_cmd_t *feptx_cmd=(feptx_cmd_t*)NotifiedFifoData(req);
#endif
feptx_cmd->aid = aid;
feptx_cmd->ru = ru;
feptx_cmd->slot = slot;
feptx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot>>1;
feptx_cmd->numSymbols = ru->nr_frame_parms->symbols_per_slot>>1;
#ifdef TASK_MANAGER_RU
task_t t = {.func = nr_feptx, .args = feptx_cmd};
async_task_manager(&ru->man, t);
#else
pushTpool(ru->threadPool,req);
#endif
nbfeptx++;
}
}
#ifdef TASK_MANAGER_RU
if(nbfeptx > 0)
wait_task_status_completed(nbfeptx, tasks_done);
#else
while (nbfeptx>0) {
notifiedFIFO_elt_t *req=pullTpool(ru->respfeptx, ru->threadPool);
delNotifiedFIFO_elt(req);
nbfeptx--;
}
#endif
stop_meas(&ru->ofdm_total_stats);
if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM, 0 );
}
@@ -391,41 +435,82 @@ void nr_fep(void* arg) {
tti_rx,
ru->N_TA_offset);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+aid, 0);
#ifdef TASK_MANAGER_RU
// assert(atomic_load(feprx_cmd->task_done->completed) == 0);
atomic_store_explicit(&feprx_cmd->task_done->completed, 1, memory_order_release);
#endif
}
// RU RX FEP using thread-pool
void nr_fep_tp(RU_t *ru, int slot) {
void nr_fep_tp(RU_t *ru, int slot)
{
int nbfeprx=0;
if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 );
start_meas(&ru->ofdm_demod_stats);
#ifdef TASK_MANAGER_RU
size_t const sz = ru->nb_rx + (ru->half_slot_parallelization>0)*ru->nb_rx;
feprx_cmd_t arr[sz];
task_status_t tasks_done[sz];
memset(&tasks_done, 0, sizeof(task_status_t) * sz);
#endif
for (int aid=0;aid<ru->nb_rx;aid++) {
#ifdef TASK_MANAGER_RU
feprx_cmd_t* feprx_cmd= &arr[nbfeprx];
feprx_cmd->task_done = &tasks_done[nbfeprx];
#else
notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(feprx_cmd_t), 1000 + aid,ru->respfeprx,nr_fep);
feprx_cmd_t *feprx_cmd=(feprx_cmd_t*)NotifiedFifoData(req);
#endif
feprx_cmd->aid = aid;
feprx_cmd->ru = ru;
feprx_cmd->slot = ru->proc.tti_rx;
feprx_cmd->startSymbol = 0;
feprx_cmd->endSymbol = (ru->half_slot_parallelization > 0)?(ru->nr_frame_parms->symbols_per_slot>>1)-1:(ru->nr_frame_parms->symbols_per_slot-1);
#ifdef TASK_MANAGER_RU
task_t t = {.func = nr_fep, .args = feprx_cmd};
async_task_manager(&ru->man, t);
#else
pushTpool(ru->threadPool,req);
#endif
nbfeprx++;
if (ru->half_slot_parallelization>0) {
#ifdef TASK_MANAGER_RU
feprx_cmd_t * feprx_cmd= &arr[nbfeprx];
feprx_cmd->task_done = &tasks_done[nbfeprx];
#else
notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(feprx_cmd_t), 1000 + aid + ru->nb_rx,ru->respfeprx,nr_fep);
feprx_cmd_t *feprx_cmd=(feprx_cmd_t*)NotifiedFifoData(req);
#endif
feprx_cmd->aid = aid;
feprx_cmd->ru = ru;
feprx_cmd->slot = ru->proc.tti_rx;
feprx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot>>1;
feprx_cmd->endSymbol = ru->nr_frame_parms->symbols_per_slot-1;
#ifdef TASK_MANAGER_RU
task_t t = {.func = nr_fep, .args = feprx_cmd};
async_task_manager(&ru->man, t);
#else
pushTpool(ru->threadPool,req);
#endif
nbfeprx++;
}
}
#ifdef TASK_MANAGER_RU
if(nbfeprx > 0)
wait_task_status_completed(nbfeprx, tasks_done);
#else
while (nbfeprx>0) {
notifiedFIFO_elt_t *req=pullTpool(ru->respfeprx, ru->threadPool);
delNotifiedFIFO_elt(req);
nbfeprx--;
}
#endif
stop_meas(&ru->ofdm_demod_stats);
if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 0 );
}

View File

@@ -39,10 +39,25 @@
#include "executables/softmodem-common.h"
#include "nfapi/oai_integration/vendor_ext.h"
#include "NR_SRS-ResourceSet.h"
#include "common/utils/thread_pool/task_manager.h"
#include "assertions.h"
#include <time.h>
#include <stdint.h>
static
int64_t time_now_ns(void)
{
struct timespec tms;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &tms)) {
return -1;
}
int64_t nanos = tms.tv_sec * 1000000000 + tms.tv_nsec;
return nanos;
}
//#define DEBUG_RXDATA
//#define SRS_IND_DEBUG
@@ -238,9 +253,14 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX + gNB->CC_id, 0);
}
#ifdef TASK_MANAGER
static void nr_postDecode(PHY_VARS_gNB *gNB, ldpcDecode_t *rdata)
{
#else
static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
{
ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
#endif
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
NR_gNB_ULSCH_t *ulsch = rdata->ulsch;
int r = rdata->segment_r;
@@ -254,7 +274,6 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
rdata->nbSegments);
if (decodeSuccess) {
memcpy(ulsch_harq->b + rdata->offset, ulsch_harq->c[r], rdata->Kr_bytes - (ulsch_harq->F >> 3) - ((ulsch_harq->C > 1) ? 3 : 0));
} else {
LOG_D(PHY, "ULSCH %d in error\n", rdata->ulsch_id);
}
@@ -352,7 +371,11 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
}
}
#ifdef TASK_MANAGER
static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid, thread_info_tm_t* t_info)
#else
static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid)
#endif
{
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu;
@@ -399,8 +422,12 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int
//----------------------------------------------------------
start_meas(&gNB->ulsch_decoding_stats);
int nbDecode =
nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G);
#ifdef TASK_MANAGER
int const nbDecode = nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G, t_info);
#else
int nbDecode = nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G);
#endif
return nbDecode;
}
@@ -728,8 +755,43 @@ int check_srs_pdu(const nfapi_nr_srs_pdu_t *srs_pdu, nfapi_nr_srs_pdu_t *saved_s
return 0;
}
#ifdef TASK_MANAGER
/*
static
bool nr_ulsch_procedures_sched(PHY_VARS_gNB const* gNB, int frame_rx, int slot_rx)
{
for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
if ((ulsch->active == true) && (ulsch->frame == frame_rx) && (ulsch->slot == slot_rx) && (ulsch->handled == 0)) {
return true;
}
}
return false;
}
static
bool maybe_trigger_and_spin_threads(PHY_VARS_gNB* gNB, int frame_rx, int slot_rx)
{
if(nr_ulsch_procedures_sched(gNB, frame_rx, slot_rx) == true){
// Wake up threads and spin in an atomic
trigger_and_spin_task_manager(&gNB->man);
return true;
}
return false;
}
*/
#endif
static int cnt = 0;
int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
{
#ifdef TASK_MANAGER
// maybe_trigger_and_spin_threads(gNB, frame_rx, slot_rx);
#endif
/* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */
int pucch_decode_done = 0;
int pusch_decode_done = 0;
@@ -750,6 +812,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
}
else
num_symb = NR_NUMBER_OF_SYMBOLS_PER_SLOT;
gNB_I0_measurements(gNB,slot_rx,first_symb,num_symb);
const int soffset = (slot_rx & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size;
@@ -821,6 +884,13 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
}
}
#ifdef TASK_MANAGER
ldpcDecode_t arr[16];
task_status_t tasks_remaining[16] = {0};
thread_info_tm_t t_info = {.buf = (uint8_t*)arr, .len = 0, .tasks_remaining = tasks_remaining};
#endif
int64_t const t0 = time_now_ns();
int totalDecode = 0;
for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
@@ -918,13 +988,34 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
// LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1);
// LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1);
#ifdef TASK_MANAGER
int tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, &t_info);
if(tasks_added > 0) {
totalDecode += tasks_added;
// atomic_fetch_add_explicit(t_info.tasks_remaining, totalDecode, memory_order_seq_cst); // atomic
} //
#else //
int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid);
if (tasks_added > 0)
totalDecode += tasks_added;
#endif //
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0);
}
}
++cnt;
#ifdef TASK_MANAGER
if (totalDecode > 0) {
assert(totalDecode == t_info.len);
wait_task_status_completed(t_info.len, t_info.tasks_remaining);
for(int i = 0; i < t_info.len; ++i){
nr_postDecode(gNB, &arr[i]);
}
if(cnt % 1024 == 0)
printf("Decoding time %ld \n", time_now_ns() - t0);
}
#else
while (totalDecode > 0) {
notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool);
if (req == NULL)
@@ -933,7 +1024,12 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
delNotifiedFIFO_elt(req);
totalDecode--;
}
if(cnt % 1024 == 0)
printf("Decoding time %ld \n", time_now_ns() - t0);
#endif
stop_meas(&gNB->ulsch_decoding_stats);
for (int i = 0; i < gNB->max_nb_srs; i++) {
NR_gNB_SRS_t *srs = &gNB->srs[i];
if (srs) {

View File

@@ -589,6 +589,9 @@ int main(int argc, char **argv) {
nfapi_tx_request_t TX_req;
Sched_Rsp_t sched_resp;
int pa=dB0;
#ifdef TASK_MANAGER_LTE
task_manager_t man = {0};
#endif
cpu_freq_GHz = get_cpu_freq_GHz();
printf("Detected cpu_freq %f GHz\n",cpu_freq_GHz);
memset((void *)&sched_resp,0,sizeof(sched_resp));
@@ -1254,10 +1257,16 @@ int main(int argc, char **argv) {
}
L1_rxtx_proc_t *proc_eNB = &eNB->proc.L1_proc;
proc_eNB->threadPool = (tpool_t *)malloc(sizeof(tpool_t));
proc_eNB->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
initTpool("n", proc_eNB->threadPool, true);
initNotifiedFIFO(proc_eNB->respDecode);
#ifdef TASK_MANAGER_LTE
int const n_threads = 1;
init_task_manager(&man, n_threads);
proc_eNB->man = &man;
#else
proc_eNB->threadPool = (tpool_t *)malloc(sizeof(tpool_t));
initTpool("n", proc_eNB->threadPool, true);
#endif
proc_eNB->frame_tx=0;

View File

@@ -787,9 +787,17 @@ int main(int argc, char **argv) {
proc_rxtx_ue->frame_rx = (subframe<4)?(proc_rxtx->frame_tx-1):(proc_rxtx->frame_tx);
proc_rxtx_ue->subframe_tx = proc_rxtx->subframe_rx;
proc_rxtx_ue->subframe_rx = (proc_rxtx->subframe_tx+6)%10;
#ifdef TASK_MANAGER_LTE
int const n_threads = 1;
proc_rxtx->man = calloc(1, sizeof(task_manager_t));
assert(proc_rxtx->man != NULL && "Memory exhausted");
init_task_manager(proc_rxtx->man, n_threads);
#else
proc_rxtx->threadPool = (tpool_t *)malloc(sizeof(tpool_t));
proc_rxtx->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
initTpool("n", proc_rxtx->threadPool, true);
#endif
proc_rxtx->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
initNotifiedFIFO(proc_rxtx->respDecode);
printf("Init UL hopping UE\n");

View File

@@ -19,6 +19,7 @@
* contact@openairinterface.org
*/
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
@@ -50,6 +51,8 @@
#include "executables/nr-uesoftmodem.h"
#include "nfapi/oai_integration/vendor_ext.h"
#include "common/utils/thread_pool/task_manager.h"
//#define DEBUG_NR_DLSCHSIM
THREAD_STRUCT thread_struct;
@@ -99,6 +102,35 @@ nrUE_params_t *get_nrUE_params(void) {
}
configmodule_interface_t *uniqCfg = NULL;
static
int num_threads(char* parms_cpy)
{
char *saveptr, * curptr;
int nbThreads=0;
curptr=strtok_r(parms_cpy,",",&saveptr);
while ( curptr!=NULL ) {
int c=toupper(curptr[0]);
switch (c) {
case 'N':
//pool->activated=false;
break;
default: ;
int const core_id = atoi(curptr);
printf("create a thread for core %d\n", core_id);
nbThreads++;
}
curptr=strtok_r(NULL,",",&saveptr);
}
return nbThreads;
}
int main(int argc, char **argv)
{
char c;
@@ -372,9 +404,15 @@ int main(int argc, char **argv)
RC.gNB = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *));
RC.gNB[0] = calloc(1, sizeof(PHY_VARS_gNB));
gNB = RC.gNB[0];
initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
//gNB_config = &gNB->gNB_config;
#ifdef TASK_MANAGER_SIM
int const n_threads = max(num_threads(gNBthreads), 1);
init_task_manager(&gNB->man, n_threads);
init_task_manager(&nrUE_params.man, max(dlsch_threads, 1));
#else
initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
#endif
//gNB_config = &gNB->gNB_config;
frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
frame_parms->nb_antennas_tx = n_tx;
frame_parms->nb_antennas_rx = n_rx;
@@ -643,6 +681,12 @@ int main(int argc, char **argv)
free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list);
free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list);
#ifdef TASK_MANAGER_SIM
void (*clean)(task_t*) = NULL;
free_task_manager(&gNB->man, clean);
free_task_manager(&nrUE_params.man, clean);
#endif
phy_free_nr_gNB(gNB);
free(RC.gNB[0]);
free(RC.gNB);

View File

@@ -19,6 +19,7 @@
* contact@openairinterface.org
*/
#include <ctype.h>
#include <fcntl.h>
#include <math.h>
#include <string.h>
@@ -30,6 +31,8 @@
#include "common/utils/nr/nr_common.h"
#include "common/utils/var_array.h"
#include "common/utils/LOG/log.h"
#include "common/utils/thread_pool/task_manager.h"
#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "LAYER2/NR_MAC_UE/mac_defs.h"
#include "LAYER2/NR_MAC_UE/mac_extern.h"
@@ -259,6 +262,34 @@ void validate_input_pmi(nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, int nrOfLaye
}
static
int num_threads(char* parms_cpy)
{
char *saveptr, * curptr;
int nbThreads=0;
curptr=strtok_r(parms_cpy,",",&saveptr);
while ( curptr!=NULL ) {
int c=toupper(curptr[0]);
switch (c) {
case 'N':
//pool->activated=false;
break;
default: ;
int const core_id = atoi(curptr);
printf("create a thread for core %d\n", core_id);
nbThreads++;
}
curptr=strtok_r(NULL,",",&saveptr);
}
return nbThreads;
}
int NB_UE_INST = 1;
configmodule_interface_t *uniqCfg = NULL;
int main(int argc, char **argv)
@@ -871,9 +902,14 @@ int main(int argc, char **argv)
unsigned char *test_input_bit;
unsigned int errors_bit = 0;
#ifdef TASK_MANAGER_SIM
if(dlsch_threads == 0)
dlsch_threads = 1;
init_task_manager(&nrUE_params.man, dlsch_threads);
#else
initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
#endif
test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
// generate signal
@@ -910,7 +946,13 @@ int main(int argc, char **argv)
//NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
int n_errs = 0;
#ifdef TASK_MANAGER_SIM
int const n_threads = max(num_threads(gNBthreads), 1);
init_task_manager(&gNB->man, n_threads );
#else
initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
#endif
initNotifiedFIFO(&gNB->L1_tx_free);
initNotifiedFIFO(&gNB->L1_tx_filled);
initNotifiedFIFO(&gNB->L1_tx_out);
@@ -1317,6 +1359,12 @@ int main(int argc, char **argv)
free(r_im[i]);
}
#ifdef TASK_MANAGER_SIM
void (*clean)(task_t*) = NULL;
free_task_manager(&nrUE_params.man, clean);
free_task_manager(&gNB->man, clean);
#endif
free(s_re);
free(s_im);
free(r_re);

View File

@@ -25,6 +25,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/sysinfo.h>
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
#include "common/utils/LOG/log.h"
@@ -50,6 +51,8 @@
#include "executables/nr-uesoftmodem.h"
#include "nfapi/oai_integration/vendor_ext.h"
#include "common/utils/thread_pool/task_manager.h"
//#define DEBUG_NR_ULSCHSIM
THREAD_STRUCT thread_struct;
@@ -91,9 +94,15 @@ void deref_sched_response(int _)
exit(1);
}
#ifdef TASK_MANAGER
int nr_postDecode_sim(PHY_VARS_gNB *gNB, ldpcDecode_t *rdata , int *nb_ok)
{
#else
int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req, int *nb_ok)
{
ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
#endif
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
int r = rdata->segment_r;
@@ -407,7 +416,14 @@ int main(int argc, char **argv)
gNB = RC.gNB[0];
//gNB_config = &gNB->gNB_config;
#ifdef TASK_MANAGER
int const log_cores = get_nprocs_conf();
assert(log_cores > 0);
init_task_manager(&gNB->man, log_cores/2);
#else
initTpool("n", &gNB->threadPool, true);
#endif
initNotifiedFIFO(&gNB->respDecode);
frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
frame_parms->N_RB_DL = N_RB_DL;
@@ -587,8 +603,25 @@ int main(int argc, char **argv)
exit(-1);
#endif
#ifdef TASK_MANAGER
ldpcDecode_t arr[64] = {0};
task_status_t tasks_remaining[64] = {0};
thread_info_tm_t t_info = {.buf = (uint8_t*)arr, .len = 0, .tasks_remaining = tasks_remaining };
int nbDecode = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G, &t_info);
assert(nbDecode > 0);
#else
int nbDecode = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G);
#endif
int nb_ok = 0;
#ifdef TASK_MANAGER
wait_task_status_completed(t_info.len, t_info.tasks_remaining);
if(nbDecode > 0){
for(size_t i = 0; i < nbDecode; ++i){
ret = nr_postDecode_sim(gNB, &arr[i], &nb_ok);
}
nbDecode = 0;
}
#else
if (nbDecode > 0)
while (nbDecode > 0) {
notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool);
@@ -596,9 +629,9 @@ int main(int argc, char **argv)
delNotifiedFIFO_elt(req);
nbDecode--;
}
if (ret)
n_errors++;
#endif
if (ret)
n_errors++;
}
printf("*****************************************\n");
@@ -623,6 +656,11 @@ int main(int argc, char **argv)
free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list);
free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list);
#ifdef TASK_MANAGER
void (*clean)(task_t* args) = NULL;
free_task_manager(&gNB->man, clean);
#endif
term_nr_ue_signal(UE, 1);
free(UE);

View File

@@ -67,6 +67,7 @@
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "executables/nr-uesoftmodem.h"
#include "common/utils/thread_pool/task_manager.h"
//#define DEBUG_ULSIM
const char *__asan_default_options()
@@ -553,7 +554,12 @@ int main(int argc, char *argv[])
gNB->ofdm_offset_divisor = UINT_MAX;
gNB->num_pusch_symbols_per_thread = 1;
#ifdef TASK_MANAGER
init_task_manager(&gNB->man, max(threadCnt, 1));
#else
initFloatingCoresTpool(threadCnt, &gNB->threadPool, false, "gNB-tpool");
#endif
initNotifiedFIFO(&gNB->respDecode);
initNotifiedFIFO(&gNB->respPuschSymb);

8
ue_mwc.conf Normal file
View File

@@ -0,0 +1,8 @@
uicc0 = {
imsi = "001010000000001";
key = "8BAF473F2F8FD09487CCCBD7097C6862";
opc = "8E27B6AF0E692E750F32667A3B14605D";
dnn = "oai";
nssai_sst=1;
}