Implemented 3GPP 36.212 Tables 5.3.3.1.5-1 and 5.3.3.1.5-2

This commit is contained in:
Xavier Arteaga 2017-10-31 12:19:35 +01:00
parent 81b34afff9
commit 98969b2011
7 changed files with 80 additions and 38 deletions

View file

@ -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

View file

@ -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))

View file

@ -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 ++) {
/* 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]);
/* Check if there has been any execution error */
if (ret) {
return ret;
/* 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_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;
}
}
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;
}
}

View file

@ -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) {

View file

@ -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

View file

@ -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)

View file

@ -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;
}
}