Files
openairinterface5g/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c
T
Robert Schmidt 8107939f08 Change OAI license to CSSL v1.0 (and others)
- all RAN code, CI code, configuration files, dockerfiles, in CSSL v1.0
- all deployment code (openshift, charts, ancillary files like shell
  scripts), in MIT
- documentation in CC-BY-4.0
- exceptions might apply and are listed in NOTICE
- there is a new LICENSES folder with all licenses
- CONTRIBUTIONS.md has been updated accordingly

For automated changes based on OAI PL v1.1:

    perl -i~ -0pe 's/\/\*.*Licensed to the OpenAirInterface.*openairinterface.org\n#?/\/*\n * SPDX-License-Identifier: LicenseRef-CSSL-1.0\n/s' **/*.{c,h,cpp}
    perl -i~ -0pe 's/\/\*.*Licensed to the OpenAirInterface.*openairinterface.org\n#?/\/*\n * SPDX-License-Identifier: LicenseRef-CSSL-1.0\n/s' **/*.ts
    perl -i~ -0pe 's/<!--.*Licensed to the OpenAirInterface.*openairinterface.org\n.*-->/<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->/s' **/*.xml

The rest (cmake, files with missing license, cmake) manually.
2026-03-27 16:36:37 +01:00

574 lines
26 KiB
C

/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
/*! \file gNB_scheduler_srs.c
* \brief MAC procedures related to SRS
* \date 2021
* \version 1.0
*/
#include <softmodem-common.h>
#include "NR_MAC_gNB/nr_mac_gNB.h"
#include "NR_MAC_gNB/mac_proto.h"
#include "common/ran_context.h"
#include "nfapi/oai_integration/vendor_ext.h"
#include "common/utils/nr/nr_common.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "PHY/sse_intrin.h"
// #define SRS_DEBUG
const uint16_t m_SRS[64] = { 4, 8, 12, 16, 16, 20, 24, 24, 28, 32, 36, 40, 48, 48, 52, 56, 60, 64, 72, 72, 76, 80, 88,
96, 96, 104, 112, 120, 120, 120, 128, 128, 128, 132, 136, 144, 144, 144, 144, 152, 160,
160, 160, 168, 176, 184, 192, 192, 192, 192, 208, 216, 224, 240, 240, 240, 240, 256, 256,
256, 264, 272, 272, 272 };
#ifdef SRS_DEBUG
static void print128_number(const simde__m128i var)
{
int32_t *var16 = (int32_t *)&var;
for (int i = 0; i < 4; i++) {
printf("%5d ", var16[i]);
}
printf("\n");
}
#endif
int most_frequent_ri(const int *arr, int n)
{
int maxcount = 0;
int element_having_max_freq = -1;
for (int i = 0; i < n; i++) {
int count = 0;
for (int j = 0; j < n; j++) {
if (arr[i] == arr[j])
count++;
}
if (count > maxcount) {
maxcount = count;
element_having_max_freq = arr[i];
}
}
return element_having_max_freq;
}
void matrix_rank_128bits(int row, int col, simde__m128i mat[4])
{
if ((row == 2 && col == 2) || (row == 4 && col == 2)) {
int32_t *mat_k = (int32_t *)&mat[0];
int32_t *mat_i = (int32_t *)&mat[1];
simde__m128 mult_128 = simde_mm_setr_ps((float)mat_i[0] / (float)mat_k[0],
(float)mat_i[0] / (float)mat_k[0],
(float)mat_i[2] / (float)mat_k[2],
(float)mat_i[2] / (float)mat_k[2]);
simde__m128i mat_kj_128 = simde_mm_setr_epi32(mat_k[0], mat_k[1], mat_k[2], mat_k[3]);
simde__m128 multiplication = simde_mm_mul_ps(mult_128, simde_mm_cvtepi32_ps(mat_kj_128));
mat[1] = simde_mm_sub_epi32(mat[1], simde_mm_cvtps_epi32(multiplication));
mat_k = (int32_t *)&mat[2];
mat_i = (int32_t *)&mat[3];
mult_128 = simde_mm_setr_ps((float)mat_i[0] / (float)mat_k[0],
(float)mat_i[0] / (float)mat_k[0],
(float)mat_i[2] / (float)mat_k[2],
(float)mat_i[2] / (float)mat_k[2]);
mat_kj_128 = simde_mm_setr_epi32(mat_k[0], mat_k[1], mat_k[2], mat_k[3]);
multiplication = simde_mm_mul_ps(mult_128, simde_mm_cvtepi32_ps(mat_kj_128));
mat[3] = simde_mm_sub_epi32(mat[3], simde_mm_cvtps_epi32(multiplication));
} else if (row == 2 && col == 4) {
int32_t *mat_k = (int32_t *)&mat[0];
int32_t *mat_i = (int32_t *)&mat[1];
simde__m128 mult_128 = simde_mm_setr_ps((float)mat_i[0] / (float)mat_k[0],
(float)mat_i[0] / (float)mat_k[0],
(float)mat_i[0] / (float)mat_k[0],
(float)mat_i[0] / (float)mat_k[0]);
simde__m128i mat_kj_128 = simde_mm_setr_epi32(mat_k[0], mat_k[1], mat_k[2], mat_k[3]);
simde__m128 multiplication = simde_mm_mul_ps(mult_128, simde_mm_cvtepi32_ps(mat_kj_128));
mat[1] = simde_mm_sub_epi32(mat[1], simde_mm_cvtps_epi32(multiplication));
mat_k = (int32_t *)&mat[2];
mat_i = (int32_t *)&mat[3];
mult_128 = simde_mm_setr_ps((float)mat_i[0] / (float)mat_k[0],
(float)mat_i[0] / (float)mat_k[0],
(float)mat_i[0] / (float)mat_k[0],
(float)mat_i[0] / (float)mat_k[0]);
mat_kj_128 = simde_mm_setr_epi32(mat_k[0], mat_k[1], mat_k[2], mat_k[3]);
multiplication = simde_mm_mul_ps(mult_128, simde_mm_cvtepi32_ps(mat_kj_128));
mat[3] = simde_mm_sub_epi32(mat[3], simde_mm_cvtps_epi32(multiplication));
} else if (row == 4 && col == 4) {
for (int k = 0; k < col; k++) {
int32_t *mat_k = (int32_t *)&mat[k];
for (int i = k + 1; i < row; i++) {
int32_t *mat_i = (int32_t *)&mat[i];
float mult = (float)mat_i[k] / (float)mat_k[k];
if (isnan(mult))
mult = 0;
if (isinf(mult))
mult = 0;
simde__m128 mult_128 = simde_mm_set1_ps(mult);
simde__m128i mat_kj_128 = simde_mm_setr_epi32(mat_k[0], mat_k[1], mat_k[2], mat_k[3]);
simde__m128 multiplication = simde_mm_mul_ps(mult_128, simde_mm_cvtepi32_ps(mat_kj_128));
mat[i] = simde_mm_sub_epi32(mat[i], simde_mm_cvtps_epi32(multiplication));
}
}
} else {
AssertFatal(1 == 0, "matrix_rank_128bits() function is not implemented for row = %i and col = %i\n", row, col);
}
}
void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_normalized_channel_iq_matrix,
const NR_UE_UL_BWP_t *current_BWP,
uint8_t *ul_ri)
{
/* already mutex protected: held in handle_nr_srs_measurements() */
NR_SCHED_ENSURE_LOCKED(&RC.nrmac[0]->sched_lock);
#ifdef SRS_DEBUG
LOG_I(NR_MAC, "num_gnb_antenna_elements = %i\n", nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements);
LOG_I(NR_MAC, "num_ue_srs_ports = %i\n", nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports);
#endif
if (nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements == 1 ||
nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports == 1 ||
current_BWP->pusch_Config == NULL ||
(current_BWP->pusch_Config && *current_BWP->pusch_Config->maxRank == 1)) {
*ul_ri = 0;
return;
}
const c16_t *ch = (c16_t *)nr_srs_normalized_channel_iq_matrix->channel_matrix;
const uint16_t num_gnb_antenna_elements = nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements;
const uint16_t num_prgs = nr_srs_normalized_channel_iq_matrix->num_prgs;
int row = num_gnb_antenna_elements;
int col = nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports;
simde__m128i mat_real128[4];
simde__m128i mat_imag128[4];
simde__m128i sum_matrix[4];
if ((row == 2 && col == 2) || (row == 4 && col == 2)) {
int array_lim = num_prgs >> 2;
AssertFatal(array_lim > 0 , "Needed to avoid UB\n");
int antenna_rank[array_lim];
int count = 0;
const uint16_t base00_idx = 0 * num_gnb_antenna_elements * num_prgs + 0 * num_prgs; // Rx antenna 0, Tx port 0
const uint16_t base01_idx = 1 * num_gnb_antenna_elements * num_prgs + 0 * num_prgs; // Rx antenna 0, Tx port 1
const uint16_t base10_idx = 0 * num_gnb_antenna_elements * num_prgs + 1 * num_prgs; // Rx antenna 1, Tx port 0
const uint16_t base11_idx = 1 * num_gnb_antenna_elements * num_prgs + 1 * num_prgs; // Rx antenna 1, Tx port 1
for (int pI = 0; pI < num_prgs; pI += 4) {
uint16_t pI00 = pI + base00_idx;
uint16_t pI10 = pI + base10_idx;
uint16_t pI01 = pI + base01_idx;
uint16_t pI11 = pI + base11_idx;
mat_real128[0] = simde_mm_setr_epi32(ch[pI00].r, ch[pI10].r, ch[pI00 + 1].r, ch[pI10 + 1].r);
mat_real128[1] = simde_mm_setr_epi32(ch[pI01].r, ch[pI11].r, ch[pI01 + 1].r, ch[pI11 + 1].r);
mat_real128[2] = simde_mm_setr_epi32(ch[pI00 + 2].r, ch[pI10 + 2].r, ch[pI00 + 3].r, ch[pI10 + 3].r);
mat_real128[3] = simde_mm_setr_epi32(ch[pI01 + 2].r, ch[pI11 + 2].r, ch[pI01 + 3].r, ch[pI11 + 3].r);
mat_imag128[0] = simde_mm_setr_epi32(ch[pI00].i, ch[pI10].i, ch[pI00 + 1].i, ch[pI10 + 1].i);
mat_imag128[1] = simde_mm_setr_epi32(ch[pI01].i, ch[pI11].i, ch[pI01 + 1].i, ch[pI11 + 1].i);
mat_imag128[2] = simde_mm_setr_epi32(ch[pI00 + 2].i, ch[pI10 + 2].i, ch[pI00 + 3].i, ch[pI10 + 3].i);
mat_imag128[3] = simde_mm_setr_epi32(ch[pI01 + 2].i, ch[pI11 + 2].i, ch[pI01 + 3].i, ch[pI11 + 3].i);
matrix_rank_128bits(row, col, mat_real128);
matrix_rank_128bits(row, col, mat_imag128);
sum_matrix[0] = simde_mm_add_epi32(mat_real128[0], mat_imag128[0]);
sum_matrix[1] = simde_mm_add_epi32(mat_real128[1], mat_imag128[1]);
sum_matrix[2] = simde_mm_add_epi32(mat_real128[2], mat_imag128[2]);
sum_matrix[3] = simde_mm_add_epi32(mat_real128[3], mat_imag128[3]);
#ifdef SRS_DEBUG
LOG_I(NR_MAC, "\nSum matrix\n");
print128_number(sum_matrix[0]);
print128_number(sum_matrix[1]);
print128_number(sum_matrix[2]);
print128_number(sum_matrix[3]);
#endif
int count_pivots = 0;
int32_t *sum_matrix_i = (int32_t *)&sum_matrix[1];
if (sum_matrix_i[1] != 0)
count_pivots++;
if (sum_matrix_i[3] != 0)
count_pivots++;
sum_matrix_i = (int32_t *)&sum_matrix[3];
if (sum_matrix_i[1] != 0)
count_pivots++;
if (sum_matrix_i[3] != 0)
count_pivots++;
antenna_rank[count] = count_pivots / 4;
count++;
}
*ul_ri = most_frequent_ri(antenna_rank, array_lim);
} else if (row == 2 && col == 4) {
int array_lim = num_prgs >> 1;
int antenna_rank[array_lim];
int count = 0;
const uint16_t base00_idx = 0 * num_gnb_antenna_elements * num_prgs + 0 * num_prgs; // Rx antenna 0, Tx port 0
const uint16_t base10_idx = 1 * num_gnb_antenna_elements * num_prgs + 0 * num_prgs; // Rx antenna 1, Tx port 0
const uint16_t base20_idx = 2 * num_gnb_antenna_elements * num_prgs + 0 * num_prgs; // Rx antenna 2, Tx port 0
const uint16_t base30_idx = 3 * num_gnb_antenna_elements * num_prgs + 0 * num_prgs; // Rx antenna 3, Tx port 0
const uint16_t base01_idx = 0 * num_gnb_antenna_elements * num_prgs + 1 * num_prgs; // Rx antenna 0, Tx port 1
const uint16_t base11_idx = 1 * num_gnb_antenna_elements * num_prgs + 1 * num_prgs; // Rx antenna 1, Tx port 1
const uint16_t base21_idx = 2 * num_gnb_antenna_elements * num_prgs + 1 * num_prgs; // Rx antenna 2, Tx port 1
const uint16_t base31_idx = 3 * num_gnb_antenna_elements * num_prgs + 1 * num_prgs; // Rx antenna 3, Tx port 1
for (int pI = 0; pI < num_prgs; pI += 2) {
mat_real128[0] = simde_mm_setr_epi32(ch[base00_idx + pI].r,
ch[base10_idx + pI].r,
ch[base20_idx + pI].r,
ch[base30_idx + pI].r);
mat_real128[1] = simde_mm_setr_epi32(ch[base01_idx + pI].r,
ch[base11_idx + pI].r,
ch[base21_idx + pI].r,
ch[base31_idx + pI].r);
mat_real128[2] = simde_mm_setr_epi32(ch[base00_idx + (pI + 1)].r,
ch[base10_idx + (pI + 1)].r,
ch[base20_idx + (pI + 1)].r,
ch[base30_idx + (pI + 1)].r);
mat_real128[3] = simde_mm_setr_epi32(ch[base01_idx + (pI + 1)].r,
ch[base11_idx + (pI + 1)].r,
ch[base21_idx + (pI + 1)].r,
ch[base31_idx + (pI + 1)].r);
mat_imag128[0] = simde_mm_setr_epi32(ch[base00_idx + pI].i,
ch[base10_idx + pI].i,
ch[base20_idx + pI].i,
ch[base30_idx + pI].i);
mat_imag128[1] = simde_mm_setr_epi32(ch[base01_idx + pI].i,
ch[base11_idx + pI].i,
ch[base21_idx + pI].i,
ch[base31_idx + pI].i);
mat_imag128[2] = simde_mm_setr_epi32(ch[base00_idx + (pI + 1)].i,
ch[base10_idx + (pI + 1)].i,
ch[base20_idx + (pI + 1)].i,
ch[base30_idx + (pI + 1)].i);
mat_imag128[3] = simde_mm_setr_epi32(ch[base01_idx + (pI + 1)].i,
ch[base11_idx + (pI + 1)].i,
ch[base21_idx + (pI + 1)].i,
ch[base31_idx + (pI + 1)].i);
matrix_rank_128bits(row, col, mat_real128);
matrix_rank_128bits(row, col, mat_imag128);
sum_matrix[0] = simde_mm_add_epi32(mat_real128[0], mat_imag128[0]);
sum_matrix[1] = simde_mm_add_epi32(mat_real128[1], mat_imag128[1]);
sum_matrix[2] = simde_mm_add_epi32(mat_real128[2], mat_imag128[2]);
sum_matrix[3] = simde_mm_add_epi32(mat_real128[3], mat_imag128[3]);
#ifdef SRS_DEBUG
LOG_I(NR_MAC, "\nSum matrix\n");
print128_number(sum_matrix[0]);
print128_number(sum_matrix[1]);
print128_number(sum_matrix[2]);
print128_number(sum_matrix[3]);
#endif
int count_pivots = 0;
int32_t *sum_matrix_i = (int32_t *)&sum_matrix[1];
if (sum_matrix_i[1] != 0)
count_pivots++;
if (sum_matrix_i[3] != 0)
count_pivots++;
sum_matrix_i = (int32_t *)&sum_matrix[3];
if (sum_matrix_i[1] != 0)
count_pivots++;
if (sum_matrix_i[3] != 0)
count_pivots++;
antenna_rank[count] = count_pivots / 2;
count++;
}
int rr = most_frequent_ri(antenna_rank, array_lim);
if (rr == 0 || rr == 1)
*ul_ri = 0;
if (rr > 1)
*ul_ri = 1;
} else if (row == 4 && col == 4) {
int antenna_rank[num_prgs];
int count = 0;
const uint16_t base00_idx = 0 * num_gnb_antenna_elements * num_prgs + 0 * num_prgs; // Rx antenna 0, Tx port 0
const uint16_t base10_idx = 1 * num_gnb_antenna_elements * num_prgs + 0 * num_prgs; // Rx antenna 1, Tx port 0
const uint16_t base20_idx = 2 * num_gnb_antenna_elements * num_prgs + 0 * num_prgs; // Rx antenna 2, Tx port 0
const uint16_t base30_idx = 3 * num_gnb_antenna_elements * num_prgs + 0 * num_prgs; // Rx antenna 3, Tx port 0
const uint16_t base01_idx = 0 * num_gnb_antenna_elements * num_prgs + 1 * num_prgs; // Rx antenna 0, Tx port 1
const uint16_t base11_idx = 1 * num_gnb_antenna_elements * num_prgs + 1 * num_prgs; // Rx antenna 1, Tx port 1
const uint16_t base21_idx = 2 * num_gnb_antenna_elements * num_prgs + 1 * num_prgs; // Rx antenna 2, Tx port 1
const uint16_t base31_idx = 3 * num_gnb_antenna_elements * num_prgs + 1 * num_prgs; // Rx antenna 3, Tx port 1
const uint16_t base02_idx = 0 * num_gnb_antenna_elements * num_prgs + 2 * num_prgs; // Rx antenna 0, Tx port 2
const uint16_t base12_idx = 1 * num_gnb_antenna_elements * num_prgs + 2 * num_prgs; // Rx antenna 1, Tx port 2
const uint16_t base22_idx = 2 * num_gnb_antenna_elements * num_prgs + 2 * num_prgs; // Rx antenna 2, Tx port 2
const uint16_t base32_idx = 3 * num_gnb_antenna_elements * num_prgs + 2 * num_prgs; // Rx antenna 3, Tx port 2
const uint16_t base03_idx = 0 * num_gnb_antenna_elements * num_prgs + 3 * num_prgs; // Rx antenna 0, Tx port 3
const uint16_t base13_idx = 1 * num_gnb_antenna_elements * num_prgs + 3 * num_prgs; // Rx antenna 1, Tx port 3
const uint16_t base23_idx = 2 * num_gnb_antenna_elements * num_prgs + 3 * num_prgs; // Rx antenna 2, Tx port 3
const uint16_t base33_idx = 3 * num_gnb_antenna_elements * num_prgs + 3 * num_prgs; // Rx antenna 3, Tx port 3
for (int pI = 0; pI < num_prgs; pI++) {
mat_real128[0] = simde_mm_setr_epi32(ch[base00_idx + pI].r, ch[base10_idx + pI].r, ch[base20_idx + pI].r, ch[base30_idx + pI].r);
mat_real128[1] = simde_mm_setr_epi32(ch[base01_idx + pI].r, ch[base11_idx + pI].r, ch[base21_idx + pI].r, ch[base31_idx + pI].r);
mat_real128[2] = simde_mm_setr_epi32(ch[base02_idx + pI].r, ch[base12_idx + pI].r, ch[base22_idx + pI].r, ch[base32_idx + pI].r);
mat_real128[3] = simde_mm_setr_epi32(ch[base03_idx + pI].r, ch[base13_idx + pI].r, ch[base23_idx + pI].r, ch[base33_idx + pI].r);
mat_imag128[0] = simde_mm_setr_epi32(ch[base00_idx + pI].i, ch[base10_idx + pI].i, ch[base20_idx + pI].i, ch[base30_idx + pI].i);
mat_imag128[1] = simde_mm_setr_epi32(ch[base01_idx + pI].i, ch[base11_idx + pI].i, ch[base21_idx + pI].i, ch[base31_idx + pI].i);
mat_imag128[2] = simde_mm_setr_epi32(ch[base02_idx + pI].i, ch[base12_idx + pI].i, ch[base22_idx + pI].i, ch[base32_idx + pI].i);
mat_imag128[3] = simde_mm_setr_epi32(ch[base03_idx + pI].i, ch[base13_idx + pI].i, ch[base23_idx + pI].i, ch[base33_idx + pI].i);
matrix_rank_128bits(row, col, mat_real128);
matrix_rank_128bits(row, col, mat_imag128);
sum_matrix[0] = simde_mm_add_epi32(mat_real128[0], mat_imag128[0]);
sum_matrix[1] = simde_mm_add_epi32(mat_real128[1], mat_imag128[1]);
sum_matrix[2] = simde_mm_add_epi32(mat_real128[2], mat_imag128[2]);
sum_matrix[3] = simde_mm_add_epi32(mat_real128[3], mat_imag128[3]);
#ifdef SRS_DEBUG
LOG_I(NR_MAC, "\nSum matrix\n");
print128_number(sum_matrix[0]);
print128_number(sum_matrix[1]);
print128_number(sum_matrix[2]);
print128_number(sum_matrix[3]);
#endif
int count_pivots = 0;
for (int i = 0; i < row; i++) {
int32_t *sum_matrix_i = (int32_t *)&sum_matrix[i];
int found_piv = 0;
for (int j = 0; j < col; j++) {
if (sum_matrix_i[j] != 0 && found_piv == 0) {
count_pivots++;
found_piv = 1;
}
}
}
antenna_rank[count] = count_pivots;
count++;
}
*ul_ri = most_frequent_ri(antenna_rank, num_prgs) - 1;
} else {
AssertFatal(1 == 0, "nr_srs_ri_computation() function is not implemented for row = %i and col = %i\n", row, col);
}
}
static void nr_configure_srs(gNB_MAC_INST *nrmac,
nfapi_nr_srs_pdu_t *srs_pdu,
int frame,
int slot,
int CC_id,
NR_UE_info_t *UE,
NR_SRS_ResourceSet_t *srs_resource_set,
NR_SRS_Resource_t *srs_resource,
int buffer_index,
int slots_per_frame)
{
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
srs_pdu->rnti = UE->rnti;
srs_pdu->handle = 0;
srs_pdu->bwp_size = current_BWP->BWPSize;
srs_pdu->bwp_start = current_BWP->BWPStart;
srs_pdu->subcarrier_spacing = current_BWP->scs;
srs_pdu->cyclic_prefix = 0;
srs_pdu->num_ant_ports = srs_resource->nrofSRS_Ports;
srs_pdu->num_symbols = srs_resource->resourceMapping.nrofSymbols;
srs_pdu->num_repetitions = srs_resource->resourceMapping.repetitionFactor;
srs_pdu->time_start_position = srs_resource->resourceMapping.startPosition;
srs_pdu->config_index = srs_resource->freqHopping.c_SRS;
srs_pdu->sequence_id = srs_resource->sequenceId;
srs_pdu->bandwidth_index = srs_resource->freqHopping.b_SRS;
srs_pdu->comb_size = srs_resource->transmissionComb.present - 1;
switch(srs_resource->transmissionComb.present) {
case NR_SRS_Resource__transmissionComb_PR_n2:
srs_pdu->comb_offset = srs_resource->transmissionComb.choice.n2->combOffset_n2;
srs_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n2->cyclicShift_n2;
break;
case NR_SRS_Resource__transmissionComb_PR_n4:
srs_pdu->comb_offset = srs_resource->transmissionComb.choice.n4->combOffset_n4;
srs_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n4->cyclicShift_n4;
break;
default:
LOG_W(NR_MAC, "Invalid or not implemented comb_size!\n");
}
srs_pdu->frequency_position = srs_resource->freqDomainPosition;
srs_pdu->frequency_shift = srs_resource->freqDomainShift;
srs_pdu->frequency_hopping = srs_resource->freqHopping.b_hop;
srs_pdu->group_or_sequence_hopping = srs_resource->groupOrSequenceHopping;
srs_pdu->resource_type = srs_resource->resourceType.present - 1;
srs_pdu->t_srs = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present];
srs_pdu->t_offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p);
// TODO: This should be completed
srs_pdu->srs_parameters_v4.srs_bandwidth_size = m_SRS[srs_pdu->config_index];
srs_pdu->srs_parameters_v4.usage = 1<<srs_resource_set->usage;
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;
srs_pdu->srs_parameters_v4.num_total_ue_antennas = 1 << srs_pdu->num_ant_ports;
/* For srs usage: codebook, this is a bitmask of the antenna ports that should be used for data.
* num_ant_ports num_total_ue_antennas sampled_ue_antennas
* 0 1 1
* 1 2 3
* 2 4 15 */
srs_pdu->srs_parameters_v4.sampled_ue_antennas = (2 << srs_pdu->num_ant_ports) - 1;
if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_beamManagement) {
srs_pdu->beamforming.trp_scheme = 0;
srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index];
srs_pdu->beamforming.prg_size = srs_pdu->srs_parameters_v4.srs_bandwidth_size;
}
const uint16_t fapi_beam = convert_to_fapi_beam(UE->UE_beam_index, nrmac->beam_info.beam_mode);
srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = fapi_beam;
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SRS in any available beam\n");
uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][buffer_index * MAX_BWP_SIZE];
uint16_t num = 1 << srs_pdu->num_symbols; // 0,1,2 means 1,2,4 symbols, see 222.10.04 table 3-105
const uint8_t l0 = NR_SYMBOLS_PER_SLOT - 1 - srs_pdu->time_start_position;
uint16_t mask = SL_to_bitmap(l0, num);
DevAssert(mask != 0);
for (int i = 0; i < srs_pdu->bwp_size; ++i) {
int rb = i + srs_pdu->bwp_start;
uint16_t alloc = vrb_map_UL[rb] & mask;
AssertFatal(nrmac->ulprbbl[rb] != 0 || alloc == 0, "RB %d not free for SRS: alloc 0x%02x for mask 0x%02x\n", rb, alloc, mask);
vrb_map_UL[rb] |= mask;
}
}
static void nr_fill_nfapi_srs(gNB_MAC_INST *nrmac,
int CC_id,
NR_UE_info_t *UE,
int frame,
int slot,
NR_SRS_ResourceSet_t *srs_resource_set,
NR_SRS_Resource_t *srs_resource)
{
int slots_frame = nrmac->frame_structure.numb_slots_frame;
int index = ul_buffer_index(frame, slot, slots_frame, nrmac->UL_tti_req_ahead_size);
nfapi_nr_ul_tti_request_t *future_ul_tti_req = &nrmac->UL_tti_req_ahead[0][index];
AssertFatal(future_ul_tti_req->n_pdus <
sizeof(future_ul_tti_req->pdus_list) / sizeof(future_ul_tti_req->pdus_list[0]),
"Invalid future_ul_tti_req->n_pdus %d\n", future_ul_tti_req->n_pdus);
future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE;
future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_srs_pdu_t);
nfapi_nr_srs_pdu_t *srs_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].srs_pdu;
memset(srs_pdu, 0, sizeof(nfapi_nr_srs_pdu_t));
future_ul_tti_req->n_pdus += 1;
index = ul_buffer_index(frame, slot, slots_frame, nrmac->vrb_map_UL_size);
nr_configure_srs(nrmac, srs_pdu, frame, slot, CC_id, UE, srs_resource_set, srs_resource, index, slots_frame);
}
/*******************************************************************
*
* NAME : nr_schedule_srs
*
* PARAMETERS : module id
* frame number for possible SRS reception
*
* DESCRIPTION : It informs the PHY layer that has an SRS to receive.
* Only for periodic scheduling yet.
*
*********************************************************************/
void nr_schedule_srs(int module_id, frame_t frame, int slot)
{
gNB_MAC_INST *nrmac = RC.nrmac[module_id];
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
NR_UEs_t *UE_info = &nrmac->UE_info;
UE_iterator(UE_info->connected_ue_list, UE) {
const int CC_id = 0;
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
if (!nr_mac_ue_is_active(UE) && !get_softmodem_params()->phy_test) {
continue;
}
NR_SRS_Config_t *srs_config = current_BWP->srs_Config;
if (!srs_config)
continue;
for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) {
// Find periodic resource set
NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
if (srs_resource_set->resourceType.present != NR_SRS_ResourceSet__resourceType_PR_periodic) {
continue;
}
// Find the corresponding srs resource
NR_SRS_Resource_t *srs_resource = NULL;
for (int r1 = 0; r1 < srs_resource_set->srs_ResourceIdList->list.count; r1++) {
for (int r2 = 0; r2 < srs_config->srs_ResourceToAddModList->list.count; r2++) {
if ((*srs_resource_set->srs_ResourceIdList->list.array[r1] ==
srs_config->srs_ResourceToAddModList->list.array[r2]->srs_ResourceId) &&
(srs_config->srs_ResourceToAddModList->list.array[r2]->resourceType.present ==
NR_SRS_Resource__resourceType_PR_periodic)) {
srs_resource = srs_config->srs_ResourceToAddModList->list.array[r2];
break;
}
}
}
if (srs_resource == NULL) {
continue;
}
// we are sheduling SRS max_k2 slot in advance for the presence of SRS to be taken into account when scheduling PUSCH
const int n_slots_frame = nrmac->frame_structure.numb_slots_frame;
const int n_ahead = n_slots_frame - 1 + get_NTN_Koffset(nrmac->common_channels[0].ServingCellConfigCommon);
const int sched_slot = (slot + n_ahead) % n_slots_frame;
const int sched_frame = (frame + (slot + n_ahead) / n_slots_frame) % MAX_FRAME_NUMBER;
const uint16_t period = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present];
const uint16_t offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p);
// Check if UE will transmit the SRS in this frame
if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0)
continue;
LOG_D(NR_MAC," %d.%d Scheduling SRS reception for %d.%d\n", frame, slot, sched_frame, sched_slot);
nr_fill_nfapi_srs(nrmac, CC_id, UE, sched_frame, sched_slot, srs_resource_set, srs_resource);
}
}
}