mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-16 14:10:28 +00:00
Compare commits
44 Commits
mp_testing
...
tp_poc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
653f32d3ca | ||
|
|
1b8c81a345 | ||
|
|
6a1704f0d2 | ||
|
|
d17d22c1b4 | ||
|
|
7794f72088 | ||
|
|
e222a86244 | ||
|
|
86013d7038 | ||
|
|
9ff74080a6 | ||
|
|
e1bea49b00 | ||
|
|
3af9a372fd | ||
|
|
a795079573 | ||
|
|
aaa9584636 | ||
|
|
a8ea220797 | ||
|
|
98fdcb61b4 | ||
|
|
8b9b8595e7 | ||
|
|
e1304a77ab | ||
|
|
9e0a3549c5 | ||
|
|
f049fe295a | ||
|
|
6a0c6da2bf | ||
|
|
028625077c | ||
|
|
a09ae006bf | ||
|
|
aa94266f3c | ||
|
|
aa44c423c8 | ||
|
|
4bb2014159 | ||
|
|
473b4167c7 | ||
|
|
ef81690d77 | ||
|
|
16bd57ae1d | ||
|
|
cdabdd06d5 | ||
|
|
ef340749e3 | ||
|
|
738ca2d23c | ||
|
|
e976c66b46 | ||
|
|
0cec575dc4 | ||
|
|
1916498903 | ||
|
|
026926265c | ||
|
|
d406eb0332 | ||
|
|
3597ac63cd | ||
|
|
3c056f5f6b | ||
|
|
dba9017edc | ||
|
|
f9a9a368d5 | ||
|
|
8054dba74d | ||
|
|
f6dc244361 | ||
|
|
6f8b4f2055 | ||
|
|
9cc244787d | ||
|
|
37a03a2212 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
2
common/utils/thread_pool/README.md
Normal file
2
common/utils/thread_pool/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
Thread Pool implemented in C following the talk of Sean Parent "Better Code: Concurrency" from 2016
|
||||
|
||||
106
common/utils/thread_pool/main.c
Normal file
106
common/utils/thread_pool/main.c
Normal 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
63
common/utils/thread_pool/run
Executable 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
|
||||
|
||||
|
||||
29
common/utils/thread_pool/task.h
Normal file
29
common/utils/thread_pool/task.h
Normal 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
|
||||
|
||||
698
common/utils/thread_pool/task_manager.c
Normal file
698
common/utils/thread_pool/task_manager.c
Normal 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
|
||||
91
common/utils/thread_pool/task_manager.h
Normal file
91
common/utils/thread_pool/task_manager.h
Normal 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
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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, ×tamp, true);
|
||||
trashed_frames+=2;
|
||||
}
|
||||
} else {
|
||||
readFrame(UE, ×tamp, 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, ×tamp, true);
|
||||
trashed_frames += 2;
|
||||
}
|
||||
} else {
|
||||
readFrame(UE, ×tamp, 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, ×tamp);
|
||||
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,
|
||||
×tamp,
|
||||
(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,
|
||||
×tamp,
|
||||
(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,
|
||||
×tamp,
|
||||
rxp,
|
||||
readBlockSize,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
AssertFatal(
|
||||
readBlockSize == UE->rfdevice.trx_read_func(&UE->rfdevice, ×tamp, 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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
269
gnb.sa.band78.fr1.106PRB.usrpb210.conf
Normal file
269
gnb.sa.band78.fr1.106PRB.usrpb210.conf
Normal 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";
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
8
ue_mwc.conf
Normal file
@@ -0,0 +1,8 @@
|
||||
uicc0 = {
|
||||
imsi = "001010000000001";
|
||||
key = "8BAF473F2F8FD09487CCCBD7097C6862";
|
||||
opc = "8E27B6AF0E692E750F32667A3B14605D";
|
||||
dnn = "oai";
|
||||
nssai_sst=1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user