Commit 463a3ad1 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/l1-rx-use-queues' into integration_2026_w16 (!3991)

L1 RX: use queues instead of arrays and linear search for PUCCH, PUSCH, SRS, PRACH

This MR is an attempt to reduce the time L1 RX searches in array for the
next job to process, and instead use a queue. This queue is a FIFO,
because the various jobs (FAPI messages) to process come in order, and
need to be processed in order. The MR (hopefully, to be measured)
reduces the amount of time spent searching for the next UE (because the
next job is always at the beginning of the queue), and should scale
better for many UEs.

It does the following:

- introduce two helper libraries for (1) Frame.Slot calculation (sfn_t),
  already introduced in !3521 (merged) commit 3102068e, and (2) a ring
  buffer with fixed size
- use sfn_t and ring buffer (gNB->pucch_queue) to remove the linear
  array for PUCCH (gNB->pucch)
- use sfn_t and ring buffer (gNB->pusch_queue) for some PUSCH lookups.
  Because we need to still store PUSCH contexts, gNB->pusch is still
  there
- use sfn_t and ring buffer (gNB->srs_queue) to remove the linear array
  for SRS (gNB->srs)
- use sfn_t and ring buffers (gNB->prach_ru_queue and
  gNB->prach_l1rx_queue) to remove the linear array for PRACH
  (gNB->prach_list)
- some minor cleanups, e.g., additional loops over the PUSCH array,
  using const, using pointers instead of indices, etc
parents 288e0e14 03096dd4
...@@ -714,6 +714,7 @@ set(SCHED_NR_SRC ...@@ -714,6 +714,7 @@ set(SCHED_NR_SRC
) )
add_library(SCHED_NR_LIB ${SCHED_NR_SRC}) add_library(SCHED_NR_LIB ${SCHED_NR_SRC})
target_link_libraries(SCHED_NR_LIB PRIVATE asn1_nr_rrc_hdrs UTIL) target_link_libraries(SCHED_NR_LIB PRIVATE asn1_nr_rrc_hdrs UTIL)
target_link_libraries(SCHED_NR_LIB PRIVATE NFAPI_LIB) # some FAPI messages pack "subPDUs"
set(SCHED_SRC_RU set(SCHED_SRC_RU
${OPENAIR1_DIR}/SCHED/ru_procedures.c ${OPENAIR1_DIR}/SCHED/ru_procedures.c
...@@ -752,6 +753,7 @@ set(NFAPI_SRC ...@@ -752,6 +753,7 @@ set(NFAPI_SRC
add_library(NFAPI_LIB ${NFAPI_SRC}) add_library(NFAPI_LIB ${NFAPI_SRC})
target_link_libraries(NFAPI_LIB PUBLIC nfapi_common) target_link_libraries(NFAPI_LIB PUBLIC nfapi_common)
target_link_libraries(NFAPI_LIB PUBLIC nr_fapi_p5 nr_fapi_p7) target_link_libraries(NFAPI_LIB PUBLIC nr_fapi_p5 nr_fapi_p7)
target_link_libraries(NFAPI_LIB PRIVATE z)
if(OAI_WLS) if(OAI_WLS)
target_compile_definitions(NFAPI_LIB PRIVATE ENABLE_WLS) target_compile_definitions(NFAPI_LIB PRIVATE ENABLE_WLS)
...@@ -1072,7 +1074,7 @@ add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON}) ...@@ -1072,7 +1074,7 @@ add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON})
target_link_libraries(PHY_NR_COMMON PUBLIC UTIL) target_link_libraries(PHY_NR_COMMON PUBLIC UTIL)
add_library(PHY_NR ${PHY_NR_SRC}) add_library(PHY_NR ${PHY_NR_SRC})
target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5 polar smallblock) target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5 polar smallblock ds)
add_library(PHY_NR_NO_AVX_256 ${PHY_NR_SRC}) add_library(PHY_NR_NO_AVX_256 ${PHY_NR_SRC})
target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common) target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common)
...@@ -1748,7 +1750,7 @@ target_link_libraries(lte-softmodem PRIVATE ...@@ -1748,7 +1750,7 @@ target_link_libraries(lte-softmodem PRIVATE
lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${NAS_UE_LIB} ITTI SIMU radio_common softmodem_common ${NAS_UE_LIB} ITTI SIMU radio_common softmodem_common
-Wl,--end-group z dl) -Wl,--end-group dl)
target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt) target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt)
target_link_libraries(lte-softmodem PRIVATE ${T_LIB}) target_link_libraries(lte-softmodem PRIVATE ${T_LIB})
...@@ -1773,7 +1775,7 @@ add_executable(oairu ...@@ -1773,7 +1775,7 @@ add_executable(oairu
target_link_libraries(oairu PRIVATE target_link_libraries(oairu PRIVATE
-Wl,--start-group -Wl,--start-group
SCHED_RU_LIB PHY_COMMON PHY_RU UTIL radio_common softmodem_common SCHED_RU_LIB PHY_COMMON PHY_RU UTIL radio_common softmodem_common
-Wl,--end-group z dl) -Wl,--end-group dl)
target_link_libraries(oairu PRIVATE pthread m CONFIG_LIB rt ${T_LIB}) target_link_libraries(oairu PRIVATE pthread m CONFIG_LIB rt ${T_LIB})
target_link_libraries(oairu PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) target_link_libraries(oairu PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
...@@ -1802,7 +1804,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE ...@@ -1802,7 +1804,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE
SECURITY UTIL SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON SECURITY UTIL SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
PHY_UE PHY_RU L2_UE L2_LTE SIMU NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB PHY_UE PHY_RU L2_UE L2_LTE SIMU NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${NAS_UE_LIB} ITTI radio_common softmodem_common ${NAS_UE_LIB} ITTI radio_common softmodem_common
-Wl,--end-group z dl) -Wl,--end-group dl)
target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt) target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt)
target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB})
...@@ -1823,7 +1825,7 @@ add_executable(nr-oru ...@@ -1823,7 +1825,7 @@ add_executable(nr-oru
${OPENAIR_DIR}/executables/main_nr_ru.c ${OPENAIR_DIR}/executables/main_nr_ru.c
) )
target_link_libraries(nr-oru PRIVATE target_link_libraries(nr-oru PRIVATE
UTIL NR_PHY_RU PHY_NR shlib_loader z dl UTIL NR_PHY_RU PHY_NR shlib_loader dl
radio_common softmodem_common) radio_common softmodem_common)
target_link_libraries(nr-oru PRIVATE pthread m CONFIG_LIB rt ${T_LIB} utils target_link_libraries(nr-oru PRIVATE pthread m CONFIG_LIB rt ${T_LIB} utils
barrier actor) barrier actor)
...@@ -1852,7 +1854,7 @@ target_link_libraries(nr-softmodem PRIVATE ...@@ -1852,7 +1854,7 @@ target_link_libraries(nr-softmodem PRIVATE
ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU
x2ap f1ap m2ap m3ap e1ap radio_common x2ap f1ap m2ap m3ap e1ap radio_common
time_management softmodem_common time_management softmodem_common
-Wl,--end-group z dl) -Wl,--end-group dl)
target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt) target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt)
target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE ${T_LIB})
...@@ -1892,7 +1894,7 @@ target_link_libraries(nr-cuup PRIVATE ...@@ -1892,7 +1894,7 @@ target_link_libraries(nr-cuup PRIVATE
GTPV1U e1ap f1ap GTPV1U e1ap f1ap
time_management softmodem_common time_management softmodem_common
alg alg
z dl pthread ${T_LIB}) dl pthread ${T_LIB})
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
if(E2_AGENT) if(E2_AGENT)
target_link_libraries(nr-cuup PRIVATE e2_agent e2_agent_arg e2_ran_func_cuup) target_link_libraries(nr-cuup PRIVATE e2_agent e2_agent_arg e2_ran_func_cuup)
...@@ -1920,7 +1922,7 @@ target_link_libraries(nr-uesoftmodem PRIVATE ...@@ -1920,7 +1922,7 @@ target_link_libraries(nr-uesoftmodem PRIVATE
PHY_NR_COMMON PHY_NR_UE NR_L2_UE MAC_NR_COMMON NFAPI_LIB PHY_NR_COMMON PHY_NR_UE NR_L2_UE MAC_NR_COMMON NFAPI_LIB
ITTI SIMU radio_common ITTI SIMU radio_common
time_management softmodem_common time_management softmodem_common
-Wl,--end-group z dl) -Wl,--end-group dl)
target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt nr_ue_phy_meas) target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt nr_ue_phy_meas)
target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB})
......
...@@ -16,7 +16,7 @@ add_subdirectory(nr) ...@@ -16,7 +16,7 @@ add_subdirectory(nr)
add_subdirectory(LOG) add_subdirectory(LOG)
add_subdirectory(threadPool) add_subdirectory(threadPool)
add_subdirectory(time_manager) add_subdirectory(time_manager)
add_library(utils utils.c system.c time_meas.c time_stat.c tuntap_if.c reverse_bits.c) add_library(utils utils.c system.c time_meas.c time_stat.c tuntap_if.c reverse_bits.c fsn.c)
target_include_directories(utils PUBLIC .) target_include_directories(utils PUBLIC .)
target_link_libraries(utils PRIVATE ${T_LIB}) target_link_libraries(utils PRIVATE ${T_LIB})
add_subdirectory(barrier) add_subdirectory(barrier)
......
...@@ -6,6 +6,7 @@ add_library(ds OBJECT ...@@ -6,6 +6,7 @@ add_library(ds OBJECT
seq_arr.c seq_arr.c
hashtable.c hashtable.c
obj_hashtable.c obj_hashtable.c
spsc_q.c
) )
target_include_directories(ds PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(ds PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
......
...@@ -10,36 +10,6 @@ ...@@ -10,36 +10,6 @@
#include "assertions.h" #include "assertions.h"
//-------------------------------------------------------------------------------------------------------------------------------
char *hashtable_rc_code2string(hashtable_rc_t rcP)
//-------------------------------------------------------------------------------------------------------------------------------
{
switch (rcP) {
case HASH_TABLE_OK:
return "HASH_TABLE_OK";
break;
case HASH_TABLE_INSERT_OVERWRITTEN_DATA:
return "HASH_TABLE_INSERT_OVERWRITTEN_DATA";
break;
case HASH_TABLE_KEY_NOT_EXISTS:
return "HASH_TABLE_KEY_NOT_EXISTS";
break;
case HASH_TABLE_KEY_ALREADY_EXISTS:
return "HASH_TABLE_KEY_ALREADY_EXISTS";
break;
case HASH_TABLE_BAD_PARAMETER_HASHTABLE:
return "HASH_TABLE_BAD_PARAMETER_HASHTABLE";
break;
default:
return "UNKNOWN hashtable_rc_t";
}
}
//-------------------------------------------------------------------------------------------------------------------------------
/* /*
* free int function * free int function
* hash_free_int_func() is used when this hashtable is used to store int values as data (pointer = value). * hash_free_int_func() is used when this hashtable is used to store int values as data (pointer = value).
...@@ -147,41 +117,6 @@ hashtable_rc_t hashtable_is_key_exists (const hash_table_t *const hashtblP, cons ...@@ -147,41 +117,6 @@ hashtable_rc_t hashtable_is_key_exists (const hash_table_t *const hashtblP, cons
return HASH_TABLE_KEY_NOT_EXISTS; return HASH_TABLE_KEY_NOT_EXISTS;
} }
//-------------------------------------------------------------------------------------------------------------------------------
hashtable_rc_t hashtable_dump_content (const hash_table_t *const hashtblP, char *const buffer_pP, int *const remaining_bytes_in_buffer_pP )
//-------------------------------------------------------------------------------------------------------------------------------
{
hash_node_t *node = NULL;
unsigned int i = 0;
if (hashtblP == NULL) {
*remaining_bytes_in_buffer_pP = snprintf(
buffer_pP,
*remaining_bytes_in_buffer_pP,
"HASH_TABLE_BAD_PARAMETER_HASHTABLE");
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
}
while ((i < hashtblP->size) && (*remaining_bytes_in_buffer_pP > 0)) {
if (hashtblP->nodes[i] != NULL) {
node=hashtblP->nodes[i];
while(node) {
*remaining_bytes_in_buffer_pP = snprintf(
buffer_pP,
*remaining_bytes_in_buffer_pP,
"Key 0x%"PRIx64" Element %p\n",
node->key,
node->data);
node=node->next;
}
}
i += 1;
}
return HASH_TABLE_OK;
}
//------------------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------------------
/* /*
......
...@@ -44,12 +44,10 @@ typedef struct hash_table_iterator_s { ...@@ -44,12 +44,10 @@ typedef struct hash_table_iterator_s {
const hash_table_t* const hashtbl; const hash_table_t* const hashtbl;
} hash_table_iterator_s; } hash_table_iterator_s;
char *hashtable_rc_code2string(hashtable_rc_t rcP);
void hash_free_int_func(void *memoryP); void hash_free_int_func(void *memoryP);
hash_table_t *hashtable_create (const hash_size_t size, hash_size_t (*hashfunc)(const hash_key_t ), void (*freefunc)(void *)); hash_table_t *hashtable_create (const hash_size_t size, hash_size_t (*hashfunc)(const hash_key_t ), void (*freefunc)(void *));
hashtable_rc_t hashtable_destroy(hash_table_t **hashtbl); hashtable_rc_t hashtable_destroy(hash_table_t **hashtbl);
hashtable_rc_t hashtable_is_key_exists (const hash_table_t *const hashtbl, const uint64_t key); hashtable_rc_t hashtable_is_key_exists (const hash_table_t *const hashtbl, const uint64_t key);
hashtable_rc_t hashtable_dump_content (const hash_table_t *const hashtblP, char *const buffer_pP, int *const remaining_bytes_in_buffer_pP );
hashtable_rc_t hashtable_insert (hash_table_t *const hashtbl, const hash_key_t key, void *data); hashtable_rc_t hashtable_insert (hash_table_t *const hashtbl, const hash_key_t key, void *data);
hashtable_rc_t hashtable_remove (hash_table_t *const hashtbl, const hash_key_t key); hashtable_rc_t hashtable_remove (hash_table_t *const hashtbl, const hash_key_t key);
hashtable_rc_t hashtable_get (const hash_table_t *const hashtbl, const hash_key_t key, void **dataP); hashtable_rc_t hashtable_get (const hash_table_t *const hashtbl, const hash_key_t key, void **dataP);
......
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "spsc_q.h"
spsc_q_t spsc_q_alloc(size_t cnt, size_t elsiz)
{
/* internally, use one element more: the ringbuffer is full if
* (write_idx + 1) % cnt == read_idx, so it's full if one element is still
* free (because otherwise write_idx == read_idx, but this is the empty
* condition) */
cnt += 1;
spsc_q_t rb = {.cnt = cnt, .elsiz = elsiz};
rb.buf = calloc(cnt, elsiz);
return rb;
}
void spsc_q_free(spsc_q_t *rb)
{
free(rb->buf);
memset(rb, 0, sizeof(*rb));
}
bool spsc_q_put(spsc_q_t *rb, const void *src, size_t elsiz)
{
assert(elsiz == rb->elsiz);
size_t w = atomic_load_explicit(&rb->write_idx, memory_order_relaxed);
size_t r = atomic_load_explicit(&rb->read_idx, memory_order_acquire);
if ((w + 1) % rb->cnt == r) {
return false;
}
uint8_t *bufpos = &rb->buf[w * rb->elsiz];
memcpy(bufpos, src, elsiz);
atomic_store_explicit(&rb->write_idx, (w + 1) % rb->cnt, memory_order_release);
return true;
}
bool spsc_q_get_if(spsc_q_t *rb, pred p, void *user, void *dest, size_t elsiz)
{
assert(elsiz == rb->elsiz);
size_t w = atomic_load_explicit(&rb->write_idx, memory_order_acquire);
size_t r = atomic_load_explicit(&rb->read_idx, memory_order_relaxed);
if (w == r) {
return false;
}
uint8_t *bufpos = &rb->buf[rb->read_idx * rb->elsiz];
if (!p(bufpos, user)) {
return false;
}
if (dest)
memcpy(dest, bufpos, elsiz);
atomic_store_explicit(&rb->read_idx, (r + 1) % rb->cnt, memory_order_release);
return true;
}
static bool always(const void *data, void *user)
{
(void) data;
(void) user;
return true;
}
bool spsc_q_get(spsc_q_t *rb, void *dest, size_t elsiz)
{
return spsc_q_get_if(rb, always, NULL, dest, elsiz);
}
int spsc_q_get_while(spsc_q_t *rb, pred p, void *user, void *dest, size_t elsiz, size_t max_len)
{
assert(elsiz == rb->elsiz);
size_t count = 0;
while (count < max_len && spsc_q_get_if(rb, p, user, dest + elsiz * count, elsiz))
count++;
return count;
}
int spsc_q_drop_while(spsc_q_t *rb, pred p, void *user)
{
size_t dropped = 0;
while (spsc_q_get_if(rb, p, user, NULL, rb->elsiz))
dropped++;
return dropped;
}
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#ifndef SPSC_Q_H_
#define SPSC_Q_H_
#include <stdint.h>
#include <stdbool.h>
#include <stdatomic.h>
#if defined(__cplusplus)
// use atomic_size_t to help interworking with C++
using std::atomic_size_t;
#endif
typedef struct spsc_q {
uint8_t *buf;
size_t elsiz;
size_t cnt;
atomic_size_t write_idx;
atomic_size_t read_idx;
} spsc_q_t;
spsc_q_t spsc_q_alloc(size_t cnt, size_t elsiz);
void spsc_q_free(spsc_q_t *rb);
bool spsc_q_put(spsc_q_t *rb, const void *src, size_t elsiz);
bool spsc_q_get(spsc_q_t *rb, void *dest, size_t elsiz);
typedef bool (*pred)(const void *data, void *user);
bool spsc_q_get_if(spsc_q_t *rb, pred p, void *user, void *dest, size_t elsiz);
int spsc_q_drop_while(spsc_q_t *rb, pred p, void *user);
int spsc_q_get_while(spsc_q_t *rb, pred p, void *user, void *dest, size_t elsiz, size_t max_len);
#endif /* SPSC_Q_H_ */
...@@ -8,5 +8,11 @@ add_test(NAME test_seq_arr COMMAND test_seq_arr) # no options required ...@@ -8,5 +8,11 @@ add_test(NAME test_seq_arr COMMAND test_seq_arr) # no options required
add_executable(test_hashtable test_hashtable.cpp) add_executable(test_hashtable test_hashtable.cpp)
add_dependencies(tests test_hashtable) add_dependencies(tests test_hashtable)
target_link_libraries(test_hashtable PRIVATE ds GTest::gtest) target_link_libraries(test_hashtable PRIVATE ds GTest::gtest)
add_test(NAME test_hashtable add_test(NAME test_hashtable COMMAND ./test_hashtable)
COMMAND ./test_hashtable)
add_executable(test_spsc_q test_spsc_q.cpp)
target_link_libraries(test_spsc_q ds GTest::gtest)
add_dependencies(tests test_spsc_q)
add_test(NAME test_spsc_q COMMAND test_spsc_q)
add_executable(test_spsc_q_perf test_spsc_q_perf.cpp)
target_link_libraries(test_spsc_q_perf PRIVATE ds benchmark::benchmark)
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#include "gtest/gtest.h"
extern "C" {
#include "spsc_q.h"
}
TEST(spsc_q, basic_test) {
spsc_q_t rb = spsc_q_alloc(2, sizeof(int));
int a = 1;
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
EXPECT_FALSE(spsc_q_put(&rb, &a, sizeof(a)));
int b;
EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
EXPECT_EQ(a, b);
EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
EXPECT_EQ(a, b);
EXPECT_FALSE(spsc_q_get(&rb, &b, sizeof(b)));
spsc_q_free(&rb);
}
TEST(spsc_q, cont_write) {
spsc_q_t rb = spsc_q_alloc(10, sizeof(int));
int a = 1;
for (int i = 0; i < 1111; ++i) {
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
a++;
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
a++;
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
a++;
int b;
EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
EXPECT_EQ(b, a - 3);
EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
EXPECT_EQ(b, a - 2);
EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
EXPECT_EQ(b, a - 1);
}
spsc_q_free(&rb);
}
bool count(const void *data, void *user)
{
EXPECT_TRUE(data != NULL);
int *c = (int *)user;
(*c)++;
return true; /* count all */
}
TEST(spsc_q, iterator) {
spsc_q_t rb = spsc_q_alloc(10, sizeof(int));
int n = 8;
for (int i = 0; i < n; ++i)
EXPECT_TRUE(spsc_q_put(&rb, &i, sizeof(i)));
int c = 0;
int results[n];
int ret = spsc_q_get_while(&rb, count, &c, results, sizeof(*results), n);
EXPECT_EQ(c, n);
EXPECT_EQ(ret, n);
for (int i = 0; i < n; ++i)
EXPECT_EQ(results[i], i);
int b;
EXPECT_FALSE(spsc_q_get(&rb, &b, sizeof(b))); /* empty! */
spsc_q_free(&rb);
}
bool drop(const void *data, void *user)
{
const int *e = (const int *)data;
int *c = (int *)user;
EXPECT_EQ(*e, *c);
(*c)++;
return true; /* drop all */
}
TEST(spsc_q, drop) {
spsc_q_t rb = spsc_q_alloc(10, sizeof(int));
int n = 8;
for (int i = 0; i < n; ++i)
EXPECT_TRUE(spsc_q_put(&rb, &i, sizeof(i)));
int c = 0;
int ret = spsc_q_drop_while(&rb, drop, &c);
EXPECT_EQ(c, n);
EXPECT_EQ(ret, n);
int b;
EXPECT_FALSE(spsc_q_get(&rb, &b, sizeof(b))); /* empty! */
spsc_q_free(&rb);
}
TEST(spsc_q, full) {
int n = 3;
spsc_q_t rb = spsc_q_alloc(n, sizeof(int));
int a = 1;
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
a++;
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
a++;
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
a++;
EXPECT_FALSE(spsc_q_put(&rb, &a, sizeof(a))); /* full! */
int b;
EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
EXPECT_EQ(b, a - n);
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
a++;
EXPECT_FALSE(spsc_q_put(&rb, &a, sizeof(a))); /* full! */
EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
EXPECT_EQ(b, a - n);
spsc_q_free(&rb);
}
int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
#include "benchmark/benchmark.h"
#include "stdio.h"
#include "assert.h"
#include "pthread.h"
extern "C" {
#include "spsc_q.h"
}
typedef struct q_args {
spsc_q_t q;
int range;
} q_args_t;
static void *producer(void *arg)
{
q_args_t *a = (q_args_t *) arg;
int i = 0;
while (i <= a->range) {
if (spsc_q_put(&a->q, &i, sizeof(i)))
i++;
}
return NULL;
}
static void *consumer(void *arg)
{
q_args_t *a = (q_args_t *) arg;
int i = 0;
while (i != a->range) {
int r;
if (spsc_q_get(&a->q, &r, sizeof(r))) {
assert(r == i);
i++;
}
}
return NULL;
}
static void run_test(int range, int q_size)
{
q_args_t args = {
.q = spsc_q_alloc(q_size, sizeof(int)),
.range = range,
};
pthread_t p, c;
int ret;
// start
ret = pthread_create(&p, NULL, producer, &args);
assert(ret == 0);
ret = pthread_create(&c, NULL, consumer, &args);
assert(ret == 0);
ret = pthread_join(p, NULL);
assert(ret == 0);
ret = pthread_join(c, NULL);
assert(ret == 0);
// stop
// data/time => throughput
spsc_q_free(&args.q);
}
static void BM_spsc_q(benchmark::State &state)
{
int range = 500000;
int q_size = state.range(0);
for (auto _ : state)
run_test(range, q_size);
}
BENCHMARK(BM_spsc_q)->RangeMultiplier(2)->Range(10, 160);
BENCHMARK_MAIN();
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#include "fsn.h"
#include <assert.h>
static int num_slots[5] = {10, 20, 40, 80, 160};
fsn_t fsn_add_delta(fsn_t fsn, uint32_t delta)
{
const int slots_frame = num_slots[fsn.mu];
int next_f = fsn.f + delta / slots_frame;
int next_s = fsn.s + delta % slots_frame;
fsn_t res = {
.f = (next_f + next_s / slots_frame) % 1024,
.s = next_s % slots_frame,
.mu = fsn.mu,
};
return res;
}
int fsn_get_diff(fsn_t a, fsn_t b)
{
assert(a.mu == b.mu);
const int slots_frame = num_slots[a.mu];
int diff = (a.f * slots_frame + a.s) - (b.f * slots_frame + b.s);
if (diff < -512 * slots_frame)
diff += 1024 * slots_frame;
else if (diff > 512 * slots_frame)
diff -= 1024 * slots_frame;
return diff;
}
fsn_t fsn_get_max(fsn_t a, fsn_t b)
{
if (fsn_get_diff(a, b) <= 0) {
return b;
} else {
return a;
}
}
bool fsn_equal(fsn_t a, fsn_t b)
{
assert(a.mu == b.mu);
return a.f == b.f && a.s == b.s && a.mu == b.mu;
}
bool fsn_in_the_past(fsn_t old, fsn_t new)
{
int diff = fsn_get_diff(old, new);
return diff < 0;
}
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#ifndef FSN_H_
#define FSN_H_
#include <stdint.h>
#include <stdbool.h>
/// helper type to encapsulate a frame/slot combination in a single type.
typedef struct fsn {
uint16_t f; /// frame
uint16_t s; /// slot
uint8_t mu; /// numerology
} fsn_t;
/* \brief Add delta slots to fsn. Note that this depends also on the stored
* numerology inside fsn. */
fsn_t fsn_add_delta(fsn_t fsn, uint32_t delta);
/* \brief Get difference of slots for a and b.
* \note asserts if numerology not the same. */
int fsn_get_diff(fsn_t a, fsn_t b);
/* \brief Gets the larger of two fsns */
fsn_t fsn_get_max(fsn_t a, fsn_t b);
/* \brief Compare if both fsn_t's are equal */
bool fsn_equal(fsn_t a, fsn_t b);
/* \brief Determine if told is in the past of tnew. The threshold is 512
* frames. */
bool fsn_in_the_past(fsn_t told, fsn_t tnew);
#endif /* FSN_H_ */
...@@ -2,3 +2,10 @@ ...@@ -2,3 +2,10 @@
add_executable(test_tpool_vs_actors test_tpool_vs_actors.c) add_executable(test_tpool_vs_actors test_tpool_vs_actors.c)
target_link_libraries(test_tpool_vs_actors PRIVATE thread-pool pthread LOG minimal_lib actor) target_link_libraries(test_tpool_vs_actors PRIVATE thread-pool pthread LOG minimal_lib actor)
add_test(NAME test_tpool_vs_actors COMMAND ./test_tpool_vs_actors)
add_dependencies(tests test_tpool_vs_actors)
add_executable(test_fsn test_fsn.cpp)
add_dependencies(tests test_fsn)
target_link_libraries(test_fsn PRIVATE utils GTest::gtest)
add_test(NAME test_fsn COMMAND ./test_fsn)
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#include <gtest/gtest.h>
extern "C" {
#include "fsn.h"
}
TEST(fsn, test_mu0_fsn_add) {
fsn_t current = {123, 5, 0};
fsn_t next = current;
next = fsn_add_delta(next, 12);
EXPECT_EQ(next.f, 124);
EXPECT_EQ(next.s, 7);
EXPECT_EQ(next.mu, 0);
next = fsn_add_delta(next, 10);
EXPECT_EQ(next.f, 125);
EXPECT_EQ(next.s, 7);
EXPECT_EQ(next.mu, 0);
next = fsn_add_delta(next, 10 * 1024);
EXPECT_EQ(next.f, 125);
EXPECT_EQ(next.s, 7);
EXPECT_EQ(next.mu, 0);
}
TEST(fsn, test_mu0_get_diff) {
fsn_t current = {123, 5, 0};
fsn_t next = fsn_add_delta(current, 12);
int diff;
diff = fsn_get_diff(current, next);
EXPECT_EQ(diff, -12);
diff = fsn_get_diff(next, current);
EXPECT_EQ(diff, 12);
}
TEST(fsn, test_mu0_get_max) {
fsn_t current = {123, 5, 0};
fsn_t next = {125, 7, 0};
fsn_t max = fsn_get_max(current, next);
EXPECT_EQ(max.f, next.f);
EXPECT_EQ(max.s, next.s);
EXPECT_EQ(max.mu, next.mu);
}
TEST(fsn, test_mu0_equal) {
fsn_t a = {123, 5, 0};
fsn_t b = a;
fsn_t c = {123, 6, 0};
EXPECT_TRUE(fsn_equal(a, b));
EXPECT_FALSE(fsn_equal(a, c));
}
TEST(fsn, test_mu0_in_the_past) {
fsn_t a = {0, 0, 0};
fsn_t n = {100, 9, 0};
fsn_t b_bef = {511, 9, 0};
fsn_t b_ex = {512, 0, 0};
fsn_t b_aft = {512, 1, 0};
// a is in the past of n
EXPECT_TRUE(fsn_in_the_past(a, n));
// similarly, a is in the past of b_bef
EXPECT_TRUE(fsn_in_the_past(a, b_bef));
// difference "to both sides" is 512 frames, so we consider a still in the
// past of b_ex
EXPECT_TRUE(fsn_in_the_past(a, b_ex));
// (b_aft - a) < (a - b_aft) => b_aft is in the past of a because of
// wrap-around
EXPECT_TRUE(fsn_in_the_past(b_aft, a));
}
int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
...@@ -161,7 +161,12 @@ static void rx_func(processingData_L1_t *info) ...@@ -161,7 +161,12 @@ static void rx_func(processingData_L1_t *info)
NR_UL_IND_t UL_INFO = {.frame = frame_rx, .slot = slot_rx, .module_id = gNB->Mod_id, .CC_id = gNB->CC_id}; NR_UL_IND_t UL_INFO = {.frame = frame_rx, .slot = slot_rx, .module_id = gNB->Mod_id, .CC_id = gNB->CC_id};
// Do PRACH RU processing // Do PRACH RU processing
UL_INFO.rach_ind.pdu_list = UL_INFO.prach_pdu_indication_list; UL_INFO.rach_ind.pdu_list = UL_INFO.prach_pdu_indication_list;
L1_nr_prach_procedures(gNB, frame_rx, slot_rx, &UL_INFO.rach_ind); UL_INFO.rach_ind.number_of_pdus = 0;
// even if processing is late, we might collect all PRACH
// the last PRACH's frame/slot is when all UE's appear to have accessed
prach_item_t p;
while (spsc_q_get(&gNB->prach_l1rx_queue, &p, sizeof(p)))
L1_nr_prach_procedures(gNB, &p, &UL_INFO.rach_ind);
//WA: comment rotation in tx/rx //WA: comment rotation in tx/rx
if (gNB->phase_comp) { if (gNB->phase_comp) {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "common/utils/nr/nr_common.h" #include "common/utils/nr/nr_common.h"
#include "common/utils/assertions.h" #include "common/utils/assertions.h"
#include "common/utils/system.h" #include "common/utils/system.h"
#include "common/utils/fsn.h"
#include "common/ran_context.h" #include "common/ran_context.h"
#include "radio/COMMON/common_lib.h" #include "radio/COMMON/common_lib.h"
...@@ -980,11 +981,16 @@ void *ru_thread(void *param) ...@@ -980,11 +981,16 @@ void *ru_thread(void *param)
proc->tti_rx * gNB->frame_parms.samples_per_slot_wCP); proc->tti_rx * gNB->frame_parms.samples_per_slot_wCP);
// Do PRACH RU processing // Do PRACH RU processing
prach_item_t *p = fsn_t now = {.f = proc->frame_rx, .s = proc->tti_rx, .mu = fp->numerology_index};
find_nr_prach(&gNB->prach_list, proc->frame_rx, proc->tti_rx, gNB->frame_parms.nb_antennas_rx, NR_SEARCH_EXIST); prach_item_t p;
if (p) { while (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) {
// need to extract RACH data for later processing by rx_nr_prach() // need to extract RACH data for later processing by rx_nr_prach()
rx_nr_prach_ru(p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); rx_nr_prach_ru(&p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset);
bool success = spsc_q_put(&gNB->prach_l1rx_queue, &p, sizeof(p));
// assume prach_l1rx_queue never full: prach_ru_queue filled at
// constant pace, but prach_l1rx_queue emptied as fast as possible,
// see rx_func()
DevAssert(success);
} // end if (prach_id >= 0) } // end if (prach_id >= 0)
} // end if (ru->feprx) } // end if (ru->feprx)
} // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { } // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
......
...@@ -50,6 +50,8 @@ int l1_north_init_gNB() ...@@ -50,6 +50,8 @@ int l1_north_init_gNB()
NR_gNB_PHY_STATS_t *get_phy_stats(PHY_VARS_gNB *gNB, uint16_t rnti) NR_gNB_PHY_STATS_t *get_phy_stats(PHY_VARS_gNB *gNB, uint16_t rnti)
{ {
// TODO reimplement with hashtable? also called from both UL/DL => not
// thread-safe
NR_gNB_PHY_STATS_t *stats; NR_gNB_PHY_STATS_t *stats;
int first_free = -1; int first_free = -1;
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
...@@ -141,16 +143,6 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) ...@@ -141,16 +143,6 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
init_DLSCH_struct(gNB); init_DLSCH_struct(gNB);
gNB->nr_srs_info = (nr_srs_info_t **)malloc16_clear(gNB->max_nb_srs * sizeof(nr_srs_info_t*));
for (int id = 0; id < gNB->max_nb_srs; id++) {
gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t));
gNB->nr_srs_info[id]->srs_generated_signal = malloc16_clear(MAX_NUM_NR_SRS_AP * sizeof(c16_t *));
for(int ap=0; ap<MAX_NUM_NR_SRS_AP; ap++) {
gNB->nr_srs_info[id]->srs_generated_signal[ap] =
malloc16_clear(fp->ofdm_symbol_size * MAX_NUM_NR_SRS_SYMBOLS * sizeof(c16_t));
}
}
/* Do NOT allocate per-antenna rxdataF: the gNB gets a pointer to the /* Do NOT allocate per-antenna rxdataF: the gNB gets a pointer to the
* RU to copy/recover freq-domain memory from there */ * RU to copy/recover freq-domain memory from there */
common_vars->rxdataF = (c16_t ***)malloc16(common_vars->num_beams_period * sizeof(c16_t**)); common_vars->rxdataF = (c16_t ***)malloc16(common_vars->num_beams_period * sizeof(c16_t**));
...@@ -174,7 +166,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) ...@@ -174,7 +166,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
common_vars->debugBuff_sample_offset = 0; common_vars->debugBuff_sample_offset = 0;
// PRACH // PRACH
init_prach_list(&gNB->prach_list); init_nr_prach(gNB);
int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value; int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value;
int n_buf = Prx*max_ul_mimo_layers; int n_buf = Prx*max_ul_mimo_layers;
...@@ -212,19 +204,11 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) ...@@ -212,19 +204,11 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
PHY_MEASUREMENTS_gNB *meas = &gNB->measurements; PHY_MEASUREMENTS_gNB *meas = &gNB->measurements;
free_and_zero(meas->n0_subband_power); free_and_zero(meas->n0_subband_power);
for (int id = 0; id < gNB->max_nb_srs; id++) {
for(int i=0; i<MAX_NUM_NR_SRS_AP; i++) {
free_and_zero(gNB->nr_srs_info[id]->srs_generated_signal[i]);
}
free_and_zero(gNB->nr_srs_info[id]->srs_generated_signal);
free_and_zero(gNB->nr_srs_info[id]);
}
free_and_zero(gNB->nr_srs_info);
free_ul_reference_signal_sequences(); free_ul_reference_signal_sequences();
free_gnb_lowpapr_sequences(); free_gnb_lowpapr_sequences();
reset_nr_transport(gNB); reset_nr_transport(gNB);
reset_nr_prach(gNB);
destroy_DLSCH_struct(gNB); destroy_DLSCH_struct(gNB);
...@@ -437,18 +421,14 @@ void init_nr_transport(PHY_VARS_gNB *gNB) ...@@ -437,18 +421,14 @@ void init_nr_transport(PHY_VARS_gNB *gNB)
else else
buffer_ul_slots = (nb_ul_slots_period < slot_ahead) ? nb_ul_slots_period : slot_ahead; buffer_ul_slots = (nb_ul_slots_period < slot_ahead) ? nb_ul_slots_period : slot_ahead;
gNB->max_nb_pucch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1;
gNB->max_nb_pusch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1; gNB->max_nb_pusch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1;
gNB->max_nb_srs = buffer_ul_slots ? buffer_ul_slots << 1 : 1; // assuming at most 2 SRS per slot
gNB->pucch = (NR_gNB_PUCCH_t *)malloc16(gNB->max_nb_pucch * sizeof(NR_gNB_PUCCH_t)); int max_nb_pucch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1;
for (int i = 0; i < gNB->max_nb_pucch; i++) { gNB->pucch_queue = spsc_q_alloc(max_nb_pucch, sizeof(NR_gNB_PUCCH_job_t));
memset(&gNB->pucch[i], 0, sizeof(gNB->pucch[i])); gNB->pusch_queue = spsc_q_alloc(gNB->max_nb_pusch, sizeof(NR_gNB_PUSCH_job_t));
}
gNB->srs = (NR_gNB_SRS_t *)malloc16(gNB->max_nb_srs * sizeof(NR_gNB_SRS_t)); int max_nb_srs = buffer_ul_slots ? buffer_ul_slots << 1 : 1; // assuming at most 2 SRS per slot
for (int i = 0; i < gNB->max_nb_srs; i++) gNB->srs_queue = spsc_q_alloc(max_nb_srs, sizeof(NR_gNB_SRS_job_t));
gNB->srs[i].active = 0;
gNB->ulsch = (NR_gNB_ULSCH_t *)malloc16(gNB->max_nb_pusch * sizeof(NR_gNB_ULSCH_t)); gNB->ulsch = (NR_gNB_ULSCH_t *)malloc16(gNB->max_nb_pusch * sizeof(NR_gNB_ULSCH_t));
for (int i = 0; i < gNB->max_nb_pusch; i++) { for (int i = 0; i < gNB->max_nb_pusch; i++) {
...@@ -465,8 +445,9 @@ void reset_nr_transport(PHY_VARS_gNB *gNB) ...@@ -465,8 +445,9 @@ void reset_nr_transport(PHY_VARS_gNB *gNB)
{ {
const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
free(gNB->pucch); spsc_q_free(&gNB->pucch_queue);
free(gNB->srs); spsc_q_free(&gNB->pusch_queue);
spsc_q_free(&gNB->srs_queue);
for (int i = 0; i < gNB->max_nb_pusch; i++) for (int i = 0; i < gNB->max_nb_pusch; i++)
free_gNB_ulsch(&gNB->ulsch[i], fp->N_RB_UL); free_gNB_ulsch(&gNB->ulsch[i], fp->N_RB_UL);
......
...@@ -251,8 +251,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) ...@@ -251,8 +251,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
ue->nr_csi_info->csi_rs_generated_signal[i] = ue->nr_csi_info->csi_rs_generated_signal[i] =
malloc16_clear(fp->samples_per_slot_wCP * sizeof(**ue->nr_csi_info->csi_rs_generated_signal)); malloc16_clear(fp->samples_per_slot_wCP * sizeof(**ue->nr_csi_info->csi_rs_generated_signal));
} }
ue->nr_srs_info = malloc16_clear(sizeof(nr_srs_info_t));
} }
ue->init_averaging = 1; ue->init_averaging = 1;
...@@ -301,8 +299,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue) ...@@ -301,8 +299,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue)
free_and_zero(ue->nr_csi_info->csi_rs_generated_signal); free_and_zero(ue->nr_csi_info->csi_rs_generated_signal);
free_and_zero(ue->nr_csi_info); free_and_zero(ue->nr_csi_info);
free_and_zero(ue->nr_srs_info);
free_and_zero(ue->prach_vars[gNB_id]); free_and_zero(ue->prach_vars[gNB_id]);
} }
......
...@@ -123,12 +123,12 @@ void dump_nr_I0_stats(FILE *fd, PHY_VARS_gNB *gNB) ...@@ -123,12 +123,12 @@ void dump_nr_I0_stats(FILE *fd, PHY_VARS_gNB *gNB)
fprintf(fd, "\nPRACH I0 = %d.%d dB\n", gNB->measurements.prach_I0 / 10, gNB->measurements.prach_I0 % 10); fprintf(fd, "\nPRACH I0 = %d.%d dB\n", gNB->measurements.prach_I0 / 10, gNB->measurements.prach_I0 % 10);
} }
void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][9]) void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][MAX_BWP_SIZE])
{ {
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
NR_gNB_COMMON *common_vars = &gNB->common_vars; NR_gNB_COMMON *common_vars = &gNB->common_vars;
PHY_MEASUREMENTS_gNB *measurements = &gNB->measurements; PHY_MEASUREMENTS_gNB *measurements = &gNB->measurements;
int nb_symb[275]={0}; int nb_symb[MAX_BWP_SIZE] = {0};
unsigned int tmp_n0_subband[frame_parms->nb_antennas_rx][frame_parms->N_RB_UL]; unsigned int tmp_n0_subband[frame_parms->nb_antennas_rx][frame_parms->N_RB_UL];
memset(tmp_n0_subband, 0, sizeof(tmp_n0_subband)); memset(tmp_n0_subband, 0, sizeof(tmp_n0_subband));
...@@ -137,7 +137,7 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy ...@@ -137,7 +137,7 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy
for (int s = first_symb; s < first_symb + num_symb; s++) { for (int s = first_symb; s < first_symb + num_symb; s++) {
int offset0 = ((slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot + s) * frame_parms->ofdm_symbol_size; int offset0 = ((slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot + s) * frame_parms->ofdm_symbol_size;
for (int rb = 0; rb < frame_parms->N_RB_UL; rb++) { for (int rb = 0; rb < frame_parms->N_RB_UL; rb++) {
if ((rb_mask_ul[s][rb >> 5] & (1U << (rb & 31))) == 0 && // check that rb was not used in this subframe if (rb_mask_ul[s][rb] == 0 && // check that rb was not used in this subframe
!(I0_SKIP_DC && rb == frame_parms->N_RB_UL >> 1)) { // skip middle PRB because of artificial noise possibly created by FFT !(I0_SKIP_DC && rb == frame_parms->N_RB_UL >> 1)) { // skip middle PRB because of artificial noise possibly created by FFT
int offset = offset0 + (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; int offset = offset0 + (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size;
nb_symb[rb]++; nb_symb[rb]++;
......
...@@ -34,7 +34,7 @@ typedef struct puschAntennaProc_s { ...@@ -34,7 +34,7 @@ typedef struct puschAntennaProc_s {
int aarx; int aarx;
int beam_nb; int beam_nb;
int numAntennas; int numAntennas;
nfapi_nr_pusch_pdu_t *pusch_pdu; const nfapi_nr_pusch_pdu_t *pusch_pdu;
int *max_ch; int *max_ch;
c16_t *pilot; c16_t *pilot;
int *nest_count; int *nest_count;
...@@ -82,7 +82,7 @@ static void nr_pusch_antenna_processing(void *arg) ...@@ -82,7 +82,7 @@ static void nr_pusch_antenna_processing(void *arg)
int aarx = rdata->aarx; int aarx = rdata->aarx;
int numAntennas = rdata->numAntennas; int numAntennas = rdata->numAntennas;
unsigned short bwp_start_subcarrier = rdata->bwp_start_subcarrier; unsigned short bwp_start_subcarrier = rdata->bwp_start_subcarrier;
nfapi_nr_pusch_pdu_t *pusch_pdu = rdata->pusch_pdu; const nfapi_nr_pusch_pdu_t *pusch_pdu = rdata->pusch_pdu;
int *max_ch = rdata->max_ch; int *max_ch = rdata->max_ch;
c16_t *pilot = rdata->pilot; c16_t *pilot = rdata->pilot;
uint64_t noise_amp2 = *(rdata->noise_amp2); uint64_t noise_amp2 = *(rdata->noise_amp2);
...@@ -452,10 +452,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -452,10 +452,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
int nl, int nl,
unsigned short p, unsigned short p,
unsigned char symbol, unsigned char symbol,
int ul_id, NR_gNB_PUSCH *pusch_vars,
int beam_nb, int beam_nb,
unsigned short bwp_start_subcarrier, unsigned short bwp_start_subcarrier,
nfapi_nr_pusch_pdu_t *pusch_pdu, const nfapi_nr_pusch_pdu_t *pusch_pdu,
int *max_ch, int *max_ch,
uint32_t *nvar, uint32_t *nvar,
c16_t *pusch_dmrs_slot_mem, c16_t *pusch_dmrs_slot_mem,
...@@ -534,7 +534,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -534,7 +534,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
int nest_count = 0; int nest_count = 0;
uint64_t noise_amp2 = 0; uint64_t noise_amp2 = 0;
delay_t *delay = &gNB->ulsch[ul_id].delay; delay_t *delay = &pusch_vars->delay;
memset(delay, 0, sizeof(*delay)); memset(delay, 0, sizeof(*delay));
int nb_antennas_rx = fp->nb_antennas_rx; int nb_antennas_rx = fp->nb_antennas_rx;
...@@ -579,7 +579,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -579,7 +579,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
rdata->delay = &delay_arr[rdata->aarx]; rdata->delay = &delay_arr[rdata->aarx];
rdata->beam_nb = beam_nb; rdata->beam_nb = beam_nb;
rdata->frame_parms = fp; rdata->frame_parms = fp;
rdata->pusch_vars = &gNB->pusch_vars[ul_id]; rdata->pusch_vars = pusch_vars;
rdata->chest_freq = gNB->chest_freq; rdata->chest_freq = gNB->chest_freq;
rdata->rxdataF = gNB->common_vars.rxdataF; rdata->rxdataF = gNB->common_vars.rxdataF;
rdata->scope = gNB->scopeData; rdata->scope = gNB->scopeData;
...@@ -628,7 +628,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -628,7 +628,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
* *
* PARAMETERS : gNB : gNB data structure * PARAMETERS : gNB : gNB data structure
* rel15_ul : UL parameters * rel15_ul : UL parameters
* UE_id : UE ID * pusch_vars : PUSCH data
* nr_tti_rx : slot rx TTI * nr_tti_rx : slot rx TTI
* dmrs_symbol_flag: DMRS Symbol Flag * dmrs_symbol_flag: DMRS Symbol Flag
* symbol : OFDM Symbol * symbol : OFDM Symbol
...@@ -646,25 +646,22 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -646,25 +646,22 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
// #define DEBUG_UL_PTRS // #define DEBUG_UL_PTRS
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *rel15_ul, const nfapi_nr_pusch_pdu_t *rel15_ul,
uint8_t ulsch_id, NR_gNB_PUSCH *pusch_vars,
uint8_t nr_tti_rx, uint8_t nr_tti_rx,
unsigned char symbol, unsigned char symbol,
uint32_t nb_re_pusch) uint32_t nb_re_pusch)
{ {
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
int32_t *ptrs_re_symbol = NULL; int32_t *ptrs_re_symbol = NULL;
int8_t ret = 0; int8_t ret = 0;
uint8_t symbInSlot = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols; uint8_t symbInSlot = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols;
uint8_t *startSymbIndex = &rel15_ul->start_symbol_index; uint8_t startSymbIndex = rel15_ul->start_symbol_index;
uint8_t *nbSymb = &rel15_ul->nr_of_symbols; uint8_t nbSymb = rel15_ul->nr_of_symbols;
uint8_t *L_ptrs = &rel15_ul->pusch_ptrs.ptrs_time_density; uint8_t L_ptrs = rel15_ul->pusch_ptrs.ptrs_time_density;
uint8_t *K_ptrs = &rel15_ul->pusch_ptrs.ptrs_freq_density; uint8_t K_ptrs = rel15_ul->pusch_ptrs.ptrs_freq_density;
uint16_t *dmrsSymbPos = &rel15_ul->ul_dmrs_symb_pos; uint16_t dmrsSymbPos = rel15_ul->ul_dmrs_symb_pos;
uint16_t *ptrsSymbPos = &pusch_vars->ptrs_symbols; uint16_t nb_rb = rel15_ul->rb_size;
uint8_t *ptrsSymbIdx = &pusch_vars->ptrs_symbol_index; uint8_t ptrsReOffset = rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
uint16_t *nb_rb = &rel15_ul->rb_size;
uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
/* loop over antennas */ /* loop over antennas */
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
...@@ -673,7 +670,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, ...@@ -673,7 +670,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
*ptrs_re_symbol = 0; *ptrs_re_symbol = 0;
phase_per_symbol[symbol].i = 0; phase_per_symbol[symbol].i = 0;
/* set DMRS estimates to 0 angle with magnitude 1 */ /* set DMRS estimates to 0 angle with magnitude 1 */
if (is_dmrs_symbol(symbol, *dmrsSymbPos)) { if (is_dmrs_symbol(symbol, dmrsSymbPos)) {
/* set DMRS real estimation to 32767 */ /* set DMRS real estimation to 32767 */
phase_per_symbol[symbol].r = INT16_MAX; // 32767 phase_per_symbol[symbol].r = INT16_MAX; // 32767
#ifdef DEBUG_UL_PTRS #ifdef DEBUG_UL_PTRS
...@@ -683,17 +680,13 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, ...@@ -683,17 +680,13 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
phase_per_symbol[symbol].r = 0; phase_per_symbol[symbol].r = 0;
} }
if (symbol == *startSymbIndex) { if (symbol == startSymbIndex) {
*ptrsSymbPos = 0; pusch_vars->ptrs_symbols = 0;
set_ptrs_symb_idx(ptrsSymbPos, *nbSymb, *startSymbIndex, 1 << *L_ptrs, *dmrsSymbPos); set_ptrs_symb_idx(&pusch_vars->ptrs_symbols, nbSymb, startSymbIndex, 1 << L_ptrs, dmrsSymbPos);
} }
/* if not PTRS symbol set current ptrs symbol index to zero*/
*ptrsSymbIdx = 0;
/* Check if current symbol contains PTRS */ /* Check if current symbol contains PTRS */
if (is_ptrs_symbol(symbol, *ptrsSymbPos)) { if (is_ptrs_symbol(symbol, pusch_vars->ptrs_symbols)) {
*ptrsSymbIdx = symbol;
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* 1) Estimate common phase error per PTRS symbol */ /* 1) Estimate common phase error per PTRS symbol */
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
...@@ -703,9 +696,9 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, ...@@ -703,9 +696,9 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
rel15_ul->scid, rel15_ul->scid,
nr_tti_rx, nr_tti_rx,
symbol); symbol);
nr_ptrs_cpe_estimation(*K_ptrs, nr_ptrs_cpe_estimation(K_ptrs,
*ptrsReOffset, ptrsReOffset,
*nb_rb, nb_rb,
rel15_ul->rnti, rel15_ul->rnti,
frame_parms->ofdm_symbol_size, frame_parms->ofdm_symbol_size,
&pusch_vars->rxdataF_comp[aarx][(symbol * nb_re_pusch)], &pusch_vars->rxdataF_comp[aarx][(symbol * nb_re_pusch)],
...@@ -720,8 +713,8 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, ...@@ -720,8 +713,8 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
/* 2) Interpolate PTRS estimated value in TD */ /* 2) Interpolate PTRS estimated value in TD */
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* If L-PTRS is > 0 then we need interpolation */ /* If L-PTRS is > 0 then we need interpolation */
if (*L_ptrs > 0) { if (L_ptrs > 0) {
ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t *)phase_per_symbol, *startSymbIndex, *nbSymb); ret = nr_ptrs_process_slot(dmrsSymbPos, pusch_vars->ptrs_symbols, (int16_t *)phase_per_symbol, startSymbIndex, nbSymb);
if (ret != 0) { if (ret != 0) {
LOG_W(PHY, "[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n"); LOG_W(PHY, "[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n");
} }
...@@ -730,17 +723,17 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, ...@@ -730,17 +723,17 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* 3) Compensated DMRS based estimated signal with PTRS estimation */ /* 3) Compensated DMRS based estimated signal with PTRS estimation */
/*--------------------------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------------------------*/
for (uint8_t i = *startSymbIndex; i < symbInSlot; i++) { for (uint8_t i = startSymbIndex; i < symbInSlot; i++) {
/* DMRS Symbol has 0 phase so no need to rotate the respective symbol */ /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
/* Skip rotation if the slot processing is wrong */ /* Skip rotation if the slot processing is wrong */
if ((!is_dmrs_symbol(i, *dmrsSymbPos)) && (ret == 0)) { if ((!is_dmrs_symbol(i, dmrsSymbPos)) && (ret == 0)) {
#ifdef DEBUG_UL_PTRS #ifdef DEBUG_UL_PTRS
printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r, phase_per_symbol[i].i); printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r, phase_per_symbol[i].i);
#endif #endif
rotate_cpx_vector(&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch], rotate_cpx_vector(&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch],
&phase_per_symbol[i], &phase_per_symbol[i],
&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch], &pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch],
((*nb_rb) * NR_NB_SC_PER_RB), (nb_rb * NR_NB_SC_PER_RB),
15); 15);
} // if not DMRS Symbol } // if not DMRS Symbol
} // symbol loop } // symbol loop
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
\param Ns slot number (0..19) \param Ns slot number (0..19)
\param p \param p
\param symbol symbol within slot \param symbol symbol within slot
\param ul_id \param pusch_vars lower-phy PUSCH info
\param bwp_start_subcarrier first allocated subcarrier \param bwp_start_subcarrier first allocated subcarrier
\param pusch_pdu \param pusch_pdu
\param max_ch maximum value of estimated channel \param max_ch maximum value of estimated channel
...@@ -29,10 +29,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -29,10 +29,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
int nl, int nl,
unsigned short p, unsigned short p,
unsigned char symbol, unsigned char symbol,
int ul_id, NR_gNB_PUSCH *pusch_vars,
int beam_nb, int beam_nb,
unsigned short bwp_start_subcarrier, unsigned short bwp_start_subcarrier,
nfapi_nr_pusch_pdu_t *pusch_pdu, const nfapi_nr_pusch_pdu_t *pusch_pdu,
int *max_ch, int *max_ch,
uint32_t *nvar, uint32_t *nvar,
c16_t *pusch_dmrs_slot_mem, c16_t *pusch_dmrs_slot_mem,
...@@ -40,7 +40,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -40,7 +40,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB); void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB);
void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][9]); void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][MAX_BWP_SIZE]);
void nr_est_srs_timing_advance_offset(uint16_t ofdm_symbol_size, void nr_est_srs_timing_advance_offset(uint16_t ofdm_symbol_size,
const c16_t srs_estimated_channel_time[][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], const c16_t srs_estimated_channel_time[][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
...@@ -52,8 +52,8 @@ void nr_est_srs_timing_advance_offset(uint16_t ofdm_symbol_size, ...@@ -52,8 +52,8 @@ void nr_est_srs_timing_advance_offset(uint16_t ofdm_symbol_size,
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *rel15_ul, const nfapi_nr_pusch_pdu_t *rel15_ul,
uint8_t ulsch_id, NR_gNB_PUSCH *pusch_vars,
uint8_t nr_tti_rx, uint8_t nr_tti_rx,
unsigned char symbol, unsigned char symbol,
uint32_t nb_re_pusch); uint32_t nb_re_pusch);
......
...@@ -12,72 +12,73 @@ ...@@ -12,72 +12,73 @@
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "openair1/PHY/NR_TRANSPORT/nr_prach.h" #include "openair1/PHY/NR_TRANSPORT/nr_prach.h"
void init_prach_list(prach_list_t *l) void init_nr_prach(PHY_VARS_gNB *gNB)
{ {
pthread_mutex_init(&l->prach_list_mutex, NULL); int num_prach = 8;
memset(l->list, 0, sizeof(l->list)); gNB->prach_ru_queue = spsc_q_alloc(num_prach, sizeof(prach_item_t));
gNB->prach_l1rx_queue = spsc_q_alloc(num_prach, sizeof(prach_item_t));
} }
void free_nr_prach_entry(prach_list_t *l, prach_item_t *p) void reset_nr_prach(PHY_VARS_gNB *gNB)
{ {
pthread_mutex_lock(&l->prach_list_mutex); spsc_q_free(&gNB->prach_ru_queue);
if (p->frame == -1) spsc_q_free(&gNB->prach_l1rx_queue);
LOG_E(NR_PHY_RACH, "Freeing a not allocated prach entry\n");
*p = (prach_item_t){.frame = -1, .slot = -1, .num_slots = -1, .nb_rx = p->nb_rx, .prach_buf = (void *)(p + 1)};
pthread_mutex_unlock(&l->prach_list_mutex);
} }
prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, int nb_rx, nr_find_type_t type) void free_nr_prach_entry(prach_item_t *p)
{ {
pthread_mutex_lock(&l->prach_list_mutex); free(p->prach_buf);
AssertFatal(nb_rx, "Error! Number of antennas set to 0.\n");
prach_item_t **p = l->list;
prach_item_t **end = p + NUMBER_OF_NR_PRACH_MAX;
for (; p < end; p++)
if ((*p) && (*p)->frame == frame && ((*p)->slot + (*p)->num_slots - 1) == slot)
break;
if (p == end) {
if (type == NR_SEARCH_EXIST) {
pthread_mutex_unlock(&l->prach_list_mutex);
return NULL;
}
for (p = l->list; p < end; p++)
if (!(*p) || ((*p)->frame == -1 && (*p)->slot == -1))
break;
}
if (p == end) {
pthread_mutex_unlock(&l->prach_list_mutex);
return NULL;
}
// mark it used, it will be filled later
if (*p && (*p)->nb_rx != nb_rx) {
LOG_W(PHY, "rach procedure nb_rx ant changed from %d to %d\n", (*p)->nb_rx, nb_rx);
free(*p);
*p = NULL;
}
if (!(*p)) {
*p = calloc(1, sizeof(prach_item_t) + sizeof(c16_t) * nb_rx * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L);
(*p)->prach_buf = (void *)((*p) + 1);
}
(*p)->nb_rx = nb_rx;
(*p)->frame = frame;
pthread_mutex_unlock(&l->prach_list_mutex);
return (*p);
} }
prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) static bool drop_old_prach(const void *data, void *user)
{
const prach_item_t *p = data;
const fsn_t *now = user;
const fsn_t t = {p->frame, p->slot, now->mu};
bool drop = fsn_in_the_past(t, *now);
if (drop)
LOG_E(NR_PHY, "%4d.%2d PRACH job is in the past (%4d.%2d)\n", now->f, now->s, t.f, t.s);
return drop;
}
static bool get_current_prach(const void *data, void *user)
{
const prach_item_t *p = data;
const fsn_t *now = user;
const fsn_t t = {p->frame, p->slot, now->mu};
return fsn_equal(t, *now);
}
bool get_next_nr_prach(spsc_q_t *q, const fsn_t *now, prach_item_t *p)
{
spsc_q_drop_while(q, drop_old_prach, (void *)now);
return spsc_q_get_if(q, get_current_prach, (void *)now, p, sizeof(*p));
}
void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
{ {
prach_item_t *prach = find_nr_prach(&gNB->prach_list, SFN, Slot, gNB->frame_parms.nb_antennas_rx, NR_SEARCH_EXIST_OR_FREE);
if (!prach) {
LOG_W(PHY, "no free space for a new detected rach, discarding\n");
return NULL;
}
const int fmt = prach_pdu->prach_format; const int fmt = prach_pdu->prach_format;
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
// we set only elements as the whole structure has been cleaned when we release it const nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config;
prach->frame = SFN; const nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra];
prach->slot = Slot; prach_item_t prach = {
prach->num_slots = fmt < 4 ? get_long_prach_dur(fmt, fp->numerology_index) : 1; .frame = SFN,
.slot = Slot,
.num_slots = fmt < 4 ? get_long_prach_dur(fmt, fp->numerology_index) : 1,
.pdu = *prach_pdu,
.rootSequenceIndex = occ->prach_root_sequence_index.value,
.numrootSequenceIndex = occ->num_root_sequences.value,
.msg1_frequencystart = occ->k1.value,
.mu = cfg->prach_sub_c_spacing.value,
.prach_sequence_length = cfg->prach_sequence_length.value,
.restricted_set = cfg->restricted_set_config.value,
.numerology_index = fp->numerology_index,
.nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value,
.Xu = gNB->X_u,
.rx_prach = &gNB->rx_prach,
// TODO can be made permanently allocated?
.prach_buf = calloc_or_fail(1, sizeof(c16_t) * prach.nb_rx * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L),
};
if (gNB->common_vars.beam_id) { if (gNB->common_vars.beam_id) {
int n_symb = get_nr_prach_duration(prach_pdu->prach_format); int n_symb = get_nr_prach_duration(prach_pdu->prach_format);
AssertFatal(prach_pdu->beamforming.dig_bf_interface < NFAPI_MAX_NUM_BG_IF, AssertFatal(prach_pdu->beamforming.dig_bf_interface < NFAPI_MAX_NUM_BG_IF,
...@@ -87,7 +88,7 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n ...@@ -87,7 +88,7 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n
int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[i].beam_idx; int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[i].beam_idx;
int start_symb = prach_pdu->prach_start_symbol + i * n_symb; int start_symb = prach_pdu->prach_start_symbol + i * n_symb;
int bitmap = SL_to_bitmap(start_symb, n_symb); int bitmap = SL_to_bitmap(start_symb, n_symb);
prach->beams[i] = beam_index_allocation(gNB->enable_analog_das, prach.beams[i] = beam_index_allocation(gNB->enable_analog_das,
fapi_beam_idx, fapi_beam_idx,
&gNB->common_vars, &gNB->common_vars,
Slot, Slot,
...@@ -95,20 +96,9 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n ...@@ -95,20 +96,9 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n
bitmap); bitmap);
} }
} }
prach->pdu = *prach_pdu; bool found = spsc_q_put(&gNB->prach_ru_queue, &prach, sizeof(prach));
nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; if (!found)
nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; LOG_W(NR_PHY, "%4d.%2d PRACH occ queue is full: dropping PRACH request\n", SFN, Slot);
prach->rootSequenceIndex = occ->prach_root_sequence_index.value;
prach->numrootSequenceIndex = occ->num_root_sequences.value;
prach->msg1_frequencystart = occ->k1.value;
prach->mu = cfg->prach_sub_c_spacing.value;
prach->prach_sequence_length = cfg->prach_sequence_length.value;
prach->restricted_set = cfg->restricted_set_config.value;
prach->numerology_index = fp->numerology_index;
prach->nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value;
prach->Xu = gNB->X_u;
prach->rx_prach = &gNB->rx_prach;
return prach;
} }
static void rx_nr_prach_ru_internal(prach_item_t *p, static void rx_nr_prach_ru_internal(prach_item_t *p,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "PHY/defs_nr_common.h" #include "PHY/defs_nr_common.h"
#include "PHY/defs_gNB.h" #include "PHY/defs_gNB.h"
#include "common/utils/fsn.h"
#define NR_PBCH_PDU_BITS 24 #define NR_PBCH_PDU_BITS 24
...@@ -85,11 +86,19 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM ...@@ -85,11 +86,19 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM
- LLR computation - LLR computation
This function supports TM1, 2, 3, 5, and 6. This function supports TM1, 2, 3, 5, and 6.
@param ue Pointer to PHY variables @param ue Pointer to PHY variables
@param UE_id id of current UE @param pusch_vars ULSCH PUSCH data
@param rel15_ul FAPI message to process
@param unav_res unav_res result
@param frame Frame number @param frame Frame number
@param slot Slot number @param slot Slot number
*/ */
int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t slot, int beam_nb); int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
NR_gNB_PUSCH *pusch_vars,
const nfapi_nr_pusch_pdu_t *rel15_ul,
uint32_t *ret_unav_res,
uint32_t frame,
uint8_t slot,
int beam_nb);
/*! /*!
\brief This function implements the idft transform precoding in PUSCH \brief This function implements the idft transform precoding in PUSCH
...@@ -159,7 +168,7 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, ...@@ -159,7 +168,7 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB,
int slot, int slot,
nfapi_nr_pusch_pdu_t *ulsch_pdu); nfapi_nr_pusch_pdu_t *ulsch_pdu);
prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu);
typedef struct rx_prach_out { typedef struct rx_prach_out {
uint16_t max_preamble; uint16_t max_preamble;
...@@ -170,12 +179,6 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *, int occasion); ...@@ -170,12 +179,6 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *, int occasion);
void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset); void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset);
typedef enum {
NR_SEARCH_EXIST = 0,
NR_SEARCH_EXIST_OR_FREE
} nr_find_type_t;
prach_item_t *find_nr_prach(prach_list_t *, int frame, int slot, int nb_rx, nr_find_type_t type);
void nr_fill_pucch(PHY_VARS_gNB *gNB, void nr_fill_pucch(PHY_VARS_gNB *gNB,
int frame, int frame,
int slot, int slot,
...@@ -189,30 +192,32 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, ...@@ -189,30 +192,32 @@ void nr_fill_srs(PHY_VARS_gNB *gNB,
int nr_get_srs_signal(PHY_VARS_gNB *gNB, int nr_get_srs_signal(PHY_VARS_gNB *gNB,
c16_t **rxdataF, c16_t **rxdataF,
slot_t slot, slot_t slot,
nfapi_nr_srs_pdu_t *srs_pdu, const nfapi_nr_srs_pdu_t *srs_pdu,
nr_srs_info_t *nr_srs_info, nr_srs_info_t *nr_srs_info,
c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)],
c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]); c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]);
void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, nr_srs_info_t nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
int frame_rx, int frame_rx,
int slot_rx, int slot_rx,
uint8_t nb_antennas_rx, uint8_t nb_antennas_rx,
uint8_t N_ap, uint8_t N_ap,
uint8_t N_symb_SRS, uint8_t N_symb_SRS,
uint16_t ofdm_symbol_size, uint16_t ofdm_symbol_size,
NR_gNB_SRS_t *srs, const NR_gNB_SRS_job_t *srs,
nr_srs_info_t *nr_srs_info,
int *srs_est, int *srs_est,
int8_t *snr,
c16_t srs_estimated_channel_freq[][N_ap][ofdm_symbol_size * N_symb_SRS], c16_t srs_estimated_channel_freq[][N_ap][ofdm_symbol_size * N_symb_SRS],
c16_t srs_estimated_channel_time[][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
int16_t *snr_per_rb, int16_t *snr_per_rb,
uint16_t *timing_advance_offset, uint16_t *timing_advance_offset,
int16_t *timing_advance_offset_nsec); int16_t *timing_advance_offset_nsec);
int get_nr_prach_duration(uint8_t prach_format); int get_nr_prach_duration(uint8_t prach_format);
void free_nr_prach_entry(prach_list_t *, prach_item_t *); void init_nr_prach(PHY_VARS_gNB *gNB);
void reset_nr_prach(PHY_VARS_gNB *gNB);
void free_nr_prach_entry(prach_item_t *);
bool get_next_nr_prach(spsc_q_t *q, const fsn_t *now, prach_item_t *p);
void nr_decode_pucch1(PHY_VARS_gNB *gNB, void nr_decode_pucch1(PHY_VARS_gNB *gNB,
c16_t **rxdataF, c16_t **rxdataF,
...@@ -227,14 +232,14 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -227,14 +232,14 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
int frame, int frame,
int slot, int slot,
nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu,
nfapi_nr_pucch_pdu_t* pucch_pdu); const nfapi_nr_pucch_pdu_t* pucch_pdu);
void nr_decode_pucch0(PHY_VARS_gNB *gNB, void nr_decode_pucch0(PHY_VARS_gNB *gNB,
c16_t **rxdataF, c16_t **rxdataF,
int frame, int frame,
int slot, int slot,
nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu, nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu,
nfapi_nr_pucch_pdu_t* pucch_pdu); const nfapi_nr_pucch_pdu_t* pucch_pdu);
#endif /*__NR_TRANSPORT__H__*/ #endif /*__NR_TRANSPORT__H__*/
...@@ -11,30 +11,6 @@ ...@@ -11,30 +11,6 @@
#include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "SCHED_NR/sched_nr.h" #include "SCHED_NR/sched_nr.h"
static NR_gNB_ULSCH_t *find_nr_ulsch(PHY_VARS_gNB *gNB, uint16_t rnti, int pid)
{
int16_t first_free_index = -1;
AssertFatal(gNB != NULL, "gNB is null\n");
NR_gNB_ULSCH_t *ulsch = NULL;
for (int i = 0; i < gNB->max_nb_pusch; i++) {
ulsch = &gNB->ulsch[i];
AssertFatal(ulsch, "gNB->ulsch[%d] is null\n", i);
if (!ulsch->active) {
if (first_free_index == -1)
first_free_index = i;
} else {
// if there is already an active ULSCH for this RNTI and HARQ_PID
if ((ulsch->harq_pid == pid) && (ulsch->rnti == rnti))
return ulsch;
}
}
if (first_free_index != -1)
ulsch = &gNB->ulsch[first_free_index];
return ulsch;
}
static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_pusch_pdu_t *pusch_pdu) static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_pusch_pdu_t *pusch_pdu)
{ {
LOG_D(PHY, LOG_D(PHY,
...@@ -117,49 +93,28 @@ static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_pusch_pdu ...@@ -117,49 +93,28 @@ static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_pusch_pdu
void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t *ulsch_pdu) void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t *ulsch_pdu)
{ {
dump_pusch_pdu(gNB->Mod_id, frame, slot, ulsch_pdu); dump_pusch_pdu(gNB->Mod_id, frame, slot, ulsch_pdu);
int harq_pid = ulsch_pdu->pusch_data.harq_process_id; LOG_D(NR_PHY,
NR_gNB_ULSCH_t *ulsch = find_nr_ulsch(gNB, ulsch_pdu->rnti, harq_pid); "%4d.%2d Programming ULSCH RNTI %04x HARQ PID %d new data indicator %d\n",
if (ulsch == NULL) { frame,
LOG_E(NR_PHY, "No ulsch_id found for rnti %04x\n", ulsch_pdu->rnti); slot,
return; ulsch_pdu->rnti,
} ulsch_pdu->pusch_data.harq_process_id,
ulsch_pdu->pusch_data.new_data_indicator);
ulsch->rnti = ulsch_pdu->rnti; NR_gNB_PUSCH_job_t pusch = {.frame = frame, .slot = slot, .pusch_pdu = *ulsch_pdu};
ulsch->harq_pid = harq_pid;
ulsch->handled = 0;
ulsch->active = true;
ulsch->beam_nb = 0;
if (gNB->common_vars.beam_id) { if (gNB->common_vars.beam_id) {
int fapi_beam_idx = ulsch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; int fapi_beam_idx = ulsch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
int bitmap = SL_to_bitmap(ulsch_pdu->start_symbol_index, ulsch_pdu->nr_of_symbols); int bitmap = SL_to_bitmap(ulsch_pdu->start_symbol_index, ulsch_pdu->nr_of_symbols);
ulsch->beam_nb = beam_index_allocation(gNB->enable_analog_das, pusch.beam_nb = beam_index_allocation(gNB->enable_analog_das,
fapi_beam_idx, fapi_beam_idx,
&gNB->common_vars, &gNB->common_vars,
slot, slot,
gNB->frame_parms.symbols_per_slot, gNB->frame_parms.symbols_per_slot,
bitmap); bitmap);
} }
ulsch->frame = frame; bool done = spsc_q_put(&gNB->pusch_queue, &pusch, sizeof(pusch));
ulsch->slot = slot; if (!done)
LOG_W(NR_PHY, "PUSCH queue is full: dropping PUSCH UE %04x\n", ulsch_pdu->rnti);
NR_UL_gNB_HARQ_t *harq = ulsch->harq_process;
if (ulsch_pdu->pusch_data.new_data_indicator)
harq->harq_to_be_cleared = true;
LOG_D(NR_PHY,
"NEW ULSCH %d.%d RNTI %x HARQ PID %d new data indicator %d\n",
frame,
slot,
ulsch_pdu->rnti,
harq_pid,
ulsch_pdu->pusch_data.new_data_indicator);
if (ulsch_pdu->pusch_data.new_data_indicator)
harq->round = 0;
else
harq->round++;
memcpy(&ulsch->harq_process->ulsch_pdu, ulsch_pdu, sizeof(ulsch->harq_process->ulsch_pdu));
LOG_D(PHY, "Initializing nFAPI for ULSCH, harq_pid %d, layers %d\n", harq_pid, ulsch_pdu->nrOfLayers);
} }
void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame) void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame)
......
...@@ -23,7 +23,6 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL); ...@@ -23,7 +23,6 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL);
@param frame_parms, Pointer to frame descriptor structure @param frame_parms, Pointer to frame descriptor structure
@param frame, current received frame @param frame, current received frame
@param nr_tti_rx, current received TTI @param nr_tti_rx, current received TTI
@param G
@param ULSCH_ids, array of ULSCH ids @param ULSCH_ids, array of ULSCH ids
@param nb_pusch, number of uplink shared channels @param nb_pusch, number of uplink shared channels
*/ */
...@@ -32,8 +31,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, ...@@ -32,8 +31,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
uint32_t frame, uint32_t frame,
uint8_t nr_tti_rx, uint8_t nr_tti_rx,
uint32_t *G, int *ULSCH_ids,
uint8_t *ULSCH_ids,
int nb_pusch); int nb_pusch);
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 /*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
......
...@@ -93,8 +93,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, ...@@ -93,8 +93,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
uint32_t frame, uint32_t frame,
uint8_t nr_tti_rx, uint8_t nr_tti_rx,
uint32_t *G, int *ULSCH_ids,
uint8_t *ULSCH_ids,
int nb_pusch) int nb_pusch)
{ {
nrLDPC_TB_decoding_parameters_t TBs[nb_pusch]; nrLDPC_TB_decoding_parameters_t TBs[nb_pusch];
...@@ -112,17 +111,29 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, ...@@ -112,17 +111,29 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id];
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu; const nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu;
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pusch_id]; nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pusch_id];
TB_parameters->G = G[pusch_id];
if (!harq_process) { if (!harq_process) {
LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n"); LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n");
return -1; return -1;
} }
uint8_t number_dmrs_symbols = count_bits64_with_mask(pusch_pdu->ul_dmrs_symb_pos, pusch_pdu->start_symbol_index, pusch_pdu->nr_of_symbols);
int factor = pusch_pdu->dmrs_config_type == pusch_dmrs_type1 ? 6 : 4;
int nb_re_dmrs = factor * pusch_pdu->num_dmrs_cdm_grps_no_data;
uint32_t G = nr_get_G(pusch_pdu->rb_size,
pusch_pdu->nr_of_symbols,
nb_re_dmrs,
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
ulsch->unav_res,
pusch_pdu->qam_mod_order,
pusch_pdu->nrOfLayers);
DevAssert(G > 0);
TB_parameters->G = G;
// The harq_pid is not unique among the active HARQ processes in the instance so we use ULSCH_id instead // The harq_pid is not unique among the active HARQ processes in the instance so we use ULSCH_id instead
TB_parameters->harq_unique_pid = ULSCH_id; TB_parameters->harq_unique_pid = ULSCH_id;
...@@ -134,10 +145,9 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, ...@@ -134,10 +145,9 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
// ------------------------------------------------------------------ // ------------------------------------------------------------------
TB_parameters->processedSegments = &harq_process->processedSegments; TB_parameters->processedSegments = &harq_process->processedSegments;
harq_process->TBS = pusch_pdu->pusch_data.tb_size;
TB_parameters->BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; TB_parameters->BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph;
TB_parameters->A = (harq_process->TBS) << 3; TB_parameters->A = pusch_pdu->pusch_data.tb_size << 3;
NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti);
if (stats) { if (stats) {
stats->frame = frame; stats->frame = frame;
...@@ -149,7 +159,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, ...@@ -149,7 +159,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
if (!harq_process->harq_to_be_cleared) { if (!harq_process->harq_to_be_cleared) {
stats->ulsch_stats.current_Qm = TB_parameters->Qm; stats->ulsch_stats.current_Qm = TB_parameters->Qm;
stats->ulsch_stats.current_RI = TB_parameters->nb_layers; stats->ulsch_stats.current_RI = TB_parameters->nb_layers;
stats->ulsch_stats.total_bytes_tx += harq_process->TBS; stats->ulsch_stats.total_bytes_tx += pusch_pdu->pusch_data.tb_size;
} }
} }
......
...@@ -80,7 +80,7 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF, ...@@ -80,7 +80,7 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF,
int rxoffset, int rxoffset,
int choffset, int choffset,
int is_dmrs_symbol, int is_dmrs_symbol,
nfapi_nr_pusch_pdu_t *pusch_pdu, const nfapi_nr_pusch_pdu_t *pusch_pdu,
NR_DL_FRAME_PARMS *frame_parms) NR_DL_FRAME_PARMS *frame_parms)
{ {
uint8_t delta = 0; uint8_t delta = 0;
...@@ -160,7 +160,7 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF, ...@@ -160,7 +160,7 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF,
} }
} }
static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul,int symbol) static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, const nfapi_nr_pusch_pdu_t *rel15_ul, int symbol)
{ {
uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
if (dmrs_symbol_flag == 1) { if (dmrs_symbol_flag == 1) {
...@@ -186,7 +186,7 @@ static void nr_ulsch_channel_compensation(uint32_t buffer_length, ...@@ -186,7 +186,7 @@ static void nr_ulsch_channel_compensation(uint32_t buffer_length,
c16_t **rxComp, c16_t **rxComp,
int nb_layers, int nb_layers,
c16_t rho[][nb_layers][buffer_length], c16_t rho[][nb_layers][buffer_length],
nfapi_nr_pusch_pdu_t *rel15_ul, const nfapi_nr_pusch_pdu_t *rel15_ul,
uint32_t symbol, uint32_t symbol,
uint32_t output_shift) uint32_t output_shift)
{ {
...@@ -857,11 +857,10 @@ static uint8_t nr_ulsch_mmse_2layers(c16_t **rxdataF_comp, ...@@ -857,11 +857,10 @@ static uint8_t nr_ulsch_mmse_2layers(c16_t **rxdataF_comp,
} }
static void inner_rx(PHY_VARS_gNB *gNB, static void inner_rx(PHY_VARS_gNB *gNB,
int ulsch_id,
int slot, int slot,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
NR_gNB_PUSCH *pusch_vars, NR_gNB_PUSCH *pusch_vars,
nfapi_nr_pusch_pdu_t *rel15_ul, const nfapi_nr_pusch_pdu_t *rel15_ul,
c16_t **rxF, c16_t **rxF,
int16_t **llr, int16_t **llr,
int soffset, int soffset,
...@@ -952,7 +951,7 @@ static void inner_rx(PHY_VARS_gNB *gNB, ...@@ -952,7 +951,7 @@ static void inner_rx(PHY_VARS_gNB *gNB,
nr_pusch_ptrs_processing(gNB, nr_pusch_ptrs_processing(gNB,
frame_parms, frame_parms,
rel15_ul, rel15_ul,
ulsch_id, pusch_vars,
slot, slot,
symbol, symbol,
buffer_length); buffer_length);
...@@ -1003,8 +1002,8 @@ static void inner_rx(PHY_VARS_gNB *gNB, ...@@ -1003,8 +1002,8 @@ static void inner_rx(PHY_VARS_gNB *gNB,
typedef struct puschSymbolProc_s { typedef struct puschSymbolProc_s {
PHY_VARS_gNB *gNB; PHY_VARS_gNB *gNB;
NR_DL_FRAME_PARMS *frame_parms; NR_DL_FRAME_PARMS *frame_parms;
nfapi_nr_pusch_pdu_t *rel15_ul; const nfapi_nr_pusch_pdu_t *rel15_ul;
int ulsch_id; NR_gNB_PUSCH *pusch_vars;
int slot; int slot;
int startSymbol; int startSymbol;
int numSymbols; int numSymbols;
...@@ -1023,12 +1022,11 @@ static void nr_pusch_symbol_processing(void *arg) ...@@ -1023,12 +1022,11 @@ static void nr_pusch_symbol_processing(void *arg)
PHY_VARS_gNB *gNB = rdata->gNB; PHY_VARS_gNB *gNB = rdata->gNB;
NR_DL_FRAME_PARMS *frame_parms = rdata->frame_parms; NR_DL_FRAME_PARMS *frame_parms = rdata->frame_parms;
nfapi_nr_pusch_pdu_t *rel15_ul = rdata->rel15_ul; const nfapi_nr_pusch_pdu_t *rel15_ul = rdata->rel15_ul;
int ulsch_id = rdata->ulsch_id;
int slot = rdata->slot; int slot = rdata->slot;
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; NR_gNB_PUSCH *pusch_vars = rdata->pusch_vars;
for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol + rdata->numSymbols; symbol++) { for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol + rdata->numSymbols; symbol++) {
if (gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol] == 0) if (pusch_vars->ul_valid_re_per_slot[symbol] == 0)
continue; continue;
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
int buffer_length = ceil_mod(pusch_vars->ul_valid_re_per_slot[symbol] * NR_NB_SC_PER_RB, 16); int buffer_length = ceil_mod(pusch_vars->ul_valid_re_per_slot[symbol] * NR_NB_SC_PER_RB, 16);
...@@ -1038,7 +1036,6 @@ static void nr_pusch_symbol_processing(void *arg) ...@@ -1038,7 +1036,6 @@ static void nr_pusch_symbol_processing(void *arg)
llrss[l] = llrs[l]; llrss[l] = llrs[l];
inner_rx(gNB, inner_rx(gNB,
ulsch_id,
slot, slot,
frame_parms, frame_parms,
pusch_vars, pusch_vars,
...@@ -1047,12 +1044,12 @@ static void nr_pusch_symbol_processing(void *arg) ...@@ -1047,12 +1044,12 @@ static void nr_pusch_symbol_processing(void *arg)
llrss, llrss,
soffset, soffset,
symbol, symbol,
gNB->pusch_vars[ulsch_id].log2_maxh, pusch_vars->log2_maxh,
rdata->nvar, rdata->nvar,
rdata->rxFext_slot_mem, rdata->rxFext_slot_mem,
rdata->pusch_ch_est_dmrs_interpl_slot_mem); rdata->pusch_ch_est_dmrs_interpl_slot_mem);
int nb_re_pusch = gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol]; int nb_re_pusch = pusch_vars->ul_valid_re_per_slot[symbol];
// layer de-mapping // layer de-mapping
int16_t *llr_ptr = llrs[0]; int16_t *llr_ptr = llrs[0];
if (rel15_ul->nrOfLayers != 1) { if (rel15_ul->nrOfLayers != 1) {
...@@ -1098,12 +1095,16 @@ static uint32_t average_u32(const uint32_t *x, uint16_t size) ...@@ -1098,12 +1095,16 @@ static uint32_t average_u32(const uint32_t *x, uint16_t size)
return (uint32_t)(sum_x / size); return (uint32_t)(sum_x / size);
} }
int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t slot, int beam_nb) int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
NR_gNB_PUSCH *pusch_vars,
const nfapi_nr_pusch_pdu_t *rel15_ul,
uint32_t *ret_unav_res,
uint32_t frame,
uint8_t slot,
int beam_nb)
{ {
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
nfapi_nr_pusch_pdu_t *rel15_ul = &gNB->ulsch[ulsch_id].harq_process->ulsch_pdu;
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
uint32_t bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start) * NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size; uint32_t bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start) * NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size;
LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset); LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset);
LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,rel15_ul->ul_dmrs_symb_pos); LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,rel15_ul->ul_dmrs_symb_pos);
...@@ -1159,7 +1160,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t ...@@ -1159,7 +1160,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t
nl, nl,
get_dmrs_port(nl, rel15_ul->dmrs_ports), get_dmrs_port(nl, rel15_ul->dmrs_ports),
symbol, symbol,
ulsch_id, pusch_vars,
beam_nb, beam_nb,
bwp_start_subcarrier, bwp_start_subcarrier,
rel15_ul, rel15_ul,
...@@ -1261,7 +1262,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t ...@@ -1261,7 +1262,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t
unav_res, unav_res,
rel15_ul->qam_mod_order, rel15_ul->qam_mod_order,
rel15_ul->nrOfLayers); rel15_ul->nrOfLayers);
gNB->ulsch[ulsch_id].unav_res = unav_res; *ret_unav_res = unav_res;
// initialize scrambling sequence // // initialize scrambling sequence //
int16_t scramblingSequence[G + 96] __attribute__((aligned(32))); int16_t scramblingSequence[G + 96] __attribute__((aligned(32)));
...@@ -1378,7 +1379,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t ...@@ -1378,7 +1379,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t
rdata->startSymbol = symbol; rdata->startSymbol = symbol;
// Last task processes remainder symbols // Last task processes remainder symbols
rdata->numSymbols = task_index == loop_iter - 1 ? rel15_ul->nr_of_symbols - (loop_iter - 1) * numSymbols : numSymbols; rdata->numSymbols = task_index == loop_iter - 1 ? rel15_ul->nr_of_symbols - (loop_iter - 1) * numSymbols : numSymbols;
rdata->ulsch_id = ulsch_id; rdata->pusch_vars = pusch_vars;
rdata->llr = pusch_vars->llr; rdata->llr = pusch_vars->llr;
rdata->scramblingSequence = scramblingSequence; rdata->scramblingSequence = scramblingSequence;
rdata->nvar = nvar; rdata->nvar = nvar;
......
...@@ -33,40 +33,32 @@ ...@@ -33,40 +33,32 @@
//#define DEBUG_NR_PUCCH_RX 1 //#define DEBUG_NR_PUCCH_RX 1
void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu)
{ {
for (int i = 0; i < gNB->max_nb_pucch; i++) { LOG_D(PHY,
NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; "%4d.%2d UE %04x Programming PUCCH format %d, nb_harq %d, nb_sr %d, nb_csi %d\n",
if (pucch->active == false) { frame,
pucch->frame = frame; slot,
pucch->slot = slot; pucch_pdu->rnti,
pucch->active = true; pucch_pdu->format_type,
pucch->beam_nb = 0; pucch_pdu->bit_len_harq,
if (gNB->common_vars.beam_id) { pucch_pdu->sr_flag,
int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; pucch_pdu->bit_len_csi_part1);
int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols); NR_gNB_PUCCH_job_t pucch = {.frame = frame, .slot = slot, .pucch_pdu = *pucch_pdu};
pucch->beam_nb = beam_index_allocation(gNB->enable_analog_das, if (gNB->common_vars.beam_id) {
fapi_beam_idx, int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
&gNB->common_vars, int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols);
slot, pucch.beam_nb = beam_index_allocation(gNB->enable_analog_das,
gNB->frame_parms.symbols_per_slot, fapi_beam_idx,
bitmap); &gNB->common_vars,
} slot,
memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t)); gNB->frame_parms.symbols_per_slot,
LOG_D(PHY, bitmap);
"Programming PUCCH[%d] for %d.%d, format %d, nb_harq %d, nb_sr %d, nb_csi %d\n",
i,
pucch->frame,
pucch->slot,
pucch->pucch_pdu.format_type,
pucch->pucch_pdu.bit_len_harq,
pucch->pucch_pdu.sr_flag,
pucch->pucch_pdu.bit_len_csi_part1);
return;
}
} }
LOG_W(PHY, "PUCCH list is full\n"); bool found = spsc_q_put(&gNB->pucch_queue, &pucch, sizeof(pucch));
if (!found)
LOG_W(NR_PHY, "PUCCH list is full: dropping PUCCH UE %04x\n", pucch_pdu->rnti);
} }
int get_pucch0_cs_lut_index(PHY_VARS_gNB *gNB, nfapi_nr_pucch_pdu_t *pucch_pdu) int get_pucch0_cs_lut_index(PHY_VARS_gNB *gNB, const nfapi_nr_pucch_pdu_t *pucch_pdu)
{ {
int i = 0; int i = 0;
...@@ -129,7 +121,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -129,7 +121,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
int frame, int frame,
int slot, int slot,
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu, nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu,
nfapi_nr_pucch_pdu_t *pucch_pdu) const nfapi_nr_pucch_pdu_t *pucch_pdu)
{ {
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
...@@ -1132,7 +1124,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1132,7 +1124,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
int frame, int frame,
int slot, int slot,
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu, nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu,
nfapi_nr_pucch_pdu_t *pucch_pdu) const nfapi_nr_pucch_pdu_t *pucch_pdu)
{ {
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
// pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); // pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
......
...@@ -29,37 +29,27 @@ ...@@ -29,37 +29,27 @@
void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu_t *srs_pdu) void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu_t *srs_pdu)
{ {
bool found = false; NR_gNB_SRS_job_t srs = {.frame = frame, .slot = slot, .srs_pdu = *srs_pdu};
for (int i = 0; i < gNB->max_nb_srs; i++) { if (gNB->common_vars.beam_id) {
NR_gNB_SRS_t *srs = &gNB->srs[i]; const uint8_t l0 = gNB->frame_parms.symbols_per_slot - 1 - srs_pdu->time_start_position;
if (srs->active == false) { int bitmap = SL_to_bitmap(l0, 1 << srs_pdu->num_symbols);
found = true; int fapi_beam_idx = srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
srs->frame = frame; srs.beam_nb = beam_index_allocation(gNB->enable_analog_das,
srs->slot = slot; fapi_beam_idx,
srs->active = true; &gNB->common_vars,
srs->beam_nb = 0; slot,
if (gNB->common_vars.beam_id) { gNB->frame_parms.symbols_per_slot,
const uint8_t l0 = gNB->frame_parms.symbols_per_slot - 1 - srs_pdu->time_start_position; bitmap);
int bitmap = SL_to_bitmap(l0, 1 << srs_pdu->num_symbols);
int fapi_beam_idx = srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
srs->beam_nb = beam_index_allocation(gNB->enable_analog_das,
fapi_beam_idx,
&gNB->common_vars,
slot,
gNB->frame_parms.symbols_per_slot,
bitmap);
}
memcpy((void *)&srs->srs_pdu, (void *)srs_pdu, sizeof(nfapi_nr_srs_pdu_t));
break;
}
} }
AssertFatal(found, "SRS list is full\n"); bool found = spsc_q_put(&gNB->srs_queue, &srs, sizeof(srs));
if (!found)
LOG_W(NR_PHY, "SRS list is full: dropping SRS UE %04x\n", srs_pdu->rnti);
} }
int nr_get_srs_signal(PHY_VARS_gNB *gNB, int nr_get_srs_signal(PHY_VARS_gNB *gNB,
c16_t **rxdataF, c16_t **rxdataF,
slot_t slot, slot_t slot,
nfapi_nr_srs_pdu_t *srs_pdu, const nfapi_nr_srs_pdu_t *srs_pdu,
nr_srs_info_t *nr_srs_info, nr_srs_info_t *nr_srs_info,
c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)],
c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)])
......
...@@ -148,11 +148,11 @@ void nr_tx_rotation_and_ofdm_mod(const uint8_t slot, ...@@ -148,11 +148,11 @@ void nr_tx_rotation_and_ofdm_mod(const uint8_t slot,
bool was_symbol_used[NR_SYMBOLS_PER_SLOT], bool was_symbol_used[NR_SYMBOLS_PER_SLOT],
bool no_phase_pre_comp); bool no_phase_pre_comp);
bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, void ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
c16_t **txdataF, c16_t **txdataF,
nr_phy_data_tx_t *phy_data, const fapi_nr_ul_config_srs_pdu *srs_config_pdu,
bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); bool was_symbol_used[NR_SYMBOLS_PER_SLOT]);
void clean_UE_harq(PHY_VARS_NR_UE *UE); void clean_UE_harq(PHY_VARS_NR_UE *UE);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "nfapi_nr_interface_scf.h" #include "nfapi_nr_interface_scf.h"
#include "common/utils/threadPool/task_ans.h" #include "common/utils/threadPool/task_ans.h"
#include "openair1/PHY/defs_RU.h" #include "openair1/PHY/defs_RU.h"
#include "common/utils/ds/spsc_q.h"
#define MAX_NUM_RU_PER_gNB 8 #define MAX_NUM_RU_PER_gNB 8
#define MAX_PUCCH0_NID 8 #define MAX_PUCCH0_NID 8
...@@ -45,14 +46,6 @@ typedef struct { ...@@ -45,14 +46,6 @@ typedef struct {
c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L]; c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L];
} prach_item_t; } prach_item_t;
typedef struct {
/// prach commands
prach_item_t *list[NUMBER_OF_NR_PRACH_MAX];
/// mutex for prach_list access
pthread_mutex_t prach_list_mutex;
} prach_list_t;
void init_prach_list(prach_list_t *);
typedef struct { typedef struct {
int nb_id; int nb_id;
int Nid[MAX_PUCCH0_NID]; int Nid[MAX_PUCCH0_NID];
...@@ -127,7 +120,7 @@ typedef struct { ...@@ -127,7 +120,7 @@ typedef struct {
typedef struct { typedef struct {
/// Nfapi ULSCH PDU /// Nfapi ULSCH PDU
nfapi_nr_pusch_pdu_t ulsch_pdu; nfapi_nr_pusch_pdu_t ulsch_pdu; // !!
/// Index of current HARQ round for this DLSCH /// Index of current HARQ round for this DLSCH
uint8_t round; uint8_t round;
bool new_rx; bool new_rx;
...@@ -135,8 +128,6 @@ typedef struct { ...@@ -135,8 +128,6 @@ typedef struct {
/// flag used to clear d properly (together with d_to_be_cleared below) /// flag used to clear d properly (together with d_to_be_cleared below)
/// set to true in nr_fill_ulsch() when new_data_indicator is received /// set to true in nr_fill_ulsch() when new_data_indicator is received
bool harq_to_be_cleared; bool harq_to_be_cleared;
/// Transport block size (This is A from 38.212 V15.4.0 section 5.1)
uint32_t TBS;
/// Pointer to the payload (38.212 V15.4.0 section 5.1) /// Pointer to the payload (38.212 V15.4.0 section 5.1)
uint8_t *b; uint8_t *b;
/// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2) /// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2)
...@@ -184,13 +175,20 @@ typedef struct { ...@@ -184,13 +175,20 @@ typedef struct {
int8_t last_iteration_cnt; int8_t last_iteration_cnt;
/// Status Flag indicating for this ULSCH /// Status Flag indicating for this ULSCH
bool active; bool active;
/// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around
uint8_t handled;
delay_t delay;
} NR_gNB_ULSCH_t; } NR_gNB_ULSCH_t;
typedef struct { typedef struct {
bool active; // identifier for concurrent beams
int beam_nb;
/// Frame where current PUSCH pdu was sent
uint32_t frame;
/// Slot where current PUSCH pdu was sent
uint32_t slot;
/// ULSCH PDU
nfapi_nr_pusch_pdu_t pusch_pdu;
} NR_gNB_PUSCH_job_t;
typedef struct {
// identifier for concurrent beams // identifier for concurrent beams
int beam_nb; int beam_nb;
/// Frame where current PUCCH pdu was sent /// Frame where current PUCCH pdu was sent
...@@ -199,21 +197,18 @@ typedef struct { ...@@ -199,21 +197,18 @@ typedef struct {
uint32_t slot; uint32_t slot;
/// ULSCH PDU /// ULSCH PDU
nfapi_nr_pucch_pdu_t pucch_pdu; nfapi_nr_pucch_pdu_t pucch_pdu;
} NR_gNB_PUCCH_t; } NR_gNB_PUCCH_job_t;
typedef struct { typedef struct {
bool active;
// identifier for concurrent beams // identifier for concurrent beams
int beam_nb; int beam_nb;
/// Frame where current SRS pdu was received /// Frame where current SRS pdu was received
uint32_t frame; uint32_t frame;
/// Slot where current SRS pdu was received /// Slot where current SRS pdu was received
uint32_t slot; uint32_t slot;
/// Measured SNR
int8_t snr;
/// ULSCH PDU /// ULSCH PDU
nfapi_nr_srs_pdu_t srs_pdu; nfapi_nr_srs_pdu_t srs_pdu;
} NR_gNB_SRS_t; } NR_gNB_SRS_job_t;
typedef struct { typedef struct {
/// \brief Pointers (dynamic) to the received data in the frequency domain. /// \brief Pointers (dynamic) to the received data in the frequency domain.
...@@ -275,6 +270,8 @@ typedef struct { ...@@ -275,6 +270,8 @@ typedef struct {
int llr_offset[14]; int llr_offset[14];
/// flag to indicate DTX on reception /// flag to indicate DTX on reception
int DTX; int DTX;
/// delay estimation
delay_t delay;
} NR_gNB_PUSCH; } NR_gNB_PUSCH;
/// Context data structure for RX/TX portion of slot processing /// Context data structure for RX/TX portion of slot processing
...@@ -369,26 +366,23 @@ typedef struct PHY_VARS_gNB_s { ...@@ -369,26 +366,23 @@ typedef struct PHY_VARS_gNB_s {
nfapi_nr_ul_tti_request_t UL_tti_req; nfapi_nr_ul_tti_request_t UL_tti_req;
int max_nb_pucch;
int max_nb_srs;
int max_nb_pdsch; int max_nb_pdsch;
int max_nb_pusch; int max_nb_pusch;
NR_gNB_COMMON common_vars; NR_gNB_COMMON common_vars;
prach_list_t prach_list; spsc_q_t prach_ru_queue;
spsc_q_t prach_l1rx_queue;
// TODO: can we remove c from NR_gNB_DLSCH_t and put it on the stack? // TODO: can we remove c from NR_gNB_DLSCH_t and put it on the stack?
NR_gNB_DLSCH_t *dlsch; NR_gNB_DLSCH_t *dlsch;
NR_gNB_PRS prs_vars; NR_gNB_PRS prs_vars;
NR_gNB_PUSCH *pusch_vars; NR_gNB_PUSCH *pusch_vars;
NR_gNB_PUCCH_t *pucch; spsc_q_t pucch_queue;
NR_gNB_SRS_t *srs; spsc_q_t pusch_queue;
spsc_q_t srs_queue;
NR_gNB_ULSCH_t *ulsch; NR_gNB_ULSCH_t *ulsch;
NR_gNB_PHY_STATS_t phy_stats[MAX_MOBILES_PER_GNB]; NR_gNB_PHY_STATS_t phy_stats[MAX_MOBILES_PER_GNB];
t_nrPolar_params **polarParams; t_nrPolar_params **polarParams;
/// SRS variables
nr_srs_info_t **nr_srs_info;
// reference amplitude for TX // reference amplitude for TX
int16_t TX_AMP; int16_t TX_AMP;
......
...@@ -402,9 +402,6 @@ typedef struct PHY_VARS_NR_UE_s { ...@@ -402,9 +402,6 @@ typedef struct PHY_VARS_NR_UE_s {
nrLDPC_coding_interface_t nrLDPC_coding_interface; nrLDPC_coding_interface_t nrLDPC_coding_interface;
uint8_t max_ldpc_iterations; uint8_t max_ldpc_iterations;
/// SRS variables
nr_srs_info_t *nr_srs_info;
/// CSI variables /// CSI variables
nr_csi_info_t *nr_csi_info; nr_csi_info_t *nr_csi_info;
......
...@@ -77,8 +77,6 @@ typedef enum{ ...@@ -77,8 +77,6 @@ typedef enum{
typedef struct { typedef struct {
uint8_t k_0_p[MAX_NUM_NR_SRS_AP][MAX_NUM_NR_SRS_SYMBOLS]; uint8_t k_0_p[MAX_NUM_NR_SRS_AP][MAX_NUM_NR_SRS_SYMBOLS];
uint8_t srs_generated_signal_bits; uint8_t srs_generated_signal_bits;
c16_t **srs_generated_signal;
bool is_signal_generated;
int B_SRS; int B_SRS;
int C_SRS; int C_SRS;
int b_hop; int b_hop;
......
...@@ -203,7 +203,7 @@ bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms, ...@@ -203,7 +203,7 @@ bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms,
nr_srs_info->srs_generated_signal_bits = log2_approx(amp); nr_srs_info->srs_generated_signal_bits = log2_approx(amp);
} }
uint64_t subcarrier_offset = frame_parms->first_carrier_offset + bwp_start * NR_NB_SC_PER_RB; uint64_t subcarrier_offset = frame_parms->first_carrier_offset + bwp_start * NR_NB_SC_PER_RB;
double sqrt_N_ap = sqrt(N_ap); float amp_sqrt_N_ap = amp / sqrt(N_ap);
int n_b[nr_srs_info->B_SRS + 1]; int n_b[nr_srs_info->B_SRS + 1];
// Find index of table which is for this SRS length // Find index of table which is for this SRS length
...@@ -298,14 +298,16 @@ bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms, ...@@ -298,14 +298,16 @@ bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms,
uint16_t l_line_offset = l_line * frame_parms->ofdm_symbol_size; uint16_t l_line_offset = l_line * frame_parms->ofdm_symbol_size;
// For each port, and for each OFDM symbol, here it is computed and mapped an SRS sequence with M_sc_b_SRS symbols // For each port, and for each OFDM symbol, here it is computed and mapped an SRS sequence with M_sc_b_SRS symbols
for (int k = 0; k < M_sc_b_SRS; k++) { for (int k = 0; k < M_sc_b_SRS; k++) {
cd_t shift = {cos(alpha_i * k), sin(alpha_i * k)}; cf_t shift = {cosf(alpha_i * k), sinf(alpha_i * k)};
const c16_t tmp = rv_ul_ref_sig[u][v][M_sc_b_SRS_index][k]; const c16_t r_overbar = rv_ul_ref_sig[u][v][M_sc_b_SRS_index][k];
cd_t r_overbar = {tmp.r, tmp.i};
// cos(x+y) = cos(x)cos(y) - sin(x)sin(y) // cos(x+y) = cos(x)cos(y) - sin(x)sin(y)
cd_t r = cdMul(shift, r_overbar); cf_t r = (cf_t) {
c16_t r_amp = {(((int32_t)round((double)amp * r.r / sqrt_N_ap)) >> 15), .r = shift.r * r_overbar.r - shift.i * r_overbar.i,
(((int32_t)round((double)amp * r.i / sqrt_N_ap)) >> 15)}; .i = shift.r * r_overbar.i + shift.i * r_overbar.r,
};
c16_t r_amp = {(((int32_t)(amp_sqrt_N_ap * r.r)) >> 15),
(((int32_t)(amp_sqrt_N_ap * r.i)) >> 15)};
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
int subcarrier_log = subcarrier-subcarrier_offset; int subcarrier_log = subcarrier-subcarrier_offset;
......
...@@ -16,18 +16,6 @@ int slot_ahead = 6; ...@@ -16,18 +16,6 @@ int slot_ahead = 6;
//uint8_t nfapi_mode=0; //uint8_t nfapi_mode=0;
NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;} NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;}
void nr_fill_ulsch(PHY_VARS_gNB *gNB,
int frame,
int slot,
nfapi_nr_pusch_pdu_t *ulsch_pdu){}
void nr_fill_pucch(PHY_VARS_gNB *gNB,
int frame,
int slot,
nfapi_nr_pucch_pdu_t *pucch_pdu){}
void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
{
}
void nr_phy_config_request(NR_PHY_Config_t *gNB){} void nr_phy_config_request(NR_PHY_Config_t *gNB){}
void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){}
...@@ -70,59 +58,6 @@ void *pnf_nr_p7_thread_start(void *ptr) ...@@ -70,59 +58,6 @@ void *pnf_nr_p7_thread_start(void *ptr)
{ {
return 0; return 0;
} }
bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *msg)
{
return false;
}
bool wls_vnf_nr_send_p5_message(vnf_t *vnf,uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len)
{
return false;
}
void *wls_fapi_vnf_nr_start_thread(void *ptr)
{
return NULL;
}
bool wls_pnf_nr_send_p7_message(pnf_p7_t* pnf_p7,nfapi_nr_p7_message_header_t *msg, uint32_t msg_len)
{
return false;
}
bool wls_pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len)
{
return false;
}
void *wls_fapi_pnf_nr_start_thread(void *ptr)
{
return NULL;
}
void wls_pnf_set_p7_config(void *p7_config)
{
}
void wls_fapi_nr_pnf_stop()
{
}
void wls_pnf_close(pthread_t p5_thread)
{
}
void wls_vnf_send_stop_request()
{
}
void wls_vnf_stop()
{
}
void socket_nfapi_nr_pnf_stop() void socket_nfapi_nr_pnf_stop()
{ {
} }
......
...@@ -21,20 +21,14 @@ int get_nr_prach_duration(uint8_t prach_format) ...@@ -21,20 +21,14 @@ int get_nr_prach_duration(uint8_t prach_format)
return val[prach_format]; return val[prach_format];
} }
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind) void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, prach_item_t *prach_id, nfapi_nr_rach_indication_t *rach_ind)
{ {
const frame_t frame = prach_id->frame;
const slot_t slot = prach_id->slot;
rach_ind->sfn = frame; rach_ind->sfn = frame;
rach_ind->slot = slot; rach_ind->slot = slot;
rach_ind->number_of_pdus = 0;
prach_item_t *prach_id = find_nr_prach(&gNB->prach_list, frame, slot, gNB->frame_parms.nb_antennas_rx, NR_SEARCH_EXIST);
if (!prach_id) {
return;
}
nfapi_nr_prach_pdu_t *prach_pdu = &prach_id->pdu; nfapi_nr_prach_pdu_t *prach_pdu = &prach_id->pdu;
LOG_D(NR_PHY_RACH, "%d.%d, prachstart slot %d prach entry occas %d\n", frame, slot, prach_id->slot, prach_pdu->num_prach_ocas); LOG_D(NR_PHY_RACH, "%d.%d, prachstart slot %d prach entry occas %d\n", frame, slot, prach_id->slot, prach_pdu->num_prach_ocas);
const int prach_start_slot = prach_id->slot;
int N_dur = get_nr_prach_duration(prach_pdu->prach_format); int N_dur = get_nr_prach_duration(prach_pdu->prach_format);
for (int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) { for (int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) {
...@@ -63,7 +57,7 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac ...@@ -63,7 +57,7 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac
"[RAPROC] %d.%d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol " "[RAPROC] %d.%d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol "
"%u freq index %u\n", "%u freq index %u\n",
frame, frame,
prach_start_slot, slot,
res.max_preamble, res.max_preamble,
res.max_preamble_energy / 10, res.max_preamble_energy / 10,
res.max_preamble_energy % 10, res.max_preamble_energy % 10,
...@@ -100,7 +94,6 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac ...@@ -100,7 +94,6 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac
if (gNB->prach_energy_counter < NUM_PRACH_RX_FOR_NOISE_ESTIMATE) if (gNB->prach_energy_counter < NUM_PRACH_RX_FOR_NOISE_ESTIMATE)
gNB->prach_energy_counter++; gNB->prach_energy_counter++;
} // if prach_id>0 } // if prach_id>0
rach_ind->slot = prach_start_slot;
LOG_D(NR_PHY_RACH, "Freeing PRACH entry\n"); LOG_D(NR_PHY_RACH, "Freeing PRACH entry\n");
free_nr_prach_entry(&gNB->prach_list, prach_id); free_nr_prach_entry(prach_id);
} }
This diff is collapsed.
...@@ -18,7 +18,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, ...@@ -18,7 +18,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
int slot); int slot);
void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req); void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req);
int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO); int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO);
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind); void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, prach_item_t *prach_id, nfapi_nr_rach_indication_t *rach_ind);
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu); void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu);
void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx); void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx);
void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa); void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa);
......
...@@ -243,7 +243,7 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx) ...@@ -243,7 +243,7 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx)
} }
} }
static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs_info_t *nr_srs_info) static void configure_srs_info(const fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs_info_t *nr_srs_info)
{ {
nr_srs_info->B_SRS = srs_config_pdu->bandwidth_index; nr_srs_info->B_SRS = srs_config_pdu->bandwidth_index;
nr_srs_info->C_SRS = srs_config_pdu->config_index; nr_srs_info->C_SRS = srs_config_pdu->config_index;
...@@ -272,25 +272,17 @@ static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs ...@@ -272,25 +272,17 @@ static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs
* PARAMETERS : pointer to ue context * PARAMETERS : pointer to ue context
* pointer to rxtx context* * pointer to rxtx context*
* *
* RETURN : 0 if it is a valid slot for transmitting srs
* -1 if srs should not be transmitted
*
* DESCRIPTION : ue srs procedure * DESCRIPTION : ue srs procedure
* send srs according to current configuration * send srs according to current configuration
* *
*********************************************************************/ *********************************************************************/
bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, void ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
c16_t **txdataF, c16_t **txdataF,
nr_phy_data_tx_t *phy_data, const fapi_nr_ul_config_srs_pdu *srs_config_pdu,
bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) bool was_symbol_used[NR_SYMBOLS_PER_SLOT])
{ {
if(phy_data->srs_vars.active == false) {
return false;
}
NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms); NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms);
fapi_nr_ul_config_srs_pdu *srs_config_pdu = &phy_data->srs_vars.srs_config_pdu;
const uint8_t l0 = frame_parms->symbols_per_slot - 1 - srs_config_pdu->time_start_position; const uint8_t l0 = frame_parms->symbols_per_slot - 1 - srs_config_pdu->time_start_position;
// Num consecutive SRS symbols according to 38.211 6.4.1.4.1 // Num consecutive SRS symbols according to 38.211 6.4.1.4.1
int num_srs_symbols[] = {1, 2, 4, 8, 12}; int num_srs_symbols[] = {1, 2, 4, 8, 12};
...@@ -326,18 +318,20 @@ bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, ...@@ -326,18 +318,20 @@ bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
LOG_I(NR_PHY,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset); LOG_I(NR_PHY,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset);
#endif #endif
configure_srs_info(srs_config_pdu, ue->nr_srs_info); nr_srs_info_t nr_srs_info = {0};
configure_srs_info(srs_config_pdu, &nr_srs_info);
uint16_t symbol_offset = l0 * frame_parms->ofdm_symbol_size; uint16_t symbol_offset = l0 * frame_parms->ofdm_symbol_size;
bool generated = generate_srs_nr(frame_parms, bool generated = generate_srs_nr(frame_parms,
txdataF, txdataF,
symbol_offset, symbol_offset,
srs_config_pdu->bwp_start, srs_config_pdu->bwp_start,
ue->nr_srs_info, &nr_srs_info,
AMP, AMP,
proc->frame_tx, proc->frame_tx,
proc->nr_slot_tx, proc->nr_slot_tx,
frame_parms->nb_antennas_tx); frame_parms->nb_antennas_tx);
return generated; DevAssert(generated); // if we can't generate despite the SRS config, there
// is a problem
} }
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txp) void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txp)
...@@ -365,7 +359,8 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n ...@@ -365,7 +359,8 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF, was_symbol_used); nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF, was_symbol_used);
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, phy_data, was_symbol_used); if (phy_data->srs_vars.active)
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, &phy_data->srs_vars.srs_config_pdu, was_symbol_used);
pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF, was_symbol_used); pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF, was_symbol_used);
......
...@@ -56,40 +56,6 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) ...@@ -56,40 +56,6 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot)
UNUSED(slot); UNUSED(slot);
} }
int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen)
{
UNUSED(pMessageBuf);
UNUSED(pPackedBuf);
UNUSED(packedBufLen);
return 0;
}
int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen)
{
UNUSED(pMessageBuf);
UNUSED(messageBufLen);
UNUSED(pUnpackedBuf);
UNUSED(unpackedBufLen);
return 0;
}
int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen)
{
UNUSED(pMessageBuf);
UNUSED(pPackedBuf);
UNUSED(packedBufLen);
return 0;
}
int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf,
uint32_t messageBufLen,
void *pUnpackedBuf,
uint32_t unpackedBufLen)
{
UNUSED(pMessageBuf);
UNUSED(messageBufLen);
UNUSED(pUnpackedBuf);
UNUSED(unpackedBufLen);
return 0;
}
void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port)
{ {
UNUSED(vnf_ip_addr); UNUSED(vnf_ip_addr);
...@@ -102,37 +68,3 @@ void configure_nr_nfapi_vnf(eth_params_t params) ...@@ -102,37 +68,3 @@ void configure_nr_nfapi_vnf(eth_params_t params)
{ {
UNUSED(params); UNUSED(params);
} }
int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config)
{
UNUSED(pMessageBuf);
UNUSED(pPackedBuf);
UNUSED(packedBufLen);
UNUSED(config);
return 0;
}
bool nfapi_nr_p7_message_unpack(void *pMessageBuf,
uint32_t messageBufLen,
void *pUnpackedBuf,
uint32_t unpackedBufLen,
nfapi_p7_codec_config_t *config)
{
UNUSED(pMessageBuf);
UNUSED(messageBufLen);
UNUSED(pUnpackedBuf);
UNUSED(unpackedBufLen);
UNUSED(config);
return false;
}
int nfapi_p7_message_header_unpack(void *pMessageBuf,
uint32_t messageBufLen,
void *pUnpackedBuf,
uint32_t unpackedBufLen,
nfapi_p7_codec_config_t *config)
{
UNUSED(pMessageBuf);
UNUSED(messageBufLen);
UNUSED(pUnpackedBuf);
UNUSED(unpackedBufLen);
UNUSED(config);
return 0;
}
...@@ -547,12 +547,10 @@ int main(int argc, char **argv){ ...@@ -547,12 +547,10 @@ int main(int argc, char **argv){
phy_init_nr_gNB(gNB); phy_init_nr_gNB(gNB);
nr_phy_init_RU(ru); nr_phy_init_RU(ru);
prach_item_t *prach_data = calloc(1,sizeof(prach_item_t)); nfapi_nr_prach_pdu_t prach_pdu = {0};
gNB->prach_list.list[0] = prach_data; prach_pdu.num_cs = get_NCS(NCS_config, format0, restrictedSetConfig);
nfapi_nr_prach_pdu_t *prach_pdu = &prach_data->pdu; prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu.num_cs));
prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); prach_pdu.prach_format = prach_format;
prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs));
prach_pdu->prach_format = prach_format;
// Configure UE // Configure UE
UE = malloc(sizeof(PHY_VARS_NR_UE)); UE = malloc(sizeof(PHY_VARS_NR_UE));
...@@ -749,14 +747,14 @@ int main(int argc, char **argv){ ...@@ -749,14 +747,14 @@ int main(int argc, char **argv){
} }
nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config;
nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu.num_ra];
prach_pdu->num_prach_ocas=1; prach_pdu.num_prach_ocas=1;
prach_item_t *in = malloc(sizeof(prach_item_t) prach_item_t *in = malloc(sizeof(prach_item_t)
+ sizeof(c16_t) * gNB->gNB_config.carrier_config.num_rx_ant.value + sizeof(c16_t) * gNB->gNB_config.carrier_config.num_rx_ant.value
* NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L); * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L);
*in = (prach_item_t){.frame = frame, *in = (prach_item_t){.frame = frame,
.slot = slot, .slot = slot,
.pdu = *prach_pdu, .pdu = prach_pdu,
.rootSequenceIndex = occ->prach_root_sequence_index.value, .rootSequenceIndex = occ->prach_root_sequence_index.value,
.numrootSequenceIndex = occ->num_root_sequences.value, .numrootSequenceIndex = occ->num_root_sequences.value,
.msg1_frequencystart = occ->k1.value, .msg1_frequencystart = occ->k1.value,
...@@ -772,7 +770,7 @@ int main(int argc, char **argv){ ...@@ -772,7 +770,7 @@ int main(int argc, char **argv){
if (n_frames == 1) if (n_frames == 1)
LOG_I(PHY, LOG_I(PHY,
"ncs %d,num_seq %d\n", "ncs %d,num_seq %d\n",
prach_pdu->num_cs, prach_pdu.num_cs,
prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value);
rx_prach_out_t out = rx_nr_prach(in, prachOccasion); rx_prach_out_t out = rx_nr_prach(in, prachOccasion);
...@@ -823,7 +821,6 @@ int main(int argc, char **argv){ ...@@ -823,7 +821,6 @@ int main(int argc, char **argv){
nr_phy_free_RU(ru); nr_phy_free_RU(ru);
free(RC.ru[0]); free(RC.ru[0]);
free(RC.ru); free(RC.ru);
free(prach_data);
phy_free_nr_gNB(gNB); phy_free_nr_gNB(gNB);
// allocated in set_tdd_config_nr() // allocated in set_tdd_config_nr()
int nb_slots_to_set = (1<<mu)*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; int nb_slots_to_set = (1<<mu)*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
......
...@@ -630,27 +630,24 @@ int main(int argc, char **argv) ...@@ -630,27 +630,24 @@ int main(int argc, char **argv)
rxlev_pucch += signal_energy((int32_t *)&rxdataF[aarx][startingSymbolIndex * frame_parms->ofdm_symbol_size], 12); rxlev_pucch += signal_energy((int32_t *)&rxdataF[aarx][startingSymbolIndex * frame_parms->ofdm_symbol_size], 12);
// set UL mask for pucch allocation // set UL mask for pucch allocation
uint32_t rb_mask_ul[14][9] = {0}; uint32_t rb_mask_ul[14][MAX_BWP_SIZE] = {0};
if (format == 1) { if (format == 1) {
for (int s = 0; s < frame_parms->symbols_per_slot; s++) { for (int s = 0; s < frame_parms->symbols_per_slot; s++) {
if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols / 2)) if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols / 2))
for (int rb = 0; rb < N_RB; rb++) { for (int rb = 0; rb < N_RB; rb++) {
int rb2 = rb + startingPRB; rb_mask_ul[s][rb + startingPRB] = 1;
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
} }
else if (s >= (startingSymbolIndex + nrofSymbols / 2) && s < startingSymbolIndex + nrofSymbols) else if (s >= (startingSymbolIndex + nrofSymbols / 2) && s < startingSymbolIndex + nrofSymbols)
for (int rb = 0; rb < N_RB; rb++) { for (int rb = 0; rb < N_RB; rb++) {
int rb2 = rb + startingPRB_intraSlotHopping; rb_mask_ul[s][rb + startingPRB_intraSlotHopping] = 1;
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
} }
} }
} else { } else {
for (int s = 0; s < frame_parms->symbols_per_slot; s++) { for (int s = 0; s < frame_parms->symbols_per_slot; s++) {
if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols)) if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols))
for (int rb = 0; rb < N_RB; rb++) { for (int rb = 0; rb < N_RB; rb++) {
int rb2 = rb + startingPRB; rb_mask_ul[s][rb + startingPRB] = 1;
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
} }
} }
} }
......
...@@ -435,11 +435,7 @@ int main(int argc, char *argv[]) ...@@ -435,11 +435,7 @@ int main(int argc, char *argv[])
.beamforming.num_prgs = m_SRS[srs_pdu.config_index], .beamforming.num_prgs = m_SRS[srs_pdu.config_index],
.beamforming.prg_size = 1}; .beamforming.prg_size = 1};
gNB->srs->srs_pdu = srs_pdu; NR_gNB_SRS_job_t srs_job = {.frame = frame, .slot = slot, .srs_pdu = srs_pdu};
gNB->srs->active = true;
gNB->srs->beam_nb = 0;
gNB->srs->frame = frame;
gNB->srs->slot = slot;
// Configure SRS parameters at UE // Configure SRS parameters at UE
fapi_nr_ul_config_srs_pdu srs_config_pdu = {.rnti = srs_pdu.rnti, fapi_nr_ul_config_srs_pdu srs_config_pdu = {.rnti = srs_pdu.rnti,
...@@ -467,11 +463,6 @@ int main(int argc, char *argv[]) ...@@ -467,11 +463,6 @@ int main(int argc, char *argv[])
.beamforming.num_prgs = srs_pdu.beamforming.num_prgs, .beamforming.num_prgs = srs_pdu.beamforming.num_prgs,
.beamforming.prg_size = srs_pdu.beamforming.prg_size}; .beamforming.prg_size = srs_pdu.beamforming.prg_size};
nr_phy_data_tx_t phy_data = {0};
phy_data.srs_vars.active = true;
phy_data.srs_vars.srs_config_pdu = srs_config_pdu;
UE->nr_srs_info = malloc16_clear(sizeof(nr_srs_info_t));
//----------- UE TX SRS procedures --------------------- //----------- UE TX SRS procedures ---------------------
UE_nr_rxtx_proc_t proc; UE_nr_rxtx_proc_t proc;
...@@ -492,7 +483,7 @@ int main(int argc, char *argv[]) ...@@ -492,7 +483,7 @@ int main(int argc, char *argv[])
for (i = 0; i < n_tx; i++) for (i = 0; i < n_tx; i++)
txd[i] = txdata[i] + slot_offset; txd[i] = txdata[i] + slot_offset;
ue_srs_procedures_nr(UE, &proc, (c16_t **)txF, &phy_data, was_symbol_used); ue_srs_procedures_nr(UE, &proc, (c16_t **)txF, &srs_config_pdu, was_symbol_used);
//------------ TX rotation and OFDM Modulation -------------------------- //------------ TX rotation and OFDM Modulation --------------------------
nr_tx_rotation_and_ofdm_mod(slot, fp, n_tx, txF, txd, link_type_ul, was_symbol_used, false); nr_tx_rotation_and_ofdm_mod(slot, fp, n_tx, txF, txd, link_type_ul, was_symbol_used, false);
...@@ -564,16 +555,15 @@ int main(int argc, char *argv[]) ...@@ -564,16 +555,15 @@ int main(int argc, char *argv[])
//----------- UE RX SRS procedures --------------------- //----------- UE RX SRS procedures ---------------------
start_meas(&gNB->rx_srs_stats); start_meas(&gNB->rx_srs_stats);
NR_gNB_SRS_t *srs = &gNB->srs[0]; uint8_t N_symb_SRS = 1 << srs_pdu.num_symbols;
uint8_t N_symb_SRS = 1 << srs->srs_pdu.num_symbols; uint8_t N_ap = 1 << srs_pdu.num_ant_ports;
uint8_t N_ap = 1 << srs->srs_pdu.num_ant_ports; int16_t snr_per_rb[srs_pdu.bwp_size];
int16_t snr_per_rb[srs->srs_pdu.bwp_size];
uint16_t timing_advance_offset; uint16_t timing_advance_offset;
int16_t timing_advance_offset_nsec[n_rx]; int16_t timing_advance_offset_nsec[n_rx];
int srs_est; int srs_est;
c16_t srs_estimated_channel_freq[n_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); c16_t srs_estimated_channel_freq[n_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32)));
c16_t srs_estimated_channel_time[n_rx][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size] __attribute__((aligned(32)));
int8_t snr;
nr_srs_rx_procedures(gNB, nr_srs_rx_procedures(gNB,
frame, frame,
slot, slot,
...@@ -581,16 +571,15 @@ int main(int argc, char *argv[]) ...@@ -581,16 +571,15 @@ int main(int argc, char *argv[])
N_ap, N_ap,
N_symb_SRS, N_symb_SRS,
ofdm_symbol_size, ofdm_symbol_size,
srs, &srs_job,
gNB->nr_srs_info[0],
&srs_est, &srs_est,
&snr,
srs_estimated_channel_freq, srs_estimated_channel_freq,
srs_estimated_channel_time,
snr_per_rb, snr_per_rb,
&timing_advance_offset, &timing_advance_offset,
timing_advance_offset_nsec); timing_advance_offset_nsec);
sum_srs_snr += pow(10, (double)gNB->srs->snr / 10.0); sum_srs_snr += pow(10, (double)snr / 10.0);
int16_t delay_ns = delay * 1e9 / (fp->samples_per_frame * 100); int16_t delay_ns = delay * 1e9 / (fp->samples_per_frame * 100);
for (int ant_idx = 0; ant_idx < n_rx; ant_idx++) { for (int ant_idx = 0; ant_idx < n_rx; ant_idx++) {
...@@ -666,7 +655,6 @@ int main(int argc, char *argv[]) ...@@ -666,7 +655,6 @@ int main(int argc, char *argv[])
phy_free_nr_gNB(gNB); phy_free_nr_gNB(gNB);
free_channel_desc_scm(UE2gNB); free_channel_desc_scm(UE2gNB);
free_and_zero(UE->nr_srs_info);
free(gNB->RU_list[0]); free(gNB->RU_list[0]);
free(UE); free(UE);
......
...@@ -414,12 +414,12 @@ int main(int argc, char **argv) ...@@ -414,12 +414,12 @@ int main(int argc, char **argv)
unsigned int TBS = 8424; unsigned int TBS = 8424;
unsigned int available_bits; unsigned int available_bits;
uint8_t nb_re_dmrs = 6; uint8_t nb_re_dmrs = 6;
uint8_t length_dmrs = 1; uint8_t length_dmrs = 2;
uint8_t N_PRB_oh; uint8_t N_PRB_oh;
uint16_t N_RE_prime,code_rate; uint16_t N_RE_prime,code_rate;
unsigned char mod_order; unsigned char mod_order;
uint8_t rvidx = 0; uint8_t rvidx = 0;
uint8_t UE_id = 0; int UE_id = 0;
NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id]; NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id];
NR_UL_gNB_HARQ_t *harq_process_gNB = ulsch_gNB->harq_process; NR_UL_gNB_HARQ_t *harq_process_gNB = ulsch_gNB->harq_process;
...@@ -429,9 +429,6 @@ int main(int argc, char **argv) ...@@ -429,9 +429,6 @@ int main(int argc, char **argv)
nr_phy_data_tx_t phy_data = {0}; nr_phy_data_tx_t phy_data = {0};
NR_UE_ULSCH_t *ulsch_ue = &phy_data.ulsch; NR_UE_ULSCH_t *ulsch_ue = &phy_data.ulsch;
if ((Nl==4)||(Nl==3))
nb_re_dmrs = nb_re_dmrs*2;
mod_order = nr_get_Qm_ul(Imcs, mcs_table); mod_order = nr_get_Qm_ul(Imcs, mcs_table);
code_rate = nr_get_code_rate_ul(Imcs, mcs_table); code_rate = nr_get_code_rate_ul(Imcs, mcs_table);
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, 0, mod_order, Nl); available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, 0, mod_order, Nl);
...@@ -445,10 +442,15 @@ int main(int argc, char **argv) ...@@ -445,10 +442,15 @@ int main(int argc, char **argv)
rel15_ul->qam_mod_order = mod_order; rel15_ul->qam_mod_order = mod_order;
rel15_ul->mcs_index = Imcs; rel15_ul->mcs_index = Imcs;
rel15_ul->pusch_data.rv_index = rvidx; rel15_ul->pusch_data.rv_index = rvidx;
rel15_ul->ul_dmrs_symb_pos = nb_re_dmrs;
rel15_ul->dmrs_config_type = pusch_dmrs_type1;
rel15_ul->num_dmrs_cdm_grps_no_data = 1;
rel15_ul->nrOfLayers = Nl; rel15_ul->nrOfLayers = Nl;
rel15_ul->target_code_rate = code_rate; rel15_ul->target_code_rate = code_rate;
rel15_ul->pusch_data.tb_size = TBS>>3; rel15_ul->pusch_data.tb_size = TBS>>3;
rel15_ul->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, code_rate); rel15_ul->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, code_rate);
int bits = count_bits64_with_mask(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, rel15_ul->nr_of_symbols);
AssertFatal(length_dmrs == bits, "length_dmrs %d bits %d\n", length_dmrs, bits);
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc
...@@ -558,9 +560,9 @@ int main(int argc, char **argv) ...@@ -558,9 +560,9 @@ int main(int argc, char **argv)
printf("\n"); printf("\n");
exit(-1); exit(-1);
#endif #endif
nr_ulsch_decoding(gNB, frame_parms, frame, subframe, &G, &UE_id, 1); nr_ulsch_decoding(gNB, frame_parms, frame, subframe, &UE_id, 1);
if (harq_process_gNB->processedSegments == harq_process_gNB->C) { if (harq_process_gNB->processedSegments == harq_process_gNB->C) {
bool crc_valid = check_crc(harq_process_gNB->b, lenWithCrc(1, (harq_process_gNB->TBS) << 3), crcType(1, (harq_process_gNB->TBS) << 3)); bool crc_valid = check_crc(harq_process_gNB->b, lenWithCrc(1, TBS << 3), crcType(1, TBS << 3));
if (!crc_valid) { if (!crc_valid) {
n_false_positive++; n_false_positive++;
} }
......
...@@ -1208,6 +1208,7 @@ int main(int argc, char *argv[]) ...@@ -1208,6 +1208,7 @@ int main(int argc, char *argv[])
uint8_t round = 0; uint8_t round = 0;
crc_status = 1; crc_status = 1;
errors_decoding = 0; errors_decoding = 0;
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[UE_id];
while (round < max_rounds && crc_status && !stop) { while (round < max_rounds && crc_status && !stop) {
...@@ -1307,7 +1308,7 @@ int main(int argc, char *argv[]) ...@@ -1307,7 +1308,7 @@ int main(int argc, char *argv[])
srs_pdu->resource_type = NR_SRS_Resource__resourceType_PR_periodic; srs_pdu->resource_type = NR_SRS_Resource__resourceType_PR_periodic;
srs_pdu->t_srs = 1; srs_pdu->t_srs = 1;
srs_pdu->srs_parameters_v4.srs_bandwidth_size = m_SRS[srs_pdu->config_index]; srs_pdu->srs_parameters_v4.srs_bandwidth_size = m_SRS[srs_pdu->config_index];
srs_pdu->srs_parameters_v4.usage = 1 << NR_SRS_ResourceSet__usage_codebook; srs_pdu->srs_parameters_v4.usage = 1 << NFAPI_NR_SRS_BEAMMANAGEMENT; // to get SNR
srs_pdu->srs_parameters_v4.report_type[0] = 1; srs_pdu->srs_parameters_v4.report_type[0] = 1;
srs_pdu->srs_parameters_v4.iq_representation = 1; srs_pdu->srs_parameters_v4.iq_representation = 1;
srs_pdu->srs_parameters_v4.prg_size = 1; srs_pdu->srs_parameters_v4.prg_size = 1;
...@@ -1594,7 +1595,6 @@ int main(int argc, char *argv[]) ...@@ -1594,7 +1595,6 @@ int main(int argc, char *argv[])
} }
} }
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[UE_id];
if (n_trials == 1 && round == 0) { if (n_trials == 1 && round == 0) {
__attribute__((unused)) int off = ((nb_rb & 1) == 1) ? 4 : 0; __attribute__((unused)) int off = ((nb_rb & 1) == 1) ? 4 : 0;
...@@ -1742,13 +1742,20 @@ int main(int argc, char *argv[]) ...@@ -1742,13 +1742,20 @@ int main(int argc, char *argv[])
if (!crc_status) if (!crc_status)
effRate += ((double)TBS) / (double)round; effRate += ((double)TBS) / (double)round;
sum_pusch_delay += ulsch_gNB->delay.est_delay; sum_pusch_delay += pusch_vars->delay.est_delay;
min_pusch_delay = min(ulsch_gNB->delay.est_delay, min_pusch_delay); min_pusch_delay = min(pusch_vars->delay.est_delay, min_pusch_delay);
max_pusch_delay = max(ulsch_gNB->delay.est_delay, max_pusch_delay); max_pusch_delay = max(pusch_vars->delay.est_delay, max_pusch_delay);
delay_pusch_est_count++; delay_pusch_est_count++;
if (do_SRS == 1) { if (do_SRS == 1) {
sum_srs_snr += gNB->srs->snr; DevAssert(UL_INFO.srs_ind.number_of_pdus == 1); // there must be SRS indication
const nfapi_nr_srs_indication_pdu_t *srs_ind = &UL_INFO.srs_ind.pdu_list[0];
DevAssert(srs_ind->srs_usage == NFAPI_NR_SRS_BEAMMANAGEMENT);
nfapi_nr_srs_beamforming_report_t bf_rep;
unpack_nr_srs_beamforming_report((void *)srs_ind->report_tlv.value, srs_ind->report_tlv.length, &bf_rep, sizeof(bf_rep));
DevAssert(bf_rep.wide_band_snr != 0xff);
int8_t snr = (bf_rep.wide_band_snr >> 1) - 64;
sum_srs_snr += snr;
srs_snr_count++; srs_snr_count++;
} }
} // trial loop } // trial loop
......
...@@ -2528,34 +2528,6 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE ...@@ -2528,34 +2528,6 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
nr_mac->cset0_bwp_size); nr_mac->cset0_bwp_size);
} }
fsn_t fs_add_delta(const frame_structure_t *fs, uint32_t delta, fsn_t fsn)
{
const int slots_frame = fs->numb_slots_frame;
fsn_t res = {
.f = (fsn.f + (fsn.s + delta) / slots_frame) % MAX_FRAME_NUMBER,
.s = (fsn.s + delta) % slots_frame,
};
return res;
}
int fs_get_diff(const frame_structure_t *fs, fsn_t a, fsn_t b)
{
const int slots_frame = fs->numb_slots_frame;
int diff = (a.f * slots_frame + a.s) - (b.f * slots_frame + b.s);
if (diff < -512 * slots_frame)
diff += 1024 * slots_frame;
else if (diff > 512 * slots_frame)
diff -= 1024 * slots_frame;
return diff;
}
fsn_t fs_get_max(const frame_structure_t *fs, fsn_t a, fsn_t b)
{
if (fs_get_diff(fs, a, b) <= 0) {
return b;
} else {
return a;
}
}
static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch) static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch)
{ {
int frame = pp_pusch->frame; int frame = pp_pusch->frame;
...@@ -2579,8 +2551,8 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp ...@@ -2579,8 +2551,8 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp
// FAPI cannot handle more than MAX_DCI_CORESET DCIs // FAPI cannot handle more than MAX_DCI_CORESET DCIs
max_dci = min(max_dci, MAX_DCI_CORESET); max_dci = min(max_dci, MAX_DCI_CORESET);
fsn_t current = {frame, slot}; fsn_t current = {frame, slot, *scc->ssbSubcarrierSpacing};
fsn_t min_next = fs_add_delta(fs, min_rxtx, current); fsn_t min_next = fsn_add_delta(current, min_rxtx);
/* if it's the last DL slot, we should try all TDAs to make sure that the /* if it's the last DL slot, we should try all TDAs to make sure that the
* scheduler can reach e.g. the next mixed slot. Otherwise, if we don't, we * scheduler can reach e.g. the next mixed slot. Otherwise, if we don't, we
* might starve HARQ processes that need a retransmission in a specific slot * might starve HARQ processes that need a retransmission in a specific slot
...@@ -2589,16 +2561,16 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp ...@@ -2589,16 +2561,16 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp
fsn_t *next = &nr_mac->ul_next; fsn_t *next = &nr_mac->ul_next;
while (max_dci > 0) { while (max_dci > 0) {
/* go to the next UL slot, skipping DL if necessary */ /* go to the next UL slot, skipping DL if necessary */
*next = fs_get_max(fs, *next, min_next); *next = fsn_get_max(*next, min_next);
while (!is_ul_slot(next->s, fs)) while (!is_ul_slot(next->s, fs))
*next = fs_add_delta(fs, 1, *next); *next = fsn_add_delta(*next, 1);
if (!is_dl_slot(current.s, fs)) // if current slot is not DL, nothing to do if (!is_dl_slot(current.s, fs)) // if current slot is not DL, nothing to do
break; break;
/* get a TDA so that next UL scheduling slot can be reached from current, /* get a TDA so that next UL scheduling slot can be reached from current,
* and exit if there is no such TDA. Remove koffset, as it is * and exit if there is no such TDA. Remove koffset, as it is
* "cell-specific", i.e., the UE will add it on the computation. */ * "cell-specific", i.e., the UE will add it on the computation. */
int k2 = fs_get_diff(fs, *next, current) - koffset; int k2 = fsn_get_diff(*next, current) - koffset;
DevAssert(k2 > 0); DevAssert(k2 > 0);
// we assume that all beams have the same symbol utilization in all RBs for // we assume that all beams have the same symbol utilization in all RBs for
// simplification (but this might not be true). Otherwise, we would need to // simplification (but this might not be true). Otherwise, we would need to
...@@ -2631,7 +2603,7 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp ...@@ -2631,7 +2603,7 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp
break; break;
max_dci -= sched; max_dci -= sched;
*next = fs_add_delta(fs, 1, *next); *next = fsn_add_delta(*next, 1);
} }
} }
......
...@@ -293,6 +293,7 @@ void mac_top_init_gNB(ngran_node_t node_type, ...@@ -293,6 +293,7 @@ void mac_top_init_gNB(ngran_node_t node_type,
RC.nrmac[i]->cset0_bwp_start = 0; RC.nrmac[i]->cset0_bwp_start = 0;
RC.nrmac[i]->cset0_bwp_size = 0; RC.nrmac[i]->cset0_bwp_size = 0;
RC.nrmac[i]->ul_next = (fsn_t) {.mu = *scc->ssbSubcarrierSpacing};
RC.nrmac[i]->print_ue_stats = true; RC.nrmac[i]->print_ue_stats = true;
pthread_mutex_init(&RC.nrmac[i]->sched_lock, NULL); pthread_mutex_init(&RC.nrmac[i]->sched_lock, NULL);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <string.h> #include <string.h>
#include <complex.h> #include <complex.h>
#include <pthread.h> #include <pthread.h>
#include "fsn.h"
#include "common/utils/ds/seq_arr.h" #include "common/utils/ds/seq_arr.h"
#include "common/utils/nr/nr_common.h" #include "common/utils/nr/nr_common.h"
#include "common/utils/ds/byte_array.h" #include "common/utils/ds/byte_array.h"
...@@ -878,14 +879,6 @@ typedef struct { ...@@ -878,14 +879,6 @@ typedef struct {
NR_ControlResourceSet_t coreset; NR_ControlResourceSet_t coreset;
} NR_sched_ctrl_sib1_t; } NR_sched_ctrl_sib1_t;
/// helper type to encapsulate a frame/slot combination in a single type.
/// Currently only used in the UL preprocessor. Note: if you use this type
/// further, please refactor it into a common type first.
typedef struct fsn {
frame_t f;
slot_t s;
} fsn_t;
typedef struct NR_du_stats { typedef struct NR_du_stats {
/// cell-wide wide-band CQI distribution, see 28.552 5.1.1.11.1; /// cell-wide wide-band CQI distribution, see 28.552 5.1.1.11.1;
/// 0-15 CQI, 1-8 RI, 1-3 CQI table /// 0-15 CQI, 1-8 RI, 1-3 CQI table
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "xran_sync_api.h" #include "xran_sync_api.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "common/utils/fsn.h"
#include "openair1/PHY/defs_gNB.h" #include "openair1/PHY/defs_gNB.h"
#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h" #include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "oaioran.h" #include "oaioran.h"
...@@ -205,19 +206,21 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) ...@@ -205,19 +206,21 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
.prach_buf = NULL, .prach_buf = NULL,
}; };
prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, ru->nr_frame_parms->nb_antennas_rx, NR_SEARCH_EXIST); prach_item_t p;
if (prach_id) { PHY_VARS_gNB *gNB = ru->gNB_list[0];
fsn_t now = {.f = *frame, .s = *slot, .mu = gNB->frame_parms.numerology_index};
if (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) {
struct xran_fh_config *fh_cfg = get_xran_fh_config(0); struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology; int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology;
uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received
// PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4 // PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4
nr_prach_info_t prach_info = get_prach_info(0); nr_prach_info_t prach_info = get_prach_info(0);
bool is_prach_frame = (*frame % prach_info.x == prach_info.y); bool is_prach_frame = (*frame % prach_info.x == prach_info.y);
bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (prach_id->slot % slots_per_subframe)); // `prach_id->slot` = slot in which PRACH is scheduled bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (p.slot % slots_per_subframe)); // `p.slot` = slot in which PRACH is scheduled
if (is_prach_slot) { if (is_prach_slot) {
ru_info.prach_buf = prach_id->prach_buf; ru_info.prach_buf = p.prach_buf;
} else { } else {
LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, prach_id->slot); LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, p.slot);
} }
} }
...@@ -232,6 +235,15 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) ...@@ -232,6 +235,15 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX function \n", f, sl); printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX function \n", f, sl);
} }
if (ru_info.prach_buf) {
// xran_fh_rx_read_slot() should have read PRACH, write back to queue
bool success = spsc_q_put(&gNB->prach_l1rx_queue, &p, sizeof(p));
// assume prach_l1rx_queue never full: prach_ru_queue filled at
// constant pace, but prach_l1rx_queue emptied as fast as possible,
// see rx_func()
DevAssert(success);
}
int slots_per_frame = 10 << (ru->openair0_cfg.nr_scs_for_raster); int slots_per_frame = 10 << (ru->openair0_cfg.nr_scs_for_raster);
proc->tti_rx = sl; proc->tti_rx = sl;
proc->frame_rx = f; proc->frame_rx = f;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment