From 7d27592b4ffae5d6e405cd3785e0e7b07ea89f8a Mon Sep 17 00:00:00 2001 From: Matthias Mehlhose Date: Tue, 3 Jun 2025 12:16:10 +0000 Subject: [PATCH 1/3] Initial unit test to refactor and fix nr_layer_precoder_simd function (See #955) --- openair1/PHY/CMakeLists.txt | 1 + openair1/PHY/MODULATION/CMakeLists.txt | 3 + openair1/PHY/MODULATION/nr_modulation.c | 5 +- openair1/PHY/MODULATION/tests/CMakeLists.txt | 5 + .../MODULATION/tests/test_nr_modulation.cpp | 153 ++++++++++++++++++ 5 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 openair1/PHY/MODULATION/CMakeLists.txt create mode 100644 openair1/PHY/MODULATION/tests/CMakeLists.txt create mode 100644 openair1/PHY/MODULATION/tests/test_nr_modulation.cpp diff --git a/openair1/PHY/CMakeLists.txt b/openair1/PHY/CMakeLists.txt index 2d74e9aedc..83e7dc0530 100644 --- a/openair1/PHY/CMakeLists.txt +++ b/openair1/PHY/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(nr_phy_common) add_subdirectory(TOOLS) add_subdirectory(NR_TRANSPORT) add_subdirectory(CODING) +add_subdirectory(MODULATION) diff --git a/openair1/PHY/MODULATION/CMakeLists.txt b/openair1/PHY/MODULATION/CMakeLists.txt new file mode 100644 index 0000000000..dc1a5e0301 --- /dev/null +++ b/openair1/PHY/MODULATION/CMakeLists.txt @@ -0,0 +1,3 @@ +if (ENABLE_TESTS) + add_subdirectory(tests) +endif() diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 994c0798c2..4df83cedf9 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -765,9 +765,8 @@ void nr_layer_precoder_simd(const int n_layers, // Multiplication and shift const simde__m256i reals = simde_mm256_srai_epi32(simde_mm256_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 - const simde__m256i imags = simde_mm256_slli_epi32( - simde_mm256_madd_epi16(x, w_s), - 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 + const simde__m256i imags = + simde_mm256_slli_epi32(simde_mm256_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 // Re-arrange to match c16_t format const simde__m256i produ = simde_mm256_blend_epi16(reals, imags, 0xAA); diff --git a/openair1/PHY/MODULATION/tests/CMakeLists.txt b/openair1/PHY/MODULATION/tests/CMakeLists.txt new file mode 100644 index 0000000000..426181698d --- /dev/null +++ b/openair1/PHY/MODULATION/tests/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(test_nr_modulation test_nr_modulation.cpp) +target_link_libraries(test_nr_modulation PRIVATE PHY_NR GTest::gtest minimal_lib) +add_dependencies(tests test_nr_modulation) +add_test(NAME test_nr_modulation + COMMAND ./test_nr_modulation) diff --git a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp new file mode 100644 index 0000000000..c6f39aee5e --- /dev/null +++ b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp @@ -0,0 +1,153 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +// Initial unit test for nr_layer_precoder_simd_[cm, simd] functions +// Issue: gNB: SIMD Precoding Bug in nr_layer_precoder_simd for PMI = 4 +// https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues/955 + +#include "gtest/gtest.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "openair1/PHY/TOOLS/tools_defs.h" // c16_t +#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" // nfapi_nr_pm_pdu_t +#include "nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h" // fapi_nr_dl_config_dci_dl_pdu_rel15_t + +//#include "openair1/PHY/MODULATION/nr_modulation.h" // nr_layer_precoder_simd_[cm, simd] + +// Forward declare the function but hide the Variable-Length Array (VLA) feature from C not available in C++ +c16_t nr_layer_precoder_cm(int n_layers, + int symbol_size, + c16_t (*dataF_in)[/*symbol_size*/], // c16_t dataF_in[n_layers][symbol_size] + int ant, + nfapi_nr_pm_pdu_t *pmi_pdu, + int offset); + +// Forward declare the function but hide the Variable-Length Array (VLA) feature from C not available in C++ +void nr_layer_precoder_simd(int n_layers, + int symbol_size, + const c16_t (*dataF_in)[/*symbol_size*/], // c16_t dataF_in[n_layers][symbol_size] + int ant, + const nfapi_nr_pm_pdu_t *pmi_pdu, + int offset, + int re_cnt, + c16_t *dataF_out); + +#ifdef __cplusplus +} +#endif + +TEST(NrLayerPrecoderTest, Basic) +{ + constexpr int n_layers = 2; + constexpr int symbol_size = 24; + constexpr int ant = 1; + constexpr int re_cnt = 24; + + // Initialize the 2D input data buffer + std::vector buffer_in(n_layers * symbol_size); + std::vector buffer_out(n_layers * symbol_size); + + for (int i = 0; i < n_layers * symbol_size; ++i) { + buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + buffer_out[i] = {static_cast(0), static_cast(0)}; + } + + // Cast flat buffer to the required 2D Variable-Length Array (VLA) style pointer + c16_t(*dataF_in)[symbol_size] = reinterpret_cast(buffer_in.data()); + c16_t(*dataF_out)[symbol_size] = reinterpret_cast(buffer_out.data()); + + // Create and populate the pmi_pdu structure + nfapi_nr_pm_pdu_t pmi_pdu = {0}; + for (int layer = 0; layer < n_layers; ++layer) { + pmi_pdu.weights[layer][ant].precoder_weight_Re = 1 << 14; // e.g., Q15 representation of ~0.5 + pmi_pdu.weights[layer][ant].precoder_weight_Im = 0; + } + + // Call the C function + for (int symbol = 0; symbol < re_cnt; symbol++) + dataF_out[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, symbol); + + // You can calculate the expected value manually or test rough correctness + for (int symbol = 0; symbol < re_cnt; symbol++) { + int result_real = 14 + (symbol - 1) & ~1; + int result_imag = 14 + (symbol) & ~1; + EXPECT_EQ(dataF_out[ant][symbol].r, result_real) + << " at [" << ant << "][" << symbol << "] got real part: " << dataF_out[ant][symbol].r; + ; + EXPECT_EQ(dataF_out[ant][symbol].i, -result_imag) + << " at [" << ant << "][" << symbol << "] got imag part: " << dataF_out[ant][symbol].i; + ; + } +} + +TEST(NrLayerPrecoderTest, SIMD) +{ + constexpr int n_layers = 2; + constexpr int symbol_size = 24; + constexpr int ant = 1; + constexpr int re_cnt = 24; + + // Initialize the 2D input data buffer + std::vector buffer_in(n_layers * symbol_size); + std::vector buffer_out(n_layers * symbol_size); + + for (int i = 0; i < n_layers * symbol_size; ++i) { + buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + buffer_out[i] = {static_cast(0), static_cast(0)}; + } + + // Cast flat buffer to the required 2D Variable-Length Array (VLA) style pointer + c16_t(*dataF_in)[symbol_size] = reinterpret_cast(buffer_in.data()); + c16_t(*dataF_out)[symbol_size] = reinterpret_cast(buffer_out.data()); + + // Create and populate the pmi_pdu structure + nfapi_nr_pm_pdu_t pmi_pdu = {0}; + for (int layer = 0; layer < n_layers; ++layer) { + pmi_pdu.weights[layer][ant].precoder_weight_Re = 1 << 14; // e.g., Q15 representation of ~0.5 + pmi_pdu.weights[layer][ant].precoder_weight_Im = 0; + } + + // Call the C function + nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, 0, re_cnt, dataF_out[ant]); + + // You can calculate the expected value manually or test rough correctness + for (int symbol = 0; symbol < re_cnt; symbol++) { + int result_real = 14 + (symbol - 1) & ~1; + int result_imag = 14 + (symbol) & ~1; + EXPECT_EQ(dataF_out[ant][symbol].r, result_real) + << " at [" << ant << "][" << symbol << "] got real part: " << dataF_out[ant][symbol].r; + ; + EXPECT_EQ(dataF_out[ant][symbol].i, -result_imag) + << " at [" << ant << "][" << symbol << "] got imag part: " << dataF_out[ant][symbol].i; + ; + } +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From 905a8a495e9f49ef23d6a03a4ebcba12f41da7ee Mon Sep 17 00:00:00 2001 From: Mario Joa-Ng Date: Wed, 4 Jun 2025 21:45:31 -0400 Subject: [PATCH 2/3] mod: unit test code to compare CM and SIMD results on both antennas --- .../MODULATION/tests/test_nr_modulation.cpp | 64 +++++++++++++++++++ openair1/PHY/TOOLS/tools_defs.h | 2 +- openair2/LAYER2/NR_MAC_gNB/config.c | 8 +-- 3 files changed, 66 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp index c6f39aee5e..2640af1c26 100644 --- a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp +++ b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp @@ -63,6 +63,7 @@ TEST(NrLayerPrecoderTest, Basic) { constexpr int n_layers = 2; constexpr int symbol_size = 24; + constexpr int n_ants = 2; constexpr int ant = 1; constexpr int re_cnt = 24; @@ -72,6 +73,8 @@ TEST(NrLayerPrecoderTest, Basic) for (int i = 0; i < n_layers * symbol_size; ++i) { buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + } + for (int i = 0; i < n_ants * symbol_size; ++i) { buffer_out[i] = {static_cast(0), static_cast(0)}; } @@ -107,6 +110,7 @@ TEST(NrLayerPrecoderTest, SIMD) { constexpr int n_layers = 2; constexpr int symbol_size = 24; + constexpr int n_ants = 2; constexpr int ant = 1; constexpr int re_cnt = 24; @@ -116,6 +120,8 @@ TEST(NrLayerPrecoderTest, SIMD) for (int i = 0; i < n_layers * symbol_size; ++i) { buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + } + for (int i = 0; i < n_ants * symbol_size; ++i) { buffer_out[i] = {static_cast(0), static_cast(0)}; } @@ -146,6 +152,64 @@ TEST(NrLayerPrecoderTest, SIMD) } } +TEST(NrLayerPrecoderTest, Compare_CM_SIMD) +{ + constexpr int n_layers = 1; + constexpr int symbol_size = 24; + constexpr int n_ants = 2; + constexpr int re_cnt = 24; + + // Initialize the 2D input data buffer + std::vector buffer_in(n_layers * symbol_size); + std::vector buffer_out(n_ants * symbol_size); + std::vector buffer_out2(n_ants * symbol_size); + + for (int i = 0; i < n_layers * symbol_size; ++i) { + buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + } + for (int i = 0; i < n_ants * symbol_size; ++i) { + buffer_out[i] = {static_cast(0), static_cast(0)}; + buffer_out2[i] = {static_cast(0), static_cast(0)}; + } + + // Cast flat buffer to the required 2D Variable-Length Array (VLA) style pointer + c16_t(*dataF_in)[symbol_size] = reinterpret_cast(buffer_in.data()); + c16_t(*dataF_out)[symbol_size] = reinterpret_cast(buffer_out.data()); + c16_t(*dataF_out2)[symbol_size] = reinterpret_cast(buffer_out2.data()); + + // Create and populate the pmi_pdu structure + nfapi_nr_pm_pdu_t pmi_pdu = {0}; + pmi_pdu.pm_idx = 4; + for (int layer = 0; layer < n_layers; ++layer) { + // Could not use convert_precoder_weight() as complex.h could not be used in googletest + // Use the logic in convert_precoder_weight() + // precoder [−1,−j] + pmi_pdu.weights[layer][0].precoder_weight_Re = round(-32767 * 1.0); + pmi_pdu.weights[layer][0].precoder_weight_Im = 0x0000; // Q15 representation of 0 + pmi_pdu.weights[layer][1].precoder_weight_Re = 0x0000; // Q15 representation of 0 + pmi_pdu.weights[layer][1].precoder_weight_Im = round(-32767 * 1.0); + } + + // Get the results for all the antenna + for (int ant = 0; ant < n_ants; ant++) { + + // Call the C function + for (int symbol = 0; symbol < re_cnt; symbol++) + dataF_out[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, symbol); + + // Call the C function + nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, 0, re_cnt, dataF_out2[ant]); + + // Compare the result from both C function + for (int symbol = 0; symbol < re_cnt; symbol++) { + EXPECT_EQ(dataF_out_cm[ant][symbol].r, dataF_out_simd[ant][symbol].r) + << " at [" << ant << "][" << symbol << "] got real part: " << dataF_out_cm[ant][symbol].r << " result " << dataF_out_simd[ant][symbol].r; + EXPECT_EQ(dataF_out_cm[ant][symbol].i, dataF_out_simd[ant][symbol].i) + << " at [" << ant << "][" << symbol << "] got imag part: " << dataF_out_cm[ant][symbol].i << " result " << dataF_out_simd[ant][symbol].i; + } + } +} + int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 64e5061476..3b8d027adf 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -163,7 +163,7 @@ extern "C" { __attribute__((always_inline)) inline c16_t c16conj(const c16_t a) { return (c16_t) { .r = a.r, - .i = (int16_t)-a.i + .i = (int16_t)-a.i }; } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index bfc9f63538..cd75bb5aee 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -61,13 +61,7 @@ c16_t convert_precoder_weight(double complex c_in) { - double cr = creal(c_in) * 32768 + 0.5; - if (cr < 0) - cr -= 1; - double ci = cimag(c_in) * 32768 + 0.5; - if (ci < 0) - ci -= 1; - return (c16_t) {.r = (short)cr, .i = (short)ci}; + return (c16_t) {.r = round(32767*creal(c_in)), .i = round(32767*cimag(c_in))}; } void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers) From 5b0b40c1026c7ebf63844bb69676cc8a13865e07 Mon Sep 17 00:00:00 2001 From: Matthias Mehlhose Date: Tue, 22 Jul 2025 13:59:38 +0000 Subject: [PATCH 3/3] mod: use random numbers in unit test function --- .../MODULATION/tests/test_nr_modulation.cpp | 47 ++++++++++--------- openair2/LAYER2/NR_MAC_gNB/config.c | 2 +- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp index 2640af1c26..ca8b61acd7 100644 --- a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp +++ b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp @@ -85,7 +85,7 @@ TEST(NrLayerPrecoderTest, Basic) // Create and populate the pmi_pdu structure nfapi_nr_pm_pdu_t pmi_pdu = {0}; for (int layer = 0; layer < n_layers; ++layer) { - pmi_pdu.weights[layer][ant].precoder_weight_Re = 1 << 14; // e.g., Q15 representation of ~0.5 + pmi_pdu.weights[layer][ant].precoder_weight_Re = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) pmi_pdu.weights[layer][ant].precoder_weight_Im = 0; } @@ -95,14 +95,13 @@ TEST(NrLayerPrecoderTest, Basic) // You can calculate the expected value manually or test rough correctness for (int symbol = 0; symbol < re_cnt; symbol++) { - int result_real = 14 + (symbol - 1) & ~1; - int result_imag = 14 + (symbol) & ~1; + int result_real = -26 - (symbol<<1); + int result_imag = -24 - (symbol<<1); + EXPECT_EQ(dataF_out[ant][symbol].r, result_real) << " at [" << ant << "][" << symbol << "] got real part: " << dataF_out[ant][symbol].r; - ; EXPECT_EQ(dataF_out[ant][symbol].i, -result_imag) << " at [" << ant << "][" << symbol << "] got imag part: " << dataF_out[ant][symbol].i; - ; } } @@ -132,7 +131,7 @@ TEST(NrLayerPrecoderTest, SIMD) // Create and populate the pmi_pdu structure nfapi_nr_pm_pdu_t pmi_pdu = {0}; for (int layer = 0; layer < n_layers; ++layer) { - pmi_pdu.weights[layer][ant].precoder_weight_Re = 1 << 14; // e.g., Q15 representation of ~0.5 + pmi_pdu.weights[layer][ant].precoder_weight_Re = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) pmi_pdu.weights[layer][ant].precoder_weight_Im = 0; } @@ -141,14 +140,13 @@ TEST(NrLayerPrecoderTest, SIMD) // You can calculate the expected value manually or test rough correctness for (int symbol = 0; symbol < re_cnt; symbol++) { - int result_real = 14 + (symbol - 1) & ~1; - int result_imag = 14 + (symbol) & ~1; + int result_real = -26 - (symbol<<1); + int result_imag = -24 - (symbol<<1); + EXPECT_EQ(dataF_out[ant][symbol].r, result_real) << " at [" << ant << "][" << symbol << "] got real part: " << dataF_out[ant][symbol].r; - ; EXPECT_EQ(dataF_out[ant][symbol].i, -result_imag) << " at [" << ant << "][" << symbol << "] got imag part: " << dataF_out[ant][symbol].i; - ; } } @@ -161,21 +159,21 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD) // Initialize the 2D input data buffer std::vector buffer_in(n_layers * symbol_size); - std::vector buffer_out(n_ants * symbol_size); - std::vector buffer_out2(n_ants * symbol_size); + std::vector buffer_out_cm(n_ants * symbol_size); + std::vector buffer_out_simd(n_ants * symbol_size); for (int i = 0; i < n_layers * symbol_size; ++i) { - buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + buffer_in[i] = {static_cast((rand() % (2 * SHRT_MAX + 1)) - SHRT_MAX), static_cast((rand() % (2 * SHRT_MAX + 1)) - SHRT_MAX)}; } for (int i = 0; i < n_ants * symbol_size; ++i) { - buffer_out[i] = {static_cast(0), static_cast(0)}; - buffer_out2[i] = {static_cast(0), static_cast(0)}; + buffer_out_cm[i] = {static_cast(0), static_cast(0)}; + buffer_out_simd[i] = {static_cast(0), static_cast(0)}; } // Cast flat buffer to the required 2D Variable-Length Array (VLA) style pointer c16_t(*dataF_in)[symbol_size] = reinterpret_cast(buffer_in.data()); - c16_t(*dataF_out)[symbol_size] = reinterpret_cast(buffer_out.data()); - c16_t(*dataF_out2)[symbol_size] = reinterpret_cast(buffer_out2.data()); + c16_t(*dataF_out_cm)[symbol_size] = reinterpret_cast(buffer_out_cm.data()); + c16_t(*dataF_out_simd)[symbol_size] = reinterpret_cast(buffer_out_simd.data()); // Create and populate the pmi_pdu structure nfapi_nr_pm_pdu_t pmi_pdu = {0}; @@ -184,10 +182,10 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD) // Could not use convert_precoder_weight() as complex.h could not be used in googletest // Use the logic in convert_precoder_weight() // precoder [−1,−j] - pmi_pdu.weights[layer][0].precoder_weight_Re = round(-32767 * 1.0); - pmi_pdu.weights[layer][0].precoder_weight_Im = 0x0000; // Q15 representation of 0 - pmi_pdu.weights[layer][1].precoder_weight_Re = 0x0000; // Q15 representation of 0 - pmi_pdu.weights[layer][1].precoder_weight_Im = round(-32767 * 1.0); + pmi_pdu.weights[layer][0].precoder_weight_Re = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) + pmi_pdu.weights[layer][0].precoder_weight_Im = 0x0000; // Q15 representation of 0 + pmi_pdu.weights[layer][1].precoder_weight_Re = 0x0000; // Q15 representation of 0 + pmi_pdu.weights[layer][1].precoder_weight_Im = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) } // Get the results for all the antenna @@ -195,10 +193,10 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD) // Call the C function for (int symbol = 0; symbol < re_cnt; symbol++) - dataF_out[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, symbol); + dataF_out_cm[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, symbol); // Call the C function - nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, 0, re_cnt, dataF_out2[ant]); + nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, 0, re_cnt, dataF_out_simd[ant]); // Compare the result from both C function for (int symbol = 0; symbol < re_cnt; symbol++) { @@ -212,6 +210,9 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD) int main(int argc, char **argv) { + // Initialize random seed + srand(time(0)); + testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index cd75bb5aee..99e4249bb2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -61,7 +61,7 @@ c16_t convert_precoder_weight(double complex c_in) { - return (c16_t) {.r = round(32767*creal(c_in)), .i = round(32767*cimag(c_in))}; + return (c16_t) {.r = round(SHRT_MAX*creal(c_in)), .i = round(SHRT_MAX*cimag(c_in))}; } void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers)