DL grant parameter are now vectors of MAX_CODEWORDS

master
Xavier Arteaga 7 years ago
parent cb4b4f4d4c
commit 2c07a16189

@ -87,6 +87,7 @@ srslte_pdsch_cfg_t pdsch_cfg;
srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS]; srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS];
srslte_regs_t regs; srslte_regs_t regs;
srslte_ra_dl_dci_t ra_dl; srslte_ra_dl_dci_t ra_dl;
int rvidx[SRSLTE_MAX_CODEWORDS] = {0, 0};
cf_t *sf_buffer[SRSLTE_MAX_PORTS] = {NULL}, *output_buffer [SRSLTE_MAX_PORTS] = {NULL}; cf_t *sf_buffer[SRSLTE_MAX_PORTS] = {NULL}, *output_buffer [SRSLTE_MAX_PORTS] = {NULL};
int sf_n_re, sf_n_samples; int sf_n_re, sf_n_samples;
@ -423,7 +424,7 @@ int update_radl() {
ra_dl.harq_process = 0; ra_dl.harq_process = 0;
ra_dl.mcs_idx = mcs_idx; ra_dl.mcs_idx = mcs_idx;
ra_dl.ndi = 0; ra_dl.ndi = 0;
ra_dl.rv_idx = 0; ra_dl.rv_idx = rvidx[0];
ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0; ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
ra_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask(); ra_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask();
ra_dl.tb_en[0] = 1; ra_dl.tb_en[0] = 1;
@ -431,7 +432,7 @@ int update_radl() {
if (nof_tb > 1) { if (nof_tb > 1) {
ra_dl.mcs_idx_1 = mcs_idx; ra_dl.mcs_idx_1 = mcs_idx;
ra_dl.ndi_1 = 0; ra_dl.ndi_1 = 0;
ra_dl.rv_idx_1 = 0; ra_dl.rv_idx_1 = rvidx[1];
ra_dl.tb_en[1] = 1; ra_dl.tb_en[1] = 1;
} }
@ -513,7 +514,7 @@ void *net_thread_fnc(void *arg) {
n = srslte_netsource_read(&net_source, &data2[rpm], DATA_BUFF_SZ-rpm); n = srslte_netsource_read(&net_source, &data2[rpm], DATA_BUFF_SZ-rpm);
if (n > 0) { if (n > 0) {
// FIXME: I assume that both transport blocks have same size in case of 2 tb are active // FIXME: I assume that both transport blocks have same size in case of 2 tb are active
int nbytes = 1 + (pdsch_cfg.grant.mcs.tbs + pdsch_cfg.grant.mcs2.tbs - 1) / 8; int nbytes = 1 + (pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs - 1) / 8;
rpm += n; rpm += n;
INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes); INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes);
wpm = 0; wpm = 0;
@ -696,12 +697,11 @@ int main(int argc, char **argv) {
INFO("Transmitting packet\n",0); INFO("Transmitting packet\n",0);
} }
} else { } else {
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs.tbs); INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs);
for (i = 0; i < pdsch_cfg.grant.mcs.tbs / 8; i++) { for (uint32_t tb = 0; tb < pdsch_cfg.grant.nof_tb; tb++) {
data[0][i] = rand() % 256; for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) {
data[tb][i] = (uint8_t) rand();
} }
for (i = 0; i < pdsch_cfg.grant.mcs2.tbs / 8; i++) {
data[1][i] = rand() % 256;
} }
/* Uncomment this to transmit on sf 0 and 5 only */ /* Uncomment this to transmit on sf 0 and 5 only */
if (sf_idx != 0 && sf_idx != 5) { if (sf_idx != 0 && sf_idx != 5) {
@ -744,7 +744,7 @@ int main(int argc, char **argv) {
/* Configure pdsch_cfg parameters */ /* Configure pdsch_cfg parameters */
srslte_ra_dl_grant_t grant; srslte_ra_dl_grant_t grant;
srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, UE_CRNTI, &grant); srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, UE_CRNTI, &grant);
if (srslte_pdsch_cfg_multi(&pdsch_cfg, cell, &grant, cfi, sf_idx, 0, 0, pdsch_cfg.mimo_type, multiplex_pmi)) { if (srslte_pdsch_cfg_multi(&pdsch_cfg, cell, &grant, cfi, sf_idx, rvidx, pdsch_cfg.mimo_type, multiplex_pmi)) {
fprintf(stderr, "Error configuring PDSCH\n"); fprintf(stderr, "Error configuring PDSCH\n");
exit(-1); exit(-1);
} }
@ -757,13 +757,9 @@ int main(int argc, char **argv) {
} }
if (net_port > 0 && net_packet_ready) { if (net_port > 0 && net_packet_ready) {
if (null_file_sink) { if (null_file_sink) {
srslte_bit_pack_vector(data[0], data_tmp, pdsch_cfg.grant.mcs.tbs); for (uint32_t tb = 0; tb < pdsch_cfg.grant.nof_tb; tb++) {
if (srslte_netsink_write(&net_sink, data_tmp, 1+(pdsch_cfg.grant.mcs.tbs-1)/8) < 0) { srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.mcs[tb].tbs);
fprintf(stderr, "Error sending data through UDP socket\n"); if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs[tb].tbs - 1) / 8) < 0) {
}
if (nof_tb > 1) {
srslte_bit_pack_vector(data[1], data_tmp, pdsch_cfg.grant.mcs2.tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs2.tbs - 1) / 8) < 0) {
fprintf(stderr, "Error sending data through UDP socket\n"); fprintf(stderr, "Error sending data through UDP socket\n");
} }
} }

@ -594,8 +594,10 @@ int main(int argc, char **argv) {
/* Send data if socket active */ /* Send data if socket active */
if (prog_args.net_port > 0) { if (prog_args.net_port > 0) {
// FIXME: UDP Data transmission does not work // FIXME: UDP Data transmission does not work
srslte_netsink_write(&net_sink, data[0], 1 + (ue_dl.pdsch_cfg.grant.mcs.tbs - 1) / 8); for (uint32_t tb = 0; tb < ue_dl.pdsch_cfg.grant.nof_tb; tb++) {
srslte_netsink_write(&net_sink, data[1], 1 + (ue_dl.pdsch_cfg.grant.mcs2.tbs - 1) / 8); srslte_netsink_write(&net_sink, data[tb], 1 + (ue_dl.pdsch_cfg.grant.mcs[tb].tbs - 1) / 8);
}
} }
#ifdef PRINT_CHANGE_SCHEDULIGN #ifdef PRINT_CHANGE_SCHEDULIGN
@ -616,12 +618,12 @@ int main(int argc, char **argv) {
nof_trials++; nof_trials++;
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1); rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1f);
rsrp0 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 0), rsrp0, 0.05); rsrp0 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 0), rsrp0, 0.05f);
rsrp1 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 1), rsrp1, 0.05); rsrp1 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 1), rsrp1, 0.05f);
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05); noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05f);
enodebrate = SRSLTE_VEC_EMA((ue_dl.pdsch_cfg.grant.mcs.tbs + ue_dl.pdsch_cfg.grant.mcs2.tbs)/1000.0, enodebrate, 0.05); enodebrate = SRSLTE_VEC_EMA((ue_dl.pdsch_cfg.grant.mcs[0].tbs + ue_dl.pdsch_cfg.grant.mcs[1].tbs)/1000.0f, enodebrate, 0.05f);
uerate = SRSLTE_VEC_EMA((n>0)?(ue_dl.pdsch_cfg.grant.mcs.tbs + ue_dl.pdsch_cfg.grant.mcs2.tbs)/1000.0:0.0, uerate, 0.01); uerate = SRSLTE_VEC_EMA((n>0)?(ue_dl.pdsch_cfg.grant.mcs[0].tbs + ue_dl.pdsch_cfg.grant.mcs[1].tbs)/1000.0f:0.0f, uerate, 0.01f);
nframes++; nframes++;
if (isnan(rsrq)) { if (isnan(rsrq)) {
@ -812,7 +814,7 @@ void *plot_thread_run(void *arg) {
while(1) { while(1) {
sem_wait(&plot_sem); sem_wait(&plot_sem);
uint32_t nof_symbols = ue_dl.pdsch_cfg.nbits.nof_re; uint32_t nof_symbols = ue_dl.pdsch_cfg.nbits[0].nof_re;
if (!prog_args.disable_plots_except_constellation) { if (!prog_args.disable_plots_except_constellation) {
for (i = 0; i < nof_re; i++) { for (i = 0; i < nof_re; i++) {
tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i])); tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i]));

@ -104,15 +104,14 @@ SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t rvidx); int rvidx);
SRSLTE_API int srslte_pdsch_cfg_multi(srslte_pdsch_cfg_t *cfg, SRSLTE_API int srslte_pdsch_cfg_multi(srslte_pdsch_cfg_t *cfg,
srslte_cell_t cell, srslte_cell_t cell,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t rvidx, int rvidx[SRSLTE_MAX_CODEWORDS],
uint32_t rvidx2,
srslte_mimo_type_t mimo_type, srslte_mimo_type_t mimo_type,
uint32_t pmi); uint32_t pmi);
@ -156,7 +155,7 @@ SRSLTE_API int srslte_pdsch_pmi_select(srslte_pdsch_t *q,
uint32_t pmi[SRSLTE_MAX_LAYERS], uint32_t pmi[SRSLTE_MAX_LAYERS],
float sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS]); float sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS]);
SRSLTE_API void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, int max_iter); SRSLTE_API void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, uint32_t max_iter);
SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q); SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q);

@ -40,13 +40,10 @@
#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/cbsegm.h"
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cbsegm_t cb_segm; srslte_cbsegm_t cb_segm[SRSLTE_MAX_CODEWORDS];
srslte_cbsegm_t cb_segm2;
srslte_ra_dl_grant_t grant; srslte_ra_dl_grant_t grant;
srslte_ra_nbits_t nbits; srslte_ra_nbits_t nbits[SRSLTE_MAX_CODEWORDS];
srslte_ra_nbits_t nbits2; uint32_t rv[SRSLTE_MAX_CODEWORDS];
uint32_t rv;
uint32_t rv2;
uint32_t sf_idx; uint32_t sf_idx;
uint32_t nof_layers; uint32_t nof_layers;
uint32_t codebook_idx; uint32_t codebook_idx;

@ -102,10 +102,8 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
bool prb_idx[2][SRSLTE_MAX_PRB]; bool prb_idx[2][SRSLTE_MAX_PRB];
uint32_t nof_prb; uint32_t nof_prb;
uint32_t Qm; uint32_t Qm[SRSLTE_MAX_CODEWORDS];
uint32_t Qm2; srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs;
srslte_ra_mcs_t mcs2;
uint32_t nof_tb; uint32_t nof_tb;
} srslte_ra_dl_grant_t; } srslte_ra_dl_grant_t;
@ -207,7 +205,7 @@ SRSLTE_API void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,
srslte_cell_t cell, srslte_cell_t cell,
uint32_t sf_idx, uint32_t sf_idx,
srslte_ra_nbits_t *nbits); srslte_ra_nbits_t nbits[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API void srslte_ra_dl_grant_to_nbits_multi(srslte_ra_dl_grant_t *grant, SRSLTE_API void srslte_ra_dl_grant_to_nbits_multi(srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,

@ -103,12 +103,6 @@ SRSLTE_API int srslte_dlsch_encode2(srslte_sch_t *q,
uint8_t *e_bits, uint8_t *e_bits,
int codeword_idx); int codeword_idx);
SRSLTE_API int srslte_dlsch_encode_multi(srslte_sch_t *q,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS],
uint8_t *data[SRSLTE_MAX_CODEWORDS],
uint8_t *e_bits[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API int srslte_dlsch_decode(srslte_sch_t *q, SRSLTE_API int srslte_dlsch_decode(srslte_sch_t *q,
srslte_pdsch_cfg_t *cfg, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer, srslte_softbuffer_rx_t *softbuffer,

@ -145,14 +145,13 @@ SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t rvidx); int rvidx);
SRSLTE_API int srslte_ue_dl_cfg_grant_multi(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_cfg_grant_multi(srslte_ue_dl_t *q,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t rvidx, int rvidx[SRSLTE_MAX_CODEWORDS],
uint32_t rvidx2,
srslte_mimo_type_t mimo_type, srslte_mimo_type_t mimo_type,
uint32_t pinfo); uint32_t pinfo);

@ -58,10 +58,10 @@ SRSLTE_API extern int srslte_verbose;
#define PRINT_NONE srslte_verbose=SRSLTE_VERBOSE_NONE #define PRINT_NONE srslte_verbose=SRSLTE_VERBOSE_NONE
#define DEBUG(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG) \ #define DEBUG(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG) \
fprintf(stdout, "[DEBUG]: " _fmt, __VA_ARGS__) fprintf(stdout, "[DEBUG]: " _fmt, ##__VA_ARGS__)
#define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO) \ #define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO) \
fprintf(stdout, "[INFO]: " _fmt, __VA_ARGS__) fprintf(stdout, "[INFO]: " _fmt, ##__VA_ARGS__)
#if CMAKE_BUILD_TYPE==Debug #if CMAKE_BUILD_TYPE==Debug
/* In debug mode, it prints out the */ /* In debug mode, it prints out the */

@ -358,50 +358,35 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
/* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg. /* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg.
* If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant * If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant
*/ */
int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, uint32_t rvidx) int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi,
{ uint32_t sf_idx, int rvidx) {
if (cfg) { int _rvids[SRSLTE_MAX_CODEWORDS] = {1};
if (grant) { _rvids[0] = rvidx;
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
}
if (srslte_cbsegm(&cfg->cb_segm, cfg->grant.mcs.tbs)) {
fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", cfg->grant.mcs.tbs);
return SRSLTE_ERROR;
}
srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, &cfg->nbits);
cfg->sf_idx = sf_idx;
cfg->rv = rvidx;
return SRSLTE_SUCCESS; return srslte_pdsch_cfg_multi(cfg, cell, grant, cfi, sf_idx, _rvids, SRSLTE_MIMO_TYPE_SINGLE_ANTENNA, 0);
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
} }
/* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg. /* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg.
* If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant * If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant
*/ */
int srslte_pdsch_cfg_multi(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi, int srslte_pdsch_cfg_multi(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi,
uint32_t sf_idx, uint32_t rvidx, uint32_t rvidx2, srslte_mimo_type_t mimo_type, uint32_t pmi) uint32_t sf_idx, int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type,
{ uint32_t pmi) {
if (cfg) { if (cfg) {
if (grant) { if (grant) {
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t)); memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
} }
if (srslte_cbsegm(&cfg->cb_segm, (uint32_t) cfg->grant.mcs.tbs)) {
fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs.tbs);
return SRSLTE_ERROR;
}
if (srslte_cbsegm(&cfg->cb_segm2, (uint32_t) cfg->grant.mcs2.tbs)) { for (int i = 0; i < grant->nof_tb; i++) {
fprintf(stderr, "Error computing Codeblock (2) segmentation for TBS=%d\n", cfg->grant.mcs2.tbs); if (srslte_cbsegm(&cfg->cb_segm[i], (uint32_t) cfg->grant.mcs[i].tbs)) {
fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs[i].tbs);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
}
srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, cfg->nbits);
srslte_ra_dl_grant_to_nbits_multi(&cfg->grant, cfi, cell, sf_idx, &cfg->nbits, &cfg->nbits2);
cfg->sf_idx = sf_idx; cfg->sf_idx = sf_idx;
cfg->rv = rvidx; memcpy(cfg->rv, rvidx, sizeof(uint32_t) * SRSLTE_MAX_CODEWORDS);
cfg->rv2 = rvidx2;
cfg->mimo_type = mimo_type; cfg->mimo_type = mimo_type;
/* Check and configure PDSCH transmission modes */ /* Check and configure PDSCH transmission modes */
@ -428,11 +413,12 @@ int srslte_pdsch_cfg_multi(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_r
cfg->codebook_idx = pmi + 1; cfg->codebook_idx = pmi + 1;
cfg->nof_layers = 2; cfg->nof_layers = 2;
} }
INFO("PDSCH configured for Spatial Multiplex; nof_codewords=%d; nof_layers=%d; codebook_idx=%d;\n", grant->nof_tb, cfg->nof_layers, cfg->codebook_idx); INFO("PDSCH configured for Spatial Multiplex; nof_codewords=%d; nof_layers=%d; codebook_idx=%d;\n",
grant->nof_tb, cfg->nof_layers, cfg->codebook_idx);
break; break;
case SRSLTE_MIMO_TYPE_CDD: case SRSLTE_MIMO_TYPE_CDD:
if (grant->nof_tb != 2) { if (grant->nof_tb != 2) {
ERROR("Number of transport blocks is not supported for CDD transmission mode."); ERROR("Number of transport blocks (%d) is not supported for CDD transmission mode.", grant->nof_tb);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
cfg->nof_layers = 2; cfg->nof_layers = 2;
@ -472,13 +458,14 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_
srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data, srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data,
uint32_t codeword_idx) { uint32_t codeword_idx) {
srslte_sch_t *dl_sch = &pdsch->dl_sch[codeword_idx]; srslte_sch_t *dl_sch = &pdsch->dl_sch[codeword_idx];
srslte_ra_nbits_t *nbits = (codeword_idx == 0) ? &cfg->nbits : &cfg->nbits2; srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
srslte_ra_mcs_t *mcs = (codeword_idx == 0) ? &cfg->grant.mcs : &cfg->grant.mcs2; srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx];
uint32_t rv = cfg->rv[codeword_idx];
if (nbits->nof_bits) { if (nbits->nof_bits) {
INFO("Encoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", 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, cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs,
nbits->nof_re, nbits->nof_bits, (codeword_idx == 0) ? cfg->rv : cfg->rv2); nbits->nof_re, nbits->nof_bits, rv);
/* Channel coding */ /* Channel coding */
if (srslte_dlsch_encode2(dl_sch, cfg, softbuffer, data, pdsch->e[codeword_idx], codeword_idx)) { if (srslte_dlsch_encode2(dl_sch, cfg, softbuffer, data, pdsch->e[codeword_idx], codeword_idx)) {
@ -516,19 +503,20 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_
srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data,
uint32_t codeword_idx) { uint32_t codeword_idx) {
srslte_sch_t *dl_sch = &pdsch->dl_sch[codeword_idx]; srslte_sch_t *dl_sch = &pdsch->dl_sch[codeword_idx];
srslte_ra_nbits_t *nbits = (codeword_idx == 0) ? &cfg->nbits : &cfg->nbits2; srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
srslte_ra_mcs_t *mcs = (codeword_idx == 0) ? &cfg->grant.mcs : &cfg->grant.mcs2; srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx];
uint32_t rv = cfg->rv[codeword_idx];
if (nbits->nof_bits) { if (nbits->nof_bits) {
INFO("Decoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", 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, cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs,
nbits->nof_re, nbits->nof_bits, (codeword_idx == 0) ? cfg->rv : cfg->rv2); nbits->nof_re, nbits->nof_bits, rv);
/* demodulate symbols /* demodulate symbols
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization * thus we don't need tot set it in the LLRs normalization
*/ */
srslte_demod_soft_demodulate_s(mcs->mod, pdsch->d[codeword_idx], pdsch->e[codeword_idx], cfg->nbits.nof_re); srslte_demod_soft_demodulate_s(mcs->mod, pdsch->d[codeword_idx], pdsch->e[codeword_idx], nbits->nof_re);
if (pdsch->users[rnti] && pdsch->users[rnti]->sequence_generated) { if (pdsch->users[rnti] && pdsch->users[rnti]->sequence_generated) {
srslte_scrambling_s_offset(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx], pdsch->e[codeword_idx], srslte_scrambling_s_offset(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx], pdsch->e[codeword_idx],
@ -596,23 +584,22 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
cfg != NULL) cfg != NULL)
{ {
INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: [%d %d], C_prb=%d\n", INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, NofSymbols: %d, C_prb=%d\n",
cfg->sf_idx, rnti, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb);
cfg->nbits.nof_bits, cfg->rv, cfg->rv2, cfg->grant.nof_prb);
for (int j=0;j<q->nof_rx_antennas;j++) { for (int j=0;j<q->nof_rx_antennas;j++) {
/* extract symbols */ /* extract symbols */
int n = srslte_pdsch_get(q, sf_symbols[j], q->symbols[j], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); int n = srslte_pdsch_get(q, sf_symbols[j], q->symbols[j], &cfg->grant, cfg->nbits[0].lstart, cfg->sf_idx);
if (n != cfg->nbits.nof_re) { if (n != cfg->nbits[0].nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits[0].nof_re, n);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
/* extract channel estimates */ /* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {
n = srslte_pdsch_get(q, ce[i][j], q->ce[i][j], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); n = srslte_pdsch_get(q, ce[i][j], q->ce[i][j], &cfg->grant, cfg->nbits[0].lstart, cfg->sf_idx);
if (n != cfg->nbits.nof_re) { if (n != cfg->nbits[0].nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits[0].nof_re, n);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} }
@ -620,21 +607,18 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
INFO("PDSCH Layer demapper and predecode: mimo_type=%d, nof_layers=%d, nof_tb=%d\n", cfg->mimo_type, INFO("PDSCH Layer demapper and predecode: mimo_type=%d, nof_layers=%d, nof_tb=%d\n", cfg->mimo_type,
cfg->nof_layers, cfg->grant.nof_tb); cfg->nof_layers, cfg->grant.nof_tb);
if (q->cell.nof_ports == 1) {
/* no need for layer demapping */
srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d[0], q->nof_rx_antennas, cfg->nbits.nof_re, noise_estimate);
} else {
int nof_symbols [SRSLTE_MAX_CODEWORDS]; int nof_symbols [SRSLTE_MAX_CODEWORDS];
nof_symbols[0] = cfg->nbits.nof_re * cfg->grant.nof_tb / cfg->nof_layers; nof_symbols[0] = cfg->nbits[0].nof_re * cfg->grant.nof_tb / cfg->nof_layers;
nof_symbols[1] = cfg->nbits2.nof_re * cfg->grant.nof_tb / cfg->nof_layers; nof_symbols[1] = cfg->nbits[1].nof_re * cfg->grant.nof_tb / cfg->nof_layers;
if (cfg->nof_layers == cfg->grant.nof_tb) { if (cfg->nof_layers == cfg->grant.nof_tb) {
/* Skip layer demap */
for (i = 0; i < cfg->nof_layers; i++) { for (i = 0; i < cfg->nof_layers; i++) {
x[i] = q->d[i]; x[i] = q->d[i];
} }
srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers,
cfg->codebook_idx, cfg->nbits.nof_re, cfg->mimo_type, noise_estimate); cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate);
} else { } else {
/* number of layers equals number of ports */ /* number of layers equals number of ports */
@ -644,12 +628,11 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
memset(&x[cfg->nof_layers], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - cfg->nof_layers)); memset(&x[cfg->nof_layers], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - cfg->nof_layers));
srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers,
cfg->codebook_idx, cfg->nbits.nof_re, cfg->mimo_type, noise_estimate); cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate);
srslte_layerdemap_type(x, q->d, cfg->nof_layers, cfg->grant.nof_tb, srslte_layerdemap_type(x, q->d, cfg->nof_layers, cfg->grant.nof_tb,
nof_symbols[0], nof_symbols, cfg->mimo_type); nof_symbols[0], nof_symbols, cfg->mimo_type);
} }
}
if (SRSLTE_VERBOSE_ISDEBUG()) { if (SRSLTE_VERBOSE_ISDEBUG()) {
char filename[FILENAME_MAX]; char filename[FILENAME_MAX];
@ -671,7 +654,7 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
} }
} }
DEBUG("SAVED FILE pdsch_symbols.dat: symbols after equalization\n",0); DEBUG("SAVED FILE pdsch_symbols.dat: symbols after equalization\n",0);
srslte_vec_save_file("pdsch_symbols.dat", q->d, cfg->nbits.nof_re*sizeof(cf_t)); srslte_vec_save_file("pdsch_symbols.dat", q->d, cfg->nbits[0].nof_re*sizeof(cf_t));
} }
for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) { for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) {
@ -680,7 +663,7 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
if (SRSLTE_VERBOSE_ISDEBUG()) { if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0); DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0);
srslte_vec_save_file("llr.dat", q->e, cfg->nbits.nof_bits*sizeof(int16_t)); srslte_vec_save_file("llr.dat", q->e, cfg->nbits[0].nof_bits*sizeof(int16_t));
} }
return ret; return ret;
@ -733,20 +716,20 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
} }
} }
if (cfg->grant.mcs.tbs == 0) { if (cfg->grant.mcs[0].tbs == 0) {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
if (cfg->nbits.nof_re > q->max_re) { if (cfg->nbits[0].nof_re > q->max_re) {
fprintf(stderr, fprintf(stderr,
"Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n",
cfg->nbits.nof_re, q->max_re, q->cell.nof_prb); cfg->nbits[0].nof_re, q->max_re, q->cell.nof_prb);
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->sf_idx, srslte_mod_string(cfg->grant.mcs[0].mod), cfg->grant.mcs[0].tbs,
cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv); cfg->nbits[0].nof_re, cfg->nbits[0].nof_bits, cfg->rv[0]);
/* number of layers equals number of ports */ /* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {
@ -761,30 +744,30 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
/* scramble */ /* scramble */
if (q->users[rnti] && q->users[rnti]->sequence_generated) { if (q->users[rnti] && q->users[rnti]->sequence_generated) {
srslte_scrambling_bytes(&q->users[rnti]->seq[0][cfg->sf_idx], (uint8_t*) q->e[0], cfg->nbits.nof_bits); srslte_scrambling_bytes(&q->users[rnti]->seq[0][cfg->sf_idx], (uint8_t*) q->e[0], cfg->nbits[0].nof_bits);
} else { } else {
srslte_sequence_t seq; srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits[0].nof_bits)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_scrambling_bytes(&seq, (uint8_t*) q->e[0], cfg->nbits.nof_bits); srslte_scrambling_bytes(&seq, (uint8_t*) q->e[0], cfg->nbits[0].nof_bits);
srslte_sequence_free(&seq); srslte_sequence_free(&seq);
} }
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e[0], q->d[0], cfg->nbits.nof_bits); srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs[0].mod], (uint8_t*) q->e[0], q->d[0], cfg->nbits[0].nof_bits);
/* TODO: only diversity supported */ /* TODO: only diversity supported */
if (q->cell.nof_ports > 1) { if (q->cell.nof_ports > 1) {
srslte_layermap_diversity(q->d[0], x, q->cell.nof_ports, cfg->nbits.nof_re); srslte_layermap_diversity(q->d[0], x, q->cell.nof_ports, cfg->nbits[0].nof_re);
srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports, srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports,
cfg->nbits.nof_re / q->cell.nof_ports); cfg->nbits[0].nof_re / q->cell.nof_ports);
} else { } else {
memcpy(q->symbols[0], q->d, cfg->nbits.nof_re * sizeof(cf_t)); memcpy(q->symbols[0], q->d, cfg->nbits[0].nof_re * sizeof(cf_t));
} }
/* mapping to resource elements */ /* mapping to resource elements */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {
srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->nbits[0].lstart, cfg->sf_idx);
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -810,15 +793,15 @@ int srslte_pdsch_encode_multi(srslte_pdsch_t *q,
} }
} }
/* If both transport block sizes are zero return error */ /* If both transport block size is zero return error */
if (cfg->grant.mcs.tbs == 0 && cfg->grant.mcs2.tbs == 0) { if (cfg->grant.mcs[0].tbs == 0) {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
if (cfg->nbits.nof_re > q->max_re) { if (cfg->nbits[0].nof_re > q->max_re) {
fprintf(stderr, fprintf(stderr,
"Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n",
cfg->nbits.nof_re, q->max_re, q->cell.nof_prb); cfg->nbits[0].nof_re, q->max_re, q->cell.nof_prb);
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
@ -833,7 +816,7 @@ int srslte_pdsch_encode_multi(srslte_pdsch_t *q,
for (i = 0; i < cfg->nof_layers; i++) { for (i = 0; i < cfg->nof_layers; i++) {
x[i] = q->d[i]; x[i] = q->d[i];
} }
nof_symbols = cfg->nbits.nof_re; nof_symbols = cfg->nbits[0].nof_re;
} else { } else {
/* Initialise layer map pointers */ /* Initialise layer map pointers */
for (i = 0; i < cfg->nof_layers; i++) { for (i = 0; i < cfg->nof_layers; i++) {
@ -842,20 +825,21 @@ int srslte_pdsch_encode_multi(srslte_pdsch_t *q,
memset(&x[cfg->nof_layers], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - cfg->nof_layers)); memset(&x[cfg->nof_layers], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - cfg->nof_layers));
nof_symbols = srslte_layermap_type(q->d, x, cfg->grant.nof_tb, cfg->nof_layers, nof_symbols = srslte_layermap_type(q->d, x, cfg->grant.nof_tb, cfg->nof_layers,
(int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits.nof_re, cfg->nbits2.nof_re}, cfg->mimo_type); (int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits[0].nof_re, cfg->nbits[1].nof_re},
cfg->mimo_type);
} }
/* Precode */ /* Precode */
srslte_precoding_type(x, q->symbols, cfg->nof_layers, q->cell.nof_ports, cfg->codebook_idx, srslte_precoding_type(x, q->symbols, cfg->nof_layers, q->cell.nof_ports, cfg->codebook_idx,
nof_symbols, cfg->mimo_type); nof_symbols, cfg->mimo_type);
} else { } else {
memcpy(q->symbols[0], q->d[0], cfg->nbits.nof_re * sizeof(cf_t)); memcpy(q->symbols[0], q->d[0], cfg->nbits[0].nof_re * sizeof(cf_t));
} }
/* mapping to resource elements */ /* mapping to resource elements */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {
srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->nbits[0].lstart, cfg->sf_idx);
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -863,7 +847,7 @@ int srslte_pdsch_encode_multi(srslte_pdsch_t *q,
return ret; return ret;
} }
void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, int max_iter) { void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, uint32_t max_iter) {
for (int cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) { for (int cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) {
srslte_sch_set_max_noi(&q->dl_sch[cw], max_iter); srslte_sch_set_max_noi(&q->dl_sch[cw], max_iter);
} }

@ -492,44 +492,43 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
fprintf(stderr, "Error decoding DCI: P/SI/RA-RNTI supports Format1A/1C only\n"); fprintf(stderr, "Error decoding DCI: P/SI/RA-RNTI supports Format1A/1C only\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
grant->mcs.mod = SRSLTE_MOD_QPSK; grant->mcs[0].mod = SRSLTE_MOD_QPSK;
grant->mcs.tbs = (uint32_t) tbs; grant->mcs[0].tbs = (uint32_t) tbs;
} else { } else {
n_prb = grant->nof_prb; n_prb = grant->nof_prb;
if (dci->tb_en[0]) { if (dci->tb_en[0]) {
grant->mcs.idx = dci->mcs_idx; grant->mcs[0].idx = dci->mcs_idx;
tbs = dl_fill_ra_mcs(&grant->mcs, n_prb); tbs = dl_fill_ra_mcs(&grant->mcs[0], n_prb);
if (tbs) { if (tbs) {
last_dl_tbs[dci->harq_process%8] = tbs; last_dl_tbs[dci->harq_process%8] = tbs;
} else { } else {
// For mcs>=29, set last TBS received for this PID // For mcs>=29, set last TBS received for this PID
grant->mcs.tbs = last_dl_tbs[dci->harq_process%8]; grant->mcs[0].tbs = last_dl_tbs[dci->harq_process%8];
} }
} else { } else {
grant->mcs.tbs = 0; grant->mcs[0].tbs = 0;
} }
if (dci->tb_en[1]) { if (dci->tb_en[1]) {
grant->mcs2.idx = dci->mcs_idx_1; grant->mcs[1].idx = dci->mcs_idx_1;
tbs = dl_fill_ra_mcs(&grant->mcs2, n_prb); tbs = dl_fill_ra_mcs(&grant->mcs[1], n_prb);
if (tbs) { if (tbs) {
last_dl_tbs2[dci->harq_process%8] = tbs; last_dl_tbs2[dci->harq_process%8] = tbs;
} else { } else {
// For mcs>=29, set last TBS received for this PID // For mcs>=29, set last TBS received for this PID
grant->mcs2.tbs = last_dl_tbs2[dci->harq_process%8]; grant->mcs[1].tbs = last_dl_tbs2[dci->harq_process%8];
} }
} else { } else {
grant->mcs2.tbs = 0; grant->mcs[1].tbs = 0;
} }
} }
grant->nof_tb = 0; grant->nof_tb = 0;
if (dci->tb_en[0]) { for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod); if (dci->tb_en[tb]) {
grant->Qm[tb] = srslte_mod_bits_x_symbol(grant->mcs[tb].mod);
grant->nof_tb++; grant->nof_tb++;
} }
if (dci->tb_en[1]) {
grant->Qm2 = srslte_mod_bits_x_symbol(grant->mcs2.mod);
grant->nof_tb++;
} }
if (tbs < 0) { if (tbs < 0) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} else { } else {
@ -537,29 +536,16 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
} }
} }
void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srslte_cell_t cell, uint32_t sf_idx, srslte_ra_nbits_t *nbits) void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srslte_cell_t cell, uint32_t sf_idx,
srslte_ra_nbits_t nbits [SRSLTE_MAX_CODEWORDS])
{ {
// Compute number of RE // Compute number of RE
nbits->nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb<10?(cfi+1):cfi); for (int i = 0; i < grant->nof_tb; i++) {
nbits->lstart = cell.nof_prb<10?(cfi+1):cfi;
nbits->nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-nbits->lstart;
nbits->nof_bits = nbits->nof_re * grant->Qm;
}
void srslte_ra_dl_grant_to_nbits_multi(srslte_ra_dl_grant_t *grant, uint32_t cfi, srslte_cell_t cell, uint32_t sf_idx,
srslte_ra_nbits_t *nbits, srslte_ra_nbits_t *nbits2) {
/* Compute number of RE for first transport block */ /* Compute number of RE for first transport block */
nbits->nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb<10?(cfi+1):cfi); nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi);
nbits->lstart = cell.nof_prb<10?(cfi+1):cfi; nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi;
nbits->nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-nbits->lstart; nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart;
nbits->nof_bits = nbits->nof_re * grant->Qm; nbits[i].nof_bits = nbits[i].nof_re * grant->Qm[i];
/*/ Compute number of RE for second transport block */
if (grant->nof_tb > 1) {
nbits2->nof_re = nbits->nof_re;
nbits2->lstart = nbits->lstart;
nbits2->nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits2->lstart;
nbits2->nof_bits = nbits2->nof_re * grant->Qm2;
} }
} }
@ -834,10 +820,11 @@ void srslte_ra_dl_grant_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
srslte_ra_prb_fprint(f, grant); srslte_ra_prb_fprint(f, grant);
fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->nof_prb); fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->nof_prb);
fprintf(f, " - Number of TBs:\t\t\t%d\n", grant->nof_tb); fprintf(f, " - Number of TBs:\t\t\t%d\n", grant->nof_tb);
fprintf(f, " - Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs.mod)); for (int i = 0; i < grant->nof_tb; i++) {
fprintf(f, " - Transport block size:\t\t%d\n", grant->mcs.tbs); fprintf(f, " - Transport block:\t\t\t%d\n", i);
fprintf(f, " - Modulation type (TB2):\t\t%s\n", srslte_mod_string(grant->mcs2.mod)); fprintf(f, " -> Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs[i].mod));
fprintf(f, " - Transport block size (TB2):\t\t%d\n", grant->mcs2.tbs); fprintf(f, " -> Transport block size:\t\t%d\n", grant->mcs[i].tbs);
}
} }
void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) { void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {

@ -515,38 +515,22 @@ static int decode_tb(srslte_sch_t *q,
} }
int srslte_dlsch_decode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, int srslte_dlsch_decode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
int16_t *e_bits, uint8_t *data) int16_t *e_bits, uint8_t *data) {
{ return srslte_dlsch_decode2(q, cfg, softbuffer, e_bits, data, 0);
return decode_tb(q,
softbuffer, &cfg->cb_segm,
cfg->grant.Qm, cfg->rv, cfg->nbits.nof_bits,
e_bits, data);
} }
int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, 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 codeword_idx) {
{
uint32_t Nl = 1; uint32_t Nl = 1;
int ret = SRSLTE_ERROR;
if (cfg->nof_layers != cfg->grant.nof_tb) { if (cfg->nof_layers != cfg->grant.nof_tb) {
Nl = 2; Nl = 2;
} }
if (codeword_idx == 0) { return decode_tb(q, softbuffer, &cfg->cb_segm[codeword_idx],
ret = decode_tb(q, softbuffer, &cfg->cb_segm, cfg->grant.Qm[codeword_idx] * Nl, cfg->rv[codeword_idx], cfg->nbits[codeword_idx].nof_bits,
cfg->grant.Qm*Nl, cfg->rv, cfg->nbits.nof_bits,
e_bits, data);
} else if (codeword_idx == 1) {
ret = decode_tb(q, softbuffer, &cfg->cb_segm2,
cfg->grant.Qm2*Nl, cfg->rv2, cfg->nbits2.nof_bits,
e_bits, data); e_bits, data);
} else {
ERROR("Not implemented");
}
return ret;
} }
/** /**
@ -562,61 +546,19 @@ int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu
int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
uint8_t *data, uint8_t *e_bits) uint8_t *data, uint8_t *e_bits)
{ {
return encode_tb(q, return srslte_dlsch_encode2(q, cfg, softbuffer, data, e_bits, 0);
softbuffer, &cfg->cb_segm,
cfg->grant.Qm, cfg->rv, cfg->nbits.nof_bits,
data, e_bits);
} }
int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, 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 codeword_idx) {
int ret = SRSLTE_ERROR;
uint32_t Nl = 1; uint32_t Nl = 1;
if (cfg->nof_layers != cfg->grant.nof_tb) { if (cfg->nof_layers != cfg->grant.nof_tb) {
Nl = 2; Nl = 2;
} }
if(codeword_idx == 0) { return encode_tb(q, softbuffer, &cfg->cb_segm[codeword_idx], cfg->grant.Qm[codeword_idx]*Nl, cfg->rv[codeword_idx],
/* Codeword 1 shall be encoded */ cfg->nbits[codeword_idx].nof_bits, data, e_bits);
ret = encode_tb(q, softbuffer, &cfg->cb_segm, cfg->grant.Qm*Nl, cfg->rv, cfg->nbits.nof_bits, data, e_bits);
} else if(codeword_idx == 1) {
/* Codeword 2 shall be encoded */
ret = encode_tb(q, softbuffer, &cfg->cb_segm2, cfg->grant.Qm2*Nl, cfg->rv2, cfg->nbits2.nof_bits, data, e_bits);
} else {
ERROR("Not implemented");
}
return ret;
}
int srslte_dlsch_encode_multi(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS],
uint8_t *data[SRSLTE_MAX_CODEWORDS], uint8_t *e_bits[SRSLTE_MAX_CODEWORDS])
{
int ret = 0;
uint32_t Nl = 1;
if (cfg->nof_layers != cfg->grant.nof_tb) {
Nl = 2;
}
/* Check if codeword 1 shall be encoded */
if(cfg->nbits.nof_bits) {
ret |= encode_tb(q,
&softbuffers[0], &cfg->cb_segm,
cfg->grant.Qm*Nl, cfg->rv, cfg->nbits.nof_bits,
data[0], e_bits[0]);
}
/* Check if codeword 2 shall be encoded */
if(cfg->nbits2.nof_bits) {
ret |= encode_tb(q,
&softbuffers[1], &cfg->cb_segm2,
cfg->grant.Qm2*Nl, cfg->rv2, cfg->nbits2.nof_bits,
data[1], e_bits[1]);
}
return ret;
} }
/* Compute the interleaving function on-the-fly, because it depends on number of RI bits /* Compute the interleaving function on-the-fly, because it depends on number of RI bits

@ -27,7 +27,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <strings.h>
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#include <srslte/phy/phch/ra.h> #include <srslte/phy/phch/ra.h>
@ -55,11 +54,9 @@ srslte_cell_t cell = {
char mimo_type_str [32] = "single"; char mimo_type_str [32] = "single";
srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA; srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
uint32_t cfi = 2; uint32_t cfi = 2;
uint32_t mcs = 0; uint32_t mcs[SRSLTE_MAX_CODEWORDS] = {0, 0};
uint32_t mcs2 = 0;
uint32_t subframe = 1; uint32_t subframe = 1;
uint32_t rv_idx = 0; int rv_idx[SRSLTE_MAX_CODEWORDS] = {0, 1};
uint32_t rv_idx2 = 1;
uint16_t rnti = 1234; uint16_t rnti = 1234;
uint32_t nof_rx_antennas = 1; uint32_t nof_rx_antennas = 1;
uint32_t pmi = 0; uint32_t pmi = 0;
@ -68,12 +65,12 @@ char *input_file = NULL;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [fmMcsrtRFpnwav] \n", prog); printf("Usage: %s [fmMcsrtRFpnwav] \n", prog);
printf("\t-f read signal from file [Default generate it with pdsch_encode()]\n"); printf("\t-f read signal from file [Default generate it with pdsch_encode()]\n");
printf("\t-m MCS [Default %d]\n", mcs); printf("\t-m MCS [Default %d]\n", mcs[0]);
printf("\t-M MCS2 [Default %d]\n", mcs2); printf("\t-M MCS2 [Default %d]\n", mcs[1]);
printf("\t-c cell id [Default %d]\n", cell.id); printf("\t-c cell id [Default %d]\n", cell.id);
printf("\t-s subframe [Default %d]\n", subframe); printf("\t-s subframe [Default %d]\n", subframe);
printf("\t-r rv_idx [Default %d]\n", rv_idx); printf("\t-r rv_idx [Default %d]\n", rv_idx[0]);
printf("\t-t rv_idx2 [Default %d]\n", rv_idx2); printf("\t-t rv_idx2 [Default %d]\n", rv_idx[1]);
printf("\t-R rnti [Default %d]\n", rnti); printf("\t-R rnti [Default %d]\n", rnti);
printf("\t-F cfi [Default %d]\n", cfi); printf("\t-F cfi [Default %d]\n", cfi);
printf("\t-x Transmission mode [single|diversity|cdd|multiplex] [Default %s]\n", mimo_type_str); printf("\t-x Transmission mode [single|diversity|cdd|multiplex] [Default %s]\n", mimo_type_str);
@ -91,19 +88,19 @@ void parse_args(int argc, char **argv) {
input_file = argv[optind]; input_file = argv[optind];
break; break;
case 'm': case 'm':
mcs = atoi(argv[optind]); mcs[0] = (uint32_t) atoi(argv[optind]);
break; break;
case 'M': case 'M':
mcs2 = (uint32_t) atoi(argv[optind]); mcs[1] = (uint32_t) atoi(argv[optind]);
break; break;
case 's': case 's':
subframe = atoi(argv[optind]); subframe = atoi(argv[optind]);
break; break;
case 'r': case 'r':
rv_idx = atoi(argv[optind]); rv_idx[0] = (uint32_t) atoi(argv[optind]);
break; break;
case 't': case 't':
rv_idx2 = (uint32_t) atoi(argv[optind]); rv_idx[1] = (uint32_t) atoi(argv[optind]);
break; break;
case 'R': case 'R':
rnti = atoi(argv[optind]); rnti = atoi(argv[optind]);
@ -197,16 +194,16 @@ int main(int argc, char **argv) {
dci.type0_alloc.rbg_bitmask = 0xffffffff; dci.type0_alloc.rbg_bitmask = 0xffffffff;
/* If transport block 0 is enabled */ /* If transport block 0 is enabled */
if (mcs != 0 || rv_idx != 1) { if (mcs[0] != 0 || rv_idx[0] != 1) {
dci.mcs_idx = mcs; dci.mcs_idx = mcs[0];
dci.rv_idx = rv_idx; dci.rv_idx = rv_idx[0];
dci.tb_en[0] = true; dci.tb_en[0] = true;
} }
/* If transport block 0 is disabled */ /* If transport block 0 is disabled */
if (mcs2 != 0 || rv_idx2 != 1) { if (mcs[1] != 0 || rv_idx[1] != 1) {
dci.mcs_idx_1 = mcs2; dci.mcs_idx_1 = mcs[1];
dci.rv_idx_1 = rv_idx2; dci.rv_idx_1 = rv_idx[1];
dci.tb_en[1] = true; dci.tb_en[1] = true;
} }
@ -235,7 +232,7 @@ int main(int argc, char **argv) {
#endif /* DO_OFDM */ #endif /* DO_OFDM */
/* Configure PDSCH */ /* Configure PDSCH */
if (srslte_pdsch_cfg_multi(&pdsch_cfg, cell, &grant, cfi, subframe, rv_idx, rv_idx2, mimo_type, pmi)) { if (srslte_pdsch_cfg_multi(&pdsch_cfg, cell, &grant, cfi, subframe, rv_idx, mimo_type, pmi)) {
fprintf(stderr, "Error configuring PDSCH\n"); fprintf(stderr, "Error configuring PDSCH\n");
goto quit; goto quit;
} }
@ -260,22 +257,15 @@ int main(int argc, char **argv) {
} }
if (grant.mcs.tbs) { for (int i = 0; i < grant.nof_tb; i++) {
data[0] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs); if (grant.mcs[i].tbs) {
if (!data[0]) { data[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs);
if (!data[i]) {
perror("srslte_vec_malloc"); perror("srslte_vec_malloc");
goto quit; goto quit;
} }
bzero(data[0], sizeof(uint8_t) * grant.mcs.tbs); bzero(data[i], sizeof(uint8_t) * grant.mcs[i].tbs);
} }
if (grant.mcs2.tbs) {
data[1] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs2.tbs);
if (!data[1]) {
perror("srslte_vec_malloc");
goto quit;
}
bzero(data[1], sizeof(uint8_t) * grant.mcs2.tbs);
} }
if (srslte_pdsch_init_rx_multi(&pdsch_rx, cell, nof_rx_antennas)) { if (srslte_pdsch_init_rx_multi(&pdsch_rx, cell, nof_rx_antennas)) {
@ -292,6 +282,7 @@ int main(int argc, char **argv) {
} }
} }
INFO(" Global:\n");
INFO(" nof_prb=%d\n", cell.nof_prb); INFO(" nof_prb=%d\n", cell.nof_prb);
INFO(" nof_ports=%d\n", cell.nof_ports); INFO(" nof_ports=%d\n", cell.nof_ports);
INFO(" id=%d\n", cell.id); INFO(" id=%d\n", cell.id);
@ -300,28 +291,22 @@ int main(int argc, char **argv) {
INFO(" phich_resources=%d\n", (int) cell.phich_resources); INFO(" phich_resources=%d\n", (int) cell.phich_resources);
INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb); INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb);
INFO(" nof_prb=%d\n", pdsch_cfg.grant.nof_prb); INFO(" nof_prb=%d\n", pdsch_cfg.grant.nof_prb);
INFO(" Qm=%d\n", pdsch_cfg.grant.Qm);
INFO(" Qm2=%d\n", pdsch_cfg.grant.Qm2);
INFO(" mcs.idx=0x%X\n", pdsch_cfg.grant.mcs.idx);
INFO(" mcs.tbs=%d\n", pdsch_cfg.grant.mcs.tbs);
INFO(" mcs.mod=%s\n", srslte_mod_string(pdsch_cfg.grant.mcs.mod));
INFO(" mcs2.idx=0x%X\n", pdsch_cfg.grant.mcs2.idx);
INFO(" mcs2.tbs=%d\n", pdsch_cfg.grant.mcs2.tbs);
INFO(" mcs2.mod=%s\n", srslte_mod_string(pdsch_cfg.grant.mcs2.mod));
INFO(" nof_layers=%d\n", pdsch_cfg.nof_layers);
INFO(" rv=%d\n", pdsch_cfg.rv);
INFO(" rv2=%d\n", pdsch_cfg.rv2);
INFO(" sf_idx=%d\n", pdsch_cfg.sf_idx); INFO(" sf_idx=%d\n", pdsch_cfg.sf_idx);
INFO(" mimo_type=%d\n", (int) pdsch_cfg.mimo_type); INFO(" mimo_type=%s\n", srslte_mimotype2str(pdsch_cfg.mimo_type));
INFO(" nof_layers=%d\n", pdsch_cfg.nof_layers);
INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb); INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb);
INFO(" lstart=%d\n", pdsch_cfg.nbits.lstart); for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
INFO(" nof_bits=%d\n", pdsch_cfg.nbits.nof_bits); INFO(" Tranport block index %d:\n", i);
INFO(" nof_re=%d\n", pdsch_cfg.nbits.nof_re); INFO(" Qm=%d\n", pdsch_cfg.grant.Qm[i]);
INFO(" nof_symb=%d\n", pdsch_cfg.nbits.nof_symb); INFO(" mcs.idx=0x%X\n", pdsch_cfg.grant.mcs[i].idx);
INFO(" lstart=%d\n", pdsch_cfg.nbits2.lstart); INFO(" mcs.tbs=%d\n", pdsch_cfg.grant.mcs[i].tbs);
INFO(" nof_bits=%d\n", pdsch_cfg.nbits2.nof_bits); INFO(" mcs.mod=%s\n", srslte_mod_string(pdsch_cfg.grant.mcs[i].mod));
INFO(" nof_re=%d\n", pdsch_cfg.nbits2.nof_re); INFO(" rv=%d\n", pdsch_cfg.rv[i]);
INFO(" nof_symb=%d\n", pdsch_cfg.nbits2.nof_symb); INFO(" lstart=%d\n", pdsch_cfg.nbits[i].lstart);
INFO(" nof_bits=%d\n", pdsch_cfg.nbits[i].nof_bits);
INFO(" nof_re=%d\n", pdsch_cfg.nbits[i].nof_re);
INFO(" nof_symb=%d\n", pdsch_cfg.nbits[i].nof_symb);
}
if (input_file) { if (input_file) {
srslte_filesource_t fsrc; srslte_filesource_t fsrc;
@ -368,29 +353,25 @@ int main(int argc, char **argv) {
} }
} }
for (i = 0; i < grant.mcs.tbs / 8; i++) { for (i = 0; i< grant.nof_tb; i++) {
data[0][i] = (uint8_t) (rand() % 256); for (i = 0; i < grant.mcs[i].tbs / 8; i++) {
data[i][i] = (uint8_t) (rand() % 256);
} }
for (i = 0; i < grant.mcs2.tbs / 8; i++) {
data[1][i] = (uint8_t) (rand() % 256);
} }
/*uint8_t databit[100000]; /*uint8_t databit[100000];
srslte_bit_unpack_vector(data, databit, grant.mcs.tbs); srslte_bit_unpack_vector(data, databit, grant.mcs.tbs);
srslte_vec_save_file("data_in", databit, grant.mcs.tbs);*/ srslte_vec_save_file("data_in", databit, grant.mcs.tbs);*/
if (rv_idx) { if (rv_idx[0] != 0 || rv_idx[1] != 0) {
/* Do 1st transmission for rv_idx!=0 */ /* Do 1st transmission for rv_idx!=0 */
pdsch_cfg.rv = 0; bzero(pdsch_cfg.rv, sizeof(uint32_t)*SRSLTE_MAX_CODEWORDS);
pdsch_cfg.rv2 = 0;
if (srslte_pdsch_encode_multi(&pdsch_tx, &pdsch_cfg, softbuffers_tx, data, rnti, tx_slot_symbols)) { if (srslte_pdsch_encode_multi(&pdsch_tx, &pdsch_cfg, softbuffers_tx, data, rnti, tx_slot_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n"); fprintf(stderr, "Error encoding PDSCH\n");
goto quit; goto quit;
} }
} }
pdsch_cfg.rv = rv_idx; memcpy(pdsch_cfg.rv, rv_idx, sizeof(uint32_t)*SRSLTE_MAX_CODEWORDS);
pdsch_cfg.rv2 = rv_idx2;
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
for (k = 0; k < M; k++) { for (k = 0; k < M; k++) {
if (srslte_pdsch_encode_multi(&pdsch_tx, &pdsch_cfg, softbuffers_tx, data, rnti, tx_slot_symbols)) { if (srslte_pdsch_encode_multi(&pdsch_tx, &pdsch_cfg, softbuffers_tx, data, rnti, tx_slot_symbols)) {
@ -401,8 +382,8 @@ int main(int argc, char **argv) {
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
printf("ENCODED in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", printf("ENCODED in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n",
(float) t[0].tv_usec/M, (float) (grant.mcs.tbs + grant.mcs2.tbs)/1000.0f, (float) t[0].tv_usec/M, (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)/1000.0f,
(float) (grant.mcs.tbs + grant.mcs2.tbs)*M/t[0].tv_usec); (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)*M/t[0].tv_usec);
#ifdef DO_OFDM #ifdef DO_OFDM
for (i = 0; i < cell.nof_ports; i++) { for (i = 0; i < cell.nof_ports; i++) {
@ -444,19 +425,18 @@ int main(int argc, char **argv) {
srslte_ofdm_rx_sf(&ofdm_rx, tx_sf_symbols[i], rx_slot_symbols[i]); srslte_ofdm_rx_sf(&ofdm_rx, tx_sf_symbols[i], rx_slot_symbols[i]);
} }
#endif #endif
if (grant.mcs.tbs) { for (i = 0; i < grant.nof_tb; i++) {
srslte_softbuffer_rx_reset_tbs(&softbuffers_rx[0], (uint32_t) grant.mcs.tbs); if (grant.mcs[i].tbs) {
srslte_softbuffer_rx_reset_tbs(&softbuffers_rx[i], (uint32_t) grant.mcs[i].tbs);
} }
if (grant.mcs2.tbs) {
srslte_softbuffer_rx_reset_tbs(&softbuffers_rx[1], (uint32_t) grant.mcs2.tbs);
} }
r = srslte_pdsch_decode_multi(&pdsch_rx, &pdsch_cfg, softbuffers_rx, rx_slot_symbols, ce, 0, rnti, data); r = srslte_pdsch_decode_multi(&pdsch_rx, &pdsch_cfg, softbuffers_rx, rx_slot_symbols, ce, 0, rnti, data);
} }
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
printf("DECODED %s in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", r?"Error":"OK", printf("DECODED %s in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", r?"Error":"OK",
(float) t[0].tv_usec/M, (float) (grant.mcs.tbs + grant.mcs2.tbs)/1000.0f, (float) t[0].tv_usec/M, (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)/1000.0f,
(float) (grant.mcs.tbs + grant.mcs2.tbs)*M/t[0].tv_usec); (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)*M/t[0].tv_usec);
if (r) { if (r) {
ret = -1; ret = -1;
goto quit; goto quit;

@ -282,14 +282,16 @@ int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *c
} }
int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, uint32_t rvidx) int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx,
{ int rvidx) {
return srslte_pdsch_cfg_multi(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx, 0, SRSLTE_MIMO_TYPE_SINGLE_ANTENNA, 0); int _rvidx [SRSLTE_MAX_CODEWORDS] = {1};
_rvidx[0] = rvidx;
return srslte_pdsch_cfg_multi(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, _rvidx, SRSLTE_MIMO_TYPE_SINGLE_ANTENNA, 0);
} }
int srslte_ue_dl_cfg_grant_multi(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, int srslte_ue_dl_cfg_grant_multi(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx,
uint32_t rvidx, uint32_t rvidx2, srslte_mimo_type_t mimo_type, uint32_t pinfo) int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type, uint32_t pinfo) {
{
uint32_t pmi = 0; uint32_t pmi = 0;
/* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */ /* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */
@ -310,7 +312,7 @@ int srslte_ue_dl_cfg_grant_multi(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant,
} }
} }
} }
return srslte_pdsch_cfg_multi(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx, rvidx2, mimo_type, pmi); return srslte_pdsch_cfg_multi(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx, mimo_type, pmi);
} }
int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t tti, uint16_t rnti) int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t tti, uint16_t rnti)
@ -357,23 +359,28 @@ int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_POR
/* ===== These lines of code are supposed to be MAC functionality === */ /* ===== These lines of code are supposed to be MAC functionality === */
uint32_t rvidx = 0; int rvidx[SRSLTE_MAX_CODEWORDS] = {1};
uint32_t rvidx2 = 0;
if (dci_unpacked.rv_idx < 0) { if (dci_unpacked.rv_idx < 0) {
uint32_t sfn = tti/10; uint32_t sfn = tti/10;
uint32_t k = (sfn/2)%4; uint32_t k = (sfn/2)%4;
rvidx = ((uint32_t) ceilf((float)1.5*k))%4; for (int i = 0; i < grant.nof_tb; i++) {
srslte_softbuffer_rx_reset_tbs(&q->softbuffers[0], (uint32_t) grant.mcs.tbs); rvidx[i] = ((uint32_t) ceilf((float) 1.5 * k)) % 4;
if (grant.nof_tb > 1) { srslte_softbuffer_rx_reset_tbs(&q->softbuffers[i], (uint32_t) grant.mcs[i].tbs);
rvidx2 = ((uint32_t) ceilf((float)1.5*k))%4;
srslte_softbuffer_rx_reset_tbs(&q->softbuffers[1], (uint32_t) grant.mcs2.tbs);
} }
} else { } else {
rvidx = (uint32_t) dci_unpacked.rv_idx; for (int i = 0; i < grant.nof_tb; i++) {
srslte_softbuffer_rx_reset_tbs(&q->softbuffers[0], (uint32_t) grant.mcs.tbs); switch(i) {
if (grant.nof_tb > 1) { case 0:
rvidx2 = (uint32_t) dci_unpacked.rv_idx_1; rvidx[i] = (uint32_t) dci_unpacked.rv_idx;
srslte_softbuffer_rx_reset_tbs(&q->softbuffers[1], (uint32_t) grant.mcs2.tbs); break;
case 1:
rvidx[i] = (uint32_t) dci_unpacked.rv_idx_1;
break;
default:
ERROR("Wrong number of transport blocks");
return SRSLTE_ERROR;
}
srslte_softbuffer_rx_reset_tbs(&q->softbuffers[i], (uint32_t) grant.mcs[i].tbs);
} }
} }
@ -408,7 +415,7 @@ int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_POR
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (srslte_ue_dl_cfg_grant_multi(q, &grant, cfi, sf_idx, rvidx, rvidx2, mimo_type, dci_unpacked.pinfo)) { if (srslte_ue_dl_cfg_grant_multi(q, &grant, cfi, sf_idx, rvidx, mimo_type, dci_unpacked.pinfo)) {
ERROR("Configuing PDSCH"); ERROR("Configuing PDSCH");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -418,7 +425,7 @@ int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_POR
q->nof_detected++; q->nof_detected++;
if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) { if (q->pdsch_cfg.grant.mcs[0].mod > 0 && q->pdsch_cfg.grant.mcs[0].tbs >= 0) {
ret = srslte_pdsch_decode_multi(&q->pdsch, &q->pdsch_cfg, q->softbuffers, ret = srslte_pdsch_decode_multi(&q->pdsch, &q->pdsch_cfg, q->softbuffers,
q->sf_symbols_m, q->ce_m, q->sf_symbols_m, q->ce_m,
noise_estimate, noise_estimate,
@ -446,7 +453,7 @@ int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_POR
q->pkts_total++; q->pkts_total++;
if (found_dci == 1 && ret == SRSLTE_SUCCESS) { if (found_dci == 1 && ret == SRSLTE_SUCCESS) {
return q->pdsch_cfg.grant.mcs.tbs; return q->pdsch_cfg.grant.mcs[0].tbs;
} else { } else {
return 0; return 0;
} }
@ -723,16 +730,16 @@ void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuf
srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce*72*sizeof(float)); srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce*72*sizeof(float));
srslte_vec_save_file("pdsch_symbols", q->pdsch.d, q->pdsch_cfg.nbits.nof_re*sizeof(cf_t)); srslte_vec_save_file("pdsch_symbols", q->pdsch.d, q->pdsch_cfg.nbits[0].nof_re*sizeof(cf_t));
srslte_vec_save_file("llr", q->pdsch.e, q->pdsch_cfg.nbits.nof_bits*sizeof(cf_t)); srslte_vec_save_file("llr", q->pdsch.e, q->pdsch_cfg.nbits[0].nof_bits*sizeof(cf_t));
int cb_len = q->pdsch_cfg.cb_segm.K1; int cb_len = q->pdsch_cfg.cb_segm[0].K1;
for (int i=0;i<q->pdsch_cfg.cb_segm.C;i++) { for (int i=0;i<q->pdsch_cfg.cb_segm[0].C;i++) {
char tmpstr[64]; char tmpstr[64];
snprintf(tmpstr,64,"rmout_%d.dat",i); snprintf(tmpstr,64,"rmout_%d.dat",i);
srslte_vec_save_file(tmpstr, softbuffer->buffer_f[i], (3*cb_len+12)*sizeof(int16_t)); srslte_vec_save_file(tmpstr, softbuffer->buffer_f[i], (3*cb_len+12)*sizeof(int16_t));
} }
printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, rv=%d, rnti=0x%x\n", tti, tti%10, cfi, printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, rv=%d, rnti=0x%x\n", tti, tti%10, cfi,
q->pdsch_cfg.grant.mcs.idx, rv_idx, rnti); q->pdsch_cfg.grant.mcs[0].idx, rv_idx, rnti);
} }

@ -632,7 +632,7 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
if (LOG_THIS(rnti)) { if (LOG_THIS(rnti)) {
uint8_t x = 0; uint8_t x = 0;
uint8_t *ptr = grants[i].data; uint8_t *ptr = grants[i].data;
uint32_t len = phy_grant.mcs.tbs/8; uint32_t len = phy_grant.mcs[0].tbs / (uint32_t) 8;
if (!ptr) { if (!ptr) {
ptr = &x; ptr = &x;
len = 1; len = 1;
@ -640,7 +640,7 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
log_h->info_hex(ptr, len, log_h->info_hex(ptr, len,
"PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n", "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n",
rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process,
phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx, tti_tx); phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx);
} }
if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffer, rnti, grants[i].grant.rv_idx, sf_idx, if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffer, rnti, grants[i].grant.rv_idx, sf_idx,
grants[i].data)) grants[i].data))
@ -650,7 +650,7 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
} }
// Save metrics stats // Save metrics stats
ue_db[rnti].metrics_dl(phy_grant.mcs.idx); ue_db[rnti].metrics_dl(phy_grant.mcs[0].idx);
} }
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;

@ -77,8 +77,19 @@ private:
bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant); bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant);
bool decode_pdcch_dl(mac_interface_phy::mac_grant_t *grant); bool decode_pdcch_dl(mac_interface_phy::mac_grant_t *grant);
bool decode_phich(bool *ack); bool decode_phich(bool *ack);
bool decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload, srslte_softbuffer_rx_t* softbuffer, int rv, uint16_t rnti, uint32_t pid);
bool decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSLTE_MAX_CODEWORDS], srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS], int rv, uint16_t rnti, uint32_t pid); bool decode_pdsch(srslte_ra_dl_grant_t *grant,
uint8_t *payload, srslte_softbuffer_rx_t *softbuffer,
int rv,
uint16_t rnti,
uint32_t pid);
bool decode_pdsch_multi(srslte_ra_dl_grant_t *grant,
uint8_t *payload[SRSLTE_MAX_CODEWORDS],
srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS],
int rv[SRSLTE_MAX_CODEWORDS],
uint16_t rnti,
uint32_t pid);
/* ... for UL */ /* ... for UL */
void encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, uint32_t current_tx_nb, srslte_softbuffer_tx_t *softbuffer, void encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, uint32_t current_tx_nb, srslte_softbuffer_tx_t *softbuffer,

@ -382,7 +382,7 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
/* Fill MAC grant structure */ /* Fill MAC grant structure */
grant->ndi = dci_unpacked.ndi; grant->ndi = dci_unpacked.ndi;
grant->pid = dci_unpacked.harq_process; grant->pid = dci_unpacked.harq_process;
grant->n_bytes = grant->phy_grant.dl.mcs.tbs/8; grant->n_bytes = grant->phy_grant.dl.mcs[0].tbs/8;
grant->tti = tti; grant->tti = tti;
grant->rv = dci_unpacked.rv_idx; grant->rv = dci_unpacked.rv_idx;
grant->rnti = dl_rnti; grant->rnti = dl_rnti;
@ -406,23 +406,70 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
} }
bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload, bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload,
srslte_softbuffer_rx_t* softbuffer, int rv, uint16_t rnti, uint32_t harq_pid) srslte_softbuffer_rx_t *softbuffer, int rv,
{ uint16_t rnti, uint32_t harq_pid) {
return decode_pdsch_multi(grant, &payload, softbuffer, rv, rnti, harq_pid); int _rv [SRSLTE_MAX_CODEWORDS] = {1};
_rv[0] = rv;
return decode_pdsch_multi(grant, &payload, softbuffer, _rv, rnti, harq_pid);
} }
bool phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSLTE_MAX_CODEWORDS], bool phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSLTE_MAX_CODEWORDS],
srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS], int rv, uint16_t rnti, uint32_t harq_pid) srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS],
{ int rv[SRSLTE_MAX_CODEWORDS],
uint16_t rnti, uint32_t harq_pid) {
char timestr[64]; char timestr[64];
bool valid_config = true;
timestr[0]='\0'; timestr[0]='\0';
srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
for (uint32_t tb = 0; tb < grant->nof_tb; tb++) {
if (rv[tb] < 0 || rv[tb] > 3) {
valid_config = false;
Error("Wrong RV (%d) for TB index %d", rv[tb], tb);
}
}
switch(phy->config->dedicated.antenna_info_explicit_value.tx_mode) {
case LIBLTE_RRC_TRANSMISSION_MODE_1:
mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
break;
case LIBLTE_RRC_TRANSMISSION_MODE_2:
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
break;
case LIBLTE_RRC_TRANSMISSION_MODE_3:
if (grant->nof_tb == 1) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else if (grant->nof_tb == 2) {
mimo_type = SRSLTE_MIMO_TYPE_CDD;
} else {
Error("Wrong number of transport blocks (%d) for TM3\n", grant->nof_tb);
valid_config = false;
}
break;
/* Not implemented cases */
case LIBLTE_RRC_TRANSMISSION_MODE_4:
case LIBLTE_RRC_TRANSMISSION_MODE_5:
case LIBLTE_RRC_TRANSMISSION_MODE_6:
case LIBLTE_RRC_TRANSMISSION_MODE_7:
case LIBLTE_RRC_TRANSMISSION_MODE_8:
Error("Not implemented Tx mode (%d)\n", phy->config->dedicated.antenna_info_explicit_value.tx_mode);
break;
/* Error cases */
case LIBLTE_RRC_TRANSMISSION_MODE_N_ITEMS:
default:
Error("Wrong Tx mode (%d)\n", phy->config->dedicated.antenna_info_explicit_value.tx_mode);
valid_config = false;
}
Debug("DL Buffer TTI %d: Decoding PDSCH\n", tti); Debug("DL Buffer TTI %d: Decoding PDSCH\n", tti);
/* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */ /* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */
if (rv >= 0 && rv <= 3) { if (valid_config) {
if (!srslte_ue_dl_cfg_grant(&ue_dl, grant, cfi, tti%10, rv)) { if (!srslte_ue_dl_cfg_grant_multi(&ue_dl, grant, cfi, tti%10, rv, mimo_type, 0)) {
if (ue_dl.pdsch_cfg.grant.mcs.mod > 0 && ue_dl.pdsch_cfg.grant.mcs.tbs >= 0) { if (ue_dl.pdsch_cfg.grant.mcs[0].mod > 0 && ue_dl.pdsch_cfg.grant.mcs[0].tbs >= 0) {
float noise_estimate = srslte_chest_dl_get_noise_estimate(&ue_dl.chest); float noise_estimate = srslte_chest_dl_get_noise_estimate(&ue_dl.chest);
@ -451,7 +498,7 @@ bool phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *paylo
Info("PDSCH: l_crb=%2d, harq=%d, tbs=%d, mcs=%d, rv=%d, crc=%s, snr=%.1f dB, n_iter=%d%s\n", Info("PDSCH: l_crb=%2d, harq=%d, tbs=%d, mcs=%d, rv=%d, crc=%s, snr=%.1f dB, n_iter=%d%s\n",
grant->nof_prb, harq_pid, grant->nof_prb, harq_pid,
grant->mcs.tbs/8, grant->mcs.idx, rv, grant->mcs[0].tbs/8, grant->mcs[0].idx, rv,
ack?"OK":"KO", ack?"OK":"KO",
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)),
srslte_pdsch_last_noi(&ue_dl.pdsch), srslte_pdsch_last_noi(&ue_dl.pdsch),
@ -461,7 +508,7 @@ bool phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *paylo
//srslte_vec_save_file("pdsch", signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb)); //srslte_vec_save_file("pdsch", signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
// Store metrics // Store metrics
dl_metrics.mcs = grant->mcs.idx; dl_metrics.mcs = grant->mcs[0].idx;
return ack; return ack;
} else { } else {
@ -470,8 +517,6 @@ bool phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *paylo
} else { } else {
Error("Error configuring DL grant\n"); Error("Error configuring DL grant\n");
} }
} else {
Error("Error RV is not set or is invalid (%d)\n", rv);
} }
return true; return true;
} }
@ -973,8 +1018,9 @@ int phch_worker::read_ce_abs(float *ce_abs) {
int phch_worker::read_pdsch_d(cf_t* pdsch_d) int phch_worker::read_pdsch_d(cf_t* pdsch_d)
{ {
memcpy(pdsch_d, ue_dl.pdsch.d, ue_dl.pdsch_cfg.nbits.nof_re*sizeof(cf_t));
return ue_dl.pdsch_cfg.nbits.nof_re; memcpy(pdsch_d, ue_dl.pdsch.d, ue_dl.pdsch_cfg.nbits[0].nof_re*sizeof(cf_t));
return ue_dl.pdsch_cfg.nbits[0].nof_re;
} }

Loading…
Cancel
Save