diff --git a/CMakeLists.txt b/CMakeLists.txt index 57c76d9666..5d9ca49a4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -714,6 +714,7 @@ set(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 NFAPI_LIB) # some FAPI messages pack "subPDUs" set(SCHED_SRC_RU ${OPENAIR1_DIR}/SCHED/ru_procedures.c @@ -752,6 +753,7 @@ set(NFAPI_SRC add_library(NFAPI_LIB ${NFAPI_SRC}) 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 PRIVATE z) if(OAI_WLS) target_compile_definitions(NFAPI_LIB PRIVATE ENABLE_WLS) @@ -1072,7 +1074,7 @@ add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON}) target_link_libraries(PHY_NR_COMMON PUBLIC UTIL) 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}) target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common) @@ -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 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 - -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 ${T_LIB}) @@ -1773,7 +1775,7 @@ add_executable(oairu target_link_libraries(oairu PRIVATE -Wl,--start-group 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 asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -1802,7 +1804,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE 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 ${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 ${T_LIB}) @@ -1823,7 +1825,7 @@ add_executable(nr-oru ${OPENAIR_DIR}/executables/main_nr_ru.c ) 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) target_link_libraries(nr-oru PRIVATE pthread m CONFIG_LIB rt ${T_LIB} utils barrier actor) @@ -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 x2ap f1ap m2ap m3ap e1ap radio_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 ${T_LIB}) @@ -1892,7 +1894,7 @@ target_link_libraries(nr-cuup PRIVATE GTPV1U e1ap f1ap time_management softmodem_common alg - z dl pthread ${T_LIB}) + dl pthread ${T_LIB}) target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) if(E2_AGENT) 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 PHY_NR_COMMON PHY_NR_UE NR_L2_UE MAC_NR_COMMON NFAPI_LIB ITTI SIMU radio_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 ${T_LIB}) diff --git a/common/utils/CMakeLists.txt b/common/utils/CMakeLists.txt index 3196b39868..fc113ffa46 100644 --- a/common/utils/CMakeLists.txt +++ b/common/utils/CMakeLists.txt @@ -16,7 +16,7 @@ add_subdirectory(nr) add_subdirectory(LOG) add_subdirectory(threadPool) 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_link_libraries(utils PRIVATE ${T_LIB}) add_subdirectory(barrier) diff --git a/common/utils/ds/CMakeLists.txt b/common/utils/ds/CMakeLists.txt index 7007d77fac..6f7053a1be 100644 --- a/common/utils/ds/CMakeLists.txt +++ b/common/utils/ds/CMakeLists.txt @@ -6,6 +6,7 @@ add_library(ds OBJECT seq_arr.c hashtable.c obj_hashtable.c + spsc_q.c ) target_include_directories(ds PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/common/utils/ds/hashtable.c b/common/utils/ds/hashtable.c index c84d332973..78a62f570c 100644 --- a/common/utils/ds/hashtable.c +++ b/common/utils/ds/hashtable.c @@ -10,36 +10,6 @@ #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 * 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 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; -} //------------------------------------------------------------------------------------------------------------------------------- /* diff --git a/common/utils/ds/hashtable.h b/common/utils/ds/hashtable.h index ba43b0230f..fd8fe013c3 100644 --- a/common/utils/ds/hashtable.h +++ b/common/utils/ds/hashtable.h @@ -44,12 +44,10 @@ typedef struct hash_table_iterator_s { const hash_table_t* const hashtbl; } hash_table_iterator_s; -char *hashtable_rc_code2string(hashtable_rc_t rcP); 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 *)); 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_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_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); diff --git a/common/utils/ds/spsc_q.c b/common/utils/ds/spsc_q.c new file mode 100644 index 0000000000..6f05a19865 --- /dev/null +++ b/common/utils/ds/spsc_q.c @@ -0,0 +1,90 @@ +/* + * SPDX-License-Identifier: LicenseRef-CSSL-1.0 + */ + +#include +#include +#include + +#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; +} diff --git a/common/utils/ds/spsc_q.h b/common/utils/ds/spsc_q.h new file mode 100644 index 0000000000..7fd968b2f0 --- /dev/null +++ b/common/utils/ds/spsc_q.h @@ -0,0 +1,37 @@ +/* + * SPDX-License-Identifier: LicenseRef-CSSL-1.0 + */ + +#ifndef SPSC_Q_H_ +#define SPSC_Q_H_ + +#include +#include +#include + +#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_ */ diff --git a/common/utils/ds/tests/CMakeLists.txt b/common/utils/ds/tests/CMakeLists.txt index a38cf159cb..1a2e5277a1 100644 --- a/common/utils/ds/tests/CMakeLists.txt +++ b/common/utils/ds/tests/CMakeLists.txt @@ -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_dependencies(tests test_hashtable) target_link_libraries(test_hashtable PRIVATE ds GTest::gtest) -add_test(NAME test_hashtable - COMMAND ./test_hashtable) +add_test(NAME 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) diff --git a/common/utils/ds/tests/test_spsc_q.cpp b/common/utils/ds/tests/test_spsc_q.cpp new file mode 100644 index 0000000000..0c1638d490 --- /dev/null +++ b/common/utils/ds/tests/test_spsc_q.cpp @@ -0,0 +1,135 @@ +/* + * 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(); +} diff --git a/common/utils/ds/tests/test_spsc_q_perf.cpp b/common/utils/ds/tests/test_spsc_q_perf.cpp new file mode 100644 index 0000000000..6487e9e6c3 --- /dev/null +++ b/common/utils/ds/tests/test_spsc_q_perf.cpp @@ -0,0 +1,75 @@ +#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(); diff --git a/common/utils/fsn.c b/common/utils/fsn.c new file mode 100644 index 0000000000..e8566a2da9 --- /dev/null +++ b/common/utils/fsn.c @@ -0,0 +1,55 @@ +/* + * SPDX-License-Identifier: LicenseRef-CSSL-1.0 + */ + +#include "fsn.h" + +#include + +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; +} diff --git a/common/utils/fsn.h b/common/utils/fsn.h new file mode 100644 index 0000000000..dfa126bc85 --- /dev/null +++ b/common/utils/fsn.h @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: LicenseRef-CSSL-1.0 + */ + +#ifndef FSN_H_ +#define FSN_H_ + +#include +#include + +/// 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_ */ diff --git a/common/utils/tests/CMakeLists.txt b/common/utils/tests/CMakeLists.txt index e3c310fed9..14d2f83d7a 100644 --- a/common/utils/tests/CMakeLists.txt +++ b/common/utils/tests/CMakeLists.txt @@ -2,3 +2,10 @@ 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) +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) diff --git a/common/utils/tests/test_fsn.cpp b/common/utils/tests/test_fsn.cpp new file mode 100644 index 0000000000..3cbe34dfb2 --- /dev/null +++ b/common/utils/tests/test_fsn.cpp @@ -0,0 +1,84 @@ +/* + * SPDX-License-Identifier: LicenseRef-CSSL-1.0 + */ + +#include +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(); +} diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index abbfa05df1..1b27b2e4e6 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -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}; // Do PRACH RU processing 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 if (gNB->phase_comp) { diff --git a/executables/nr-ru.c b/executables/nr-ru.c index ad2425f358..b66d4976c9 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -15,6 +15,7 @@ #include "common/utils/nr/nr_common.h" #include "common/utils/assertions.h" #include "common/utils/system.h" +#include "common/utils/fsn.h" #include "common/ran_context.h" #include "radio/COMMON/common_lib.h" @@ -980,11 +981,16 @@ void *ru_thread(void *param) proc->tti_rx * gNB->frame_parms.samples_per_slot_wCP); // Do PRACH RU processing - prach_item_t *p = - find_nr_prach(&gNB->prach_list, proc->frame_rx, proc->tti_rx, gNB->frame_parms.nb_antennas_rx, NR_SEARCH_EXIST); - if (p) { + fsn_t now = {.f = proc->frame_rx, .s = proc->tti_rx, .mu = fp->numerology_index}; + prach_item_t p; + while (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) { // 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 (ru->feprx) } // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 59bdd7012d..35b27468f6 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -50,6 +50,8 @@ int l1_north_init_gNB() 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; int first_free = -1; for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { @@ -141,16 +143,6 @@ void phy_init_nr_gNB(PHY_VARS_gNB *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; apnr_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 * RU to copy/recover freq-domain memory from there */ 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) common_vars->debugBuff_sample_offset = 0; // 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_buf = Prx*max_ul_mimo_layers; @@ -212,19 +204,11 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) PHY_MEASUREMENTS_gNB *meas = &gNB->measurements; free_and_zero(meas->n0_subband_power); - for (int id = 0; id < gNB->max_nb_srs; id++) { - for(int i=0; inr_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_gnb_lowpapr_sequences(); reset_nr_transport(gNB); + reset_nr_prach(gNB); destroy_DLSCH_struct(gNB); @@ -437,18 +421,14 @@ void init_nr_transport(PHY_VARS_gNB *gNB) else 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_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)); - for (int i = 0; i < gNB->max_nb_pucch; i++) { - memset(&gNB->pucch[i], 0, sizeof(gNB->pucch[i])); - } + int max_nb_pucch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1; + gNB->pucch_queue = spsc_q_alloc(max_nb_pucch, sizeof(NR_gNB_PUCCH_job_t)); + 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)); - for (int i = 0; i < gNB->max_nb_srs; i++) - gNB->srs[i].active = 0; + int max_nb_srs = buffer_ul_slots ? buffer_ul_slots << 1 : 1; // assuming at most 2 SRS per slot + gNB->srs_queue = spsc_q_alloc(max_nb_srs, sizeof(NR_gNB_SRS_job_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++) { @@ -465,8 +445,9 @@ void reset_nr_transport(PHY_VARS_gNB *gNB) { const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - free(gNB->pucch); - free(gNB->srs); + spsc_q_free(&gNB->pucch_queue); + spsc_q_free(&gNB->pusch_queue); + spsc_q_free(&gNB->srs_queue); for (int i = 0; i < gNB->max_nb_pusch; i++) free_gNB_ulsch(&gNB->ulsch[i], fp->N_RB_UL); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index d7d73e1c01..cccf4cf3a8 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -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] = 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; @@ -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); - free_and_zero(ue->nr_srs_info); - free_and_zero(ue->prach_vars[gNB_id]); } diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index a901f8dba1..f9b4991cfd 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -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); } -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_gNB_COMMON *common_vars = &gNB->common_vars; 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]; 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 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; 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 int offset = offset0 + (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; nb_symb[rb]++; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 4d70db6f02..a5190997fa 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -34,7 +34,7 @@ typedef struct puschAntennaProc_s { int aarx; int beam_nb; int numAntennas; - nfapi_nr_pusch_pdu_t *pusch_pdu; + const nfapi_nr_pusch_pdu_t *pusch_pdu; int *max_ch; c16_t *pilot; int *nest_count; @@ -82,7 +82,7 @@ static void nr_pusch_antenna_processing(void *arg) int aarx = rdata->aarx; int numAntennas = rdata->numAntennas; 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; c16_t *pilot = rdata->pilot; uint64_t noise_amp2 = *(rdata->noise_amp2); @@ -452,10 +452,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, int nl, unsigned short p, unsigned char symbol, - int ul_id, + NR_gNB_PUSCH *pusch_vars, int beam_nb, unsigned short bwp_start_subcarrier, - nfapi_nr_pusch_pdu_t *pusch_pdu, + const nfapi_nr_pusch_pdu_t *pusch_pdu, int *max_ch, uint32_t *nvar, c16_t *pusch_dmrs_slot_mem, @@ -534,7 +534,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, int nest_count = 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)); int nb_antennas_rx = fp->nb_antennas_rx; @@ -579,7 +579,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, rdata->delay = &delay_arr[rdata->aarx]; rdata->beam_nb = beam_nb; rdata->frame_parms = fp; - rdata->pusch_vars = &gNB->pusch_vars[ul_id]; + rdata->pusch_vars = pusch_vars; rdata->chest_freq = gNB->chest_freq; rdata->rxdataF = gNB->common_vars.rxdataF; rdata->scope = gNB->scopeData; @@ -628,7 +628,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, * * PARAMETERS : gNB : gNB data structure * rel15_ul : UL parameters - * UE_id : UE ID + * pusch_vars : PUSCH data * nr_tti_rx : slot rx TTI * dmrs_symbol_flag: DMRS Symbol Flag * symbol : OFDM Symbol @@ -646,25 +646,22 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, // #define DEBUG_UL_PTRS void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t *rel15_ul, - uint8_t ulsch_id, + const nfapi_nr_pusch_pdu_t *rel15_ul, + NR_gNB_PUSCH *pusch_vars, uint8_t nr_tti_rx, unsigned char symbol, uint32_t nb_re_pusch) { - NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; int32_t *ptrs_re_symbol = NULL; int8_t ret = 0; uint8_t symbInSlot = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols; - uint8_t *startSymbIndex = &rel15_ul->start_symbol_index; - uint8_t *nbSymb = &rel15_ul->nr_of_symbols; - uint8_t *L_ptrs = &rel15_ul->pusch_ptrs.ptrs_time_density; - uint8_t *K_ptrs = &rel15_ul->pusch_ptrs.ptrs_freq_density; - uint16_t *dmrsSymbPos = &rel15_ul->ul_dmrs_symb_pos; - uint16_t *ptrsSymbPos = &pusch_vars->ptrs_symbols; - uint8_t *ptrsSymbIdx = &pusch_vars->ptrs_symbol_index; - uint16_t *nb_rb = &rel15_ul->rb_size; - uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset; + uint8_t startSymbIndex = rel15_ul->start_symbol_index; + uint8_t nbSymb = rel15_ul->nr_of_symbols; + uint8_t L_ptrs = rel15_ul->pusch_ptrs.ptrs_time_density; + uint8_t K_ptrs = rel15_ul->pusch_ptrs.ptrs_freq_density; + uint16_t dmrsSymbPos = rel15_ul->ul_dmrs_symb_pos; + 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 */ for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { @@ -673,7 +670,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, *ptrs_re_symbol = 0; phase_per_symbol[symbol].i = 0; /* 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 */ phase_per_symbol[symbol].r = INT16_MAX; // 32767 #ifdef DEBUG_UL_PTRS @@ -683,17 +680,13 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, phase_per_symbol[symbol].r = 0; } - if (symbol == *startSymbIndex) { - *ptrsSymbPos = 0; - set_ptrs_symb_idx(ptrsSymbPos, *nbSymb, *startSymbIndex, 1 << *L_ptrs, *dmrsSymbPos); + if (symbol == startSymbIndex) { + pusch_vars->ptrs_symbols = 0; + 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 */ - if (is_ptrs_symbol(symbol, *ptrsSymbPos)) { - *ptrsSymbIdx = symbol; + if (is_ptrs_symbol(symbol, pusch_vars->ptrs_symbols)) { /*------------------------------------------------------------------------------------------------------- */ /* 1) Estimate common phase error per PTRS symbol */ /*------------------------------------------------------------------------------------------------------- */ @@ -703,9 +696,9 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, rel15_ul->scid, nr_tti_rx, symbol); - nr_ptrs_cpe_estimation(*K_ptrs, - *ptrsReOffset, - *nb_rb, + nr_ptrs_cpe_estimation(K_ptrs, + ptrsReOffset, + nb_rb, rel15_ul->rnti, frame_parms->ofdm_symbol_size, &pusch_vars->rxdataF_comp[aarx][(symbol * nb_re_pusch)], @@ -720,8 +713,8 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, /* 2) Interpolate PTRS estimated value in TD */ /*------------------------------------------------------------------------------------------------------- */ /* If L-PTRS is > 0 then we need interpolation */ - if (*L_ptrs > 0) { - ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t *)phase_per_symbol, *startSymbIndex, *nbSymb); + if (L_ptrs > 0) { + ret = nr_ptrs_process_slot(dmrsSymbPos, pusch_vars->ptrs_symbols, (int16_t *)phase_per_symbol, startSymbIndex, nbSymb); if (ret != 0) { 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, /*------------------------------------------------------------------------------------------------------- */ /* 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 */ /* 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 printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r, phase_per_symbol[i].i); #endif rotate_cpx_vector(&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch], &phase_per_symbol[i], &pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch], - ((*nb_rb) * NR_NB_SC_PER_RB), + (nb_rb * NR_NB_SC_PER_RB), 15); } // if not DMRS Symbol } // symbol loop diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 540a04ec52..34bf64cc51 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -17,7 +17,7 @@ \param Ns slot number (0..19) \param p \param symbol symbol within slot -\param ul_id +\param pusch_vars lower-phy PUSCH info \param bwp_start_subcarrier first allocated subcarrier \param pusch_pdu \param max_ch maximum value of estimated channel @@ -29,10 +29,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, int nl, unsigned short p, unsigned char symbol, - int ul_id, + NR_gNB_PUSCH *pusch_vars, int beam_nb, unsigned short bwp_start_subcarrier, - nfapi_nr_pusch_pdu_t *pusch_pdu, + const nfapi_nr_pusch_pdu_t *pusch_pdu, int *max_ch, uint32_t *nvar, c16_t *pusch_dmrs_slot_mem, @@ -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 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, 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, void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t *rel15_ul, - uint8_t ulsch_id, + const nfapi_nr_pusch_pdu_t *rel15_ul, + NR_gNB_PUSCH *pusch_vars, uint8_t nr_tti_rx, unsigned char symbol, uint32_t nb_re_pusch); diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index c54c9ccc29..dc3cb1950d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -12,72 +12,73 @@ #include "PHY/NR_TRANSPORT/nr_transport_common_proto.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); - memset(l->list, 0, sizeof(l->list)); + int num_prach = 8; + 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); - if (p->frame == -1) - 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); + spsc_q_free(&gNB->prach_ru_queue); + spsc_q_free(&gNB->prach_l1rx_queue); } -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); - 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); + free(p->prach_buf); } -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; - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - // we set only elements as the whole structure has been cleaned when we release it - prach->frame = SFN; - prach->slot = Slot; - prach->num_slots = fmt < 4 ? get_long_prach_dur(fmt, fp->numerology_index) : 1; + const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + const nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; + const nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; + prach_item_t prach = { + .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) { int n_symb = get_nr_prach_duration(prach_pdu->prach_format); 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 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 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, &gNB->common_vars, Slot, @@ -95,20 +96,9 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n bitmap); } } - prach->pdu = *prach_pdu; - 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]; - 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; + bool found = spsc_q_put(&gNB->prach_ru_queue, &prach, sizeof(prach)); + if (!found) + LOG_W(NR_PHY, "%4d.%2d PRACH occ queue is full: dropping PRACH request\n", SFN, Slot); } static void rx_nr_prach_ru_internal(prach_item_t *p, diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index f7497a148a..863903c242 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -11,6 +11,7 @@ #include "PHY/defs_nr_common.h" #include "PHY/defs_gNB.h" +#include "common/utils/fsn.h" #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 - LLR computation This function supports TM1, 2, 3, 5, and 6. @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 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 @@ -159,7 +168,7 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int slot, 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 { uint16_t max_preamble; @@ -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); -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, int frame, int slot, @@ -189,30 +192,32 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, int nr_get_srs_signal(PHY_VARS_gNB *gNB, c16_t **rxdataF, 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, 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)]); -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 slot_rx, uint8_t nb_antennas_rx, uint8_t N_ap, uint8_t N_symb_SRS, uint16_t ofdm_symbol_size, - NR_gNB_SRS_t *srs, - nr_srs_info_t *nr_srs_info, + const NR_gNB_SRS_job_t *srs, 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_time[][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], int16_t *snr_per_rb, uint16_t *timing_advance_offset, int16_t *timing_advance_offset_nsec); 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, c16_t **rxdataF, @@ -227,14 +232,14 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, int frame, int slot, 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, c16_t **rxdataF, int frame, int slot, 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__*/ diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c index 2d7727b55a..51d885cc1e 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -11,30 +11,6 @@ #include "PHY/NR_TRANSPORT/nr_ulsch.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) { LOG_D(PHY, @@ -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) { dump_pusch_pdu(gNB->Mod_id, frame, slot, ulsch_pdu); - int harq_pid = ulsch_pdu->pusch_data.harq_process_id; - NR_gNB_ULSCH_t *ulsch = find_nr_ulsch(gNB, ulsch_pdu->rnti, harq_pid); - if (ulsch == NULL) { - LOG_E(NR_PHY, "No ulsch_id found for rnti %04x\n", ulsch_pdu->rnti); - return; - } + LOG_D(NR_PHY, + "%4d.%2d Programming ULSCH RNTI %04x HARQ PID %d new data indicator %d\n", + frame, + slot, + ulsch_pdu->rnti, + ulsch_pdu->pusch_data.harq_process_id, + ulsch_pdu->pusch_data.new_data_indicator); - ulsch->rnti = ulsch_pdu->rnti; - ulsch->harq_pid = harq_pid; - ulsch->handled = 0; - ulsch->active = true; - ulsch->beam_nb = 0; + NR_gNB_PUSCH_job_t pusch = {.frame = frame, .slot = slot, .pusch_pdu = *ulsch_pdu}; if (gNB->common_vars.beam_id) { 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); - ulsch->beam_nb = beam_index_allocation(gNB->enable_analog_das, + pusch.beam_nb = beam_index_allocation(gNB->enable_analog_das, fapi_beam_idx, &gNB->common_vars, slot, gNB->frame_parms.symbols_per_slot, bitmap); } - ulsch->frame = frame; - ulsch->slot = slot; - - 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); + bool done = spsc_q_put(&gNB->pusch_queue, &pusch, sizeof(pusch)); + if (!done) + LOG_W(NR_PHY, "PUSCH queue is full: dropping PUSCH UE %04x\n", ulsch_pdu->rnti); } void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index b1e932f60d..816ce9a16a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -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, current received frame @param nr_tti_rx, current received TTI - @param G @param ULSCH_ids, array of ULSCH ids @param nb_pusch, number of uplink shared channels */ @@ -32,8 +31,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, NR_DL_FRAME_PARMS *frame_parms, uint32_t frame, uint8_t nr_tti_rx, - uint32_t *G, - uint8_t *ULSCH_ids, + int *ULSCH_ids, int nb_pusch); /*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 29a53ec5a0..9cb6e22c03 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -93,8 +93,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, NR_DL_FRAME_PARMS *frame_parms, uint32_t frame, uint8_t nr_tti_rx, - uint32_t *G, - uint8_t *ULSCH_ids, + int *ULSCH_ids, int nb_pusch) { nrLDPC_TB_decoding_parameters_t TBs[nb_pusch]; @@ -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_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; 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]; - TB_parameters->G = G[pusch_id]; - if (!harq_process) { LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n"); 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 TB_parameters->harq_unique_pid = ULSCH_id; @@ -134,10 +145,9 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, // ------------------------------------------------------------------ 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->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); if (stats) { stats->frame = frame; @@ -149,7 +159,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, if (!harq_process->harq_to_be_cleared) { stats->ulsch_stats.current_Qm = TB_parameters->Qm; 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; } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 82d6b0d99d..684e65699e 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -80,7 +80,7 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF, int rxoffset, int choffset, 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) { uint8_t delta = 0; @@ -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; if (dmrs_symbol_flag == 1) { @@ -186,7 +186,7 @@ static void nr_ulsch_channel_compensation(uint32_t buffer_length, c16_t **rxComp, int nb_layers, 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 output_shift) { @@ -857,11 +857,10 @@ static uint8_t nr_ulsch_mmse_2layers(c16_t **rxdataF_comp, } static void inner_rx(PHY_VARS_gNB *gNB, - int ulsch_id, int slot, NR_DL_FRAME_PARMS *frame_parms, NR_gNB_PUSCH *pusch_vars, - nfapi_nr_pusch_pdu_t *rel15_ul, + const nfapi_nr_pusch_pdu_t *rel15_ul, c16_t **rxF, int16_t **llr, int soffset, @@ -952,7 +951,7 @@ static void inner_rx(PHY_VARS_gNB *gNB, nr_pusch_ptrs_processing(gNB, frame_parms, rel15_ul, - ulsch_id, + pusch_vars, slot, symbol, buffer_length); @@ -1003,8 +1002,8 @@ static void inner_rx(PHY_VARS_gNB *gNB, typedef struct puschSymbolProc_s { PHY_VARS_gNB *gNB; NR_DL_FRAME_PARMS *frame_parms; - nfapi_nr_pusch_pdu_t *rel15_ul; - int ulsch_id; + const nfapi_nr_pusch_pdu_t *rel15_ul; + NR_gNB_PUSCH *pusch_vars; int slot; int startSymbol; int numSymbols; @@ -1023,12 +1022,11 @@ static void nr_pusch_symbol_processing(void *arg) PHY_VARS_gNB *gNB = rdata->gNB; NR_DL_FRAME_PARMS *frame_parms = rdata->frame_parms; - nfapi_nr_pusch_pdu_t *rel15_ul = rdata->rel15_ul; - int ulsch_id = rdata->ulsch_id; + const nfapi_nr_pusch_pdu_t *rel15_ul = rdata->rel15_ul; 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++) { - if (gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol] == 0) + if (pusch_vars->ul_valid_re_per_slot[symbol] == 0) continue; 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); @@ -1038,7 +1036,6 @@ static void nr_pusch_symbol_processing(void *arg) llrss[l] = llrs[l]; inner_rx(gNB, - ulsch_id, slot, frame_parms, pusch_vars, @@ -1047,12 +1044,12 @@ static void nr_pusch_symbol_processing(void *arg) llrss, soffset, symbol, - gNB->pusch_vars[ulsch_id].log2_maxh, + pusch_vars->log2_maxh, rdata->nvar, rdata->rxFext_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 int16_t *llr_ptr = llrs[0]; if (rel15_ul->nrOfLayers != 1) { @@ -1098,12 +1095,16 @@ static uint32_t average_u32(const uint32_t *x, uint16_t 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; - 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; 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); @@ -1159,7 +1160,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t nl, get_dmrs_port(nl, rel15_ul->dmrs_ports), symbol, - ulsch_id, + pusch_vars, beam_nb, bwp_start_subcarrier, rel15_ul, @@ -1261,7 +1262,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t unav_res, rel15_ul->qam_mod_order, rel15_ul->nrOfLayers); - gNB->ulsch[ulsch_id].unav_res = unav_res; + *ret_unav_res = unav_res; // initialize scrambling sequence // 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 rdata->startSymbol = symbol; // Last task processes remainder symbols 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->scramblingSequence = scramblingSequence; rdata->nvar = nvar; diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 8017fb0bc9..fd6bd8ea42 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -33,40 +33,32 @@ //#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) { - for (int i = 0; i < gNB->max_nb_pucch; i++) { - NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; - if (pucch->active == false) { - pucch->frame = frame; - pucch->slot = slot; - pucch->active = true; - pucch->beam_nb = 0; - if (gNB->common_vars.beam_id) { - int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; - int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols); - pucch->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 *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t)); - LOG_D(PHY, - "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_D(PHY, + "%4d.%2d UE %04x Programming PUCCH format %d, nb_harq %d, nb_sr %d, nb_csi %d\n", + frame, + slot, + pucch_pdu->rnti, + pucch_pdu->format_type, + pucch_pdu->bit_len_harq, + pucch_pdu->sr_flag, + pucch_pdu->bit_len_csi_part1); + NR_gNB_PUCCH_job_t pucch = {.frame = frame, .slot = slot, .pucch_pdu = *pucch_pdu}; + if (gNB->common_vars.beam_id) { + int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; + int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols); + pucch.beam_nb = beam_index_allocation(gNB->enable_analog_das, + fapi_beam_idx, + &gNB->common_vars, + slot, + gNB->frame_parms.symbols_per_slot, + bitmap); } - 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; @@ -129,7 +121,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int frame, int slot, 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; 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, int frame, int slot, 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; // pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index fb6f5f648e..b0436cb2d7 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -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) { - bool found = false; - for (int i = 0; i < gNB->max_nb_srs; i++) { - NR_gNB_SRS_t *srs = &gNB->srs[i]; - if (srs->active == false) { - found = true; - srs->frame = frame; - srs->slot = slot; - srs->active = true; - srs->beam_nb = 0; - if (gNB->common_vars.beam_id) { - const uint8_t l0 = gNB->frame_parms.symbols_per_slot - 1 - srs_pdu->time_start_position; - 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; - } + NR_gNB_SRS_job_t srs = {.frame = frame, .slot = slot, .srs_pdu = *srs_pdu}; + if (gNB->common_vars.beam_id) { + const uint8_t l0 = gNB->frame_parms.symbols_per_slot - 1 - srs_pdu->time_start_position; + 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); } - 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, c16_t **rxdataF, 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, 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)]) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 32d03c1010..7de87cc2ee 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -148,11 +148,11 @@ void nr_tx_rotation_and_ofdm_mod(const uint8_t slot, bool was_symbol_used[NR_SYMBOLS_PER_SLOT], bool no_phase_pre_comp); -bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - c16_t **txdataF, - nr_phy_data_tx_t *phy_data, - bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); +void ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + c16_t **txdataF, + const fapi_nr_ul_config_srs_pdu *srs_config_pdu, + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); void clean_UE_harq(PHY_VARS_NR_UE *UE); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index a6fb9d8890..3e627c38cd 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -19,6 +19,7 @@ #include "nfapi_nr_interface_scf.h" #include "common/utils/threadPool/task_ans.h" #include "openair1/PHY/defs_RU.h" +#include "common/utils/ds/spsc_q.h" #define MAX_NUM_RU_PER_gNB 8 #define MAX_PUCCH0_NID 8 @@ -45,14 +46,6 @@ typedef struct { c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L]; } 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 { int nb_id; int Nid[MAX_PUCCH0_NID]; @@ -127,7 +120,7 @@ typedef struct { typedef struct { /// 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 uint8_t round; bool new_rx; @@ -135,8 +128,6 @@ typedef struct { /// 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 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) uint8_t *b; /// 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 { int8_t last_iteration_cnt; /// Status Flag indicating for this ULSCH 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; 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 int beam_nb; /// Frame where current PUCCH pdu was sent @@ -199,21 +197,18 @@ typedef struct { uint32_t slot; /// ULSCH PDU nfapi_nr_pucch_pdu_t pucch_pdu; -} NR_gNB_PUCCH_t; +} NR_gNB_PUCCH_job_t; typedef struct { - bool active; // identifier for concurrent beams int beam_nb; /// Frame where current SRS pdu was received uint32_t frame; /// Slot where current SRS pdu was received uint32_t slot; - /// Measured SNR - int8_t snr; /// ULSCH PDU nfapi_nr_srs_pdu_t srs_pdu; -} NR_gNB_SRS_t; +} NR_gNB_SRS_job_t; typedef struct { /// \brief Pointers (dynamic) to the received data in the frequency domain. @@ -275,6 +270,8 @@ typedef struct { int llr_offset[14]; /// flag to indicate DTX on reception int DTX; + /// delay estimation + delay_t delay; } NR_gNB_PUSCH; /// Context data structure for RX/TX portion of slot processing @@ -369,26 +366,23 @@ typedef struct PHY_VARS_gNB_s { nfapi_nr_ul_tti_request_t UL_tti_req; - int max_nb_pucch; - int max_nb_srs; int max_nb_pdsch; int max_nb_pusch; 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? NR_gNB_DLSCH_t *dlsch; NR_gNB_PRS prs_vars; NR_gNB_PUSCH *pusch_vars; - NR_gNB_PUCCH_t *pucch; - NR_gNB_SRS_t *srs; + spsc_q_t pucch_queue; + spsc_q_t pusch_queue; + spsc_q_t srs_queue; NR_gNB_ULSCH_t *ulsch; NR_gNB_PHY_STATS_t phy_stats[MAX_MOBILES_PER_GNB]; t_nrPolar_params **polarParams; - /// SRS variables - nr_srs_info_t **nr_srs_info; - // reference amplitude for TX int16_t TX_AMP; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index c0326693a2..3f4c29bdaf 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -402,9 +402,6 @@ typedef struct PHY_VARS_NR_UE_s { nrLDPC_coding_interface_t nrLDPC_coding_interface; uint8_t max_ldpc_iterations; - /// SRS variables - nr_srs_info_t *nr_srs_info; - /// CSI variables nr_csi_info_t *nr_csi_info; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 7cd439bcee..8b50f36290 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -77,8 +77,6 @@ typedef enum{ typedef struct { uint8_t k_0_p[MAX_NUM_NR_SRS_AP][MAX_NUM_NR_SRS_SYMBOLS]; uint8_t srs_generated_signal_bits; - c16_t **srs_generated_signal; - bool is_signal_generated; int B_SRS; int C_SRS; int b_hop; diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c index 76ad47a4e2..3bd4746c92 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c @@ -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); } 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]; // 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, 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 (int k = 0; k < M_sc_b_SRS; k++) { - cd_t shift = {cos(alpha_i * k), sin(alpha_i * k)}; - const c16_t tmp = rv_ul_ref_sig[u][v][M_sc_b_SRS_index][k]; - cd_t r_overbar = {tmp.r, tmp.i}; + cf_t shift = {cosf(alpha_i * k), sinf(alpha_i * k)}; + const c16_t r_overbar = rv_ul_ref_sig[u][v][M_sc_b_SRS_index][k]; // cos(x+y) = cos(x)cos(y) - sin(x)sin(y) - cd_t r = cdMul(shift, r_overbar); - c16_t r_amp = {(((int32_t)round((double)amp * r.r / sqrt_N_ap)) >> 15), - (((int32_t)round((double)amp * r.i / sqrt_N_ap)) >> 15)}; + cf_t r = (cf_t) { + .r = shift.r * r_overbar.r - shift.i * r_overbar.i, + .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 int subcarrier_log = subcarrier-subcarrier_offset; diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c index 1c22057064..55c339d7c8 100644 --- a/openair1/SCHED/nfapi_lte_dummy.c +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -16,18 +16,6 @@ int slot_ahead = 6; //uint8_t nfapi_mode=0; 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_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} @@ -70,59 +58,6 @@ void *pnf_nr_p7_thread_start(void *ptr) { 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() { } diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index fcaf2f1c1b..929bf476f3 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -21,20 +21,14 @@ int get_nr_prach_duration(uint8_t 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->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; 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); 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 "[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", frame, - prach_start_slot, + slot, res.max_preamble, 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 if (gNB->prach_energy_counter < NUM_PRACH_RX_FOR_NOISE_ESTIMATE) gNB->prach_energy_counter++; } // if prach_id>0 - rach_ind->slot = prach_start_slot; LOG_D(NR_PHY_RACH, "Freeing PRACH entry\n"); - free_nr_prach_entry(&gNB->prach_list, prach_id); + free_nr_prach_entry(prach_id); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index f3597f47ea..58d9ad398a 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -2,6 +2,7 @@ * SPDX-License-Identifier: LicenseRef-CSSL-1.0 */ +#include "common/utils/fsn.h" #include "PHY/defs_gNB.h" #include "sched_nr.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" @@ -26,22 +27,14 @@ //#define DEBUG_RXDATA //#define SRS_IND_DEBUG -static void nr_fill_indication(PHY_VARS_gNB *gNB, - int frame, - int slot_rx, - int UE_id, - uint8_t harq_pid, - uint8_t crc_flag, - int dtx_flag, - nfapi_nr_crc_t *crc, - nfapi_nr_rx_data_pdu_t *pdu); -static void nr_fill_indication(PHY_VARS_gNB *gNB, +static void nr_fill_indication(const PHY_VARS_gNB *gNB, int frame, int slot_rx, - int ULSCH_id, - uint8_t harq_pid, - uint8_t crc_flag, + const NR_gNB_PUSCH *pusch, + const nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_gNB_PHY_STATS_t *stats, + uint8_t *payload, int dtx_flag, nfapi_nr_crc_t *crc, nfapi_nr_rx_data_pdu_t *pdu); @@ -322,91 +315,33 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, stop_meas(&gNB->phase_comp_stats); } -static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, bool *ulsch_to_decode, NR_UL_IND_t *UL_INFO) +static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int *ulsch_to_decode, int nb_pusch, NR_UL_IND_t *UL_INFO) { + DevAssert(nb_pusch > 0); NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - - int nb_pusch = 0; - for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { - if (ulsch_to_decode[ULSCH_id]) { - nb_pusch++; - } - } - - if (nb_pusch == 0) { - return 0; - } - - uint8_t ULSCH_ids[nb_pusch]; - uint32_t G[nb_pusch]; - int pusch_id = 0; - for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { - - if (ulsch_to_decode[ULSCH_id]) { - - ULSCH_ids[pusch_id] = ULSCH_id; - - nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu; - - uint16_t nb_re_dmrs; - uint16_t start_symbol = pusch_pdu->start_symbol_index; - uint16_t number_symbols = pusch_pdu->nr_of_symbols; - - uint8_t number_dmrs_symbols = 0; - for (int l = start_symbol; l < start_symbol + number_symbols; l++) - number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos)>>l)&0x01; - - if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1) - nb_re_dmrs = 6*pusch_pdu->num_dmrs_cdm_grps_no_data; - else - nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data; - - G[pusch_id] = nr_get_G(pusch_pdu->rb_size, - number_symbols, - nb_re_dmrs, - number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs - gNB->ulsch[ULSCH_id].unav_res, - pusch_pdu->qam_mod_order, - pusch_pdu->nrOfLayers); - AssertFatal(G[pusch_id]>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n", - pusch_pdu->rb_size, - number_symbols, - nb_re_dmrs, - number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs - pusch_pdu->qam_mod_order, - pusch_pdu->nrOfLayers); - LOG_D(PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n", - pusch_pdu->rb_size, - number_symbols, - nb_re_dmrs, - pusch_pdu->ul_dmrs_symb_pos, - number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs - pusch_pdu->qam_mod_order, - pusch_pdu->nrOfLayers); - pusch_id++; - } - } //---------------------------------------------------------- //--------------------- ULSCH decoding --------------------- //---------------------------------------------------------- - int ret_nr_ulsch_decoding = nr_ulsch_decoding(gNB, frame_parms, frame_rx, slot_rx, G, ULSCH_ids, nb_pusch); + int ret_nr_ulsch_decoding = nr_ulsch_decoding(gNB, frame_parms, frame_rx, slot_rx, ulsch_to_decode, nb_pusch); // CRC check per uplink shared channel - for (pusch_id = 0; pusch_id < nb_pusch; pusch_id++) { - uint8_t ULSCH_id = ULSCH_ids[pusch_id]; + for (int pusch_id = 0; pusch_id < nb_pusch; pusch_id++) { + uint8_t ULSCH_id = ulsch_to_decode[pusch_id]; NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id]; NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; - nfapi_nr_pusch_pdu_t *pusch_pdu = &ulsch_harq->ulsch_pdu; + NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti); + const nfapi_nr_pusch_pdu_t *pusch_pdu = &ulsch_harq->ulsch_pdu; bool crc_valid = false; // if all segments are done if (ulsch_harq->processedSegments == ulsch_harq->C) { if (ulsch_harq->C > 1) { - crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, (ulsch_harq->TBS) << 3), crcType(1, (ulsch_harq->TBS) << 3)); + int tbs = pusch_pdu->pusch_data.tb_size; + crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, tbs << 3), crcType(1, tbs << 3)); } else { // When the number of code blocks is 1 (C = 1) and ulsch_harq->processedSegments = 1, we can assume a good TB because of the // CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block @@ -471,8 +406,8 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo T_INT((int)dmrs_port), // dmrs_antenna_port T_INT((int)pusch_pdu->scid), // dmrs_nscid T_INT((int)frame_parms->nb_antennas_rx), // rx antenna - T_INT(((ulsch_harq->TBS) << 3)), // number_of_bits - T_BUFFER((uint8_t *)((ulsch_harq->b)), ((ulsch_harq->TBS) << 3) / 8)); // data + T_INT((pusch_pdu->pusch_data.tb_size << 3)), // number_of_bits + T_BUFFER((uint8_t *)((ulsch_harq->b)), pusch_pdu->pusch_data.tb_size)); // data } #endif @@ -491,9 +426,9 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo pusch_pdu->pusch_data.new_data_indicator, ulsch->active, ulsch_harq->round, - ulsch_harq->TBS, + pusch_pdu->pusch_data.tb_size, ulsch->max_ldpc_iterations); - nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 0, 0, crc, pdu); + nr_fill_indication(gNB, ulsch->frame, ulsch->slot, pusch, pusch_pdu, stats, ulsch->harq_process->b, 0, crc, pdu); LOG_D(PHY, "ULSCH received ok \n"); ulsch->active = false; ulsch_harq->round = 0; @@ -512,10 +447,9 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo ulsch_harq->ulsch_pdu.pusch_data.rv_index, ulsch_harq->ulsch_pdu.rb_start, ulsch_harq->ulsch_pdu.rb_size, - ulsch_harq->TBS); - nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 1, 0, crc, pdu); + pusch_pdu->pusch_data.tb_size); + nr_fill_indication(gNB, ulsch->frame, ulsch->slot, pusch, pusch_pdu, stats, NULL, 0, crc, pdu); gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_NACK"); - ulsch->handled = 1; LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id); ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations; // Setting to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure } @@ -524,24 +458,19 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo return ret_nr_ulsch_decoding; } -static void nr_fill_indication(PHY_VARS_gNB *gNB, +static void nr_fill_indication(const PHY_VARS_gNB *gNB, int frame, int slot_rx, - int ULSCH_id, - uint8_t harq_pid, - uint8_t crc_flag, + const NR_gNB_PUSCH *pusch, + const nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_gNB_PHY_STATS_t *stats, + uint8_t *payload, int dtx_flag, nfapi_nr_crc_t *crc, nfapi_nr_rx_data_pdu_t *pdu) { - NR_UL_gNB_HARQ_t *harq_process = gNB->ulsch[ULSCH_id].harq_process; - NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, gNB->ulsch[ULSCH_id].rnti); - NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id]; - - nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu; - // Get estimated timing advance for MAC - const int sync_pos = gNB->ulsch[ULSCH_id].delay.est_delay; + const int sync_pos = pusch->delay.est_delay; // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048; @@ -562,14 +491,6 @@ static void nr_fill_indication(PHY_VARS_gNB *gNB, timing_advance_update = max(timing_advance_update, 0); timing_advance_update = min(timing_advance_update, 63); - if (crc_flag == 0) - LOG_D(PHY, - "%d.%d : Received PUSCH : Estimated timing advance PUSCH is = %d, timing_advance_update is %d \n", - frame, - slot_rx, - sync_pos, - timing_advance_update); - // estimate UL_CQI for MAC int SNRtimes10 = dB_fixed_x10(pusch->ulsch_power_tot) - dB_fixed_x10(pusch->ulsch_noise_power_tot); @@ -589,8 +510,8 @@ static void nr_fill_indication(PHY_VARS_gNB *gNB, crc->handle = pusch_pdu->handle; crc->rnti = pusch_pdu->rnti; - crc->harq_id = harq_pid; - crc->tb_crc_status = crc_flag; + crc->harq_id = pusch_pdu->pusch_data.harq_process_id; + crc->tb_crc_status = payload == NULL; // 222.10.02/04: pass 0, fail 1 crc->num_cb = pusch_pdu->pusch_data.num_cb; crc->ul_cqi = cqi; crc->timing_advance = timing_advance_update; @@ -599,92 +520,62 @@ static void nr_fill_indication(PHY_VARS_gNB *gNB, pdu->handle = pusch_pdu->handle; pdu->rnti = pusch_pdu->rnti; - pdu->harq_id = harq_pid; + pdu->harq_id = pusch_pdu->pusch_data.harq_process_id; pdu->ul_cqi = cqi; pdu->timing_advance = timing_advance_update; pdu->rssi = crc->rssi; - if (crc_flag) - pdu->pdu_length = 0; - else { - pdu->pdu_length = harq_process->TBS; - pdu->pdu = harq_process->b; - } + pdu->pdu_length = payload != NULL ? pusch_pdu->pusch_data.tb_size : 0; + pdu->pdu = payload; } // Function to fill UL RB mask to be used for N0 measurements static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, - int frame_rx, - int slot_rx, - uint32_t rb_mask_ul[14][9], - nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf) + fsn_t now, + uint32_t rb_mask_ul[14][MAX_BWP_SIZE], + const NR_gNB_PUCCH_job_t *pucch, + int n_pucch, + const NR_gNB_PUSCH_job_t *pusch, + int n_pusch, + const NR_gNB_SRS_job_t *srs, + int n_srs) { for (int symbol = 0; symbol < 14; symbol++) { - for (int m = 0; m < 9; m++) { - rb_mask_ul[symbol][m] = 0; - for (int i = 0; i < 32; i++) { - int prbpos = (m * 32) + i; - if (prbpos > gNB->frame_parms.N_RB_UL) - break; - rb_mask_ul[symbol][m] |= (gNB->ulprbbl[prbpos] > 0 ? 1U : 0) << i; - } + for (int prb = 0; prb < MAX_BWP_SIZE; prb++) { + rb_mask_ul[symbol][prb] = gNB->ulprbbl[prb] > 0; } } - for (int i = 0; i < gNB->max_nb_pucch; i++){ - const NR_gNB_PUCCH_t *pucch = gNB->pucch + i; - if (!(pucch && pucch->active && pucch->frame == frame_rx && pucch->slot == slot_rx)) - continue; - const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; + for (int i = 0; i < n_pucch; ++i) { + const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch[i].pucch_pdu; const int start = pucch_pdu->start_symbol_index; - LOG_D(PHY, - "%d.%d pucch %d : start_symbol %d, nb_symbols %d, prb_size %d\n", - frame_rx, - slot_rx, - i, - start, - pucch_pdu->nr_of_symbols, - pucch_pdu->prb_size); - for (int symbol = start; symbol < (start + pucch_pdu->nr_of_symbols); symbol++) { - if (gNB->frame_parms.frame_type == FDD || (gNB->frame_parms.frame_type == TDD && slot_conf[symbol].slot_config.value == 1)) { - for (int rb = 0; rb < pucch_pdu->prb_size; rb++) { - int rb2 = - rb + pucch_pdu->bwp_start - + ((symbol < start + (pucch_pdu->nr_of_symbols >> 1)) || (pucch_pdu->freq_hop_flag == 0) ? pucch_pdu->prb_start - : pucch_pdu->second_hop_prb); - rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31); - } + for (int symbol = start; symbol < start + pucch_pdu->nr_of_symbols; symbol++) { + bool first_hop = symbol < start + (pucch_pdu->nr_of_symbols >> 1); + int prb_first_second = first_hop || pucch_pdu->freq_hop_flag == 0 ? pucch_pdu->prb_start : pucch_pdu->second_hop_prb; + for (int rb = 0; rb < pucch_pdu->prb_size; rb++) { + int prb = rb + pucch_pdu->bwp_start + prb_first_second; + rb_mask_ul[symbol][prb] = 1; } } } - for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { - NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; - NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; - AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); - if (!(ulsch->active && ulsch->frame == frame_rx && ulsch->slot == slot_rx && !ulsch->handled)) - continue; - uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; - uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; + for (int i = 0; i < n_pusch; i++) { + const nfapi_nr_pusch_pdu_t *pusch_pdu = &pusch[i].pusch_pdu; + uint8_t symbol_start = pusch_pdu->start_symbol_index; + uint8_t symbol_end = symbol_start + pusch_pdu->nr_of_symbols; for (int symbol = symbol_start; symbol < symbol_end; symbol++) { - if (gNB->frame_parms.frame_type == FDD || (gNB->frame_parms.frame_type == TDD && slot_conf[symbol].slot_config.value == 1)) { - LOG_D(PHY, "symbol %d Filling rb_mask_ul rb_size %d\n", symbol, ulsch_harq->ulsch_pdu.rb_size); - for (int rb = 0; rb < ulsch_harq->ulsch_pdu.rb_size; rb++) { - int rb2 = rb + ulsch_harq->ulsch_pdu.rb_start + ulsch_harq->ulsch_pdu.bwp_start; - rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31); - } + for (int rb = 0; rb < pusch_pdu->rb_size; rb++) { + int prb = rb + pusch_pdu->rb_start + pusch_pdu->bwp_start; + rb_mask_ul[symbol][prb] = 1; } } } - for (int i = 0; i < gNB->max_nb_srs; i++) { - NR_gNB_SRS_t *srs = &gNB->srs[i]; - if (!(srs && srs->active && srs->frame == frame_rx && srs->slot == slot_rx)) - continue; - nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; + for (int i = 0; i < n_srs; i++) { + const nfapi_nr_srs_pdu_t *srs_pdu = &srs[i].srs_pdu; const uint8_t l0 = gNB->frame_parms.symbols_per_slot - 1 - srs_pdu->time_start_position; for (int symbol = 0; symbol < (1 << srs_pdu->num_symbols); symbol++) { for (int rb = srs_pdu->bwp_start; rb < (srs_pdu->bwp_start + srs_pdu->bwp_size); rb++) { - rb_mask_ul[l0 + symbol][rb >> 5] |= 1U << (rb & 31); + rb_mask_ul[l0 + symbol][rb] = 1; } } } @@ -785,66 +676,46 @@ static void copy_srs_info(const nfapi_nr_srs_pdu_t *srs_config_pdu, nr_srs_info_ nr_srs_info->resource_type = srs_config_pdu->resource_type; } -static bool srs_has_changed(const nfapi_nr_srs_pdu_t *srs_config_pdu, nr_srs_info_t *nr_srs_info) -{ - return nr_srs_info->B_SRS != srs_config_pdu->bandwidth_index - || nr_srs_info->C_SRS != srs_config_pdu->config_index - || nr_srs_info->b_hop != srs_config_pdu->frequency_hopping - || nr_srs_info->comb_size != srs_config_pdu->comb_size - || nr_srs_info->K_TC_overbar != srs_config_pdu->comb_offset - || nr_srs_info->n_SRS_cs != srs_config_pdu->cyclic_shift - || nr_srs_info->n_ID_SRS != srs_config_pdu->sequence_id - || nr_srs_info->n_shift != srs_config_pdu->frequency_position - || nr_srs_info->n_RRC != srs_config_pdu->frequency_shift - || nr_srs_info->groupOrSequenceHopping != srs_config_pdu->group_or_sequence_hopping - || nr_srs_info->l_offset != srs_config_pdu->time_start_position - || nr_srs_info->T_SRS != srs_config_pdu->t_srs - || nr_srs_info->T_offset != srs_config_pdu->t_offset - || nr_srs_info->R != 1 << srs_config_pdu->num_repetitions - || nr_srs_info->N_symb_SRS != 1 << srs_config_pdu->num_symbols - || nr_srs_info->n_srs_ports != 1 << srs_config_pdu->num_ant_ports - || nr_srs_info->resource_type != srs_config_pdu->resource_type; -} - -static bool check_and_configure_srs_info(nfapi_nr_srs_pdu_t *srs_config_pdu, nr_srs_info_t *nr_srs_info) -{ - if (srs_has_changed(srs_config_pdu, nr_srs_info)) { - copy_srs_info(srs_config_pdu, nr_srs_info); - return true; - } - return false; -} - -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 slot_rx, uint8_t nb_antennas_rx, uint8_t N_ap, uint8_t N_symb_SRS, uint16_t ofdm_symbol_size, - NR_gNB_SRS_t *srs, - nr_srs_info_t *nr_srs_info, + const NR_gNB_SRS_job_t *srs, 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_time[][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], int16_t *snr_per_rb, uint16_t *timing_advance_offset, int16_t *timing_advance_offset_nsec) { NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; + const nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; + + c16_t srs_estimated_channel_time[nb_antennas_rx][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size] + __attribute__((aligned(32))); c16_t srs_received_signal[nb_antennas_rx][ofdm_symbol_size * N_symb_SRS]; c16_t srs_received_noise[nb_antennas_rx][ofdm_symbol_size * N_symb_SRS]; c16_t srs_estimated_channel_time_shifted[nb_antennas_rx][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size]; start_meas(&gNB->generate_srs_stats); - if (check_and_configure_srs_info(srs_pdu, nr_srs_info)) { + nr_srs_info_t nr_srs_info = {0}; + copy_srs_info(srs_pdu, &nr_srs_info); + + // TODO permanently allocate? + c16_t srs_generated_signal_tmp[N_ap][ofdm_symbol_size * MAX_NUM_NR_SRS_SYMBOLS]; + c16_t *srs_generated_signal[N_ap]; + for (int i = 0; i < N_ap; ++i) + srs_generated_signal[i] = srs_generated_signal_tmp[i]; + if (true) { generate_srs_nr(frame_parms, - nr_srs_info->srs_generated_signal, + srs_generated_signal, 0, srs_pdu->bwp_start, - nr_srs_info, + &nr_srs_info, AMP, frame_rx, slot_rx, @@ -854,7 +725,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, stop_meas(&gNB->generate_srs_stats); c16_t **rxdataF = gNB->common_vars.rxdataF[srs->beam_nb]; start_meas(&gNB->get_srs_signal_stats); - *srs_est = nr_get_srs_signal(gNB, rxdataF, slot_rx, srs_pdu, nr_srs_info, srs_received_signal, srs_received_noise); + *srs_est = nr_get_srs_signal(gNB, rxdataF, slot_rx, srs_pdu, &nr_srs_info, srs_received_signal, srs_received_noise); stop_meas(&gNB->get_srs_signal_stats); uint32_t signal_power_avg = 0; @@ -873,8 +744,8 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, frame_parms->first_carrier_offset, N_symb_SRS, srs_pdu, - nr_srs_info, - nr_srs_info->srs_generated_signal[p_ind], + &nr_srs_info, + srs_generated_signal[p_ind], srs_received_signal[ant_rx_ind], srs_ls_estimated_channel[ant_rx_ind][p_ind], &delay_aux); @@ -892,7 +763,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, frame_parms->first_carrier_offset, N_symb_SRS, srs_pdu, - nr_srs_info, + &nr_srs_info, srs_ls_estimated_channel[ant_rx_ind][p_ind], delay.est_delay, srs_received_noise[ant_rx_ind], @@ -937,7 +808,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, frame_parms->first_carrier_offset, N_symb_SRS, srs_pdu, - nr_srs_info, + &nr_srs_info, signal_power_avg, srs_received_noise[ant_rx_ind], &noise_power_per_ant, @@ -946,7 +817,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, } noise_power_avg /= nb_antennas_rx; - gNB->srs->snr = dB_fixed(signal_power_avg) - dB_fixed(max(noise_power_avg, 1)); + *snr = dB_fixed(signal_power_avg) - dB_fixed(max(noise_power_avg, 1)); const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index); for (int rb = 0; rb < m_SRS_b; rb++) { @@ -981,29 +852,362 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, T_INT(slot_rx), T_BUFFER(timing_advance_offset_nsec, nb_antennas_rx * sizeof(int16_t))); } + return nr_srs_info; +} + +static void handle_srs(fsn_t now, PHY_VARS_gNB *gNB, const NR_gNB_SRS_job_t *srs, nfapi_nr_srs_indication_pdu_t *srs_indication) +{ + const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + const uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; + const uint16_t ofdm_symbol_size = frame_parms->ofdm_symbol_size; + const nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; + + uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols; + uint8_t N_ap = 1 << srs_pdu->num_ant_ports; + int16_t snr_per_rb[srs_pdu->bwp_size]; + uint16_t timing_advance_offset; + int16_t timing_advance_offset_nsec[nb_antennas_rx]; + int srs_est; + + c16_t srs_estimated_channel_freq[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); + + int8_t snr; + nr_srs_info_t srs_info = nr_srs_rx_procedures(gNB, + now.f, + now.s, + nb_antennas_rx, + N_ap, + N_symb_SRS, + ofdm_symbol_size, + srs, + &srs_est, + &snr, + srs_estimated_channel_freq, + snr_per_rb, + &timing_advance_offset, + timing_advance_offset_nsec); + + if ((snr * 10) < gNB->srs_thres) { + srs_est = -1; + } + + srs_indication->handle = srs_pdu->handle; + srs_indication->rnti = srs_pdu->rnti; + srs_indication->timing_advance_offset = srs_est >= 0 ? timing_advance_offset : 0xFFFF; + // TODO: currently we fill timing_advance_offset_nsec for antenna 0. Need to extend it for other antennas + srs_indication->timing_advance_offset_nsec = srs_est >= 0 ? timing_advance_offset_nsec[0] : 0x8000; + switch (srs_pdu->srs_parameters_v4.usage) { + case 0: + LOG_W(NR_PHY, "SRS report was not requested by MAC\n"); + return; + case 1 << NFAPI_NR_SRS_BEAMMANAGEMENT: + srs_indication->srs_usage = NFAPI_NR_SRS_BEAMMANAGEMENT; + break; + case 1 << NFAPI_NR_SRS_CODEBOOK: + srs_indication->srs_usage = NFAPI_NR_SRS_CODEBOOK; + break; + case 1 << NFAPI_NR_SRS_NONCODEBOOK: + srs_indication->srs_usage = NFAPI_NR_SRS_NONCODEBOOK; + break; + case 1 << NFAPI_NR_SRS_ANTENNASWITCH: + srs_indication->srs_usage = NFAPI_NR_SRS_ANTENNASWITCH; + break; + default: + LOG_E(NR_PHY, "Invalid srs_pdu->srs_parameters_v4.usage %i\n", srs_pdu->srs_parameters_v4.usage); + } + srs_indication->report_type = srs_pdu->srs_parameters_v4.report_type[0]; + + nfapi_srs_report_tlv_t *report_tlv = &srs_indication->report_tlv; + report_tlv->tag = 0; + report_tlv->length = 0; + + start_meas(&gNB->srs_report_tlv_stats); + switch (srs_indication->srs_usage) { + case NFAPI_NR_SRS_BEAMMANAGEMENT: { + start_meas(&gNB->srs_beam_report_stats); + nfapi_nr_srs_beamforming_report_t nr_srs_bf_report; + nr_srs_bf_report.prg_size = srs_pdu->beamforming.prg_size; + nr_srs_bf_report.num_symbols = N_symb_SRS; + nr_srs_bf_report.wide_band_snr = srs_est >= 0 ? (snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid + nr_srs_bf_report.num_reported_symbols = N_symb_SRS; + AssertFatal(nr_srs_bf_report.num_reported_symbols == 1, + "nr_srs_bf_report.num_reported_symbols %i not handled yet!\n", + nr_srs_bf_report.num_reported_symbols); + fill_srs_reported_symbol(&nr_srs_bf_report.reported_symbol_list[0], srs_pdu, snr_per_rb, srs_est); + + report_tlv->length = pack_nr_srs_beamforming_report(&nr_srs_bf_report, report_tlv->value, sizeof(report_tlv->value)); + stop_meas(&gNB->srs_beam_report_stats); + break; + } + + case NFAPI_NR_SRS_CODEBOOK: { + start_meas(&gNB->srs_iq_matrix_stats); + nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_channel_iq_matrix; + fill_srs_channel_matrix(&nr_srs_channel_iq_matrix, + srs_pdu, + &srs_info, + frame_parms, + srs_estimated_channel_freq); + + report_tlv->length = + pack_nr_srs_normalized_channel_iq_matrix(&nr_srs_channel_iq_matrix, report_tlv->value, sizeof(report_tlv->value)); + stop_meas(&gNB->srs_iq_matrix_stats); + break; + } + + case NFAPI_NR_SRS_NONCODEBOOK: + case NFAPI_NR_SRS_ANTENNASWITCH: + LOG_W(NR_PHY, "PHY procedures for this SRS usage are not implemented yet!\n"); + break; + + default: + AssertFatal(1 == 0, "Invalid SRS usage\n"); + } + stop_meas(&gNB->srs_report_tlv_stats); +} + +static void handle_pucch(PHY_VARS_gNB *gNB, c16_t **rxdataF, const NR_gNB_PUCCH_job_t *pucch, nfapi_nr_uci_t *uci) +{ + const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; + + switch (pucch_pdu->format_type) { + case 0: + uci->pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE; + uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t); + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &uci->pucch_pdu_format_0_1; + nr_decode_pucch0(gNB, rxdataF, pucch->frame, pucch->slot, uci_pdu_format0, pucch_pdu); + break; + case 2: + uci->pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE; + uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t); + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &uci->pucch_pdu_format_2_3_4; + nr_decode_pucch2(gNB, rxdataF, pucch->frame, pucch->slot, uci_pdu_format2, pucch_pdu); + break; + default: + AssertFatal(1 == 0, "Only PUCCH formats 0 and 2 are currently supported\n"); + } +} + +static bool handle_pusch_decode_trigger(PHY_VARS_gNB *gNB, NR_gNB_PUSCH *pusch_vars, NR_gNB_ULSCH_t *ulsch, NR_UL_IND_t *UL_INFO, int *pusch_DTX) +{ + NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; + AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); + const nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu; + +#ifdef DEBUG_RXDATA + RU_t *ru = gNB->RU_list[0]; + int slot_offset = frame_parms->get_samples_slot_timestamp(ulsch->slot, frame_parms, 0); + slot_offset -= ru->N_TA_offset; + int32_t sample_offset = gNB->common_vars.debugBuff_sample_offset; + int16_t buf = (int16_t *)&gNB->common_vars.debugBuff[offset]; + buf[0] = (int16_t)ulsch->rnti; + buf[1] = (int16_t)pdu->rb_size; + buf[2] = (int16_t)pdu->rb_start; + buf[3] = (int16_t)pdu->nr_of_symbols; + buf[4] = (int16_t)pdu->start_symbol_index; + buf[5] = (int16_t)pdu->mcs_index; + buf[6] = (int16_t)pdu->pusch_data.rv_index; + buf[7] = (int16_t)ulsch->harq_pid; + memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset + 4], + &ru->common.rxdata[0][slot_offset], + frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) * sizeof(int32_t)); + gNB->common_vars.debugBuff_sample_offset += (frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) + 1000 + 4); + if (gNB->common_vars.debugBuff_sample_offset > ((frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) + 1000 + 2) * 20)) { + FILE *f; + f = fopen("rxdata_buff.raw", "w"); + if (f == NULL) + exit(1); + fwrite((int16_t *)gNB->common_vars.debugBuff, + 2, + (frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) + 1000 + 4) * 20 * 2, + f); + fclose(f); + exit(-1); + } +#endif + + start_meas(&gNB->rx_pusch_stats); + nr_rx_pusch_tp(gNB, pusch_vars, pdu, &ulsch->unav_res, ulsch->frame, ulsch->slot, ulsch->beam_nb); + pusch_vars->ulsch_power_tot = 0; + pusch_vars->ulsch_noise_power_tot = 0; + for (int aarx = 0; aarx < gNB->frame_parms.nb_antennas_rx; aarx++) { + pusch_vars->ulsch_power_tot += pusch_vars->ulsch_power[aarx]; + pusch_vars->ulsch_noise_power_tot += pusch_vars->ulsch_noise_power[aarx]; + } + if (dB_fixed_x10(pusch_vars->ulsch_power_tot) < dB_fixed_x10(pusch_vars->ulsch_noise_power_tot) + gNB->pusch_thres) { + NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti); + + LOG_D(PHY, + "PUSCH not detected in %d.%d (%d,%d,%d)\n", + ulsch->frame, + ulsch->slot, + dB_fixed_x10(pusch_vars->ulsch_power_tot), + dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), + gNB->pusch_thres); + pusch_vars->ulsch_power_tot = pusch_vars->ulsch_noise_power_tot; + pusch_vars->DTX = 1; + if (stats) + stats->ulsch_stats.DTX++; + if (!get_softmodem_params()->phy_test) { + /* in case of phy_test mode, we still want to decode to measure execution time. + Therefore, we don't yet call nr_fill_indication, it will be called later */ + nfapi_nr_crc_t *crc = &UL_INFO->crc_ind.crc_list[UL_INFO->crc_ind.number_crcs++]; + nfapi_nr_rx_data_pdu_t *rx = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++]; + nr_fill_indication(gNB, ulsch->frame, ulsch->slot, pusch_vars, pdu, stats, NULL, 1, crc, rx); + (*pusch_DTX)++; + gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX"); + return false; + } + } else { + LOG_D(PHY, + "PUSCH detected in %d.%d (%d,%d,%d)\n", + ulsch->frame, + ulsch->slot, + dB_fixed_x10(pusch_vars->ulsch_power_tot), + dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), + gNB->pusch_thres); + + pusch_vars->DTX = 0; + } + stop_meas(&gNB->rx_pusch_stats); + + return true; +} + +static bool drop_old_pucch(const void *data, void *user) +{ + const NR_gNB_PUCCH_job_t *pucch = data; + const fsn_t *now = user; + const fsn_t t = {pucch->frame, pucch->slot, now->mu}; + bool drop = fsn_in_the_past(t, *now); + if (drop) + LOG_E(NR_PHY, "%4d.%2d PUCCH job for UE %04x is in the past (%4d.%2d)\n", now->f, now->s, pucch->pucch_pdu.rnti, t.f, t.s); + return drop; +} + +static bool get_current_pucch(const void *data, void *user) +{ + const NR_gNB_PUCCH_job_t *pucch = data; + const fsn_t *now = user; + const fsn_t t = {pucch->frame, pucch->slot, now->mu}; + return fsn_equal(t, *now); +} + +static bool drop_old_pusch(const void *data, void *user) +{ + const NR_gNB_PUSCH_job_t *pusch = data; + const fsn_t *now = user; + const fsn_t t = {pusch->frame, pusch->slot, now->mu}; + bool drop = fsn_in_the_past(t, *now); + if (drop) + LOG_E(NR_PHY, "%4d.%2d PUSCH job for UE %04x is in the past (%4d.%2d)\n", now->f, now->s, pusch->pusch_pdu.rnti, t.f, t.s); + return drop; +} + +static bool get_current_pusch(const void *data, void *user) +{ + const NR_gNB_PUSCH_job_t *pusch = data; + const fsn_t *now = user; + const fsn_t t = {pusch->frame, pusch->slot, now->mu}; + return fsn_equal(t, *now); +} + +static bool drop_old_srs(const void *data, void *user) +{ + const NR_gNB_SRS_job_t *srs = data; + const fsn_t *now = user; + const fsn_t t = {srs->frame, srs->slot, now->mu}; + bool drop = fsn_in_the_past(t, *now); + if (drop) + LOG_E(NR_PHY, "%4d.%2d SRS job for UE %04x is in the past (%4d.%2d)\n", now->f, now->s, srs->srs_pdu.rnti, t.f, t.s); + return drop; +} + +static bool get_current_srs(const void *data, void *user) +{ + const NR_gNB_SRS_job_t *srs = data; + const fsn_t *now = user; + const fsn_t t = {srs->frame, srs->slot, now->mu}; + return fsn_equal(t, *now); +} + +static int find_nr_ulsch_idx(PHY_VARS_gNB *gNB, uint16_t rnti, int pid) +{ + AssertFatal(gNB != NULL, "gNB is null\n"); + + int16_t first_free_index = -1; + for (int i = 0; i < gNB->max_nb_pusch; i++) { + const NR_gNB_ULSCH_t *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 i; + } + } + return first_free_index; +} +static int handle_pusch_job_trigger(PHY_VARS_gNB *gNB, const NR_gNB_PUSCH_job_t *job) +{ + const nfapi_nr_pusch_pdu_t *pdu = &job->pusch_pdu; + int pid = pdu->pusch_data.harq_process_id; + int ULSCH_id = find_nr_ulsch_idx(gNB, pdu->rnti, pid); + if (ULSCH_id < 0) { + LOG_E(NR_PHY, "%4d.%2d cannot handle PUSCH job of RNTI %04x: no space\n", job->frame, job->slot, pdu->rnti); + return -1; + } + /* (re-)initialize this PUSCH context from job data */ + NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; + ulsch->active = true; + ulsch->frame = job->frame; + ulsch->slot = job->slot; + ulsch->rnti = pdu->rnti; + ulsch->harq_pid = pid; + ulsch->beam_nb = job->beam_nb; + ulsch->harq_process->ulsch_pdu = job->pusch_pdu; + if (pdu->pusch_data.new_data_indicator) { + ulsch->harq_process->harq_to_be_cleared = true; + ulsch->harq_process->round = 0; + } else { + ulsch->harq_process->round++; + } + return ULSCH_id; } int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO) { /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */ - int pucch_decode_done = 0; - int pusch_decode_done = 0; int pusch_DTX = 0; const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; const uint16_t ofdm_symbol_size = frame_parms->ofdm_symbol_size; - const uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; + + fsn_t now = {frame_rx, slot_rx, frame_parms->numerology_index}; + + spsc_q_drop_while(&gNB->pucch_queue, drop_old_pucch, &now); + NR_gNB_PUCCH_job_t pucch[MAX_NUM_NR_UCI_PDUS]; + int n_pucch = spsc_q_get_while(&gNB->pucch_queue, get_current_pucch, &now, pucch, sizeof(*pucch), MAX_NUM_NR_UCI_PDUS); + + spsc_q_drop_while(&gNB->pusch_queue, drop_old_pusch, &now); + NR_gNB_PUSCH_job_t pusch[MAX_UL_PDUS_PER_SLOT]; + int n_pusch_jobs = spsc_q_get_while(&gNB->pusch_queue, get_current_pusch, &now, pusch, sizeof(*pusch), MAX_UL_PDUS_PER_SLOT); + + spsc_q_drop_while(&gNB->srs_queue, drop_old_srs, &now); + NR_gNB_SRS_job_t srs[MAX_NUM_NR_SRS_PDUS]; + int n_srs = spsc_q_get_while(&gNB->srs_queue, get_current_srs, &now, srs, sizeof(*srs), MAX_NUM_NR_SRS_PDUS); + LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); { // Mask of occupied RBs, per symbol and PRB - uint32_t rb_mask_ul[14][9]; - nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf = NULL; - if (frame_parms->frame_type == TDD) - slot_conf = gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list; - fill_ul_rb_mask(gNB, frame_rx, slot_rx, rb_mask_ul, slot_conf); + uint32_t rb_mask_ul[14][MAX_BWP_SIZE] = {0}; + fill_ul_rb_mask(gNB, now, rb_mask_ul, pucch, n_pucch, pusch, n_pusch_jobs, srs, n_srs); int first_symb = 0, num_symb = 0; - if (frame_parms->frame_type == TDD) + if (frame_parms->frame_type == TDD) { + const nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf = gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list; for (int symbol_count = 0; symbol_count < frame_parms->symbols_per_slot; symbol_count++) { if (slot_conf[symbol_count].slot_config.value == 1) { if (num_symb == 0) @@ -1011,51 +1215,21 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N num_symb++; } } - else + } else { num_symb = frame_parms->symbols_per_slot; + } gNB_I0_measurements(gNB, slot_rx, first_symb, num_symb, rb_mask_ul); } - const int soffset = (slot_rx & 3) * frame_parms->symbols_per_slot * ofdm_symbol_size; start_meas(&gNB->phy_proc_rx); - - for (int i = 0; i < gNB->max_nb_pucch; i++) { - NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; - if (!(pucch && pucch->active && pucch->frame == frame_rx && pucch->slot == slot_rx)) - continue; + UL_INFO->uci_ind.uci_list = UL_INFO->uci_pdu_list; + UL_INFO->uci_ind.sfn = frame_rx; + UL_INFO->uci_ind.slot = slot_rx; + UL_INFO->uci_ind.num_ucis = n_pucch; + nfapi_nr_uci_t *uci = UL_INFO->uci_ind.uci_list; + for (int i = 0; i < n_pucch; ++i) { c16_t **rxdataF = gNB->common_vars.rxdataF[pucch->beam_nb]; - pucch_decode_done = 1; - nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; - UL_INFO->uci_ind.uci_list = UL_INFO->uci_pdu_list; - nfapi_nr_uci_t *uci = UL_INFO->uci_ind.uci_list + UL_INFO->uci_ind.num_ucis; - UL_INFO->uci_ind.sfn = frame_rx; - UL_INFO->uci_ind.slot = slot_rx; - switch (pucch_pdu->format_type) { - case 0: - uci->pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE; - uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t); - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &uci->pucch_pdu_format_0_1; - int offset = - pucch_pdu->start_symbol_index * ofdm_symbol_size + (frame_parms->first_carrier_offset + pucch_pdu->prb_start * 12); - LOG_D(NR_PHY, - "frame %d, slot %d: PUCCH signal energy %d\n", - frame_rx, - slot_rx, - signal_energy_nodc(&rxdataF[0][soffset + offset], 12)); - nr_decode_pucch0(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format0, pucch_pdu); - break; - case 2: - uci->pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE; - uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t); - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &uci->pucch_pdu_format_2_3_4; - LOG_D(PHY, "%d.%d Calling nr_decode_pucch2\n", frame_rx, slot_rx); - nr_decode_pucch2(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format2, pucch_pdu); - break; - default: - AssertFatal(1 == 0, "Only PUCCH formats 0 and 2 are currently supported\n"); - } - UL_INFO->uci_ind.num_ucis += 1; - pucch->active = false; + handle_pucch(gNB, rxdataF, &pucch[i], uci++); } UL_INFO->crc_ind.sfn = frame_rx; @@ -1064,95 +1238,16 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N UL_INFO->rx_ind.sfn = frame_rx; UL_INFO->rx_ind.slot = slot_rx; UL_INFO->rx_ind.pdu_list = UL_INFO->rx_pdu_list; - bool ulsch_to_decode[gNB->max_nb_pusch]; - bzero(ulsch_to_decode, sizeof(ulsch_to_decode)); - for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { - NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; - NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; - AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); - if (!(ulsch->active && ulsch->frame == frame_rx && ulsch->slot == slot_rx && !ulsch->handled)) + int ulsch_idx_to_decode[MAX_UL_PDUS_PER_SLOT]; + int num_pusch = 0; + for (int i = 0; i < n_pusch_jobs; ++i) { + int ULSCH_id = handle_pusch_job_trigger(gNB, &pusch[i]); + if (ULSCH_id < 0) continue; - LOG_D(PHY, "PUSCH ID %d with RNTI %x detection started in frame %d slot %d\n", ULSCH_id, ulsch->rnti, frame_rx, slot_rx); - -#ifdef DEBUG_RXDATA - RU_t *ru = gNB->RU_list[0]; - int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx, frame_parms, 0); - slot_offset -= ru->N_TA_offset; - int32_t sample_offset = gNB->common_vars.debugBuff_sample_offset; - int16_t buf = (int16_t *)&gNB->common_vars.debugBuff[offset]; - buf[0] = (int16_t)ulsch->rnti; - buf[1] = (int16_t)pdu->rb_size; - buf[2] = (int16_t)pdu->rb_start; - buf[3] = (int16_t)pdu->nr_of_symbols; - buf[4] = (int16_t)pdu->start_symbol_index; - buf[5] = (int16_t)pdu->mcs_index; - buf[6] = (int16_t)pdu->pusch_data.rv_index; - buf[7] = (int16_t)ulsch->harq_pid; - memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset + 4], - &ru->common.rxdata[0][slot_offset], - get_samples_per_slot(slot_rx, frame_parms) * sizeof(int32_t)); - gNB->common_vars.debugBuff_sample_offset += (get_samples_per_slot(slot_rx, frame_parms) + 1000 + 4); - if (gNB->common_vars.debugBuff_sample_offset > ((get_samples_per_slot(slot_rx, frame_parms) + 1000 + 2) * 20)) { - FILE *f; - f = fopen("rxdata_buff.raw", "w"); - if (f == NULL) - exit(1); - fwrite((int16_t *)gNB->common_vars.debugBuff, 2, (get_samples_per_slot(slot_rx, frame_parms) + 1000 + 4) * 20 * 2, f); - fclose(f); - exit(-1); - } -#endif - - pusch_decode_done = 1; - - start_meas(&gNB->rx_pusch_stats); - nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->beam_nb); NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; - pusch_vars->ulsch_power_tot = 0; - pusch_vars->ulsch_noise_power_tot = 0; - for (int aarx = 0; aarx < nb_antennas_rx; aarx++) { - pusch_vars->ulsch_power_tot += pusch_vars->ulsch_power[aarx]; - pusch_vars->ulsch_noise_power_tot += pusch_vars->ulsch_noise_power[aarx]; - } - if (dB_fixed_x10(pusch_vars->ulsch_power_tot) < dB_fixed_x10(pusch_vars->ulsch_noise_power_tot) + gNB->pusch_thres) { - NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti); - - LOG_D(PHY, - "PUSCH not detected in %d.%d (%d,%d,%d)\n", - frame_rx, - slot_rx, - dB_fixed_x10(pusch_vars->ulsch_power_tot), - dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), - gNB->pusch_thres); - pusch_vars->ulsch_power_tot = pusch_vars->ulsch_noise_power_tot; - pusch_vars->DTX = 1; - if (stats) - stats->ulsch_stats.DTX++; - if (!get_softmodem_params()->phy_test) { - /* in case of phy_test mode, we still want to decode to measure execution time. - Therefore, we don't yet call nr_fill_indication, it will be called later */ - nfapi_nr_crc_t *crc = &UL_INFO->crc_ind.crc_list[UL_INFO->crc_ind.number_crcs++]; - nfapi_nr_rx_data_pdu_t *pdu = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++]; - nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1, crc, pdu); - pusch_DTX++; - gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX"); - continue; - } - } else { - LOG_D(PHY, - "PUSCH detected in %d.%d (%d,%d,%d)\n", - frame_rx, - slot_rx, - dB_fixed_x10(pusch_vars->ulsch_power_tot), - dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), - gNB->pusch_thres); - - pusch_vars->DTX = 0; - } - ulsch_to_decode[ULSCH_id] = true; - stop_meas(&gNB->rx_pusch_stats); - // LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); - // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); + NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; + if (handle_pusch_decode_trigger(gNB, pusch_vars, ulsch, UL_INFO, &pusch_DTX)) + ulsch_idx_to_decode[num_pusch++] = ULSCH_id; } /* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1 @@ -1162,9 +1257,10 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N if (gNB->max_nb_pusch == 1) start_meas(&gNB->ulsch_decoding_stats); - int const ret_nr_ulsch_procedures = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ulsch_to_decode, UL_INFO); - if (ret_nr_ulsch_procedures != 0) { - LOG_E(PHY,"Error in nr_ulsch_procedures, returned %d\n",ret_nr_ulsch_procedures); + if (num_pusch > 0) { + int ret_nr_ulsch_procedures = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ulsch_idx_to_decode, num_pusch, UL_INFO); + if (ret_nr_ulsch_procedures != 0) + LOG_E(PHY,"Error in nr_ulsch_procedures, returned %d\n",ret_nr_ulsch_procedures); } /* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1 @@ -1174,203 +1270,20 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N if (gNB->max_nb_pusch == 1) stop_meas(&gNB->ulsch_decoding_stats); - for (int i = 0; i < gNB->max_nb_srs; i++) { - NR_gNB_SRS_t *srs = &gNB->srs[i]; - if (!(srs && srs->active && srs->frame == frame_rx && srs->slot == slot_rx)) - continue; - LOG_D(NR_PHY, "(%d.%d) gNB is waiting for SRS, id = %i\n", frame_rx, slot_rx, i); - + UL_INFO->srs_ind.sfn = frame_rx; + UL_INFO->srs_ind.slot = slot_rx; + UL_INFO->srs_ind.pdu_list = UL_INFO->srs_pdu_list; + UL_INFO->srs_ind.number_of_pdus = n_srs; + for (int i = 0; i < n_srs; ++i) { start_meas(&gNB->rx_srs_stats); - - uint8_t N_symb_SRS = 1 << srs->srs_pdu.num_symbols; - uint8_t N_ap = 1 << srs->srs_pdu.num_ant_ports; - int16_t snr_per_rb[srs->srs_pdu.bwp_size]; - nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; - uint16_t timing_advance_offset; - int16_t timing_advance_offset_nsec[nb_antennas_rx]; - int srs_est; - - c16_t srs_estimated_channel_freq[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); - c16_t srs_estimated_channel_time[nb_antennas_rx][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size] - __attribute__((aligned(32))); - - nr_srs_rx_procedures(gNB, - frame_rx, - slot_rx, - nb_antennas_rx, - N_ap, - N_symb_SRS, - ofdm_symbol_size, - srs, - gNB->nr_srs_info[i], - &srs_est, - srs_estimated_channel_freq, - srs_estimated_channel_time, - snr_per_rb, - &timing_advance_offset, - timing_advance_offset_nsec); - - if ((gNB->srs->snr * 10) < gNB->srs_thres) { - srs_est = -1; - } - - UL_INFO->srs_ind.sfn = frame_rx; - UL_INFO->srs_ind.slot = slot_rx; - - // data model difficult to understand, nfapi do malloc for this pointer - UL_INFO->srs_ind.pdu_list = UL_INFO->srs_pdu_list; - nfapi_nr_srs_indication_pdu_t *srs_indication = UL_INFO->srs_pdu_list + UL_INFO->srs_ind.number_of_pdus++; - srs_indication->handle = srs_pdu->handle; - srs_indication->rnti = srs_pdu->rnti; - srs_indication->timing_advance_offset = srs_est >= 0 ? timing_advance_offset : 0xFFFF; - // TODO: currently we fill timing_advance_offset_nsec for antenna 0. Need to extend it for other antennas - srs_indication->timing_advance_offset_nsec = srs_est >= 0 ? timing_advance_offset_nsec[0] : 0x8000; - switch (srs_pdu->srs_parameters_v4.usage) { - case 0: - LOG_W(NR_PHY, "SRS report was not requested by MAC\n"); - return 0; - case 1 << NFAPI_NR_SRS_BEAMMANAGEMENT: - srs_indication->srs_usage = NFAPI_NR_SRS_BEAMMANAGEMENT; - break; - case 1 << NFAPI_NR_SRS_CODEBOOK: - srs_indication->srs_usage = NFAPI_NR_SRS_CODEBOOK; - break; - case 1 << NFAPI_NR_SRS_NONCODEBOOK: - srs_indication->srs_usage = NFAPI_NR_SRS_NONCODEBOOK; - break; - case 1 << NFAPI_NR_SRS_ANTENNASWITCH: - srs_indication->srs_usage = NFAPI_NR_SRS_ANTENNASWITCH; - break; - default: - LOG_E(NR_PHY, "Invalid srs_pdu->srs_parameters_v4.usage %i\n", srs_pdu->srs_parameters_v4.usage); - } - srs_indication->report_type = srs_pdu->srs_parameters_v4.report_type[0]; - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "UL_INFO->srs_ind.sfn = %i\n", UL_INFO->srs_ind.sfn); - LOG_I(NR_PHY, "UL_INFO->srs_ind.slot = %i\n", UL_INFO->srs_ind.slot); - LOG_I(NR_PHY, "srs_indication->rnti = %04x\n", srs_indication->rnti); - LOG_I(NR_PHY, "srs_indication->timing_advance = %i\n", srs_indication->timing_advance_offset); - LOG_I(NR_PHY, "srs_indication->timing_advance_offset_nsec = %i\n", srs_indication->timing_advance_offset_nsec); - LOG_I(NR_PHY, "srs_indication->srs_usage = %i\n", srs_indication->srs_usage); - LOG_I(NR_PHY, "srs_indication->report_type = %i\n", srs_indication->report_type); -#endif - - nfapi_srs_report_tlv_t *report_tlv = &srs_indication->report_tlv; - report_tlv->tag = 0; - report_tlv->length = 0; - - start_meas(&gNB->srs_report_tlv_stats); - switch (srs_indication->srs_usage) { - case NFAPI_NR_SRS_BEAMMANAGEMENT: { - start_meas(&gNB->srs_beam_report_stats); - nfapi_nr_srs_beamforming_report_t nr_srs_bf_report; - nr_srs_bf_report.prg_size = srs_pdu->beamforming.prg_size; - nr_srs_bf_report.num_symbols = N_symb_SRS; - nr_srs_bf_report.wide_band_snr = - srs_est >= 0 ? (gNB->srs->snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid - nr_srs_bf_report.num_reported_symbols = N_symb_SRS; - AssertFatal(nr_srs_bf_report.num_reported_symbols == 1, - "nr_srs_bf_report.num_reported_symbols %i not handled yet!\n", - nr_srs_bf_report.num_reported_symbols); - fill_srs_reported_symbol(&nr_srs_bf_report.reported_symbol_list[0], srs_pdu, snr_per_rb, srs_est); - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "nr_srs_bf_report.prg_size = %i\n", nr_srs_bf_report.prg_size); - LOG_I(NR_PHY, "nr_srs_bf_report.num_symbols = %i\n", nr_srs_bf_report.num_symbols); - LOG_I(NR_PHY, - "nr_srs_bf_report.wide_band_snr = %i (%i dB)\n", - nr_srs_bf_report.wide_band_snr, - (nr_srs_bf_report.wide_band_snr >> 1) - 64); - LOG_I(NR_PHY, "nr_srs_bf_report.num_reported_symbols = %i\n", nr_srs_bf_report.num_reported_symbols); - LOG_I(NR_PHY, - "nr_srs_bf_report.reported_symbol_list[0].num_prgs = %i\n", - nr_srs_bf_report.reported_symbol_list[0].num_prgs); - for (int prg_idx = 0; prg_idx < nr_srs_bf_report.reported_symbol_list[0].num_prgs; prg_idx++) { - LOG_I(NR_PHY, - "nr_srs_beamforming_report.reported_symbol_list[0].prg_list[%3i].rb_snr = %i (%i dB)\n", - prg_idx, - nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr, - (nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr >> 1) - 64); - } -#endif - - report_tlv->length = pack_nr_srs_beamforming_report(&nr_srs_bf_report, report_tlv->value, sizeof(report_tlv->value)); - stop_meas(&gNB->srs_beam_report_stats); - break; - } - - case NFAPI_NR_SRS_CODEBOOK: { - start_meas(&gNB->srs_iq_matrix_stats); - nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_channel_iq_matrix; - fill_srs_channel_matrix(&nr_srs_channel_iq_matrix, - srs_pdu, - gNB->nr_srs_info[i], - frame_parms, - srs_estimated_channel_freq); - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, - "nr_srs_channel_iq_matrix.normalized_iq_representation = %i\n", - nr_srs_channel_iq_matrix.normalized_iq_representation); - LOG_I(NR_PHY, - "nr_srs_channel_iq_matrix.num_gnb_antenna_elements = %i\n", - nr_srs_channel_iq_matrix.num_gnb_antenna_elements); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_ue_srs_ports = %i\n", nr_srs_channel_iq_matrix.num_ue_srs_ports); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.prg_size = %i\n", nr_srs_channel_iq_matrix.prg_size); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_prgs = %i\n", nr_srs_channel_iq_matrix.num_prgs); - c16_t *channel_matrix16 = (c16_t *)nr_srs_channel_iq_matrix.channel_matrix; - c8_t *channel_matrix8 = (c8_t *)nr_srs_channel_iq_matrix.channel_matrix; - for (int uI = 0; uI < nr_srs_channel_iq_matrix.num_ue_srs_ports; uI++) { - for (int gI = 0; gI < nr_srs_channel_iq_matrix.num_gnb_antenna_elements; gI++) { - for (int pI = 0; pI < nr_srs_channel_iq_matrix.num_prgs; pI++) { - uint16_t index = uI * nr_srs_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_channel_iq_matrix.num_prgs - + gI * nr_srs_channel_iq_matrix.num_prgs + pI; - LOG_I( - NR_PHY, - "(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n", - uI, - gI, - pI, - nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].r : channel_matrix16[index].r, - nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].i - : channel_matrix16[index].i); - } - } - } -#endif - - report_tlv->length = - pack_nr_srs_normalized_channel_iq_matrix(&nr_srs_channel_iq_matrix, report_tlv->value, sizeof(report_tlv->value)); - stop_meas(&gNB->srs_iq_matrix_stats); - break; - } - - case NFAPI_NR_SRS_NONCODEBOOK: - case NFAPI_NR_SRS_ANTENNASWITCH: - LOG_W(NR_PHY, "PHY procedures for this SRS usage are not implemented yet!\n"); - break; - - default: - AssertFatal(1 == 0, "Invalid SRS usage\n"); - } - stop_meas(&gNB->srs_report_tlv_stats); - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "report_tlv->tag = %i\n", report_tlv->tag); - LOG_I(NR_PHY, "report_tlv->length = %i\n", report_tlv->length); - char *value = (char *)report_tlv->value; - for (int b = 0; b < report_tlv->length; b++) { - LOG_I(NR_PHY, "value[%i] = 0x%02x\n", b, value[b] & 0xFF); - } -#endif - srs->active = false; + handle_srs(now, gNB, &srs[i], &UL_INFO->srs_ind.pdu_list[i]); stop_meas(&gNB->rx_srs_stats); } stop_meas(&gNB->phy_proc_rx); - if (pucch_decode_done || pusch_decode_done) { + if (n_pucch > 0 || num_pusch > 0) { + UNUSED(ofdm_symbol_size); // only used if T activated T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), @@ -1406,9 +1319,7 @@ void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req break; case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; - prach_item_t *prach = nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); - if (!prach) - LOG_W(NR_PHY_RACH, "Error in scheduling rach\n"); + nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); } break; case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: nr_fill_srs(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu); diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index 7ff044b46c..ba1d00457b 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -18,7 +18,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int slot); 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); -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_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); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 225634937b..f9c8f38b56 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -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->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 * PARAMETERS : pointer to ue 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 * 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, 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]) { - if(phy_data->srs_vars.active == false) { - return false; - } - 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; // Num consecutive SRS symbols according to 38.211 6.4.1.4.1 int num_srs_symbols[] = {1, 2, 4, 8, 12}; @@ -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); #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; bool generated = generate_srs_nr(frame_parms, txdataF, symbol_offset, srs_config_pdu->bwp_start, - ue->nr_srs_info, + &nr_srs_info, AMP, proc->frame_tx, proc->nr_slot_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) @@ -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); - 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); diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c index 3c0e2ee87c..4f76749c8d 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c @@ -56,40 +56,6 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t 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) { UNUSED(vnf_ip_addr); @@ -102,37 +68,3 @@ void configure_nr_nfapi_vnf(eth_params_t 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; -} diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 6e29abd9a5..b47b35b470 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -547,12 +547,10 @@ int main(int argc, char **argv){ phy_init_nr_gNB(gNB); nr_phy_init_RU(ru); - prach_item_t *prach_data = calloc(1,sizeof(prach_item_t)); - gNB->prach_list.list[0] = prach_data; - nfapi_nr_prach_pdu_t *prach_pdu = &prach_data->pdu; - prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); - 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; + nfapi_nr_prach_pdu_t prach_pdu = {0}; + prach_pdu.num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); + 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 UE = malloc(sizeof(PHY_VARS_NR_UE)); @@ -749,14 +747,14 @@ int main(int argc, char **argv){ } 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]; - prach_pdu->num_prach_ocas=1; + 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_item_t *in = malloc(sizeof(prach_item_t) + sizeof(c16_t) * gNB->gNB_config.carrier_config.num_rx_ant.value * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L); *in = (prach_item_t){.frame = frame, .slot = slot, - .pdu = *prach_pdu, + .pdu = prach_pdu, .rootSequenceIndex = occ->prach_root_sequence_index.value, .numrootSequenceIndex = occ->num_root_sequences.value, .msg1_frequencystart = occ->k1.value, @@ -772,7 +770,7 @@ int main(int argc, char **argv){ if (n_frames == 1) LOG_I(PHY, "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); rx_prach_out_t out = rx_nr_prach(in, prachOccasion); @@ -823,7 +821,6 @@ int main(int argc, char **argv){ nr_phy_free_RU(ru); free(RC.ru[0]); free(RC.ru); - free(prach_data); phy_free_nr_gNB(gNB); // allocated in set_tdd_config_nr() int nb_slots_to_set = (1<ofdm_symbol_size], 12); // 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) { for (int s = 0; s < frame_parms->symbols_per_slot; s++) { if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols / 2)) for (int rb = 0; rb < N_RB; rb++) { - int rb2 = rb + startingPRB; - rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31)); + rb_mask_ul[s][rb + startingPRB] = 1; } else if (s >= (startingSymbolIndex + nrofSymbols / 2) && s < startingSymbolIndex + nrofSymbols) for (int rb = 0; rb < N_RB; rb++) { - int rb2 = rb + startingPRB_intraSlotHopping; - rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31)); + rb_mask_ul[s][rb + startingPRB_intraSlotHopping] = 1; } } } else { for (int s = 0; s < frame_parms->symbols_per_slot; s++) { if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols)) for (int rb = 0; rb < N_RB; rb++) { - int rb2 = rb + startingPRB; - rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31)); + rb_mask_ul[s][rb + startingPRB] = 1; } } } diff --git a/openair1/SIMULATION/NR_PHY/srssim.c b/openair1/SIMULATION/NR_PHY/srssim.c index afb4da5a80..0ab34dac47 100644 --- a/openair1/SIMULATION/NR_PHY/srssim.c +++ b/openair1/SIMULATION/NR_PHY/srssim.c @@ -435,11 +435,7 @@ int main(int argc, char *argv[]) .beamforming.num_prgs = m_SRS[srs_pdu.config_index], .beamforming.prg_size = 1}; - gNB->srs->srs_pdu = srs_pdu; - gNB->srs->active = true; - gNB->srs->beam_nb = 0; - gNB->srs->frame = frame; - gNB->srs->slot = slot; + NR_gNB_SRS_job_t srs_job = {.frame = frame, .slot = slot, .srs_pdu = srs_pdu}; // Configure SRS parameters at UE fapi_nr_ul_config_srs_pdu srs_config_pdu = {.rnti = srs_pdu.rnti, @@ -467,11 +463,6 @@ int main(int argc, char *argv[]) .beamforming.num_prgs = srs_pdu.beamforming.num_prgs, .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_nr_rxtx_proc_t proc; @@ -492,7 +483,7 @@ int main(int argc, char *argv[]) for (i = 0; i < n_tx; i++) 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 -------------------------- 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[]) //----------- UE RX SRS procedures --------------------- start_meas(&gNB->rx_srs_stats); - NR_gNB_SRS_t *srs = &gNB->srs[0]; - uint8_t N_symb_SRS = 1 << srs->srs_pdu.num_symbols; - uint8_t N_ap = 1 << srs->srs_pdu.num_ant_ports; - int16_t snr_per_rb[srs->srs_pdu.bwp_size]; + uint8_t N_symb_SRS = 1 << srs_pdu.num_symbols; + uint8_t N_ap = 1 << srs_pdu.num_ant_ports; + int16_t snr_per_rb[srs_pdu.bwp_size]; uint16_t timing_advance_offset; int16_t timing_advance_offset_nsec[n_rx]; 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_time[n_rx][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size] __attribute__((aligned(32))); + int8_t snr; nr_srs_rx_procedures(gNB, frame, slot, @@ -581,16 +571,15 @@ int main(int argc, char *argv[]) N_ap, N_symb_SRS, ofdm_symbol_size, - srs, - gNB->nr_srs_info[0], + &srs_job, &srs_est, + &snr, srs_estimated_channel_freq, - srs_estimated_channel_time, snr_per_rb, &timing_advance_offset, 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); for (int ant_idx = 0; ant_idx < n_rx; ant_idx++) { @@ -666,7 +655,6 @@ int main(int argc, char *argv[]) phy_free_nr_gNB(gNB); free_channel_desc_scm(UE2gNB); - free_and_zero(UE->nr_srs_info); free(gNB->RU_list[0]); free(UE); diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index f07ad92ca9..c5b8723908 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -414,12 +414,12 @@ int main(int argc, char **argv) unsigned int TBS = 8424; unsigned int available_bits; uint8_t nb_re_dmrs = 6; - uint8_t length_dmrs = 1; + uint8_t length_dmrs = 2; uint8_t N_PRB_oh; uint16_t N_RE_prime,code_rate; unsigned char mod_order; uint8_t rvidx = 0; - uint8_t UE_id = 0; + int UE_id = 0; NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id]; NR_UL_gNB_HARQ_t *harq_process_gNB = ulsch_gNB->harq_process; @@ -429,9 +429,6 @@ int main(int argc, char **argv) nr_phy_data_tx_t phy_data = {0}; 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); 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); @@ -445,10 +442,15 @@ int main(int argc, char **argv) rel15_ul->qam_mod_order = mod_order; rel15_ul->mcs_index = Imcs; 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->target_code_rate = code_rate; rel15_ul->pusch_data.tb_size = TBS>>3; 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 @@ -558,9 +560,9 @@ int main(int argc, char **argv) printf("\n"); exit(-1); #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) { - 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) { n_false_positive++; } diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 0d432bfdd0..7e74f26f56 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1208,6 +1208,7 @@ int main(int argc, char *argv[]) uint8_t round = 0; crc_status = 1; errors_decoding = 0; + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[UE_id]; while (round < max_rounds && crc_status && !stop) { @@ -1307,7 +1308,7 @@ int main(int argc, char *argv[]) srs_pdu->resource_type = NR_SRS_Resource__resourceType_PR_periodic; srs_pdu->t_srs = 1; 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.iq_representation = 1; srs_pdu->srs_parameters_v4.prg_size = 1; @@ -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) { __attribute__((unused)) int off = ((nb_rb & 1) == 1) ? 4 : 0; @@ -1742,13 +1742,20 @@ int main(int argc, char *argv[]) if (!crc_status) effRate += ((double)TBS) / (double)round; - sum_pusch_delay += ulsch_gNB->delay.est_delay; - min_pusch_delay = min(ulsch_gNB->delay.est_delay, min_pusch_delay); - max_pusch_delay = max(ulsch_gNB->delay.est_delay, max_pusch_delay); + sum_pusch_delay += pusch_vars->delay.est_delay; + min_pusch_delay = min(pusch_vars->delay.est_delay, min_pusch_delay); + max_pusch_delay = max(pusch_vars->delay.est_delay, max_pusch_delay); delay_pusch_est_count++; 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++; } } // trial loop diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index be869d9de9..db35776944 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -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); } -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) { int frame = pp_pusch->frame; @@ -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 max_dci = min(max_dci, MAX_DCI_CORESET); - fsn_t current = {frame, slot}; - fsn_t min_next = fs_add_delta(fs, min_rxtx, current); + fsn_t current = {frame, slot, *scc->ssbSubcarrierSpacing}; + 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 * 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 @@ -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; while (max_dci > 0) { /* 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)) - *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 break; /* 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 * "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); // 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 @@ -2631,7 +2603,7 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp break; max_dci -= sched; - *next = fs_add_delta(fs, 1, *next); + *next = fsn_add_delta(*next, 1); } } diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index ca12c48c48..1f619308c2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -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_size = 0; + RC.nrmac[i]->ul_next = (fsn_t) {.mu = *scc->ssbSubcarrierSpacing}; RC.nrmac[i]->print_ue_stats = true; pthread_mutex_init(&RC.nrmac[i]->sched_lock, NULL); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index f7ea466a94..391bfeabe8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -16,6 +16,7 @@ #include #include #include +#include "fsn.h" #include "common/utils/ds/seq_arr.h" #include "common/utils/nr/nr_common.h" #include "common/utils/ds/byte_array.h" @@ -878,14 +879,6 @@ typedef struct { NR_ControlResourceSet_t coreset; } 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 { /// cell-wide wide-band CQI distribution, see 28.552 5.1.1.11.1; /// 0-15 CQI, 1-8 RI, 1-3 CQI table diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index a7624f92c5..3a670f5f7f 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -12,6 +12,7 @@ #include "xran_sync_api.h" #include "common/utils/LOG/log.h" +#include "common/utils/fsn.h" #include "openair1/PHY/defs_gNB.h" #include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h" #include "oaioran.h" @@ -205,19 +206,21 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) .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); - if (prach_id) { + prach_item_t p; + 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); int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology; 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 nr_prach_info_t prach_info = get_prach_info(0); 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) { - ru_info.prach_buf = prach_id->prach_buf; + ru_info.prach_buf = p.prach_buf; } 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) 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); proc->tti_rx = sl; proc->frame_rx = f;