From 98969b2011fc7fdbc6aa995645b0f5585fb7f27e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 31 Oct 2017 12:19:35 +0100 Subject: [PATCH] Implemented 3GPP 36.212 Tables 5.3.3.1.5-1 and 5.3.3.1.5-2 --- lib/include/srslte/phy/phch/pdsch_cfg.h | 1 + lib/include/srslte/phy/phch/ra.h | 1 + lib/src/phy/phch/pdsch.c | 64 ++++++++++++++----------- lib/src/phy/phch/ra.c | 5 +- lib/src/phy/phch/sch.c | 12 ++--- lib/src/phy/phch/test/CMakeLists.txt | 16 +++++++ lib/src/phy/phch/test/pdsch_test.c | 17 ++++++- 7 files changed, 79 insertions(+), 37 deletions(-) diff --git a/lib/include/srslte/phy/phch/pdsch_cfg.h b/lib/include/srslte/phy/phch/pdsch_cfg.h index eb4927fbb..63b3fefcc 100644 --- a/lib/include/srslte/phy/phch/pdsch_cfg.h +++ b/lib/include/srslte/phy/phch/pdsch_cfg.h @@ -48,6 +48,7 @@ typedef struct SRSLTE_API { uint32_t nof_layers; uint32_t codebook_idx; srslte_mimo_type_t mimo_type; + bool tb_cw_swap; } srslte_pdsch_cfg_t; #endif diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index e9c402236..f4274e416 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -107,6 +107,7 @@ typedef struct SRSLTE_API { srslte_sf_t sf_type; bool tb_en[SRSLTE_MAX_CODEWORDS]; uint32_t pinfo; + bool tb_cw_swap; } srslte_ra_dl_grant_t; #define SRSLTE_RA_DL_GRANT_NOF_TB(G) ((((G)->tb_en[0])?1:0)+(((G)->tb_en[1])?1:0)) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 99f4fbfa5..7c744f552 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -477,6 +477,7 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra cfg->sf_idx = sf_idx; memcpy(cfg->rv, rvidx, sizeof(uint32_t) * SRSLTE_MAX_CODEWORDS); cfg->mimo_type = mimo_type; + cfg->tb_cw_swap = grant->tb_cw_swap; /* Check and configure PDSCH transmission modes */ switch(mimo_type) { @@ -543,19 +544,19 @@ static srslte_sequence_t *get_user_sequence(srslte_pdsch_t *q, uint16_t rnti, static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data, - uint32_t codeword_idx) { - srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx]; - srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx]; - uint32_t rv = cfg->rv[codeword_idx]; + uint32_t codeword_idx, uint32_t tb_idx) { + srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; + srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; + uint32_t rv = cfg->rv[tb_idx]; if (nbits->nof_bits) { - INFO("Encoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, + INFO("Encoding PDSCH SF: %d (TB%d -> CW%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", + cfg->sf_idx, tb_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); /* Channel coding */ - if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], codeword_idx)) { - ERROR("Error encoding TB %d", codeword_idx); + if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], tb_idx)) { + ERROR("Error encoding (TB%d -> CW%d)", tb_idx, codeword_idx); return SRSLTE_ERROR; } @@ -577,15 +578,15 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data, - uint32_t codeword_idx, bool *ack) { - srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx]; - srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx]; - uint32_t rv = cfg->rv[codeword_idx]; + uint32_t codeword_idx, uint32_t tb_idx, bool *ack) { + srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; + srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; + uint32_t rv = cfg->rv[tb_idx]; int ret = SRSLTE_ERROR_INVALID_INPUTS; if (softbuffer && data && ack) { - INFO("Decoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, + INFO("Decoding PDSCH SF: %d (CW%d -> TB%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", + cfg->sf_idx, codeword_idx, tb_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); /* demodulate symbols @@ -601,7 +602,7 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c srslte_scrambling_s_offset(seq, q->e[codeword_idx], 0, nbits->nof_bits); /* Return */ - ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, codeword_idx); + ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, tb_idx); q->last_nof_iterations[codeword_idx] = srslte_sch_last_noi(&q->dl_sch); @@ -690,16 +691,22 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_layerdemap_type(x, q->d, cfg->nof_layers, nof_tb, nof_symbols[0], nof_symbols, cfg->mimo_type); } - // Codeword decoding - for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) { + + /* Codeword decoding: Implementation of 3GPP 36.212 Table 5.3.3.1.5-1 and Table 5.3.3.1.5-2 */ + uint32_t cw_idx = (nof_tb == SRSLTE_MAX_TB && cfg->tb_cw_swap) ? 1 : 0; + for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { /* Decode only if transport block is enabled and the default ACK is not true */ - if (cfg->grant.tb_en[tb] && !acks[tb]) { - int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb, &acks[tb]); + if (cfg->grant.tb_en[tb_idx]) { + if (!acks[tb_idx]) { + int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx, &acks[tb_idx]); - /* Check if there has been any execution error */ - if (ret) { - return ret; + /* Check if there has been any execution error */ + if (ret) { + return ret; + } } + + cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS; } } @@ -772,20 +779,23 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, } /* If both transport block size is zero return error */ - if (cfg->grant.mcs[0].tbs == 0) { + if (!nof_tb) { return SRSLTE_ERROR_INVALID_INPUTS; } - if (cfg->nbits[0].nof_re > q->max_re) { + if (cfg->nbits[0].nof_re > q->max_re || cfg->nbits[1].nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", cfg->nbits[0].nof_re, q->max_re, q->cell.nof_prb); return SRSLTE_ERROR_INVALID_INPUTS; } - for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) { - if (cfg->grant.tb_en[tb]) { - ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb); + /* Implementation of 3GPP 36.212 Table 5.3.3.1.5-1 and Table 5.3.3.1.5-2 */ + uint32_t cw_idx = (nof_tb == SRSLTE_MAX_TB && cfg->tb_cw_swap) ? 1 : 0; + for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { + if (cfg->grant.tb_en[tb_idx]) { + ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx); + cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS; } } diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 8fe0ef934..735794e35 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -546,6 +546,7 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr } } grant->pinfo = dci->pinfo; + grant->tb_cw_swap = dci->tb_cw_swap; if (grant->mcs[0].tbs < 0 || grant->mcs[1].tbs < 0) { return SRSLTE_ERROR; @@ -559,10 +560,10 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl { // Compute number of RE for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi); + nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi; if (grant->tb_en[i]) { /* Compute number of RE for first transport block */ - nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi); - nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi; if (SRSLTE_SF_NORM == grant->sf_type) { nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart; } else if (SRSLTE_SF_MBSFN == grant->sf_type) { diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index b9860ffa4..930364725 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -517,15 +517,15 @@ int srslte_dlsch_decode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, - int16_t *e_bits, uint8_t *data, int codeword_idx) { + int16_t *e_bits, uint8_t *data, int tb_idx) { uint32_t Nl = 1; if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) { Nl = 2; } - return decode_tb(q, softbuffer, &cfg->cb_segm[codeword_idx], - cfg->grant.Qm[codeword_idx] * Nl, cfg->rv[codeword_idx], cfg->nbits[codeword_idx].nof_bits, + return decode_tb(q, softbuffer, &cfg->cb_segm[tb_idx], + cfg->grant.Qm[tb_idx] * Nl, cfg->rv[tb_idx], cfg->nbits[tb_idx].nof_bits, e_bits, data); } @@ -546,15 +546,15 @@ int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf } int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, uint8_t *e_bits, int codeword_idx) { + uint8_t *data, uint8_t *e_bits, int tb_idx) { uint32_t Nl = 1; if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) { Nl = 2; } - return encode_tb(q, softbuffer, &cfg->cb_segm[codeword_idx], cfg->grant.Qm[codeword_idx]*Nl, cfg->rv[codeword_idx], - cfg->nbits[codeword_idx].nof_bits, data, e_bits); + return encode_tb(q, softbuffer, &cfg->cb_segm[tb_idx], cfg->grant.Qm[tb_idx]*Nl, cfg->rv[tb_idx], + cfg->nbits[tb_idx].nof_bits, data, e_bits); } /* Compute the interleaving function on-the-fly, because it depends on number of RI bits diff --git a/lib/src/phy/phch/test/CMakeLists.txt b/lib/src/phy/phch/test/CMakeLists.txt index 6e6b8c024..f1a2bccee 100644 --- a/lib/src/phy/phch/test/CMakeLists.txt +++ b/lib/src/phy/phch/test/CMakeLists.txt @@ -119,6 +119,14 @@ add_test(pdsch_test_multiplex1cw_p0_50 pdsch_test -x multiplex -a 2 -p 0 -n 50) add_test(pdsch_test_multiplex1cw_p0_75 pdsch_test -x multiplex -a 2 -p 0 -n 75) add_test(pdsch_test_multiplex1cw_p0_100 pdsch_test -x multiplex -a 2 -p 0 -n 100) +# PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (1 codeword, swapped) +add_test(pdsch_test_multiplex1cw_p0_6_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 6 -F 1) +add_test(pdsch_test_multiplex1cw_p0_15_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 15) +add_test(pdsch_test_multiplex1cw_p0_25_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 25) +add_test(pdsch_test_multiplex1cw_p0_50_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 50) +add_test(pdsch_test_multiplex1cw_p0_75_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 75) +add_test(pdsch_test_multiplex1cw_p0_100_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 100) + # PDSCH test for Spatial Multiplex transmision mode with PMI = 1 (1 codeword) add_test(pdsch_test_multiplex1cw_p1_6 pdsch_test -x multiplex -a 2 -p 1 -n 6) add_test(pdsch_test_multiplex1cw_p1_12 pdsch_test -x multiplex -a 2 -p 1 -n 12) @@ -151,6 +159,14 @@ add_test(pdsch_test_multiplex2cw_p0_50 pdsch_test -x multiplex -a 2 -t 0 -p 0 - add_test(pdsch_test_multiplex2cw_p0_75 pdsch_test -x multiplex -a 2 -t 0 -p 0 -n 75) add_test(pdsch_test_multiplex2cw_p0_100 pdsch_test -x multiplex -a 2 -t 0 -p 0 -n 100) +# PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (2 codeword, swapped) +add_test(pdsch_test_multiplex2cw_p0_6_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 6 -w -F 1) +add_test(pdsch_test_multiplex2cw_p0_12_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 12 -w) +add_test(pdsch_test_multiplex2cw_p0_25_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 25 -w) +add_test(pdsch_test_multiplex2cw_p0_50_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 50 -w) +add_test(pdsch_test_multiplex2cw_p0_75_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 75 -w) +add_test(pdsch_test_multiplex2cw_p0_100_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 100 -w) + # PDSCH test for Spatial Multiplex transmision mode with PMI = 1 (2 codeword) add_test(pdsch_test_multiplex2cw_p1_6 pdsch_test -x multiplex -a 2 -t 0 -p 1 -n 6) add_test(pdsch_test_multiplex2cw_p1_12 pdsch_test -x multiplex -a 2 -t 0 -p 1 -n 12) diff --git a/lib/src/phy/phch/test/pdsch_test.c b/lib/src/phy/phch/test/pdsch_test.c index 0c98079b9..b97e8b299 100644 --- a/lib/src/phy/phch/test/pdsch_test.c +++ b/lib/src/phy/phch/test/pdsch_test.c @@ -59,6 +59,7 @@ uint32_t subframe = 1; int rv_idx[SRSLTE_MAX_CODEWORDS] = {0, 1}; uint16_t rnti = 1234; uint32_t nof_rx_antennas = 1; +bool tb_cw_swap = false; uint32_t pmi = 0; char *input_file = NULL; @@ -77,12 +78,13 @@ void usage(char *prog) { printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb); printf("\t-a nof_rx_antennas [Default %d]\n", nof_rx_antennas); printf("\t-p pmi (multiplex only) [Default %d]\n", pmi); + printf("\t-w Swap Transport Blocks\n"); printf("\t-v [set srslte_verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "fmMcsrtRFpnavx")) != -1) { + while ((opt = getopt(argc, argv, "fmMcsrtRFpnawvx")) != -1) { switch(opt) { case 'f': input_file = argv[optind]; @@ -123,6 +125,9 @@ void parse_args(int argc, char **argv) { case 'a': nof_rx_antennas = (uint32_t) atoi(argv[optind]); break; + case 'w': + tb_cw_swap = true; + break; case 'v': srslte_verbose++; break; @@ -207,6 +212,11 @@ int main(int argc, char **argv) { dci.tb_en[1] = true; } + /* Enable swap */ + if (SRSLTE_RA_DL_GRANT_NOF_TB(&dci) == SRSLTE_MAX_TB && tb_cw_swap) { + dci.tb_cw_swap = tb_cw_swap; + } + /* Generate grant from DCI */ if (srslte_ra_dl_dci_to_grant(&dci, cell.nof_prb, rnti, &grant)) { fprintf(stderr, "Error computing resource allocation\n"); @@ -255,7 +265,7 @@ int main(int argc, char **argv) { } - for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + for (i = 0; i < SRSLTE_MAX_TB; i++) { if (grant.tb_en[i]) { data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs); if (!data_tx[i]) { @@ -271,6 +281,9 @@ int main(int argc, char **argv) { } bzero(data_rx[i], sizeof(uint8_t) * grant.mcs[i].tbs); + } else { + data_tx[i] = NULL; + data_rx[i] = NULL; } }