feat(nr): implement rank-8 PDSCH

This commit is contained in:
2026-09-15 00:36:01 +09:00
parent 04ee4ea8e5
commit c50fe1af53
42 changed files with 3244 additions and 648 deletions
@@ -16,13 +16,14 @@ extern "C" {
#include "openair1/PHY/TOOLS/tools_defs.h" // c16_t
#include "nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h" // fapi_nr_dl_config_dci_dl_pdu_rel15_t
#include "common/utils/LOG/log.h"
//#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]
const c16_t (*dataF_in)[/*symbol_size*/], // c16_t dataF_in[n_layers][symbol_size]
int ant,
c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS],
int offset);
@@ -37,6 +38,14 @@ void nr_layer_precoder_simd(int n_layers,
int re_cnt,
c16_t *dataF_out);
// Forward declare the layer mapper while hiding its C VLA dimension.
void nr_layer_mapping(int nb_codewords,
const c16_t *const mod_symbols[2],
const uint32_t n_symbols_per_codeword[2],
uint8_t n_layers,
int layer_size,
c16_t (*tx_layers)[/*layer_size*/]);
#ifdef __cplusplus
}
#endif
@@ -185,11 +194,50 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD)
}
}
TEST(NrLayerMappingTest, Rank8UsesTwoCodewordsAcrossEightDistinctLayers)
{
constexpr int n_codewords = 2;
constexpr int n_layers = 8;
constexpr int layers_per_codeword = 4;
constexpr int symbols_per_layer = 7;
constexpr int symbols_per_codeword = layers_per_codeword * symbols_per_layer;
std::vector<c16_t> cw0(symbols_per_codeword);
std::vector<c16_t> cw1(symbols_per_codeword);
for (int i = 0; i < symbols_per_codeword; ++i) {
cw0[i] = {static_cast<int16_t>(100 + i), static_cast<int16_t>(-100 - i)};
cw1[i] = {static_cast<int16_t>(1000 + i), static_cast<int16_t>(-1000 - i)};
}
const c16_t *mod_symbols[2] = {cw0.data(), cw1.data()};
const uint32_t n_symbols_per_codeword[2] = {symbols_per_codeword, symbols_per_codeword};
std::vector<c16_t> layer_storage(n_layers * symbols_per_layer, c16_t{SHRT_MIN, SHRT_MIN});
c16_t(*tx_layers)[symbols_per_layer] = reinterpret_cast<c16_t(*)[symbols_per_layer]>(layer_storage.data());
nr_layer_mapping(n_codewords,
mod_symbols,
n_symbols_per_codeword,
n_layers,
symbols_per_layer,
tx_layers);
for (int re = 0; re < symbols_per_layer; ++re) {
for (int layer = 0; layer < n_layers; ++layer) {
const int cw = layer / layers_per_codeword;
const int cw_layer = layer % layers_per_codeword;
const c16_t expected = mod_symbols[cw][re * layers_per_codeword + cw_layer];
EXPECT_EQ(tx_layers[layer][re].r, expected.r) << "real mismatch at layer " << layer << ", RE " << re;
EXPECT_EQ(tx_layers[layer][re].i, expected.i) << "imag mismatch at layer " << layer << ", RE " << re;
}
}
}
int main(int argc, char **argv)
{
// Initialize random seed
srand(time(0));
logInit();
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}