mirror of https://github.com/PentHertz/srsLTE.git
Provide PUSCH BLER test
The new test measures BLER and received throughput for the PUSCH. For now, only AWGN channel and perfect equalization are considered.
This commit is contained in:
parent
3fad800ef6
commit
6b0a3669cf
|
@ -678,6 +678,9 @@ add_nr_test(pusch_nr_ack2_csi4_test pusch_nr_test -p 50 -m 20 -A 2 -C 4)
|
||||||
add_nr_test(pusch_nr_ack4_csi4_test pusch_nr_test -p 50 -m 20 -A 4 -C 4)
|
add_nr_test(pusch_nr_ack4_csi4_test pusch_nr_test -p 50 -m 20 -A 4 -C 4)
|
||||||
add_nr_test(pusch_nr_ack20_csi4_test pusch_nr_test -p 50 -m 20 -A 20 -C 4)
|
add_nr_test(pusch_nr_ack20_csi4_test pusch_nr_test -p 50 -m 20 -A 20 -C 4)
|
||||||
|
|
||||||
|
add_executable(pusch_nr_bler_test EXCLUDE_FROM_ALL pusch_nr_bler_test.c)
|
||||||
|
target_link_libraries(pusch_nr_bler_test srsran_phy)
|
||||||
|
# this is just for performance evaluation, not for unit testing
|
||||||
|
|
||||||
add_executable(pdcch_nr_test pdcch_nr_test.c)
|
add_executable(pdcch_nr_test pdcch_nr_test.c)
|
||||||
target_link_libraries(pdcch_nr_test srsran_phy)
|
target_link_libraries(pdcch_nr_test srsran_phy)
|
||||||
|
|
|
@ -0,0 +1,376 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "srsran/phy/channel/ch_awgn.h"
|
||||||
|
#include "srsran/phy/phch/pusch_nr.h"
|
||||||
|
#include "srsran/phy/phch/ra_nr.h"
|
||||||
|
#include "srsran/phy/phch/ra_ul_nr.h"
|
||||||
|
#include "srsran/phy/utils/debug.h"
|
||||||
|
#include "srsran/phy/utils/random.h"
|
||||||
|
#include "srsran/phy/utils/vector.h"
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
static srsran_carrier_nr_t carrier = SRSRAN_DEFAULT_CARRIER_NR;
|
||||||
|
static uint32_t n_prb = 0; // Set to 0 for steering
|
||||||
|
static uint32_t mcs = 30; // Set to 30 for steering
|
||||||
|
static srsran_sch_cfg_nr_t pusch_cfg = {};
|
||||||
|
static uint16_t rnti = 0x1234;
|
||||||
|
static uint32_t nof_ack_bits = 0;
|
||||||
|
static uint32_t nof_csi_bits = 0;
|
||||||
|
static float snr = 10;
|
||||||
|
static bool full_check = false;
|
||||||
|
|
||||||
|
void usage(char* prog)
|
||||||
|
{
|
||||||
|
printf("Usage: %s [pmTLACsv] \n", prog);
|
||||||
|
printf("\t-p Number of grant PRB, set to 0 for steering [Default %d]\n", n_prb);
|
||||||
|
printf("\t-m MCS PRB, set to >28 for steering [Default %d]\n", mcs);
|
||||||
|
printf("\t-T Provide MCS table (64qam, 256qam, 64qamLowSE) [Default %s]\n",
|
||||||
|
srsran_mcs_table_to_str(pusch_cfg.sch_cfg.mcs_table));
|
||||||
|
printf("\t-L Provide number of layers [Default %d]\n", carrier.max_mimo_layers);
|
||||||
|
printf("\t-A Provide a number of HARQ-ACK bits [Default %d]\n", nof_ack_bits);
|
||||||
|
printf("\t-C Provide a number of CSI bits [Default %d]\n", nof_csi_bits);
|
||||||
|
printf("\t-s Signal-to-Noise Ratio in dB [Default %.1f]\n", snr);
|
||||||
|
printf("\t-f Perform full BLER check instead of CRC only [Default %s]\n", full_check ? "true" : "false");
|
||||||
|
printf("\t-v [set srsran_verbose to debug, default none]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_args(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int opt = 0;
|
||||||
|
while ((opt = getopt(argc, argv, "p:m:T:L:A:C:s:fv")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'p':
|
||||||
|
n_prb = (uint32_t)strtol(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
mcs = (uint32_t)strtol(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
pusch_cfg.sch_cfg.mcs_table = srsran_mcs_table_from_str(optarg);
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
carrier.max_mimo_layers = (uint32_t)strtol(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
nof_ack_bits = (uint32_t)strtol(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
nof_csi_bits = (uint32_t)strtol(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
snr = strtof(optarg, NULL);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
full_check = true;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
increase_srsran_verbose_level();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
return SRSRAN_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRSRAN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int ret = SRSRAN_ERROR;
|
||||||
|
srsran_pusch_nr_t pusch_tx = {};
|
||||||
|
srsran_pusch_nr_t pusch_rx = {};
|
||||||
|
srsran_chest_dl_res_t chest = {};
|
||||||
|
srsran_random_t rand_gen = srsran_random_init(1234);
|
||||||
|
|
||||||
|
srsran_pusch_data_nr_t data_tx = {};
|
||||||
|
srsran_pusch_res_nr_t data_rx = {};
|
||||||
|
cf_t* sf_symbols_tx[SRSRAN_MAX_LAYERS_NR] = {};
|
||||||
|
cf_t* sf_symbols_rx[SRSRAN_MAX_LAYERS_NR] = {};
|
||||||
|
|
||||||
|
// Set default PUSCH configuration
|
||||||
|
pusch_cfg.sch_cfg.mcs_table = srsran_mcs_table_64qam;
|
||||||
|
|
||||||
|
if (parse_args(argc, argv) < SRSRAN_SUCCESS) {
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
srsran_pusch_nr_args_t pusch_args = {};
|
||||||
|
pusch_args.sch.disable_simd = false;
|
||||||
|
pusch_args.measure_evm = true;
|
||||||
|
|
||||||
|
if (srsran_pusch_nr_init_ue(&pusch_tx, &pusch_args) < SRSRAN_SUCCESS) {
|
||||||
|
ERROR("Error initiating PUSCH for Tx");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srsran_pusch_nr_init_gnb(&pusch_rx, &pusch_args) < SRSRAN_SUCCESS) {
|
||||||
|
ERROR("Error initiating SCH NR for Rx");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srsran_pusch_nr_set_carrier(&pusch_tx, &carrier)) {
|
||||||
|
ERROR("Error setting SCH NR carrier");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srsran_pusch_nr_set_carrier(&pusch_rx, &carrier)) {
|
||||||
|
ERROR("Error setting SCH NR carrier");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t slot_length = SRSRAN_SLOT_LEN_RE_NR(carrier.nof_prb);
|
||||||
|
for (uint32_t i = 0; i < carrier.max_mimo_layers; i++) {
|
||||||
|
sf_symbols_tx[i] = srsran_vec_cf_malloc(slot_length);
|
||||||
|
sf_symbols_rx[i] = srsran_vec_cf_malloc(slot_length);
|
||||||
|
if (sf_symbols_tx[i] == NULL || sf_symbols_rx[i] == NULL) {
|
||||||
|
ERROR("Error malloc");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < pusch_tx.max_cw; i++) {
|
||||||
|
data_tx.payload[i] = srsran_vec_u8_malloc(SRSRAN_SLOT_MAX_NOF_BITS_NR);
|
||||||
|
data_rx.tb[i].payload = srsran_vec_u8_malloc(SRSRAN_SLOT_MAX_NOF_BITS_NR);
|
||||||
|
if (data_tx.payload[i] == NULL || data_rx.tb[i].payload == NULL) {
|
||||||
|
ERROR("Error malloc");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
srsran_softbuffer_tx_t softbuffer_tx = {};
|
||||||
|
srsran_softbuffer_rx_t softbuffer_rx = {};
|
||||||
|
|
||||||
|
if (srsran_softbuffer_tx_init_guru(&softbuffer_tx, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) <
|
||||||
|
SRSRAN_SUCCESS) {
|
||||||
|
ERROR("Error init soft-buffer");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srsran_softbuffer_rx_init_guru(&softbuffer_rx, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) <
|
||||||
|
SRSRAN_SUCCESS) {
|
||||||
|
ERROR("Error init soft-buffer");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use grant default A time resources with m=0
|
||||||
|
if (srsran_ra_ul_nr_pusch_time_resource_default_A(carrier.scs, 0, &pusch_cfg.grant) < SRSRAN_SUCCESS) {
|
||||||
|
ERROR("Error loading default grant");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set PUSCH grant without considering any procedure
|
||||||
|
pusch_cfg.grant.nof_dmrs_cdm_groups_without_data = 1; // No need for MIMO
|
||||||
|
pusch_cfg.grant.nof_layers = carrier.max_mimo_layers;
|
||||||
|
pusch_cfg.grant.dci_format = srsran_dci_format_nr_1_0;
|
||||||
|
pusch_cfg.grant.rnti = rnti;
|
||||||
|
|
||||||
|
// Check input: PRB
|
||||||
|
if (n_prb > carrier.nof_prb) {
|
||||||
|
ERROR("Invalid number of PRB");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check input: MCS
|
||||||
|
uint32_t mcs_end = pusch_cfg.sch_cfg.mcs_table == srsran_mcs_table_256qam ? 28 : 29;
|
||||||
|
if (mcs > mcs_end) {
|
||||||
|
ERROR("Invalid MCS");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
srsran_sch_hl_cfg_nr_t sch_hl_cfg = {};
|
||||||
|
sch_hl_cfg.scaling = 1.0F;
|
||||||
|
sch_hl_cfg.beta_offsets.fix_ack = 12.625F;
|
||||||
|
sch_hl_cfg.beta_offsets.fix_csi1 = 2.25F;
|
||||||
|
sch_hl_cfg.beta_offsets.fix_csi2 = 2.25F;
|
||||||
|
|
||||||
|
if (srsran_chest_dl_res_init(&chest, carrier.nof_prb) < SRSRAN_SUCCESS) {
|
||||||
|
ERROR("Initiating chest");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t n = 0; n < SRSRAN_MAX_PRB_NR; n++) {
|
||||||
|
pusch_cfg.grant.prb_idx[n] = (n < n_prb);
|
||||||
|
}
|
||||||
|
pusch_cfg.grant.nof_prb = n_prb;
|
||||||
|
|
||||||
|
pusch_cfg.grant.dci_format = srsran_dci_format_nr_0_0;
|
||||||
|
pusch_cfg.grant.nof_dmrs_cdm_groups_without_data = 2;
|
||||||
|
pusch_cfg.dmrs.type = srsran_dmrs_sch_type_1;
|
||||||
|
pusch_cfg.dmrs.length = srsran_dmrs_sch_len_1;
|
||||||
|
pusch_cfg.dmrs.additional_pos = srsran_dmrs_sch_add_pos_2;
|
||||||
|
if (srsran_ra_nr_fill_tb(&pusch_cfg, &pusch_cfg.grant, mcs, &pusch_cfg.grant.tb[0]) < SRSRAN_SUCCESS) {
|
||||||
|
ERROR("Error filling tb");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t n_blocks = 0;
|
||||||
|
uint32_t n_errors = 0;
|
||||||
|
float evm = 0;
|
||||||
|
for (; n_blocks < 2000000 && n_errors < 100; n_blocks++) {
|
||||||
|
// Generate SCH payload
|
||||||
|
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
|
||||||
|
// Skip TB if no allocated
|
||||||
|
if (data_tx.payload[tb] == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load payload with bytes
|
||||||
|
for (uint32_t i = 0; i < pusch_cfg.grant.tb[tb].tbs / 8 + 1; i++) {
|
||||||
|
data_tx.payload[tb][i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, UINT8_MAX);
|
||||||
|
}
|
||||||
|
pusch_cfg.grant.tb[tb].softbuffer.tx = &softbuffer_tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate HARQ ACK bits
|
||||||
|
if (nof_ack_bits > 0) {
|
||||||
|
pusch_cfg.uci.ack.count = nof_ack_bits;
|
||||||
|
for (uint32_t i = 0; i < nof_ack_bits; i++) {
|
||||||
|
data_tx.uci.ack[i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate CSI report bits
|
||||||
|
uint8_t csi_report_tx[SRSRAN_UCI_NR_MAX_CSI1_BITS] = {};
|
||||||
|
uint8_t csi_report_rx[SRSRAN_UCI_NR_MAX_CSI1_BITS] = {};
|
||||||
|
if (nof_csi_bits > 0) {
|
||||||
|
pusch_cfg.uci.csi[0].cfg.quantity = SRSRAN_CSI_REPORT_QUANTITY_NONE;
|
||||||
|
pusch_cfg.uci.csi[0].K_csi_rs = nof_csi_bits;
|
||||||
|
pusch_cfg.uci.nof_csi = 1;
|
||||||
|
data_tx.uci.csi[0].none = csi_report_tx;
|
||||||
|
for (uint32_t i = 0; i < nof_csi_bits; i++) {
|
||||||
|
csi_report_tx[i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_rx.uci.csi[0].none = csi_report_rx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srsran_ra_ul_set_grant_uci_nr(&carrier, &sch_hl_cfg, &pusch_cfg.uci, &pusch_cfg) < SRSRAN_SUCCESS) {
|
||||||
|
ERROR("Setting UCI");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srsran_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_cfg.grant, &data_tx, sf_symbols_tx) < SRSRAN_SUCCESS) {
|
||||||
|
ERROR("Error encoding");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
float noise_std_1d = srsran_convert_dB_to_amplitude(-snr - 3.0103F);
|
||||||
|
for (uint32_t i = 0; i < carrier.max_mimo_layers; i++) {
|
||||||
|
srsran_ch_awgn_f((float*)sf_symbols_tx[i], (float*)sf_symbols_rx[i], noise_std_1d, 2 * slot_length);
|
||||||
|
// memcpy(sf_symbols_rx[i], sf_symbols_tx[i], slot_length * sizeof(cf_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_srsran_verbose_level() >= SRSRAN_VERBOSE_INFO) {
|
||||||
|
uint32_t nof_re_total = carrier.nof_prb * SRSRAN_NRE;
|
||||||
|
uint32_t nof_re_used = pusch_cfg.grant.nof_prb * SRSRAN_NRE;
|
||||||
|
for (int i_layer = 0; i_layer < carrier.max_mimo_layers; i_layer++) {
|
||||||
|
INFO("Layer %d", i_layer);
|
||||||
|
float tx_power = 0;
|
||||||
|
float rx_power = 0;
|
||||||
|
uint8_t n_symbols = 0;
|
||||||
|
for (int i = 0; i < SRSRAN_NSYMB_PER_SLOT_NR; i++) {
|
||||||
|
if (!pusch_tx.dmrs_re_pattern.symbol[i]) {
|
||||||
|
n_symbols++;
|
||||||
|
tx_power += srsran_vec_avg_power_cf(sf_symbols_tx[0] + i * nof_re_total, nof_re_total);
|
||||||
|
rx_power += srsran_vec_avg_power_cf(sf_symbols_rx[0] + i * nof_re_total, nof_re_total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tx_power *= (float)nof_re_total / nof_re_used; // compensate for unused REs
|
||||||
|
INFO(" Tx power: %.3f", tx_power / n_symbols);
|
||||||
|
INFO(" Rx power: %.3f", rx_power / n_symbols);
|
||||||
|
INFO(" SNR: %.3f dB", srsran_convert_power_to_dB(tx_power / (rx_power - tx_power)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
|
||||||
|
pusch_cfg.grant.tb[tb].softbuffer.rx = &softbuffer_rx;
|
||||||
|
srsran_softbuffer_rx_reset(pusch_cfg.grant.tb[tb].softbuffer.rx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assume perfect channel estimation (including noise variance)
|
||||||
|
for (uint32_t i = 0; i < pusch_cfg.grant.tb->nof_re; i++) {
|
||||||
|
chest.ce[0][0][i] = 1.0F;
|
||||||
|
}
|
||||||
|
chest.nof_re = pusch_cfg.grant.tb->nof_re;
|
||||||
|
chest.noise_estimate = 4 * noise_std_1d * noise_std_1d;
|
||||||
|
|
||||||
|
if (srsran_pusch_nr_decode(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &chest, sf_symbols_rx, &data_rx) <
|
||||||
|
SRSRAN_SUCCESS) {
|
||||||
|
ERROR("Error encoding");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
evm += data_rx.evm[0];
|
||||||
|
// Validate UL-SCH CRC check
|
||||||
|
if (!data_rx.tb[0].crc) {
|
||||||
|
n_errors++;
|
||||||
|
printf("*");
|
||||||
|
fflush(stdout);
|
||||||
|
if (n_errors % 20 == 0) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (full_check) {
|
||||||
|
// Validate by comparing payload (recall, payload is represented in bytes)
|
||||||
|
if ((memcmp(data_rx.tb[0].payload, data_tx.payload[0], pusch_cfg.grant.tb[0].tbs * sizeof(uint8_t) / 8) == 0) !=
|
||||||
|
data_rx.tb[0].crc) {
|
||||||
|
printf("\nWarning! Bit comparison and CRC do not match!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char str[512];
|
||||||
|
srsran_pusch_nr_rx_info(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &data_rx, str, (uint32_t)sizeof(str));
|
||||||
|
|
||||||
|
char str_extra[2048];
|
||||||
|
srsran_sch_cfg_nr_info(&pusch_cfg, str_extra, (uint32_t)sizeof(str_extra));
|
||||||
|
printf("\nPUSCH: %s\n%s", str, str_extra);
|
||||||
|
|
||||||
|
printf("\nNominal SNR: %.1f dB\n", snr);
|
||||||
|
printf("Average EVM: %.3f\n", evm / n_blocks);
|
||||||
|
|
||||||
|
printf("BLER: %.3e (%d errors out of %d blocks)\n", (double)n_errors / n_blocks, n_errors, n_blocks);
|
||||||
|
printf("Tx Throughput: %.3e Mbps -- Rx Throughput: %.3e Mbps (%.2f%%)\n",
|
||||||
|
pusch_cfg.grant.tb[0].tbs / 1e3,
|
||||||
|
(n_blocks - n_errors) / 1e3 * pusch_cfg.grant.tb[0].tbs / n_blocks,
|
||||||
|
100.0F * (n_blocks - n_errors) / n_blocks);
|
||||||
|
|
||||||
|
ret = SRSRAN_SUCCESS;
|
||||||
|
|
||||||
|
clean_exit:
|
||||||
|
srsran_chest_dl_res_free(&chest);
|
||||||
|
srsran_random_free(rand_gen);
|
||||||
|
srsran_pusch_nr_free(&pusch_tx);
|
||||||
|
srsran_pusch_nr_free(&pusch_rx);
|
||||||
|
for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) {
|
||||||
|
if (data_tx.payload[i]) {
|
||||||
|
free(data_tx.payload[i]);
|
||||||
|
}
|
||||||
|
if (data_rx.tb[i].payload) {
|
||||||
|
free(data_rx.tb[i].payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < SRSRAN_MAX_LAYERS_NR; i++) {
|
||||||
|
if (sf_symbols_tx[i]) {
|
||||||
|
free(sf_symbols_tx[i]);
|
||||||
|
}
|
||||||
|
if (sf_symbols_rx[i]) {
|
||||||
|
free(sf_symbols_rx[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
srsran_softbuffer_tx_free(&softbuffer_tx);
|
||||||
|
srsran_softbuffer_rx_free(&softbuffer_rx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
Loading…
Reference in New Issue