mirror of https://github.com/PentHertz/srsLTE.git
Implemented 3GPP 36.212 Tables 5.3.3.1.5-1 and 5.3.3.1.5-2
This commit is contained in:
parent
81b34afff9
commit
98969b2011
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue