mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Compare commits
18 Commits
23796f054f
...
gNB_TX_opt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
716b073f5d | ||
|
|
9badca3581 | ||
|
|
cf72d4f423 | ||
|
|
01bc3ae955 | ||
|
|
6527be8b60 | ||
|
|
c13eca8ac7 | ||
|
|
fd45788653 | ||
|
|
a1f9dd97cc | ||
|
|
2753e8a0c3 | ||
|
|
a5388fa897 | ||
|
|
e8b1ce6250 | ||
|
|
1f0ce04bda | ||
|
|
4fd7833f26 | ||
|
|
99a87e9210 | ||
|
|
679e640116 | ||
|
|
c82f43fe17 | ||
|
|
e48b5ae299 | ||
|
|
324f6731b2 |
@@ -20,7 +20,7 @@ CMAKE_BUILD_TYPE="RelWithDebInfo"
|
||||
CMAKE_CMD="$CMAKE"
|
||||
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_aal websrv oai_iqplayer imscope imscope_record"
|
||||
TARGET_LIST=""
|
||||
BUILD_TOOL_OPT="-j$(nproc)"
|
||||
BUILD_TOOL_OPT="-j8"
|
||||
|
||||
function print_help() {
|
||||
echo_info "
|
||||
|
||||
@@ -19,10 +19,6 @@ COPY . .
|
||||
|
||||
# build all targets so final targets can be created afterwards
|
||||
RUN \
|
||||
# Mount CCache cache direrctory
|
||||
--mount=type=cache,target=/root/.cache/ccache/ \
|
||||
# Mount CPM package cache
|
||||
--mount=type=cache,target=/root/.cache/cpm/ \
|
||||
/bin/sh oaienv && \
|
||||
cd cmake_targets && \
|
||||
mkdir -p log && \
|
||||
@@ -45,8 +41,6 @@ RUN \
|
||||
|
||||
## Build FlexRIC for SM Models
|
||||
RUN \
|
||||
# Mount CCache cache direrctory
|
||||
--mount=type=cache,target=/root/.cache/ccache/ \
|
||||
mkdir -p openair2/E2AP/flexric/build && \
|
||||
cd openair2/E2AP/flexric/build && \
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Release \
|
||||
|
||||
@@ -215,6 +215,174 @@ void nr_modulation(const uint32_t *in, uint32_t length, uint16_t mod_order, int1
|
||||
AssertFatal(false, "Invalid or unsupported modulation order %d\n", mod_order);
|
||||
}
|
||||
|
||||
static inline uint8_t get_packed_symbol(const uint8_t *in_bytes, uint32_t length, uint16_t mod_order, uint32_t symbol_idx)
|
||||
{
|
||||
const uint32_t bit_offset = symbol_idx * mod_order;
|
||||
const uint32_t byte_offset = bit_offset >> 3;
|
||||
const uint32_t bit_shift = bit_offset & 0x7;
|
||||
const uint32_t num_bytes = (length + 7) >> 3;
|
||||
uint16_t packed = in_bytes[byte_offset];
|
||||
if (bit_shift > 8 - mod_order && byte_offset + 1 < num_bytes)
|
||||
packed |= (uint16_t)in_bytes[byte_offset + 1] << 8;
|
||||
return (packed >> bit_shift) & ((1U << mod_order) - 1);
|
||||
}
|
||||
|
||||
static inline uint64_t get_packed_bits(const uint8_t *in_bytes, uint32_t length, uint32_t bit_offset, uint8_t width)
|
||||
{
|
||||
const uint32_t byte_offset = bit_offset >> 3;
|
||||
const uint32_t bit_shift = bit_offset & 0x7;
|
||||
const uint32_t num_bytes = (length + 7) >> 3;
|
||||
const uint32_t bytes_needed = (bit_shift + width + 7) >> 3;
|
||||
uint64_t packed = 0;
|
||||
for (uint32_t i = 0; i < bytes_needed && byte_offset + i < num_bytes; i++)
|
||||
packed |= (uint64_t)in_bytes[byte_offset + i] << (i << 3);
|
||||
return (packed >> bit_shift) & ((UINT64_C(1) << width) - 1);
|
||||
}
|
||||
|
||||
bool nr_modulation_layer_mapping(const uint32_t *in,
|
||||
uint32_t length,
|
||||
uint16_t mod_order,
|
||||
uint8_t n_layers,
|
||||
int layerSz,
|
||||
c16_t tx_layers[][layerSz])
|
||||
{
|
||||
if (n_layers < 1 || n_layers > 4)
|
||||
return false;
|
||||
|
||||
const uint32_t n_symbs = length / mod_order;
|
||||
if ((n_symbs % n_layers) != 0)
|
||||
return false;
|
||||
|
||||
const uint8_t *in_bytes = (const uint8_t *)in;
|
||||
|
||||
switch (mod_order) {
|
||||
case 2: {
|
||||
const c16_t *nr_mod_table = nr_qpsk_mod_table;
|
||||
if (n_layers == 1) {
|
||||
nr_modulation(in, length, mod_order, (int16_t *)tx_layers[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t sym = 0, layer_sym = 0; sym < n_symbs; sym += n_layers, layer_sym++) {
|
||||
for (uint8_t layer = 0; layer < n_layers; layer++) {
|
||||
const uint8_t idx = get_packed_symbol(in_bytes, length, mod_order, sym + layer);
|
||||
tx_layers[layer][layer_sym] = nr_mod_table[idx];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case 4: {
|
||||
const int32_t *nr_mod_table = nr_16qam_mod_table;
|
||||
if (n_layers == 1) {
|
||||
nr_modulation(in, length, mod_order, (int16_t *)tx_layers[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t sym = 0, layer_sym = 0; sym < n_symbs; sym += n_layers, layer_sym++) {
|
||||
for (uint8_t layer = 0; layer < n_layers; layer++) {
|
||||
const uint8_t idx = get_packed_symbol(in_bytes, length, mod_order, sym + layer);
|
||||
((int32_t *)tx_layers[layer])[layer_sym] = nr_mod_table[idx];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case 6: {
|
||||
const c16_t *nr_mod_table = (const c16_t *)nr_64qam_mod_table;
|
||||
if (n_layers == 1) {
|
||||
c16_t *tx0 = tx_layers[0];
|
||||
uint32_t sym = 0;
|
||||
for (; sym + 2 <= n_symbs; sym += 2) {
|
||||
const uint16_t idx = get_packed_bits(in_bytes, length, sym * mod_order, 12);
|
||||
tx0[sym] = nr_mod_table[idx * 2];
|
||||
tx0[sym + 1] = nr_mod_table[idx * 2 + 1];
|
||||
}
|
||||
if (sym < n_symbs) {
|
||||
const uint8_t idx = get_packed_symbol(in_bytes, length, mod_order, sym);
|
||||
tx0[sym] = nr_mod_table[idx * 2];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (n_layers == 2) {
|
||||
c16_t *tx0 = tx_layers[0];
|
||||
c16_t *tx1 = tx_layers[1];
|
||||
for (uint32_t sym = 0, layer_sym = 0; sym < n_symbs; sym += 2, layer_sym++) {
|
||||
const uint16_t idx = get_packed_bits(in_bytes, length, sym * mod_order, 12);
|
||||
tx0[layer_sym] = nr_mod_table[idx * 2];
|
||||
tx1[layer_sym] = nr_mod_table[idx * 2 + 1];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (n_layers == 3) {
|
||||
c16_t *tx0 = tx_layers[0];
|
||||
c16_t *tx1 = tx_layers[1];
|
||||
c16_t *tx2 = tx_layers[2];
|
||||
uint32_t sym = 0;
|
||||
uint32_t layer_sym = 0;
|
||||
for (; sym + 6 <= n_symbs; sym += 6, layer_sym += 2) {
|
||||
const uint64_t bits = get_packed_bits(in_bytes, length, sym * mod_order, 36);
|
||||
const uint16_t idx0 = bits & 0xfff;
|
||||
const uint16_t idx1 = (bits >> 12) & 0xfff;
|
||||
const uint16_t idx2 = (bits >> 24) & 0xfff;
|
||||
tx0[layer_sym] = nr_mod_table[idx0 * 2];
|
||||
tx1[layer_sym] = nr_mod_table[idx0 * 2 + 1];
|
||||
tx2[layer_sym] = nr_mod_table[idx1 * 2];
|
||||
tx0[layer_sym + 1] = nr_mod_table[idx1 * 2 + 1];
|
||||
tx1[layer_sym + 1] = nr_mod_table[idx2 * 2];
|
||||
tx2[layer_sym + 1] = nr_mod_table[idx2 * 2 + 1];
|
||||
}
|
||||
if (sym < n_symbs) {
|
||||
for (uint8_t layer = 0; layer < 3; layer++) {
|
||||
const uint8_t idx = get_packed_symbol(in_bytes, length, mod_order, sym + layer);
|
||||
tx_layers[layer][layer_sym] = nr_mod_table[idx * 2];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (n_layers == 4) {
|
||||
c16_t *tx0 = tx_layers[0];
|
||||
c16_t *tx1 = tx_layers[1];
|
||||
c16_t *tx2 = tx_layers[2];
|
||||
c16_t *tx3 = tx_layers[3];
|
||||
for (uint32_t sym = 0, layer_sym = 0; sym < n_symbs; sym += 4, layer_sym++) {
|
||||
const uint32_t bits = get_packed_bits(in_bytes, length, sym * mod_order, 24);
|
||||
const uint16_t idx0 = bits & 0xfff;
|
||||
const uint16_t idx1 = (bits >> 12) & 0xfff;
|
||||
tx0[layer_sym] = nr_mod_table[idx0 * 2];
|
||||
tx1[layer_sym] = nr_mod_table[idx0 * 2 + 1];
|
||||
tx2[layer_sym] = nr_mod_table[idx1 * 2];
|
||||
tx3[layer_sym] = nr_mod_table[idx1 * 2 + 1];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
case 8: {
|
||||
const int32_t *nr_mod_table = nr_256qam_mod_table;
|
||||
if (n_layers == 1) {
|
||||
nr_modulation(in, length, mod_order, (int16_t *)tx_layers[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t sym = 0, layer_sym = 0; sym < n_symbs; sym += n_layers, layer_sym++) {
|
||||
for (uint8_t layer = 0; layer < n_layers; layer++) {
|
||||
const uint8_t idx = get_packed_symbol(in_bytes, length, mod_order, sym + layer);
|
||||
((int32_t *)tx_layers[layer])[layer_sym] = nr_mod_table[idx];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_layer_mapping(int nbCodes,
|
||||
int encoded_len,
|
||||
c16_t mod_symbs[nbCodes][encoded_len],
|
||||
@@ -257,16 +425,12 @@ void nr_layer_mapping(int nbCodes,
|
||||
}
|
||||
#endif
|
||||
#if defined(__aarch64__) && defined(USE_NEON)
|
||||
// SIMDe doesn't handle this properly, gcc up to 14.2 neither
|
||||
uint8_t const perm0[16] = {0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15};
|
||||
uint8x16_t perm = vld1q_u8(perm0);
|
||||
uint8x16_t d;
|
||||
for (; i < (n_symbs & (~3)); i += 4) {
|
||||
d = vqtbl1q_u8(*(uint8x16_t *)(mod + i), perm);
|
||||
*(int64_t *)tx0 = vgetq_lane_u64((uint64x2_t)d, 0);
|
||||
*(int64_t *)tx1 = vgetq_lane_u64((uint64x2_t)d, 1);
|
||||
tx0 += 2;
|
||||
tx1 += 2;
|
||||
for (; i < (n_symbs & ~7); i += 8) {
|
||||
uint32x4x2_t d = vld2q_u32((const uint32_t *)(mod + i));
|
||||
vst1q_u32((uint32_t *)tx0, d.val[0]);
|
||||
vst1q_u32((uint32_t *)tx1, d.val[1]);
|
||||
tx0 += 4;
|
||||
tx1 += 4;
|
||||
}
|
||||
#endif
|
||||
for (; i < n_symbs; i += 2) {
|
||||
@@ -375,6 +539,17 @@ void nr_layer_mapping(int nbCodes,
|
||||
tx2 += 8;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(__aarch64__) && defined(USE_NEON)
|
||||
for (; i < (n_symbs & ~11); i += 12) {
|
||||
uint32x4x3_t d = vld3q_u32((const uint32_t *)(mod + i));
|
||||
vst1q_u32((uint32_t *)tx0, d.val[0]);
|
||||
vst1q_u32((uint32_t *)tx1, d.val[1]);
|
||||
vst1q_u32((uint32_t *)tx2, d.val[2]);
|
||||
tx0 += 4;
|
||||
tx1 += 4;
|
||||
tx2 += 4;
|
||||
}
|
||||
#endif
|
||||
for (; i < n_symbs; i += 3) {
|
||||
*tx0++ = mod[i];
|
||||
@@ -448,17 +623,16 @@ void nr_layer_mapping(int nbCodes,
|
||||
}
|
||||
#endif
|
||||
#if defined(__aarch64__) && defined(USE_NEON)
|
||||
// SIMDe doesn't handle this properly, gcc up to 14.2 neither
|
||||
for (; i < (n_symbs & ~3); i += 4) {
|
||||
uint32x4_t d4 = *(uint32x4_t *)(mod + i);
|
||||
*(uint32_t *)tx0 = vgetq_lane_u32(d4, 0);
|
||||
tx0++;
|
||||
*(uint32_t *)tx1 = vgetq_lane_u32(d4, 1);
|
||||
tx1++;
|
||||
*(uint32_t *)tx2 = vgetq_lane_u32(d4, 2);
|
||||
tx2++;
|
||||
*(uint32_t *)tx3 = vgetq_lane_u32(d4, 3);
|
||||
tx3++;
|
||||
for (; i < (n_symbs & ~15); i += 16) {
|
||||
uint32x4x4_t d = vld4q_u32((const uint32_t *)(mod + i));
|
||||
vst1q_u32((uint32_t *)tx0, d.val[0]);
|
||||
vst1q_u32((uint32_t *)tx1, d.val[1]);
|
||||
vst1q_u32((uint32_t *)tx2, d.val[2]);
|
||||
vst1q_u32((uint32_t *)tx3, d.val[3]);
|
||||
tx0 += 4;
|
||||
tx1 += 4;
|
||||
tx2 += 4;
|
||||
tx3 += 4;
|
||||
}
|
||||
#endif
|
||||
for (; i < n_symbs; i += 4) {
|
||||
@@ -740,21 +914,47 @@ static inline __attribute__((always_inline)) __m256i cmac_prec256(__m256i y, __m
|
||||
}
|
||||
#endif
|
||||
#ifdef __aarch64__
|
||||
#ifdef NEWOPTIM
|
||||
static inline __attribute__((always_inline)) int16x4x2_t cmac0_prec4(int16x8_t x, int16x4_t wr, int16x4_t wi) {
|
||||
const int16x4_t x_lo = vget_low_s16(x);
|
||||
const int16x4_t x_hi = vget_high_s16(x);
|
||||
const int16x4_t xr = vuzp1_s16(x_lo, x_hi);
|
||||
const int16x4_t xi = vuzp2_s16(x_lo, x_hi);
|
||||
#else
|
||||
static inline __attribute__((always_inline)) int16x8_t cmac0_prec128(int16x8_t x, int16x8_t wr, int16x8_t wi) {
|
||||
//
|
||||
int16x8_t xr = vuzp1q_s16(x, x); // even lanes
|
||||
int16x8_t xi = vuzp2q_s16(x, x); // odd lanes
|
||||
#endif
|
||||
#ifdef __ARM_FEATURE_QRDMX
|
||||
// ARMv8.1-A: Use RDM instructions
|
||||
#ifdef NEWOPTIM
|
||||
// real = ar*br - ai*bi (Q15 scaling via high-half doubling muls)
|
||||
int16x4_t real = vqdmulh_s16(xr, wr); // ≈ round((2*xr*wr)/2^16)
|
||||
real = vqrdmlsh_s16(real, xi, wi); // real -= round((2*xi*wi)/2^16)
|
||||
// imag = ar*bi + ai*br
|
||||
int16x4_t imag = vqdmulh_s16(xr, wi);
|
||||
imag = vqrdmlah_s16(imag, xi, wr); // imag += round((2*xi*wr)/2^16)
|
||||
#else
|
||||
// real = ar*br - ai*bi (Q15 scaling via high-half doubling muls)
|
||||
int16x8_t real = vqdmulhq_s16(xr, wr); // ≈ round((2*xr*wr)/2^16)
|
||||
real = vqrdmlshq_s16(real, xi, wi); // real -= round((2*xi*wi)/2^16)
|
||||
//
|
||||
// imag = ar*bi + ai*br
|
||||
int16x8_t imag = vqdmulhq_s16(xr, wi);
|
||||
imag = vqrdmlahq_s16(imag, xi, wr); // imag += round((2*xi*wr)/2^16)
|
||||
#endif
|
||||
#else
|
||||
// ARMv8.0-A fallback: Use standard 32-bit multiply
|
||||
#ifdef NEWOPTIM
|
||||
int32x4_t real_prod = vmull_s16(xr, wr);
|
||||
real_prod = vmlsl_s16(real_prod, xi, wi);
|
||||
|
||||
int32x4_t imag_prod = vmull_s16(xr, wi);
|
||||
imag_prod = vmlal_s16(imag_prod, xi, wr);
|
||||
|
||||
int16x4_t real = vqrshrn_n_s32(real_prod, 15);
|
||||
int16x4_t imag = vqrshrn_n_s32(imag_prod, 15);
|
||||
#else
|
||||
int32x4_t real_lo = vmull_s16(vget_low_s16(xr), vget_low_s16(wr));
|
||||
int32x4_t real_hi = vmull_s16(vget_high_s16(xr), vget_high_s16(wr));
|
||||
real_lo = vmlsl_s16(real_lo, vget_low_s16(xi), vget_low_s16(wi));
|
||||
@@ -768,15 +968,33 @@ static inline __attribute__((always_inline)) int16x8_t cmac0_prec128(int16x8_t x
|
||||
int16x8_t real = vcombine_s16(vqrshrn_n_s32(real_lo, 15), vqrshrn_n_s32(real_hi, 15));
|
||||
int16x8_t imag = vcombine_s16(vqrshrn_n_s32(imag_lo, 15), vqrshrn_n_s32(imag_hi, 15));
|
||||
#endif
|
||||
#endif
|
||||
#ifdef NEWOPTIM
|
||||
int16x4x2_t produ;
|
||||
produ.val[0] = real;
|
||||
produ.val[1] = imag;
|
||||
return produ;
|
||||
#else
|
||||
// Re-interleave [real, imag]
|
||||
int16x8x2_t produ = vzipq_s16(real, imag);
|
||||
return produ.val[0];
|
||||
return produ.val[0];
|
||||
#endif
|
||||
}
|
||||
#ifdef NEWOPTIM
|
||||
static inline __attribute__((always_inline)) int16x4x2_t cmac_prec4(int16x4x2_t y, int16x8_t x, int16x4_t wr, int16x4_t wi) {
|
||||
const int16x4x2_t produ = cmac0_prec4(x, wr, wi);
|
||||
y.val[0] = vadd_s16(y.val[0], produ.val[0]);
|
||||
y.val[1] = vadd_s16(y.val[1], produ.val[1]);
|
||||
return y;
|
||||
}
|
||||
#else
|
||||
static inline __attribute__((always_inline)) int16x8_t cmac_prec128(int16x8_t y, int16x8_t x, int16x8_t wr, int16x8_t wi) {
|
||||
int16x8_t produ = cmac0_prec128(x, wr, wi);
|
||||
return vaddq_s16(y, produ);
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
#else // __x86 128-bit
|
||||
static inline __attribute__((always_inline)) simde__m128i cmac0_prec128(simde__m128i x, simde__m128i w_c, simde__m128i w_s)
|
||||
{
|
||||
// Multiplication and shift
|
||||
@@ -807,6 +1025,12 @@ static inline __attribute__((always_inline)) __m128i cmac_prec128(__m128i y, __m
|
||||
const Type w_c##Rank = Instruct(c16toI32(c16conj(weights[Rank][ant]))); \
|
||||
const Type w_s##Rank = Instruct(c16toI32(c16swap(weights[Rank][ant]))); \
|
||||
const Type *in##Rank = (Type *)(txdataF_res_mapped[Rank] + sc_offset + (out-beginning));
|
||||
#if defined(NEWOPTIM) && defined(__aarch64__)
|
||||
#define load_consts_arm(Rank) \
|
||||
const int16x4_t wr##Rank = vdup_n_s16(weights[Rank][ant].r); \
|
||||
const int16x4_t wi##Rank = vdup_n_s16(weights[Rank][ant].i); \
|
||||
const int16x8_t *in##Rank = (const int16x8_t *)(txdataF_res_mapped[Rank] + sc_offset + (out - beginning));
|
||||
#endif
|
||||
|
||||
void nr_layer_precoder_simd(const int n_layers,
|
||||
const int symSz,
|
||||
@@ -943,19 +1167,37 @@ void nr_layer_precoder_simd(const int n_layers,
|
||||
}
|
||||
#endif
|
||||
#ifdef __aarch64__
|
||||
load_consts(int16x8_t, vdupq_n_s16, 0);
|
||||
#ifdef NEWOPTIM
|
||||
load_consts_arm(0);
|
||||
#else
|
||||
load_consts(int16x8_t, vdupq_n_s16, 0);
|
||||
#endif
|
||||
if (n_layers == 1) {
|
||||
for (; out < end; out += sizeof(int16x8_t) / sizeof(*out)) {
|
||||
#ifdef NEWOPTIM
|
||||
const int16x4x2_t y = cmac0_prec4(vld1q_s16((const int16_t *)in0++), wr0, wi0);
|
||||
vst2_s16((int16_t *)out, y);
|
||||
#else
|
||||
const int16x8_t x0 = vld1q_s16((const int16_t *)in0++);
|
||||
// Accumulate the product
|
||||
int16x8_t y = cmac0_prec128(x0, w_c0, w_s0);
|
||||
// Store the result to txdataF
|
||||
*(int16x8_t *)out = y;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (n_layers == 2) {
|
||||
load_consts(int16x8_t, vdupq_n_s16, 1);
|
||||
#ifdef NEWOPTIM
|
||||
load_consts_arm(1);
|
||||
#else
|
||||
load_consts(int16x8_t, vdupq_n_s16, 1);
|
||||
#endif
|
||||
for (; out < end; out += sizeof(int16x8_t) / sizeof(*out)) {
|
||||
#ifdef NEWOPTIM
|
||||
int16x4x2_t y = cmac0_prec4(vld1q_s16((const int16_t *)in0++), wr0, wi0);
|
||||
y = cmac_prec4(y, vld1q_s16((const int16_t *)in1++), wr1, wi1);
|
||||
vst2_s16((int16_t *)out, y);
|
||||
#else
|
||||
const int16x8_t x0 = vld1q_s16((const int16_t *)in0++);
|
||||
const int16x8_t x1 = vld1q_s16((const int16_t *)in1++);
|
||||
// Accumulate the product
|
||||
@@ -963,41 +1205,66 @@ void nr_layer_precoder_simd(const int n_layers,
|
||||
y = cmac_prec128(y, x1, w_c1, w_s1);
|
||||
// Store the result to txdataF
|
||||
*(int16x8_t *)out = y;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (n_layers == 3) {
|
||||
#ifdef NEWOPTIM
|
||||
load_consts_arm(1);
|
||||
load_consts_arm(2);
|
||||
#else
|
||||
load_consts(int16x8_t, vdupq_n_s16, 1);
|
||||
load_consts(int16x8_t, vdupq_n_s16, 2);
|
||||
#endif
|
||||
for (; out < end; out += sizeof(int16x8_t) / sizeof(*out)) {
|
||||
#ifdef NEWOPTIM
|
||||
int16x4x2_t y = cmac0_prec4(vld1q_s16((const int16_t *)in0++), wr0, wi0);
|
||||
y = cmac_prec4(y, vld1q_s16((const int16_t *)in1++), wr1, wi1);
|
||||
y = cmac_prec4(y, vld1q_s16((const int16_t *)in2++), wr2, wi2);
|
||||
vst2_s16((int16_t *)out, y);
|
||||
#else
|
||||
const int16x8_t x0 = vld1q_s16((const int16_t *)in0++);
|
||||
const int16x8_t x1 = vld1q_s16((const int16_t *)in1++);
|
||||
const int16x8_t x2 = vld1q_s16((const int16_t *)in2++);
|
||||
// Accumulate the product
|
||||
int16x8_t y = cmac0_prec128(x0, w_c0, w_s0);
|
||||
;
|
||||
y = cmac_prec128(y, x1, w_c1, w_s1);
|
||||
y = cmac_prec128(y, x2, w_c2, w_s2);
|
||||
// Store the result to txdataF
|
||||
*(int16x8_t *)out = y;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (n_layers == 4) {
|
||||
#ifdef NEWOPTIM
|
||||
load_consts_arm(1);
|
||||
load_consts_arm(2);
|
||||
load_consts_arm(3);
|
||||
#else
|
||||
load_consts(int16x8_t, vdupq_n_s16, 1);
|
||||
load_consts(int16x8_t, vdupq_n_s16, 2);
|
||||
load_consts(int16x8_t, vdupq_n_s16, 3);
|
||||
#endif
|
||||
for (; out < end; out += sizeof(int16x8_t) / sizeof(*out)) {
|
||||
#ifdef NEWOPTIM
|
||||
int16x4x2_t y = cmac0_prec4(vld1q_s16((const int16_t *)in0++), wr0, wi0);
|
||||
y = cmac_prec4(y, vld1q_s16((const int16_t *)in1++), wr1, wi1);
|
||||
y = cmac_prec4(y, vld1q_s16((const int16_t *)in2++), wr2, wi2);
|
||||
y = cmac_prec4(y, vld1q_s16((const int16_t *)in3++), wr3, wi3);
|
||||
vst2_s16((int16_t *)out, y);
|
||||
#else
|
||||
const int16x8_t x0 = vld1q_s16((const int16_t *)in0++);
|
||||
const int16x8_t x1 = vld1q_s16((const int16_t *)in1++);
|
||||
const int16x8_t x2 = vld1q_s16((const int16_t *)in2++);
|
||||
const int16x8_t x3 = vld1q_s16((const int16_t *)in3++);
|
||||
// Accumulate the product
|
||||
int16x8_t y = cmac0_prec128(x0, w_c0, w_s0);
|
||||
;
|
||||
y = cmac_prec128(y, x1, w_c1, w_s1);
|
||||
y = cmac_prec128(y, x2, w_c2, w_s2);
|
||||
y = cmac_prec128(y, x3, w_c3, w_s3);
|
||||
// Store the result to txdataF
|
||||
*(int16x8_t *)out = y;
|
||||
*(int16x8_t *)out = y;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -28,6 +28,13 @@ void nr_modulation(const uint32_t *in,
|
||||
uint16_t mod_order,
|
||||
int16_t *out);
|
||||
|
||||
bool nr_modulation_layer_mapping(const uint32_t *in,
|
||||
uint32_t length,
|
||||
uint16_t mod_order,
|
||||
uint8_t n_layers,
|
||||
int layerSz,
|
||||
c16_t tx_layers[][layerSz]);
|
||||
|
||||
/*! \brief Perform NR layer mapping. TS 38.211 V15.4.0 subclause 7.3.1.3
|
||||
@param[in] mod_symbs, double Pointer to modulated symbols for each codeword
|
||||
@param[in] n_layers, number of layers
|
||||
|
||||
@@ -27,11 +27,26 @@ static void nr_pdcch_scrambling(uint32_t *in, uint32_t size, uint32_t Nid, uint3
|
||||
out[i] = in[i] ^ seq[i];
|
||||
}
|
||||
|
||||
static inline void mark_prb(uint64_t *prb_mask, int prb_mask_words, int symbol, int prb)
|
||||
{
|
||||
uint64_t *symbol_mask = prb_mask + symbol * prb_mask_words;
|
||||
symbol_mask[prb >> 6] |= UINT64_C(1) << (prb & 63);
|
||||
}
|
||||
|
||||
static inline bool prb_marked(const uint64_t *prb_mask, int prb)
|
||||
{
|
||||
return (prb_mask[prb >> 6] >> (prb & 63)) & 0x1;
|
||||
}
|
||||
|
||||
void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int slot)
|
||||
int slot,
|
||||
uint64_t *phase_comp_prb_mask,
|
||||
int prb_mask_words)
|
||||
{
|
||||
uint64_t local_phase_comp_prb_mask[gNB->common_vars.num_beams_period][frame_parms->symbols_per_slot][prb_mask_words];
|
||||
memset(local_phase_comp_prb_mask, 0, sizeof(local_phase_comp_prb_mask));
|
||||
// fill reg list per symbol
|
||||
int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE];
|
||||
nr_fill_reg_list(reg_list, pdcch_pdu_rel15);
|
||||
@@ -172,6 +187,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
dmrs_idx = (reg_list[d][reg_count] + pdcch_pdu_rel15->BWPStart + rb_offset) * 3;
|
||||
else
|
||||
dmrs_idx = (reg_list[d][reg_count] + rb_offset) * 3;
|
||||
const int reg_prb = pdcch_pdu_rel15->BWPStart + reg_list[d][reg_count] + rb_offset;
|
||||
|
||||
int k_prime = 0;
|
||||
|
||||
@@ -199,6 +215,8 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
|
||||
k++;
|
||||
} // m
|
||||
if (gNB->phase_comp)
|
||||
mark_prb(&local_phase_comp_prb_mask[beam_nb][0][0], prb_mask_words, l, reg_prb);
|
||||
} // reg_count
|
||||
} // symbol_idx
|
||||
|
||||
@@ -207,4 +225,33 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
dci_pdu->PayloadSizeBits,
|
||||
*(unsigned long long *)dci_pdu->Payload);
|
||||
} // for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++)
|
||||
|
||||
if (!gNB->phase_comp)
|
||||
return;
|
||||
|
||||
const int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot;
|
||||
for (int beam = 0; beam < gNB->common_vars.num_beams_period; beam++) {
|
||||
c16_t *txdataF = gNB->common_vars.txdataF[beam][0];
|
||||
for (int symbol = pdcch_pdu_rel15->StartSymbolIndex;
|
||||
symbol < pdcch_pdu_rel15->StartSymbolIndex + pdcch_pdu_rel15->DurationSymbols;
|
||||
symbol++) {
|
||||
uint64_t *local_symbol_mask = &local_phase_comp_prb_mask[beam][symbol][0];
|
||||
int prb = 0;
|
||||
while (prb < frame_parms->N_RB_DL) {
|
||||
while (prb < frame_parms->N_RB_DL && !prb_marked(local_symbol_mask, prb))
|
||||
prb++;
|
||||
const int start_prb = prb;
|
||||
while (prb < frame_parms->N_RB_DL && prb_marked(local_symbol_mask, prb))
|
||||
prb++;
|
||||
if (prb > start_prb) {
|
||||
c16_t *this_symbol = txdataF + symbol * frame_parms->ofdm_symbol_size + start_prb * NR_NB_SC_PER_RB;
|
||||
const c16_t *rot = &frame_parms->symbol_rotation[0][symb_offset + symbol];
|
||||
rotate_cpx_vector(this_symbol, rot, this_symbol, (prb - start_prb) * NR_NB_SC_PER_RB, 15);
|
||||
uint64_t *global_symbol_mask = phase_comp_prb_mask + (beam * frame_parms->symbols_per_slot + symbol) * prb_mask_words;
|
||||
for (int rr = start_prb; rr < prb; rr++)
|
||||
global_symbol_mask[rr >> 6] |= UINT64_C(1) << (rr & 63);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int slot);
|
||||
int slot,
|
||||
uint64_t *phase_comp_prb_mask,
|
||||
int prb_mask_words);
|
||||
|
||||
void nr_fill_dci(PHY_VARS_gNB *gNB,
|
||||
int frame,
|
||||
|
||||
@@ -500,12 +500,21 @@ typedef struct pdschSymbolProc_s {
|
||||
unsigned int dlPtrsSymPos;
|
||||
unsigned int n_ptrs;
|
||||
unsigned int beam_nb;
|
||||
uint64_t *pdsch_phase_comp_prb_mask;
|
||||
int prb_mask_words;
|
||||
unsigned int re_beginning_of_symbol[14];
|
||||
c16_t *tx_layers[4];
|
||||
time_stats_t dlsch_resource_mapping_stats;
|
||||
time_stats_t dlsch_precoding_stats;
|
||||
} pdschSymbolProc_t;
|
||||
|
||||
static inline void mark_prb_range(uint64_t *prb_mask, int prb_mask_words, int symbol, int start_prb, int nb_prb)
|
||||
{
|
||||
uint64_t *symbol_mask = prb_mask + symbol * prb_mask_words;
|
||||
for (int prb = start_prb; prb < start_prb + nb_prb; prb++)
|
||||
symbol_mask[prb >> 6] |= UINT64_C(1) << (prb & 63);
|
||||
}
|
||||
|
||||
static void nr_pdsch_symbol_processing(void *arg)
|
||||
{
|
||||
pdschSymbolProc_t *rdata = (pdschSymbolProc_t *)arg;
|
||||
@@ -525,6 +534,7 @@ static void nr_pdsch_symbol_processing(void *arg)
|
||||
const int symbol_sz = frame_parms->ofdm_symbol_size;
|
||||
|
||||
c16_t **txdataF = gNB->common_vars.txdataF[rdata->beam_nb];
|
||||
const int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot;
|
||||
|
||||
for (int l_symbol = rdata->startSymbol; l_symbol < rdata->startSymbol + rdata->numSymbols; l_symbol++) {
|
||||
start_meas(&rdata->dlsch_resource_mapping_stats);
|
||||
@@ -593,6 +603,12 @@ static void nr_pdsch_symbol_processing(void *arg)
|
||||
block_end - block_start + 1,
|
||||
txdataF_offset_per_symbol);
|
||||
|
||||
if (gNB->phase_comp) {
|
||||
c16_t *pdsch_sc = &txdataF[ant][txdataF_offset_per_symbol + block_start];
|
||||
const c16_t *rot = &frame_parms->symbol_rotation[0][symb_offset + l_symbol];
|
||||
rotate_cpx_vector(pdsch_sc, rot, pdsch_sc,(block_end - block_start + 1)*NR_NB_SC_PER_RB, 15);
|
||||
mark_prb_range(rdata->pdsch_phase_comp_prb_mask, rdata->prb_mask_words, l_symbol, block_start, block_end - block_start + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
stop_meas(&rdata->dlsch_precoding_stats);
|
||||
@@ -601,7 +617,12 @@ static void nr_pdsch_symbol_processing(void *arg)
|
||||
completed_task_ans(rdata->ans);
|
||||
}
|
||||
|
||||
static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSCH_t *dlsch, int slot)
|
||||
static int do_one_dlsch(unsigned char *input_ptr,
|
||||
PHY_VARS_gNB *gNB,
|
||||
NR_gNB_DLSCH_t *dlsch,
|
||||
int slot,
|
||||
uint64_t *pdsch_phase_comp_prb_mask,
|
||||
int prb_mask_words)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
|
||||
@@ -650,51 +671,67 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
if (IS_SOFTMODEM_DLSIM)
|
||||
memcpy(dlsch->f, input_ptr, (encoded_length + 7) >> 3);
|
||||
|
||||
c16_t mod_symbs[rel15->NrOfCodewords][encoded_length] __attribute__((aligned(64)));
|
||||
for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) {
|
||||
/// scrambling
|
||||
start_meas(dlsch_scrambling_stats);
|
||||
uint32_t scrambled_output[(encoded_length >> 5) + 4]; // modulator acces by 4 bytes in some cases
|
||||
memset(scrambled_output, 0, sizeof(scrambled_output));
|
||||
nr_pdsch_codeword_scrambling(input_ptr, encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output);
|
||||
|
||||
#ifdef DEBUG_DLSCH
|
||||
printf("PDSCH scrambling:\n");
|
||||
for (int i = 0; i < encoded_length >> 8; i++) {
|
||||
for (int j = 0; j < 8; j++)
|
||||
printf("0x%08x\t", scrambled_output[(i << 3) + j]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
stop_meas(dlsch_scrambling_stats);
|
||||
/// Modulation
|
||||
start_meas(dlsch_modulation_stats);
|
||||
nr_modulation(scrambled_output, encoded_length, Qm, (int16_t *)mod_symbs[codeWord]);
|
||||
stop_meas(dlsch_modulation_stats);
|
||||
#ifdef DEBUG_DLSCH
|
||||
printf("PDSCH Modulation: Qm %d(%d)\n", Qm, nb_re);
|
||||
for (int i = 0; i < nb_re; i += 8) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
printf("%d %d\t", mod_symbs[codeWord][i + j].r, mod_symbs[codeWord][i + j].i);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
start_meas(&gNB->dlsch_pdsch_generation_stats);
|
||||
/// Resource mapping
|
||||
// Non interleaved VRB to PRB mapping
|
||||
|
||||
AssertFatal(n_dmrs, "n_dmrs can't be 0\n");
|
||||
// make a large enough tail to process all re with SIMD regardless a garbadge filler
|
||||
|
||||
start_meas(&gNB->dlsch_layer_mapping_stats);
|
||||
int layerSz2 = (layerSz + 63) & ~63;
|
||||
c16_t tx_layers[rel15->nrOfLayers][layerSz2] __attribute__((aligned(64)));
|
||||
memset(tx_layers, 0, sizeof(tx_layers));
|
||||
nr_layer_mapping(rel15->NrOfCodewords, encoded_length, mod_symbs, rel15->nrOfLayers, layerSz2, nb_re, tx_layers);
|
||||
const bool use_fused_mod_layer =
|
||||
rel15->NrOfCodewords == 1 && (rel15->nrOfLayers == 3 || rel15->nrOfLayers == 4) && (Qm == 2 || Qm == 4 || Qm == 6 || Qm == 8);
|
||||
|
||||
if (use_fused_mod_layer) {
|
||||
start_meas(dlsch_scrambling_stats);
|
||||
uint32_t scrambled_output[(encoded_length >> 5) + 4]; // modulator access by 4 bytes in some cases
|
||||
memset(scrambled_output, 0, sizeof(scrambled_output));
|
||||
start_meas(dlsch_modulation_stats);
|
||||
nr_pdsch_codeword_scrambling(input_ptr, encoded_length, 0, rel15->dataScramblingId, rel15->rnti, scrambled_output);
|
||||
stop_meas(dlsch_scrambling_stats);
|
||||
|
||||
const bool fused_ok =
|
||||
nr_modulation_layer_mapping(scrambled_output, encoded_length, Qm, rel15->nrOfLayers, layerSz2, tx_layers);
|
||||
AssertFatal(fused_ok,
|
||||
"Unsupported fused modulation/layer mapping for Qm %d, %d layers, %d codewords\n",
|
||||
Qm,
|
||||
rel15->nrOfLayers,
|
||||
rel15->NrOfCodewords);
|
||||
stop_meas(dlsch_modulation_stats);
|
||||
} else {
|
||||
c16_t mod_symbs[rel15->NrOfCodewords][encoded_length] __attribute__((aligned(64)));
|
||||
for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) {
|
||||
/// scrambling
|
||||
start_meas(dlsch_scrambling_stats);
|
||||
uint32_t scrambled_output[(encoded_length >> 5) + 4]; // modulator acces by 4 bytes in some cases
|
||||
memset(scrambled_output, 0, sizeof(scrambled_output));
|
||||
nr_pdsch_codeword_scrambling(input_ptr, encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output);
|
||||
|
||||
#ifdef DEBUG_DLSCH
|
||||
printf("PDSCH scrambling:\n");
|
||||
for (int i = 0; i < encoded_length >> 8; i++) {
|
||||
for (int j = 0; j < 8; j++)
|
||||
printf("0x%08x\t", scrambled_output[(i << 3) + j]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
stop_meas(dlsch_scrambling_stats);
|
||||
/// Modulation
|
||||
start_meas(dlsch_modulation_stats);
|
||||
nr_modulation(scrambled_output, encoded_length, Qm, (int16_t *)mod_symbs[codeWord]);
|
||||
stop_meas(dlsch_modulation_stats);
|
||||
#ifdef DEBUG_DLSCH
|
||||
printf("PDSCH Modulation: Qm %d(%d)\n", Qm, nb_re);
|
||||
for (int i = 0; i < nb_re; i += 8) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
printf("%d %d\t", mod_symbs[codeWord][i + j].r, mod_symbs[codeWord][i + j].i);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
start_meas(&gNB->dlsch_layer_mapping_stats);
|
||||
nr_layer_mapping(rel15->NrOfCodewords, encoded_length, mod_symbs, rel15->nrOfLayers, layerSz2, nb_re, tx_layers);
|
||||
stop_meas(&gNB->dlsch_layer_mapping_stats);
|
||||
}
|
||||
|
||||
/// Layer Precoding and Antenna port mapping
|
||||
// tx_layers 1-8 are mapped on antenna ports 1000-1007
|
||||
@@ -712,7 +749,11 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
slot,
|
||||
frame_parms->symbols_per_slot,
|
||||
bitmap);
|
||||
stop_meas(&gNB->dlsch_layer_mapping_stats);
|
||||
/// Resource mapping
|
||||
// Non interleaved VRB to PRB mapping
|
||||
|
||||
AssertFatal(n_dmrs, "n_dmrs can't be 0\n");
|
||||
// make a large enough tail to process all re with SIMD regardless a garbadge filler
|
||||
|
||||
// spawn symbol threads
|
||||
|
||||
@@ -752,6 +793,8 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
rdata->dlPtrsSymPos = dlPtrsSymPos;
|
||||
rdata->n_ptrs = n_ptrs;
|
||||
rdata->beam_nb = beam_nb;
|
||||
rdata->pdsch_phase_comp_prb_mask = pdsch_phase_comp_prb_mask + beam_nb * frame_parms->symbols_per_slot * prb_mask_words;
|
||||
rdata->prb_mask_words = prb_mask_words;
|
||||
for (int s = l_symbol; s < l_symbol + rdata->numSymbols; s++) {
|
||||
rdata->re_beginning_of_symbol[s] = re_beginning_of_symbol;
|
||||
re_beginning_of_symbol += freq_alloc->num_rbs * NR_NB_SC_PER_RB;
|
||||
@@ -785,7 +828,13 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
return ((size_output_tb + 511) >> 9) << 6;
|
||||
}
|
||||
|
||||
void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_array, int frame, int slot)
|
||||
void nr_generate_pdsch(PHY_VARS_gNB *gNB,
|
||||
int n_dlsch,
|
||||
NR_gNB_DLSCH_t *dlsch_array,
|
||||
int frame,
|
||||
int slot,
|
||||
uint64_t *pdsch_phase_comp_prb_mask,
|
||||
int prb_mask_words)
|
||||
{
|
||||
time_stats_t *dlsch_encoding_stats = &gNB->dlsch_encoding_stats;
|
||||
time_stats_t *tinput = &gNB->tinput;
|
||||
@@ -867,7 +916,7 @@ void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_arr
|
||||
|
||||
unsigned char *output_ptr = output;
|
||||
for (int i = 0; i < n_dlsch; i++) {
|
||||
output_ptr += do_one_dlsch(output_ptr, gNB, &dlsch_array[i], slot);
|
||||
output_ptr += do_one_dlsch(output_ptr, gNB, &dlsch_array[i], slot, pdsch_phase_comp_prb_mask, prb_mask_words);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,13 @@
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
|
||||
void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_array, int frame, int slot);
|
||||
void nr_generate_pdsch(PHY_VARS_gNB *gNB,
|
||||
int n_dlsch,
|
||||
NR_gNB_DLSCH_t *dlsch_array,
|
||||
int frame,
|
||||
int slot,
|
||||
uint64_t *pdsch_phase_comp_prb_mask,
|
||||
int prb_mask_words);
|
||||
|
||||
int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
int n_dlsch,
|
||||
|
||||
@@ -16,11 +16,11 @@ void nr_codeword_scrambling(uint8_t *in,
|
||||
const int roundedSz = (size + 31) / 32;
|
||||
uint32_t *seq = gold_cache((n_RNTI << 15) + (q << 14) + Nid, roundedSz);
|
||||
unsigned int i_32 = 0;
|
||||
#if defined(__AVX512F__) && defined(__AVX512VL__)
|
||||
#ifdef __AVX2__
|
||||
for (; i_32 < ((roundedSz >> 3) << 3); i_32 += 8) {
|
||||
__m256i in_256 = _mm256_load_epi32(&((uint32_t *)in)[i_32]);
|
||||
__m256i seq_256 = _mm256_load_epi32(&seq[i_32]);
|
||||
_mm256_storeu_epi32(&out[i_32], _mm256_xor_si256(in_256, seq_256));
|
||||
__m256i in_256 = _mm256_loadu_si256((void*)&((uint32_t *)in)[i_32]);
|
||||
__m256i seq_256 = _mm256_loadu_si256((void*)&seq[i_32]);
|
||||
_mm256_storeu_si256((void*)&out[i_32], _mm256_xor_si256(in_256, seq_256));
|
||||
}
|
||||
#endif
|
||||
#if defined(__aarch64__)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
|
||||
#include "T.h"
|
||||
#include "T_messages_creator.h"
|
||||
#include "executables/nr-softmodem.h"
|
||||
@@ -39,6 +40,90 @@ static void nr_fill_indication(const PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_crc_t *crc,
|
||||
nfapi_nr_rx_data_pdu_t *pdu);
|
||||
|
||||
static inline bool prb_is_rotated(const uint64_t *prb_mask, int prb)
|
||||
{
|
||||
return (prb_mask[prb >> 6] >> (prb & 63)) & 0x1;
|
||||
}
|
||||
|
||||
static inline void mark_prb(uint64_t *prb_mask, int prb_mask_words, int symbol, int prb)
|
||||
{
|
||||
uint64_t *symbol_mask = prb_mask + symbol * prb_mask_words;
|
||||
symbol_mask[prb >> 6] |= UINT64_C(1) << (prb & 63);
|
||||
}
|
||||
|
||||
static inline void mark_prb_range(uint64_t *prb_mask, int prb_mask_words, int symbol, int first_prb, int nb_prb)
|
||||
{
|
||||
for (int prb = first_prb; prb < first_prb + nb_prb; prb++)
|
||||
mark_prb(prb_mask, prb_mask_words, symbol, prb);
|
||||
}
|
||||
|
||||
static inline void apply_nr_rotation_TX_segment(const NR_DL_FRAME_PARMS *fp,
|
||||
c16_t *txdataF,
|
||||
const c16_t *symbol_rotation,
|
||||
int slot,
|
||||
int symbol,
|
||||
int first_prb,
|
||||
int nb_prb)
|
||||
{
|
||||
const int symb_offset = (slot % fp->slots_per_subframe) * fp->symbols_per_slot;
|
||||
const c16_t *rot = &symbol_rotation[symb_offset + symbol];
|
||||
c16_t *this_symbol = txdataF + symbol * fp->ofdm_symbol_size + first_prb * NR_NB_SC_PER_RB;
|
||||
rotate_cpx_vector(this_symbol, rot, this_symbol, nb_prb * NR_NB_SC_PER_RB, 15);
|
||||
}
|
||||
|
||||
static void merge_prb_mask(const NR_DL_FRAME_PARMS *fp,
|
||||
const uint64_t *local_prb_mask,
|
||||
uint64_t *global_prb_mask,
|
||||
int prb_mask_words)
|
||||
{
|
||||
for (int symbol = 0; symbol < fp->symbols_per_slot; symbol++) {
|
||||
const uint64_t *local_symbol_mask = local_prb_mask + symbol * prb_mask_words;
|
||||
uint64_t *global_symbol_mask = global_prb_mask + symbol * prb_mask_words;
|
||||
int prb = 0;
|
||||
while (prb < fp->N_RB_DL) {
|
||||
while (prb < fp->N_RB_DL && !prb_is_rotated(local_symbol_mask, prb))
|
||||
prb++;
|
||||
const int start_prb = prb;
|
||||
while (prb < fp->N_RB_DL && prb_is_rotated(local_symbol_mask, prb))
|
||||
prb++;
|
||||
if (prb > start_prb) {
|
||||
for (int rr = start_prb; rr < prb; rr++)
|
||||
global_symbol_mask[rr >> 6] |= UINT64_C(1) << (rr & 63);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_nr_rotation_TX_masked(const NR_DL_FRAME_PARMS *fp,
|
||||
c16_t **txdataF,
|
||||
int num_tx_buffers,
|
||||
const c16_t *symbol_rotation,
|
||||
int slot,
|
||||
const uint64_t *local_prb_mask,
|
||||
uint64_t *global_prb_mask,
|
||||
int prb_mask_words)
|
||||
{
|
||||
for (int aa = 0; aa < num_tx_buffers; aa++) {
|
||||
if (!txdataF[aa])
|
||||
continue;
|
||||
for (int symbol = 0; symbol < fp->symbols_per_slot; symbol++) {
|
||||
const uint64_t *local_symbol_mask = local_prb_mask + symbol * prb_mask_words;
|
||||
int prb = 0;
|
||||
while (prb < fp->N_RB_DL) {
|
||||
while (prb < fp->N_RB_DL && !prb_is_rotated(local_symbol_mask, prb))
|
||||
prb++;
|
||||
const int start_prb = prb;
|
||||
while (prb < fp->N_RB_DL && prb_is_rotated(local_symbol_mask, prb))
|
||||
prb++;
|
||||
if (prb > start_prb)
|
||||
apply_nr_rotation_TX_segment(fp, txdataF[aa], symbol_rotation, slot, symbol, start_prb, prb - start_prb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
merge_prb_mask(fp, local_prb_mask, global_prb_mask, prb_mask_words);
|
||||
}
|
||||
|
||||
int beam_index_allocation(bool das,
|
||||
int fapi_beam_index,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
@@ -78,7 +163,12 @@ int beam_index_allocation(bool das,
|
||||
return idx;
|
||||
}
|
||||
|
||||
void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu)
|
||||
void nr_common_signal_procedures(PHY_VARS_gNB *gNB,
|
||||
int frame,
|
||||
int slot,
|
||||
const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
|
||||
uint64_t *phase_comp_prb_mask,
|
||||
int prb_mask_words)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
const nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu->ssb_pdu_rel15;
|
||||
@@ -164,6 +254,26 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n
|
||||
frame,
|
||||
cfg,
|
||||
fp);
|
||||
|
||||
if (!gNB->phase_comp)
|
||||
return;
|
||||
|
||||
uint64_t local_phase_comp_prb_mask[fp->symbols_per_slot][prb_mask_words];
|
||||
memset(local_phase_comp_prb_mask, 0, sizeof(local_phase_comp_prb_mask));
|
||||
const int ssb_start_prb = fp->ssb_start_subcarrier / NR_NB_SC_PER_RB;
|
||||
const int ssb_nb_prb = (fp->ssb_start_subcarrier % NR_NB_SC_PER_RB + 240 + NR_NB_SC_PER_RB - 1) / NR_NB_SC_PER_RB;
|
||||
for (int symbol = ssb_start_symbol; symbol < ssb_start_symbol + NR_N_SYMBOLS_SSB; symbol++)
|
||||
mark_prb_range(&local_phase_comp_prb_mask[0][0], prb_mask_words, symbol, ssb_start_prb, ssb_nb_prb);
|
||||
|
||||
c16_t *ssb_txdataF[] = {txdataF[beam_nb][0]};
|
||||
apply_nr_rotation_TX_masked(fp,
|
||||
ssb_txdataF,
|
||||
1,
|
||||
fp->symbol_rotation[0],
|
||||
slot,
|
||||
&local_phase_comp_prb_mask[0][0],
|
||||
phase_comp_prb_mask + beam_nb * fp->symbols_per_slot * prb_mask_words,
|
||||
prb_mask_words);
|
||||
}
|
||||
|
||||
// clearing beam information to be provided to RU for all slots (DL and UL)
|
||||
@@ -177,7 +287,11 @@ void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot)
|
||||
}
|
||||
}
|
||||
|
||||
static void nr_generate_csi_rs_gNB(PHY_VARS_gNB *gNB, int slot, const nfapi_nr_dl_tti_csi_rs_pdu *csi_rs_pdu)
|
||||
static void nr_generate_csi_rs_gNB(PHY_VARS_gNB *gNB,
|
||||
int slot,
|
||||
const nfapi_nr_dl_tti_csi_rs_pdu *csi_rs_pdu,
|
||||
uint64_t *phase_comp_prb_mask,
|
||||
int prb_mask_words)
|
||||
{
|
||||
const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csi_rs_pdu->csi_rs_pdu_rel15;
|
||||
if (csi_params->csi_type == 2) // ZP-CSI
|
||||
@@ -211,6 +325,60 @@ static void nr_generate_csi_rs_gNB(PHY_VARS_gNB *gNB, int slot, const nfapi_nr_d
|
||||
csi_params->power_control_offset_ss,
|
||||
csi_params->cdm_type,
|
||||
gNB->common_vars.txdataF[beam_nb]);
|
||||
|
||||
if (!gNB->phase_comp)
|
||||
return;
|
||||
|
||||
uint64_t local_phase_comp_prb_mask[gNB->frame_parms.symbols_per_slot][prb_mask_words];
|
||||
memset(local_phase_comp_prb_mask, 0, sizeof(local_phase_comp_prb_mask));
|
||||
for (int rb = csi_params->start_rb; rb < csi_params->start_rb + csi_params->nr_of_rbs; rb++) {
|
||||
if ((csi_params->freq_density <= 1) && (csi_params->freq_density != (rb % 2)))
|
||||
continue;
|
||||
for (int j = 0; j < mapping_parms.size; j++) {
|
||||
for (int lp = 0; lp <= mapping_parms.lprime; lp++) {
|
||||
const int symbol = mapping_parms.loverline[j] + lp;
|
||||
mark_prb(&local_phase_comp_prb_mask[0][0], prb_mask_words, symbol, rb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply_nr_rotation_TX_masked(&gNB->frame_parms,
|
||||
gNB->common_vars.txdataF[beam_nb],
|
||||
min(mapping_parms.ports, gNB->gNB_config.carrier_config.num_tx_ant.value),
|
||||
gNB->frame_parms.symbol_rotation[0],
|
||||
slot,
|
||||
&local_phase_comp_prb_mask[0][0],
|
||||
phase_comp_prb_mask + beam_nb * gNB->frame_parms.symbols_per_slot * prb_mask_words,
|
||||
prb_mask_words);
|
||||
}
|
||||
|
||||
static void nr_generate_prs_gNB(PHY_VARS_gNB *gNB,
|
||||
int slot,
|
||||
int slot_prs,
|
||||
prs_config_t *prs_config,
|
||||
uint64_t *phase_comp_prb_mask,
|
||||
int prb_mask_words)
|
||||
{
|
||||
const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
nr_generate_prs(slot_prs, gNB->common_vars.txdataF[0][0], AMP, prs_config, fp);
|
||||
|
||||
if (!gNB->phase_comp)
|
||||
return;
|
||||
|
||||
uint64_t local_phase_comp_prb_mask[fp->symbols_per_slot][prb_mask_words];
|
||||
memset(local_phase_comp_prb_mask, 0, sizeof(local_phase_comp_prb_mask));
|
||||
for (int symbol = prs_config->SymbolStart; symbol < prs_config->SymbolStart + prs_config->NumPRSSymbols; symbol++)
|
||||
mark_prb_range(&local_phase_comp_prb_mask[0][0], prb_mask_words, symbol, prs_config->RBOffset, prs_config->NumRB);
|
||||
|
||||
c16_t *prs_txdataF[] = {gNB->common_vars.txdataF[0][0]};
|
||||
apply_nr_rotation_TX_masked(fp,
|
||||
prs_txdataF,
|
||||
1,
|
||||
fp->symbol_rotation[0],
|
||||
slot,
|
||||
&local_phase_comp_prb_mask[0][0],
|
||||
phase_comp_prb_mask,
|
||||
prb_mask_words);
|
||||
}
|
||||
|
||||
void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
|
||||
@@ -226,6 +394,10 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
|
||||
if ((cfg->cell_config.frame_duplex_type.value == TDD) && (nr_slot_select(cfg,frame,slot) == NR_UPLINK_SLOT))
|
||||
return;
|
||||
|
||||
const int prb_mask_words = (fp->N_RB_DL + 63) >> 6;
|
||||
uint64_t phase_comp_prb_mask[gNB->common_vars.num_beams_period][fp->symbols_per_slot][prb_mask_words];
|
||||
memset(phase_comp_prb_mask, 0, sizeof(phase_comp_prb_mask));
|
||||
|
||||
// clear the transmit data array and beam index for the current slot
|
||||
for (int i = 0; i < gNB->common_vars.num_beams_period; i++) {
|
||||
for (int aa = 0; aa < cfg->carrier_config.num_tx_ant.value; aa++) {
|
||||
@@ -243,26 +415,41 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
|
||||
{
|
||||
int slot_prs = (slot - i * prs_config->PRSResourceTimeGap + fp->slots_per_frame) % fp->slots_per_frame;
|
||||
LOG_D(PHY,"gNB_TX: frame %d, slot %d, slot_prs %d, PRS Resource ID %d\n",frame, slot, slot_prs, rsc_id);
|
||||
nr_generate_prs(slot_prs, gNB->common_vars.txdataF[0][0], AMP, prs_config, fp);
|
||||
nr_generate_prs_gNB(gNB, slot, slot_prs, prs_config, &phase_comp_prb_mask[0][0][0], prb_mask_words);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < UL_dci_req->numPdus; ++i)
|
||||
nr_generate_dci(gNB, &UL_dci_req->ul_dci_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15, &gNB->frame_parms, slot);
|
||||
nr_generate_dci(gNB,
|
||||
&UL_dci_req->ul_dci_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15,
|
||||
&gNB->frame_parms,
|
||||
slot,
|
||||
&phase_comp_prb_mask[0][0][0],
|
||||
prb_mask_words);
|
||||
|
||||
int num_pdsch = 0;
|
||||
for (int i = 0; i < DL_req->dl_tti_request_body.nPDUs; ++i) {
|
||||
const nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i];
|
||||
switch (dl_tti_pdu->PDUType) {
|
||||
case NFAPI_NR_DL_TTI_SSB_PDU_TYPE:
|
||||
nr_common_signal_procedures(gNB, frame, slot, &dl_tti_pdu->ssb_pdu);
|
||||
nr_common_signal_procedures(gNB,
|
||||
frame,
|
||||
slot,
|
||||
&dl_tti_pdu->ssb_pdu,
|
||||
&phase_comp_prb_mask[0][0][0],
|
||||
prb_mask_words);
|
||||
break;
|
||||
case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE:
|
||||
nr_generate_dci(gNB, &dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15, &gNB->frame_parms, slot);
|
||||
nr_generate_dci(gNB,
|
||||
&dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15,
|
||||
&gNB->frame_parms,
|
||||
slot,
|
||||
&phase_comp_prb_mask[0][0][0],
|
||||
prb_mask_words);
|
||||
break;
|
||||
case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE:
|
||||
nr_generate_csi_rs_gNB(gNB, slot, &dl_tti_pdu->csi_rs_pdu);
|
||||
nr_generate_csi_rs_gNB(gNB, slot, &dl_tti_pdu->csi_rs_pdu, &phase_comp_prb_mask[0][0][0], prb_mask_words);
|
||||
break;
|
||||
case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: {
|
||||
int tx_data_idx = dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15.pduIndex;
|
||||
@@ -287,23 +474,12 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
|
||||
|
||||
if (num_pdsch > 0) {
|
||||
LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", num_pdsch, frame, slot);
|
||||
nr_generate_pdsch(gNB, num_pdsch, gNB->dlsch, frame, slot);
|
||||
nr_generate_pdsch(gNB, num_pdsch, gNB->dlsch, frame, slot, &phase_comp_prb_mask[0][0][0], prb_mask_words);
|
||||
}
|
||||
|
||||
//apply the OFDM symbol rotation here
|
||||
start_meas(&gNB->phase_comp_stats);
|
||||
for (int i = 0; i < gNB->common_vars.num_beams_period; ++i) {
|
||||
for (int aa = 0; aa < cfg->carrier_config.num_tx_ant.value; aa++) {
|
||||
if (gNB->phase_comp) {
|
||||
apply_nr_rotation_TX(fp,
|
||||
gNB->common_vars.txdataF[i][aa],
|
||||
true,
|
||||
fp->symbol_rotation[0],
|
||||
slot,
|
||||
fp->N_RB_DL,
|
||||
0,
|
||||
fp->Ncp == NR_EXTENDED ? 12 : 14);
|
||||
}
|
||||
T(T_GNB_PHY_DL_OUTPUT_SIGNAL,
|
||||
T_INT(0),
|
||||
T_INT(frame),
|
||||
|
||||
@@ -19,7 +19,12 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
|
||||
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, prach_item_t *prach_id, nfapi_nr_rach_indication_t *rach_ind);
|
||||
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu);
|
||||
void nr_common_signal_procedures(PHY_VARS_gNB *gNB,
|
||||
int frame,
|
||||
int slot,
|
||||
const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu,
|
||||
uint64_t *phase_comp_prb_mask,
|
||||
int prb_mask_words);
|
||||
void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx);
|
||||
void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa);
|
||||
void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx);
|
||||
|
||||
@@ -722,7 +722,6 @@ int main(int argc, char **argv)
|
||||
|
||||
AssertFatal((gNB->if_inst = NR_IF_Module_init(0)) != NULL, "Cannot register interface");
|
||||
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
gNB->num_pdsch_symbols_per_thread = num_pdsch_symbols_per_thread;
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(*scc));;
|
||||
prepare_scc(scc);
|
||||
@@ -828,6 +827,7 @@ int main(int argc, char **argv)
|
||||
// nr_mac_config_scc()
|
||||
gNB_mac->pre_processor_dl = nr_dlsim_preprocessor;
|
||||
phy_init_nr_gNB(gNB);
|
||||
gNB->num_pdsch_symbols_per_thread = num_pdsch_symbols_per_thread;
|
||||
N_RB_DL = gNB->frame_parms.N_RB_DL;
|
||||
NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.connected_ue_list[0];
|
||||
|
||||
@@ -1416,16 +1416,21 @@ int main(int argc, char **argv)
|
||||
printStatIndent3(&gNB->toutput,"DLSCH LDPC output generation time");
|
||||
printStatIndent3(&gNB->dlsch_rate_matching_stats,"DLSCH Rate Matching time");
|
||||
printStatIndent3(&gNB->dlsch_interleaving_stats, "DLSCH Interleaving time");
|
||||
printStatIndent2(&gNB->dlsch_modulation_stats,"DLSCH modulation time");
|
||||
printStatIndent2(&gNB->dlsch_scrambling_stats, "DLSCH scrambling time");
|
||||
printStatIndent2(&gNB->dlsch_pdsch_generation_stats,"DLSCH PDSCH Generation time");
|
||||
printStatIndent3(&gNB->dlsch_layer_mapping_stats,"DLSCH Layer Mapping time");
|
||||
gNB->dlsch_resource_mapping_stats.trials = gNB->dlsch_layer_mapping_stats.trials;
|
||||
printStatIndent3(&gNB->dlsch_resource_mapping_stats,"DLSCH Resource Mapping time");
|
||||
gNB->dlsch_precoding_stats.trials = gNB->dlsch_layer_mapping_stats.trials;
|
||||
printStatIndent3(&gNB->dlsch_precoding_stats,"DLSCH Precoding time");
|
||||
if (gNB->phase_comp)
|
||||
printStatIndent2(&gNB->phase_comp_stats, "Phase Compensation");
|
||||
printStatIndent3(&gNB->dlsch_scrambling_stats, "DLSCH scrambling time");
|
||||
if (gNB->dlsch_layer_mapping_stats.trials > 0) {
|
||||
printStatIndent3(&gNB->dlsch_modulation_stats,"DLSCH modulation time");
|
||||
printStatIndent3(&gNB->dlsch_layer_mapping_stats,"DLSCH Layer Mapping time");
|
||||
}
|
||||
else {
|
||||
printStatIndent3(&gNB->dlsch_modulation_stats,"DLSCH mod/lm time");
|
||||
}
|
||||
if (num_pdsch_symbols_per_thread == 0) {
|
||||
gNB->dlsch_resource_mapping_stats.trials = gNB->dlsch_modulation_stats.trials;
|
||||
if (gNB->dlsch_precoding_stats.trials > 0) printStatIndent3(&gNB->dlsch_resource_mapping_stats,"DLSCH Resource Mapping time");
|
||||
gNB->dlsch_precoding_stats.trials = gNB->dlsch_modulation_stats.trials;
|
||||
if (gNB->dlsch_precoding_stats.trials > 0) printStatIndent3(&gNB->dlsch_precoding_stats,"DLSCH Precoding time");
|
||||
}
|
||||
|
||||
if (use_cuda) {
|
||||
printStatIndent(&pipeline_stats, "GPU Channel Pipeline");
|
||||
|
||||
@@ -395,6 +395,7 @@ int main(int argc, char **argv)
|
||||
RC.gNB[0] = malloc16_clear(sizeof(*(RC.gNB[0])));
|
||||
gNB = RC.gNB[0];
|
||||
gNB->ofdm_offset_divisor = UINT_MAX;
|
||||
gNB->phase_comp = true;
|
||||
frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
|
||||
frame_parms->nb_antennas_tx = n_tx;
|
||||
frame_parms->nb_antennas_rx = n_rx;
|
||||
@@ -488,6 +489,9 @@ int main(int argc, char **argv)
|
||||
__attribute__ ((aligned(32))) c16_t rxdataF[UE->frame_parms.nb_antennas_rx][rxdataF_sz];
|
||||
nfapi_nr_dl_tti_ssb_pdu ssb_pdu[64] = {0};
|
||||
if (input_fd==NULL) {
|
||||
const int prb_mask_words = (frame_parms->N_RB_DL + 63) / 64;
|
||||
uint64_t phase_comp_prb_mask[gNB->common_vars.num_beams_period][frame_parms->symbols_per_slot][prb_mask_words];
|
||||
memset(phase_comp_prb_mask, 0, sizeof(phase_comp_prb_mask));
|
||||
|
||||
for (i=0; i<frame_parms->Lmax; i++) {
|
||||
if((SSB_positions >> i) & 0x01) {
|
||||
@@ -505,22 +509,18 @@ int main(int argc, char **argv)
|
||||
for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++)
|
||||
memset(gNB->common_vars.txdataF[0][aa], 0, frame_parms->samples_per_slot_wCP * sizeof(int32_t));
|
||||
|
||||
nr_common_signal_procedures (gNB,frame,slot, &ssb_pdu[i]);
|
||||
nr_common_signal_procedures(gNB,
|
||||
frame,
|
||||
slot,
|
||||
&ssb_pdu[i],
|
||||
&phase_comp_prb_mask[0][0][0],
|
||||
prb_mask_words);
|
||||
|
||||
int samp = get_samples_slot_timestamp(frame_parms, slot);
|
||||
for (aa = 0; aa < gNB->frame_parms.nb_antennas_tx; aa++) {
|
||||
c16_t fft_in_buff[frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot] __attribute__((aligned(64)));
|
||||
memset(fft_in_buff, 0, sizeof(fft_in_buff));
|
||||
if (cyclic_prefix_type == 1) {
|
||||
apply_nr_rotation_TX(frame_parms,
|
||||
gNB->common_vars.txdataF[0][aa],
|
||||
true,
|
||||
frame_parms->symbol_rotation[0],
|
||||
slot,
|
||||
frame_parms->N_RB_DL,
|
||||
0,
|
||||
12);
|
||||
|
||||
fft_shift(gNB->common_vars.txdataF[0][aa],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
frame_parms->N_RB_DL,
|
||||
@@ -536,15 +536,6 @@ int main(int argc, char **argv)
|
||||
frame_parms->nb_prefix_samples,
|
||||
CYCLIC_PREFIX);
|
||||
} else {
|
||||
apply_nr_rotation_TX(frame_parms,
|
||||
gNB->common_vars.txdataF[0][aa],
|
||||
true,
|
||||
frame_parms->symbol_rotation[0],
|
||||
slot,
|
||||
frame_parms->N_RB_DL,
|
||||
0,
|
||||
14);
|
||||
|
||||
fft_shift(gNB->common_vars.txdataF[0][aa],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
frame_parms->N_RB_DL,
|
||||
|
||||
Reference in New Issue
Block a user