DL-SCH NR added traces and fixes

master
Xavier Arteaga 4 years ago committed by Andre Puschmann
parent 2aa7e43771
commit 4e5edb5168

@ -160,12 +160,12 @@ bool srslte_cbsegm_cbsize_isvalid(uint32_t size)
static int cbsegm_ldpc_select_ls(uint32_t Kp, uint32_t K_b, uint32_t* Z_c, uint8_t* i_ls)
{
// Early return if the minimum required lift size is too high
if (Kp / K_b > MAX_LIFTSIZE) {
if (CEIL(Kp, K_b) > MAX_LIFTSIZE) {
return SRSLTE_ERROR;
}
// Iterate from the minimum required lift size to the maximum value
for (uint16_t Z = Kp / K_b; Z <= MAX_LIFTSIZE; Z++) {
for (uint16_t Z = CEIL(Kp, K_b); Z <= MAX_LIFTSIZE; Z++) {
// Get index for a selected lifting size
uint8_t i = get_ls_index(Z);

@ -85,7 +85,7 @@ int srslte_dlsch_nr_fill_cfg(srslte_sch_nr_t* q,
// Compute code block segmentation
srslte_cbsegm_t cbsegm = {};
if (cfg->bg == BG1) {
if (bg == BG1) {
if (srslte_cbsegm_ldpc_bg1(&cbsegm, tb->tbs) != SRSLTE_SUCCESS) {
ERROR("Error: calculating LDPC BG1 code block segmentation for tbs=%d\n", tb->tbs);
return SRSLTE_ERROR;
@ -180,7 +180,7 @@ static inline int sch_nr_init_common(srslte_sch_nr_t* q)
}
if (!q->temp_cb) {
q->temp_cb = srslte_vec_u8_malloc(SRSLTE_LDPC_MAX_LEN_CB);
q->temp_cb = srslte_vec_u8_malloc(SRSLTE_LDPC_MAX_LEN_CB * 8);
if (!q->temp_cb) {
return SRSLTE_ERROR;
}
@ -416,6 +416,7 @@ int srslte_dlsch_nr_encode(srslte_sch_nr_t* q,
// Append TB CRC
uint8_t* ptr = &q->temp_cb[cfg.Kp - cfg.L_cb - cfg.L_tb];
srslte_bit_unpack(checksum_tb, &ptr, cfg.L_tb);
INFO("CB %d: appending TB CRC=%06x\n", r, checksum_tb);
} else {
// Copy payload
srslte_bit_unpack_vector(data, q->temp_cb, (int)(cfg.Kp - cfg.L_cb));
@ -424,6 +425,7 @@ int srslte_dlsch_nr_encode(srslte_sch_nr_t* q,
// Attach code block CRC if required
if (cfg.L_cb) {
srslte_crc_attach(&q->crc_cb, q->temp_cb, (int)(cfg.Kp - cfg.L_cb));
INFO("CB %d: CRC=%06x\n", r, (uint32_t)srslte_crc_checksum_get(&q->crc_cb));
}
// Insert filler bits
@ -445,6 +447,15 @@ int srslte_dlsch_nr_encode(srslte_sch_nr_t* q,
j++;
// LDPC Rate matching
INFO("RM CB %d: E=%d; F=%d; BG=%d; Z=%d; RV=%d; Qm=%d; Nref=%d;\n",
r,
E,
cfg.F,
cfg.bg == BG1 ? 1 : 2,
cfg.Z,
tb->rv,
cfg.Qm,
cfg.Nref);
srslte_ldpc_rm_tx(&q->tx_rm, rm_buffer, output_ptr, E, cfg.bg, cfg.Z, tb->rv, tb->mod, cfg.Nref);
output_ptr += E;
}
@ -512,6 +523,15 @@ int srslte_dlsch_nr_decode(srslte_sch_nr_t* q,
j++;
// LDPC Rate matching
INFO("RM CB %d: E=%d; F=%d; BG=%d; Z=%d; RV=%d; Qm=%d; Nref=%d;\n",
r,
E,
cfg.F,
cfg.bg == BG1 ? 1 : 2,
cfg.Z,
tb->rv,
cfg.Qm,
cfg.Nref);
srslte_ldpc_rm_rx_c(&q->rx_rm, input_ptr, rm_buffer, E, cfg.F, cfg.bg, cfg.Z, tb->rv, tb->mod, cfg.Nref);
// Decode
@ -525,6 +545,12 @@ int srslte_dlsch_nr_decode(srslte_sch_nr_t* q,
uint32_t checksum2 = srslte_bit_pack(&ptr, cfg.L_cb);
tb->softbuffer.rx->cb_crc[r] = (checksum1 == checksum2);
INFO("CB %d: CRC={%06x, %06x} ... %s\n",
r,
checksum1,
checksum2,
tb->softbuffer.rx->cb_crc[r] ? "OK" : "KOtb->softbuffer.rx->cb_crc[r]");
// Pack only if CRC is match
if (tb->softbuffer.rx->cb_crc[r]) {
srslte_bit_pack_vector(q->temp_cb, tb->softbuffer.rx->data[r], cb_len);
@ -566,6 +592,9 @@ int srslte_dlsch_nr_decode(srslte_sch_nr_t* q,
// Calculate TB CRC from packed data
uint32_t checksum1 = srslte_crc_checksum_byte(cfg.crc_tb, data, tb->tbs);
*crc_ok = (checksum1 == checksum2);
INFO("TB: TBS=%d; CRC={%06x, %06x}\n", tb->tbs, checksum1, checksum2);
// srslte_vec_fprint_byte(stdout, data, tb->tbs / 8);
} else {
*crc_ok = false;
}

@ -624,3 +624,4 @@ endif(RF_FOUND)
add_executable(dlsch_nr_test dlsch_nr_test.c)
target_link_libraries(dlsch_nr_test srslte_phy)
add_test(dlsch_nr_test dlsch_nr_test)

@ -0,0 +1,237 @@
/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/phy/phch/sch_nr.h"
#include "srslte/phy/ue/ue_dl_nr_data.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
#include <getopt.h>
#include <srslte/phy/utils/random.h>
static srslte_carrier_nr_t carrier = {
0, // cell_id
0, // numerology
SRSLTE_MAX_PRB_NR, // nof_prb
0 // start
};
static uint32_t n_prb = 1; // Set to 0 for steering
static uint32_t mcs = 16; // Set to 30 for steering
static srslte_pdsch_cfg_nr_t pdsch_cfg = {};
static srslte_pdsch_grant_nr_t pdsch_grant = {};
void usage(char* prog)
{
printf("Usage: %s [pTL] \n", prog);
printf("\t-p Number of carrier PRB [Default %d]\n", carrier.nof_prb);
printf("\t-T Provide MCS table (64qam, 256qam, 64qamLowSE) [Default %s]\n",
srslte_mcs_table_to_str(pdsch_cfg.mcs_table));
printf("\t-L Provide number of layers [Default %d]\n", pdsch_cfg.serving_cell_cfg.max_mimo_layers);
printf("\t-v [set srslte_verbose to debug, default none]\n");
}
int parse_args(int argc, char** argv)
{
int opt;
while ((opt = getopt(argc, argv, "pTLv")) != -1) {
switch (opt) {
case 'p':
carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
break;
case 'T':
pdsch_cfg.mcs_table = srslte_mcs_table_from_str(argv[optind]);
break;
case 'L':
pdsch_cfg.serving_cell_cfg.max_mimo_layers = (uint32_t)strtol(argv[optind], NULL, 10);
break;
case 'v':
srslte_verbose++;
break;
default:
usage(argv[0]);
return SRSLTE_ERROR;
}
}
srslte_verbose++;
return SRSLTE_SUCCESS;
}
int main(int argc, char** argv)
{
int ret = SRSLTE_ERROR;
srslte_sch_nr_t sch_nr_tx = {};
srslte_sch_nr_t sch_nr_rx = {};
srslte_random_t rand_gen = srslte_random_init(1234);
uint8_t* data_tx = srslte_vec_u8_malloc(1024 * 1024);
uint8_t* encoded = srslte_vec_u8_malloc(1024 * 1024 * 8);
int8_t* llr = srslte_vec_i8_malloc(1024 * 1024 * 8);
uint8_t* data_rx = srslte_vec_u8_malloc(1024 * 1024);
// Set default PDSCH configuration
pdsch_cfg.mcs_table = srslte_mcs_table_256qam;
pdsch_cfg.serving_cell_cfg.max_mimo_layers = 2;
if (parse_args(argc, argv) < SRSLTE_SUCCESS) {
goto clean_exit;
}
if (data_tx == NULL || data_rx == NULL) {
goto clean_exit;
}
if (srslte_sch_nr_init_tx(&sch_nr_tx) < SRSLTE_SUCCESS) {
ERROR("Error initiating SCH NR for Tx\n");
goto clean_exit;
}
srslte_sch_nr_decoder_cfg_t decoder_cfg = {};
decoder_cfg.disable_simd = true;
if (srslte_sch_nr_init_rx(&sch_nr_rx, &decoder_cfg) < SRSLTE_SUCCESS) {
ERROR("Error initiating SCH NR for Rx\n");
goto clean_exit;
}
if (srslte_sch_nr_set_carrier(&sch_nr_tx, &carrier)) {
ERROR("Error setting SCH NR carrier\n");
goto clean_exit;
}
if (srslte_sch_nr_set_carrier(&sch_nr_rx, &carrier)) {
ERROR("Error setting SCH NR carrier\n");
goto clean_exit;
}
srslte_softbuffer_tx_t softbuffer_tx = {};
srslte_softbuffer_rx_t softbuffer_rx = {};
if (srslte_softbuffer_tx_init_guru(&softbuffer_tx, 50, 18000) < SRSLTE_SUCCESS) {
ERROR("Error init soft-buffer\n");
goto clean_exit;
}
if (srslte_softbuffer_rx_init_guru(&softbuffer_rx, 50, 18000) < SRSLTE_SUCCESS) {
ERROR("Error init soft-buffer\n");
goto clean_exit;
}
// Use grant default A time resources with m=0
if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_cfg_typeA.typeA_pos, &pdsch_grant) <
SRSLTE_SUCCESS) {
ERROR("Error loading default grant\n");
goto clean_exit;
}
pdsch_grant.nof_layers = pdsch_cfg.serving_cell_cfg.max_mimo_layers;
pdsch_grant.dci_format = srslte_dci_format_nr_1_0;
uint32_t n_prb_start = 1;
uint32_t n_prb_end = carrier.nof_prb + 1;
if (n_prb > 0) {
n_prb_start = SRSLTE_MIN(n_prb, n_prb_end - 1);
n_prb_end = SRSLTE_MIN(n_prb + 1, n_prb_end);
}
uint32_t mcs_start = 0;
uint32_t mcs_end = pdsch_cfg.mcs_table == srslte_mcs_table_256qam ? 28 : 29;
if (mcs < mcs_end) {
mcs_start = SRSLTE_MIN(mcs, mcs_end - 1);
mcs_end = SRSLTE_MIN(mcs + 1, mcs_end);
}
for (n_prb = n_prb_start; n_prb < n_prb_end; n_prb++) {
for (mcs = mcs_start; mcs < mcs_end; mcs++) {
for (uint32_t n = 0; n < SRSLTE_MAX_PRB_NR; n++) {
pdsch_grant.prb_idx[n] = (n < n_prb);
}
srslte_ra_tb_nr_t tb = {};
if (srslte_ra_nr_fill_tb(&pdsch_cfg, &pdsch_grant, mcs, &tb) < SRSLTE_SUCCESS) {
ERROR("Error filing tb\n");
goto clean_exit;
}
for (uint32_t i = 0; i < tb.tbs; i++) {
data_tx[i] = (uint8_t)srslte_random_uniform_int_dist(rand_gen, 0, UINT8_MAX);
}
tb.softbuffer.tx = &softbuffer_tx;
if (srslte_dlsch_nr_encode(&sch_nr_tx, &pdsch_cfg, &tb, data_tx, encoded) < SRSLTE_SUCCESS) {
ERROR("Error encoding\n");
goto clean_exit;
}
for (uint32_t i = 0; i < tb.nof_bits; i++) {
llr[i] = encoded[i] ? -10 : +10;
}
tb.softbuffer.rx = &softbuffer_rx;
srslte_softbuffer_rx_reset(tb.softbuffer.rx);
bool crc = false;
if (srslte_dlsch_nr_decode(&sch_nr_rx, &pdsch_cfg, &tb, llr, data_rx, &crc) < SRSLTE_SUCCESS) {
ERROR("Error encoding\n");
goto clean_exit;
}
if (!crc) {
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;\n", n_prb, mcs, tb.tbs);
goto clean_exit;
}
if (memcmp(data_tx, data_rx, tb.tbs / 8) != 0) {
ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;\n", n_prb, mcs, tb.tbs);
printf("Tx data: ");
srslte_vec_fprint_byte(stdout, data_tx, tb.tbs / 8);
printf("Rx data: ");
srslte_vec_fprint_byte(stdout, data_rx, tb.tbs / 8);
goto clean_exit;
}
printf("n_prb=%d; mcs=%d; TBS=%d; PASSED!\n", n_prb, mcs, tb.tbs);
}
}
ret = SRSLTE_SUCCESS;
clean_exit:
srslte_random_free(rand_gen);
srslte_sch_nr_free(&sch_nr_tx);
srslte_sch_nr_free(&sch_nr_rx);
if (data_tx) {
free(data_tx);
}
if (data_rx) {
free(data_rx);
}
if (llr) {
free(llr);
}
if (encoded) {
free(encoded);
}
srslte_softbuffer_tx_free(&softbuffer_tx);
srslte_softbuffer_rx_free(&softbuffer_rx);
return SRSLTE_SUCCESS;
}
Loading…
Cancel
Save