Scalable PDSCH with MAX_CODEWORDS PDSCH plus decoding threads for bitrate increase

This commit is contained in:
Xavier Arteaga 2017-08-17 10:23:03 +02:00
parent 48d508aeba
commit 94325d13d2
14 changed files with 492 additions and 238 deletions

View File

@ -320,7 +320,7 @@ int main(int argc, char **argv) {
} else if (n == 0) {
printf("CFO: %+6.4f kHz, SFO: %+6.4f kHz, NOI: %.2f, PDCCH-Det: %.3f\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000,
srslte_sch_average_noi(&ue_dl.pdsch.dl_sch),
srslte_pdsch_average_noi(&ue_dl.pdsch),
(float) ue_dl.nof_detected/nof_trials);
nof_trials++;
} else {

View File

@ -846,7 +846,7 @@ void *plot_thread_run(void *arg) {
plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce);
}
plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d, nof_symbols);
plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d[0], nof_symbols);
if (plot_sf_idx == 1) {
if (prog_args.net_port_signal > 0) {

View File

@ -35,6 +35,13 @@
#ifndef PDSCH_
#define PDSCH_
#ifndef SRSLTE_SINGLE_THREAD
#include <pthread.h>
#include <semaphore.h>
#endif /* SRSLTE_SINGLE_THREAD */
#include "srslte/config.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/mimo/precoding.h"
@ -48,11 +55,38 @@
#include "srslte/phy/phch/pdsch_cfg.h"
typedef struct {
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq2[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq[SRSLTE_MAX_CODEWORDS][SRSLTE_NSUBFRAMES_X_FRAME];
bool sequence_generated;
} srslte_pdsch_user_t;
#ifndef SRSLTE_SINGLE_THREAD
typedef struct {
/* Thread identifier: they must set before thread creation */
uint32_t codeword_idx;
void *pdsch_ptr;
/* Configuration Encoder/Decoder: they must be set before posting start semaphore */
srslte_pdsch_cfg_t *cfg;
uint16_t rnti;
/* Encoder/Decoder data pointers: they must be set before posting start semaphore */
uint8_t *data;
void *softbuffer;
/* Execution status */
int ret_status;
/* Semaphores */
sem_t start;
sem_t finish;
/* Thread kill flag */
bool quit;
} srslte_pdsch_thread_args_t;
#endif /* SRSLTE_SINGLE_THREAD */
/* PDSCH object */
typedef struct SRSLTE_API {
srslte_cell_t cell;
@ -66,10 +100,8 @@ typedef struct SRSLTE_API {
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */
cf_t *symbols[SRSLTE_MAX_PORTS]; /* PDSCH Encoded/Decoded Symbols */
cf_t *x[SRSLTE_MAX_LAYERS]; /* Layer mapped */
cf_t *d; /* Modulated/Demodulated codeword 1 */
cf_t *d2; /* Modulated/Demodulated codeword 2 */
void *e;
void *e2;
cf_t *d[SRSLTE_MAX_CODEWORDS]; /* Modulated/Demodulated codewords */
void *e[SRSLTE_MAX_CODEWORDS];
/* tx & rx objects */
srslte_modem_table_t mod[4];
@ -77,7 +109,14 @@ typedef struct SRSLTE_API {
// This is to generate the scrambling seq for multiple CRNTIs
srslte_pdsch_user_t **users;
srslte_sch_t dl_sch;
srslte_sch_t dl_sch[SRSLTE_MAX_CODEWORDS];
#ifndef SRSLTE_SINGLE_THREAD
pthread_t threads[SRSLTE_MAX_CODEWORDS];
srslte_pdsch_thread_args_t thread_args[SRSLTE_MAX_CODEWORDS];
#endif /* SRSLTE_SINGLE_THREAD */
} srslte_pdsch_t;
@ -151,6 +190,17 @@ SRSLTE_API int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
uint16_t rnti,
uint8_t *data[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API int srslte_pdsch_ri_pmi_select(srslte_pdsch_t *q,
srslte_pdsch_cfg_t *cfg,
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate,
uint32_t nof_ce,
uint32_t *ri,
uint32_t *pmi,
float *current_sinr);
SRSLTE_API void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, int max_iter);
SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q);
SRSLTE_API uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q);

View File

@ -223,6 +223,13 @@ SRSLTE_API void srslte_ra_dl_grant_to_nbits_multi(srslte_ra_dl_grant_t *grant,
srslte_ra_nbits_t *nbits,
srslte_ra_nbits_t *nbits2);
SRSLTE_API 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);
SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell,
uint32_t nof_prb,
uint32_t nof_ctrl_symbols);

View File

@ -96,6 +96,13 @@ SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q,
uint8_t *data,
uint8_t *e_bits);
SRSLTE_API 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);
SRSLTE_API int srslte_dlsch_encode_multi(srslte_sch_t *q,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS],

View File

@ -197,6 +197,11 @@ SRSLTE_API int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t * q,
uint32_t tti,
uint16_t rnti);
SRSLTE_API int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q,
uint32_t *ri,
uint32_t *pmi,
float *current_sinr);
SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q,
uint32_t sf_idx,
uint32_t n_prb_lowest,

View File

@ -63,6 +63,11 @@ SRSLTE_API extern int srslte_verbose;
#define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO) \
fprintf(stdout, "[INFO]: " _fmt, __VA_ARGS__)
#define ERROR(_fmt) fprintf(stderr, "%s.%d: " _fmt "\n", __FILE__, __LINE__)
#if CMAKE_BUILD_TYPE==Debug
/* In debug mode, it prints out the */
#define ERROR(_fmt, ...) fprintf(stderr, "%s.%d: " _fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#else
#define ERROR(_fmt, ...) fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__)
#endif /* CMAKE_BUILD_TYPE==Debug */
#endif // DEBUG_H

View File

@ -32,9 +32,13 @@
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include <srslte/phy/phch/pdsch.h>
#include <srslte/phy/phch/ra.h>
#include <srslte/phy/phch/pdsch_cfg.h>
#ifndef SRSLTE_SINGLE_THREAD
#include <pthread.h>
#include <semaphore.h>
#endif /* SRSLTE_SINGLE_THREAD */
#include "prb_dl.h"
#include "srslte/phy/phch/pdsch.h"
@ -60,6 +64,13 @@ extern int indices[100000];
extern int indices_ptr;
#endif
#ifndef SRSLTE_SINGLE_THREAD
static void *srslte_pdsch_encode_thread (void *arg);
static void *srslte_pdsch_decode_thread (void *arg);
#endif /* SRSLTE_SINGLE_THREAD */
float srslte_pdsch_coderate(uint32_t tbs, uint32_t nof_re)
{
return (float) (tbs + 24)/(nof_re);
@ -235,27 +246,37 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_
srslte_modem_table_bytes(&q->mod[i]);
}
srslte_sch_init(&q->dl_sch);
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (srslte_sch_init(&q->dl_sch[i])) {
ERROR("Initiating DL SCH");
goto clean;
}
// Allocate int16_t for reception (LLRs)
q->e = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM));
if (!q->e) {
goto clean;
}
// Allocate int16_t for reception (LLRs)
q->e[i] = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM));
if (!q->e[i]) {
goto clean;
}
q->e2 = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM));
if (!q->e) {
goto clean;
}
q->d[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->d[i]) {
goto clean;
}
q->d = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->d) {
goto clean;
}
q->d2 = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->d) {
goto clean;
#ifndef SRSLTE_SINGLE_THREAD
if (sem_init(&q->thread_args[i].start, 0, 0)) {
ERROR("Creating semaphore");
goto clean;
}
if (sem_init(&q->thread_args[i].finish, 0, 0)) {
ERROR("Creating semaphore");
goto clean;
}
q->thread_args[i].codeword_idx = (uint32_t) i;
q->thread_args[i].pdsch_ptr = q;
pthread_create(&q->threads[i], NULL, (is_receiver) ? srslte_pdsch_decode_thread : srslte_pdsch_encode_thread,
(void *) &q->thread_args[i]);
#endif /* SRSLTE_SINGLE_THREAD */
}
/* Layer mapped symbols memory allocation */
@ -290,9 +311,10 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_
perror("malloc");
goto clean;
}
}
ret = SRSLTE_SUCCESS;
ret = SRSLTE_SUCCESS;
}
clean:
if (ret == SRSLTE_ERROR) {
srslte_pdsch_free(q);
@ -315,18 +337,31 @@ int srslte_pdsch_init_rx_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t n
void srslte_pdsch_free(srslte_pdsch_t *q) {
int i;
if (q->e) {
free(q->e);
}
if (q->e2) {
free(q->e2);
}
if (q->d) {
free(q->d);
}
if (q->d2) {
free(q->d2);
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
#ifndef SRSLTE_SINGLE_THREAD
/* Stop threads */
q->thread_args[i].quit = true;
sem_post(&q->thread_args[i].start);
pthread_join(q->threads[i], NULL);
pthread_detach(q->threads[i]);
#endif /* SRSLTE_SINGLE_THREAD */
if (q->e[i]) {
free(q->e[i]);
}
if (q->d[i]) {
free(q->d[i]);
}
/* Free sch objects */
srslte_sch_free(&q->dl_sch[i]);
}
for (i = 0; i < q->cell.nof_ports; i++) {
if (q->x[i]) {
free(q->x[i]);
@ -354,8 +389,6 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
srslte_modem_table_free(&q->mod[i]);
}
srslte_sch_free(&q->dl_sch);
bzero(q, sizeof(srslte_pdsch_t));
}
@ -454,18 +487,17 @@ int srslte_pdsch_cfg_multi(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_r
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
*/
int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
uint32_t i;
uint32_t i, j;
if (!q->users[rnti]) {
q->users[rnti] = calloc(1, sizeof(srslte_pdsch_user_t));
if (q->users[rnti]) {
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
if (srslte_sequence_pdsch(&q->users[rnti]->seq[i], rnti, 0, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
return SRSLTE_ERROR;
}
if (srslte_sequence_pdsch(&q->users[rnti]->seq2[i], rnti, 1, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
return SRSLTE_ERROR;
for (j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
if (srslte_sequence_pdsch(&q->users[rnti]->seq[j][i], rnti, j, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
ERROR("Generating scrambling sequence");
return SRSLTE_ERROR;
}
}
}
q->users[rnti]->sequence_generated = true;
@ -474,12 +506,142 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
return SRSLTE_SUCCESS;
}
static inline int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data,
uint32_t 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_mcs_t *mcs = (codeword_idx == 0) ? &cfg->grant.mcs : &cfg->grant.mcs2;
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,
nbits->nof_re, nbits->nof_bits, (codeword_idx == 0) ? cfg->rv : cfg->rv2);
/* Channel coding */
if (srslte_dlsch_encode2(dl_sch, cfg, softbuffer, data, pdsch->e[codeword_idx], codeword_idx)) {
ERROR("Error encoding TB %d", codeword_idx);
return SRSLTE_ERROR;
}
/* Bit scrambling */
if (!pdsch->users[rnti]) {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, codeword_idx, 2 * cfg->sf_idx, pdsch->cell.id, nbits->nof_bits)) {
ERROR("Initialising scrambling sequence");
return SRSLTE_ERROR;
}
srslte_scrambling_bytes(&seq, (uint8_t *) pdsch->e[codeword_idx], nbits->nof_bits);
srslte_sequence_free(&seq);
} else {
srslte_scrambling_bytes(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx],
(uint8_t *) pdsch->e[codeword_idx],
nbits->nof_bits);
}
/* Bit mapping */
srslte_mod_modulate_bytes(&pdsch->mod[mcs->mod],
(uint8_t *) pdsch->e[codeword_idx],
pdsch->d[codeword_idx], nbits->nof_bits);
}
return SRSLTE_SUCCESS;
}
#ifndef SRSLTE_SINGLE_THREAD
static void *srslte_pdsch_encode_thread(void *arg) {
srslte_pdsch_thread_args_t *q = (srslte_pdsch_thread_args_t *) arg;
uint32_t codeword_idx = q->codeword_idx;
INFO("[PDSCH Encoder CW %d] waiting for data\n", codeword_idx);
sem_wait(&q->start);
while (!q->quit) {
q->ret_status = srslte_pdsch_codeword_encode(q->pdsch_ptr, q->cfg, q->softbuffer, q->rnti, q->data, codeword_idx);
/* Post finish semaphore */
sem_post(&q->finish);
/* Wait for next loop */
sem_wait(&q->start);
}
pthread_exit(NULL);
return q;
}
#endif /* SRSLTE_SINGLE_THREAD */
static inline int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data,
uint32_t 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_mcs_t *mcs = (codeword_idx == 0) ? &cfg->grant.mcs : &cfg->grant.mcs2;
if (nbits->nof_bits) {
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,
nbits->nof_re, nbits->nof_bits, (codeword_idx == 0) ? cfg->rv : cfg->rv2);
srslte_demod_soft_demodulate_s(mcs->mod, pdsch->d[codeword_idx], pdsch->e[codeword_idx], cfg->nbits.nof_re);
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],
0, nbits->nof_bits);
} else {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, codeword_idx, 2 * cfg->sf_idx, pdsch->cell.id, nbits->nof_bits)) {
ERROR("Initialising scrambling sequence");
return SRSLTE_ERROR;
}
srslte_scrambling_s_offset(&seq, pdsch->e[codeword_idx], codeword_idx, nbits->nof_bits);
srslte_sequence_free(&seq);
}
return srslte_dlsch_decode2(dl_sch, cfg, softbuffer, pdsch->e[codeword_idx], data, codeword_idx);
}
return SRSLTE_SUCCESS;
}
#ifndef SRSLTE_SINGLE_THREAD
static void *srslte_pdsch_decode_thread(void *arg) {
srslte_pdsch_thread_args_t *q = (srslte_pdsch_thread_args_t *) arg;
uint32_t codeword_idx = q->codeword_idx;
INFO("[PDSCH Encoder CW %d] waiting for data\n", codeword_idx);
sem_wait(&q->start);
while (!q->quit) {
q->ret_status = srslte_pdsch_codeword_decode(q->pdsch_ptr, q->cfg, q->softbuffer, q->rnti, q->data, codeword_idx);
/* Post finish semaphore */
sem_post(&q->finish);
/* Wait for next loop */
sem_wait(&q->start);
}
pthread_exit(NULL);
return q;
}
#endif /* SRSLTE_SINGLE_THREAD */
void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti)
{
if (q->users[rnti]) {
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
srslte_sequence_free(&q->users[rnti]->seq[i]);
srslte_sequence_free(&q->users[rnti]->seq2[i]);
for (int j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
srslte_sequence_free(&q->users[rnti]->seq[j][i]);
}
}
free(q->users[rnti]);
q->users[rnti] = NULL;
@ -510,7 +672,7 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
{
/* Set pointers for layermapping & precoding */
uint32_t i, n;
uint32_t i;
cf_t *x[SRSLTE_MAX_LAYERS];
int ret = 0;
@ -524,15 +686,9 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
cfg->sf_idx, rnti, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->nbits.nof_re,
cfg->nbits.nof_bits, cfg->rv, cfg->rv2, cfg->grant.nof_prb);
/* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) {
x[i] = q->x[i];
}
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
for (int j=0;j<q->nof_rx_antennas;j++) {
/* extract symbols */
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.lstart, cfg->sf_idx);
if (n != cfg->nbits.nof_re) {
fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n);
return SRSLTE_ERROR;
@ -552,16 +708,33 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
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, q->nof_rx_antennas, cfg->nbits.nof_re, noise_estimate);
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];
nof_symbols[0] = cfg->nbits.nof_re * cfg->grant.nof_tb / cfg->nof_layers;
nof_symbols[1] = cfg->nbits2.nof_re * cfg->grant.nof_tb / 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, 0.0);
srslte_layerdemap_type(x, (cf_t *[SRSLTE_MAX_CODEWORDS]) {q->d, q->d2}, cfg->nof_layers, cfg->grant.nof_tb,
nof_symbols[0], nof_symbols, cfg->mimo_type);
if (cfg->nof_layers == cfg->grant.nof_tb) {
for (i = 0; i < cfg->nof_layers; 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,
cfg->codebook_idx, cfg->nbits.nof_re, cfg->mimo_type, noise_estimate);
} else {
/* number of layers equals number of ports */
for (i = 0; i < cfg->nof_layers; i++) {
x[i] = q->x[i];
}
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,
cfg->codebook_idx, cfg->nbits.nof_re, cfg->mimo_type, noise_estimate);
srslte_layerdemap_type(x, q->d, cfg->nof_layers, cfg->grant.nof_tb,
nof_symbols[0], nof_symbols, cfg->mimo_type);
}
}
if (SRSLTE_VERBOSE_ISDEBUG()) {
@ -587,46 +760,32 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
srslte_vec_save_file("pdsch_symbols.dat", q->d, cfg->nbits.nof_re*sizeof(cf_t));
}
#ifndef SRSLTE_SINGLE_THREAD
for (i = 0; i < cfg->grant.nof_tb; i++) {
srslte_pdsch_thread_args_t *thread_args = &q->thread_args[i];
thread_args->cfg = cfg;
thread_args->softbuffer = &softbuffers[i];
thread_args->data = data[i];
thread_args->rnti = rnti;
sem_post(&thread_args->start);
}
for (i = 0; i < cfg->grant.nof_tb; i++) {
srslte_pdsch_thread_args_t *thread_args = &q->thread_args[i];
sem_wait(&thread_args->finish);
ret |= thread_args->ret_status;
}
#else
/* demodulate symbols
* 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
*/
if (cfg->nbits.nof_bits) {
INFO("Decoding CW 0 (%d bits)\n", cfg->nbits.nof_bits);
srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re);
if (q->users[rnti] && q->users[rnti]->sequence_generated) {
srslte_scrambling_s_offset(&q->users[rnti]->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits);
} else {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_s_offset(&seq, q->e, 0, cfg->nbits.nof_bits);
srslte_sequence_free(&seq);
}
ret |= srslte_dlsch_decode2(&q->dl_sch, cfg, &softbuffers[0], q->e, data[0], 0);
for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) {
ret |= srslte_pdsch_codeword_decode(q, cfg, &softbuffers[tb], rnti, data[tb], tb);
}
if (cfg->nbits2.nof_bits) {
INFO("Decoding CW 1 (%d bits)\n", cfg->nbits2.nof_bits);
srslte_demod_soft_demodulate_s(cfg->grant.mcs2.mod, q->d2, q->e2, cfg->nbits2.nof_re);
if (q->users[rnti] && q->users[rnti]->sequence_generated) {
srslte_scrambling_s_offset(&q->users[rnti]->seq2[cfg->sf_idx], q->e2, 0, cfg->nbits2.nof_bits);
} else {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, 1, 2 * cfg->sf_idx, q->cell.id, cfg->nbits2.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_s_offset(&seq, q->e2, 0, cfg->nbits2.nof_bits);
srslte_sequence_free(&seq);
}
ret |= srslte_dlsch_decode2(&q->dl_sch, cfg, &softbuffers[1], q->e2, data[1], 1);
}
#endif /* SRSLTE_SINGLE_THREAD */
if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0);
@ -688,13 +847,13 @@ int srslte_pdsch_ri_pmi_select(srslte_pdsch_t *q,
*pmi = (best_sinr_1l > best_sinr_2l) ? best_pmi_1l : best_pmi_2l;
}
/* Set current condition number */
if (current_sinr != NULL) {
/* Set current SINR */
if (current_sinr != NULL && cfg->mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
if (cfg->nof_layers == 1) {
*current_sinr = sinr_1l[cfg->codebook_idx];
} else if (cfg->nof_layers == 2) {
*current_sinr = sinr_2l[cfg->codebook_idx - 1];
}else {
} else {
ERROR("Not implemented number of layers");
return SRSLTE_ERROR;
}
@ -754,28 +913,28 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
}
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
if (srslte_dlsch_encode(&q->dl_sch, cfg, softbuffer, data, q->e)) {
if (srslte_dlsch_encode(&q->dl_sch[0], cfg, softbuffer, data, q->e[0])) {
fprintf(stderr, "Error encoding TB\n");
return SRSLTE_ERROR;
}
/* scramble */
if (q->users[rnti] && q->users[rnti]->sequence_generated) {
srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits.nof_bits);
srslte_scrambling_bytes(&q->users[rnti]->seq[0][cfg->sf_idx], (uint8_t*) q->e[0], cfg->nbits.nof_bits);
} else {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_bytes(&seq, (uint8_t*) q->e, cfg->nbits.nof_bits);
srslte_scrambling_bytes(&seq, (uint8_t*) q->e[0], cfg->nbits.nof_bits);
srslte_sequence_free(&seq);
}
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits);
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e[0], q->d[0], cfg->nbits.nof_bits);
/* TODO: only diversity supported */
if (q->cell.nof_ports > 1) {
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, cfg->nbits.nof_re);
srslte_layermap_diversity(q->d[0], x, q->cell.nof_ports, cfg->nbits.nof_re);
srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports,
cfg->nbits.nof_re / q->cell.nof_ports);
} else {
@ -822,73 +981,57 @@ int srslte_pdsch_encode_multi(srslte_pdsch_t *q,
return SRSLTE_ERROR_INVALID_INPUTS;
}
INFO("Encoding PDSCH SF: %d (TB 1), 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->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv);
if (cfg->grant.nof_tb > 1) {
INFO("Encoding PDSCH SF: %d (TB 2), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
cfg->sf_idx, srslte_mod_string(cfg->grant.mcs2.mod), cfg->grant.mcs2.tbs,
cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv2);
#ifndef SRSLTE_SINGLE_THREAD
for (int tb = 0; tb < cfg->grant.nof_tb; tb++) {
srslte_pdsch_thread_args_t *thread_args = &q->thread_args[tb];
thread_args->cfg = cfg;
thread_args->softbuffer = &softbuffers[tb];
thread_args->data = data[tb];
thread_args->rnti = rnti;
sem_post(&thread_args->start);
}
/* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) {
x[i] = q->x[i];
}
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports));
if (srslte_dlsch_encode_multi(&q->dl_sch, cfg, softbuffers, data, (uint8_t *[SRSLTE_MAX_CODEWORDS]) {q->e, q->e2})) {
fprintf(stderr, "Error encoding TB\n");
return SRSLTE_ERROR;
for (int tb = 0; tb < cfg->grant.nof_tb; tb++) {
srslte_pdsch_thread_args_t *thread_args = &q->thread_args[tb];
sem_wait(&thread_args->finish);
ret |= thread_args->ret_status;
}
/* scramble */
if (!q->users[rnti]) {
srslte_sequence_t seq;
if (cfg->nbits.nof_bits) {
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_bytes(&seq, (uint8_t *) q->e, cfg->nbits.nof_bits);
srslte_sequence_free(&seq);
}
if (cfg->nbits2.nof_bits) {
if (srslte_sequence_pdsch(&seq, rnti, 1, 2 * cfg->sf_idx, q->cell.id, cfg->nbits2.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_bytes(&seq, (uint8_t *) q->e2, cfg->nbits2.nof_bits);
srslte_sequence_free(&seq);
}
} else {
if (cfg->nbits.nof_bits) {
srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t *) q->e, cfg->nbits.nof_bits);
}
if (cfg->nbits2.nof_bits) {
srslte_scrambling_bytes(&q->users[rnti]->seq2[cfg->sf_idx], (uint8_t *) q->e2, cfg->nbits2.nof_bits);
}
}
if (cfg->nbits.nof_bits) {
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t *) q->e, q->d, cfg->nbits.nof_bits);
}
if (cfg->nbits2.nof_bits) {
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs2.mod], (uint8_t *) q->e2, q->d2, cfg->nbits2.nof_bits);
#else
for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) {
ret |= srslte_pdsch_codeword_encode(q, cfg, &softbuffers[tb], rnti, data[tb], tb);
}
#endif /* SRSLTE_SINGLE_THREAD */
if (q->cell.nof_ports > 1) {
int nof_symbols = srslte_layermap_type((cf_t *[SRSLTE_MAX_CODEWORDS]) {q->d, q->d2}, x, cfg->grant.nof_tb, cfg->nof_layers,
(int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits.nof_re, cfg->nbits2.nof_re}, cfg->mimo_type);
int nof_symbols;
/* If number of layers is equal to transport blocks (codewords) skip layer mapping */
if (cfg->nof_layers == cfg->grant.nof_tb) {
for (i = 0; i < cfg->nof_layers; i++) {
x[i] = q->d[i];
}
nof_symbols = cfg->nbits.nof_re;
} else {
/* Initialise layer map pointers */
for (i = 0; i < cfg->nof_layers; i++) {
x[i] = q->x[i];
}
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,
(int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits.nof_re, cfg->nbits2.nof_re}, cfg->mimo_type);
}
/* Precode */
srslte_precoding_type(x, q->symbols, cfg->nof_layers, q->cell.nof_ports, cfg->codebook_idx,
nof_symbols, cfg->mimo_type);
} else {
memcpy(q->symbols[0], q->d, cfg->nbits.nof_re * sizeof(cf_t));
memcpy(q->symbols[0], q->d[0], cfg->nbits.nof_re * sizeof(cf_t));
}
/* mapping to resource elements */
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);
}
@ -898,13 +1041,18 @@ int srslte_pdsch_encode_multi(srslte_pdsch_t *q,
return ret;
}
float srslte_pdsch_average_noi(srslte_pdsch_t *q)
{
return q->dl_sch.average_nof_iterations;
void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, int max_iter) {
for (int cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) {
srslte_sch_set_max_noi(&q->dl_sch[cw], max_iter);
}
}
float srslte_pdsch_average_noi(srslte_pdsch_t *q) {
return q->dl_sch[0].average_nof_iterations;
}
uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q) {
return q->dl_sch.nof_iterations;
return q->dl_sch[0].nof_iterations;
}

View File

@ -528,24 +528,25 @@ int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu
int16_t *e_bits, uint8_t *data, int codeword_idx)
{
uint32_t Nl = 1;
int ret = SRSLTE_ERROR;
if (cfg->nof_layers != cfg->grant.nof_tb) {
Nl = 2;
}
if (codeword_idx == 0) {
return decode_tb(q, softbuffer, &cfg->cb_segm,
ret = decode_tb(q, softbuffer, &cfg->cb_segm,
cfg->grant.Qm*Nl, cfg->rv, cfg->nbits.nof_bits,
e_bits, data);
}
if (codeword_idx == 1) {
return decode_tb(q, softbuffer, &cfg->cb_segm2,
} 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);
} else {
ERROR("Not implemented");
}
return SRSLTE_ERROR;
return ret;
}
/**
@ -567,6 +568,28 @@ int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf
data, e_bits);
}
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) {
int ret = SRSLTE_ERROR;
uint32_t Nl = 1;
if (cfg->nof_layers != cfg->grant.nof_tb) {
Nl = 2;
}
if(codeword_idx == 0) {
/* Codeword 1 shall be encoded */
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])
{

View File

@ -46,7 +46,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
int i;
srslte_sch_t dlsch;
srslte_pdsch_cfg_t cfg;
srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_CODEWORDS];
srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS];
uint32_t nof_codewords = 1;
memset(&dlsch, 0, sizeof(srslte_sch_t));
@ -107,8 +107,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
/* Initialise buffers */
for (i = 0; i < nof_codewords; i++) {
softbuffers[i] = srslte_vec_malloc(sizeof(srslte_softbuffer_tx_t));
if (srslte_softbuffer_tx_init(softbuffers[i], cell.nof_prb)) {
if (srslte_softbuffer_tx_init(&softbuffers[i], cell.nof_prb)) {
mexErrMsgTxt("Error initiating DL-SCH soft buffer\n");
return;
}
@ -151,8 +150,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
free(e_bits);
free(e_bits_unpacked);
for (i = 0; i < nof_codewords; i++) {
srslte_softbuffer_tx_free(softbuffers[i]);
free(softbuffers[i]);
srslte_softbuffer_tx_free(&softbuffers[i]);
}
return;
}

View File

@ -155,6 +155,7 @@ int main(int argc, char **argv) {
int ret = -1;
struct timeval t[3];
srslte_softbuffer_tx_t softbuffers_tx[SRSLTE_MAX_CODEWORDS];
int M=10;
parse_args(argc,argv);
@ -265,6 +266,7 @@ int main(int argc, char **argv) {
perror("srslte_vec_malloc");
goto quit;
}
bzero(data[0], sizeof(uint8_t) * grant.mcs.tbs);
}
if (grant.mcs2.tbs) {
@ -273,6 +275,7 @@ int main(int argc, char **argv) {
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)) {
@ -388,10 +391,18 @@ int main(int argc, char **argv) {
}
pdsch_cfg.rv = rv_idx;
pdsch_cfg.rv2 = rv_idx2;
if (srslte_pdsch_encode_multi(&pdsch_tx, &pdsch_cfg, softbuffers_tx, data, rnti, tx_slot_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n");
goto quit;
gettimeofday(&t[1], NULL);
for (k = 0; k < M; k++) {
if (srslte_pdsch_encode_multi(&pdsch_tx, &pdsch_cfg, softbuffers_tx, data, rnti, tx_slot_symbols)) {
ERROR("Error encoding PDSCH");
goto quit;
}
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
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) (grant.mcs.tbs + grant.mcs2.tbs)*M/t[0].tv_usec);
#ifdef DO_OFDM
for (i = 0; i < cell.nof_ports; i++) {
@ -422,9 +433,9 @@ int main(int argc, char **argv) {
}
int M=10;
int r=0;
srslte_sch_set_max_noi(&pdsch_rx.dl_sch, 10);
srslte_pdsch_set_max_noi(&pdsch_rx, 10);
gettimeofday(&t[1], NULL);
for (k = 0; k < M; k++) {
#ifdef DO_OFDM
@ -443,7 +454,7 @@ int main(int argc, char **argv) {
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
INFO("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) (grant.mcs.tbs + grant.mcs2.tbs)*M/t[0].tv_usec);
if (r) {

View File

@ -213,7 +213,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
srslte_sch_set_max_noi(&pdsch.dl_sch, max_iterations);
srslte_pdsch_set_max_noi(&pdsch, max_iterations);
bool input_fft_allocated = false;
int r=-1;
@ -291,10 +291,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.nbits.nof_re, 1);
}
if (nlhs >= 4) {
mexutils_write_cf(pdsch.d, &plhs[3], cfg.nbits.nof_re, 1);
mexutils_write_cf(pdsch.d[0], &plhs[3], cfg.nbits.nof_re, 1);
}
if (nlhs >= 5) {
mexutils_write_s(pdsch.e, &plhs[4], cfg.nbits.nof_bits, 1);
mexutils_write_s(pdsch.e[0], &plhs[4], cfg.nbits.nof_bits, 1);
}
if (nlhs >= 6) {
uint32_t len = nof_antennas*cell.nof_ports*SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);

View File

@ -293,19 +293,19 @@ int srslte_ue_dl_cfg_grant_multi(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant,
uint32_t pmi = 0;
/* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */
if (q->pdsch_cfg.mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
if (q->pdsch_cfg.grant.nof_tb == 1) {
if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
if (grant->nof_tb == 1) {
if (pinfo > 0 && pinfo < 5) {
pmi = pinfo - 1;
} else {
ERROR("Not Implemented");
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", q->pdsch_cfg.grant.nof_tb, pinfo);
return SRSLTE_ERROR;
}
} else {
if (pinfo < 2) {
pmi = pinfo;
} else {
ERROR("Not Implemented");
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", q->pdsch_cfg.grant.nof_tb, pinfo);
return SRSLTE_ERROR;
}
}

View File

@ -432,7 +432,7 @@ bool phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *paylo
/* Set decoder iterations */
if (phy->args->pdsch_max_its > 0) {
srslte_sch_set_max_noi(&ue_dl.pdsch.dl_sch, phy->args->pdsch_max_its);
srslte_pdsch_set_max_noi(&ue_dl.pdsch, phy->args->pdsch_max_its);
}