mirror of https://github.com/PentHertz/srsLTE.git
Added MMSE in SSE and AVX plus subroutines refactor
This commit is contained in:
parent
d1709e06af
commit
a9d9c92205
|
@ -175,6 +175,11 @@ typedef enum SRSLTE_API {
|
|||
SRSLTE_MIMO_TYPE_CDD
|
||||
} srslte_mimo_type_t;
|
||||
|
||||
typedef enum SRSLTE_API {
|
||||
SRSLTE_MIMO_DECODER_ZF,
|
||||
SRSLTE_MIMO_DECODER_MMSE
|
||||
} srslte_mimo_decoder_t;
|
||||
|
||||
typedef enum SRSLTE_API {
|
||||
SRSLTE_MOD_BPSK = 0,
|
||||
SRSLTE_MOD_QPSK,
|
||||
|
|
|
@ -107,6 +107,8 @@ SRSLTE_API int srslte_predecoding_type(cf_t *y,
|
|||
srslte_mimo_type_t type,
|
||||
float noise_estimate);
|
||||
|
||||
SRSLTE_API void srslte_predecoding_set_mimo_decoder (srslte_mimo_decoder_t _mimo_decoder);
|
||||
|
||||
SRSLTE_API int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS],
|
||||
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
|
@ -118,11 +120,11 @@ SRSLTE_API int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS],
|
|||
srslte_mimo_type_t type,
|
||||
float noise_estimate);
|
||||
|
||||
int srslte_precoding_pmi_select (cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
uint32_t nof_symbols,
|
||||
float noise_estimate,
|
||||
int nof_layers,
|
||||
uint32_t *pmi,
|
||||
float sinr[SRSLTE_MAX_CODEBOOKS]);
|
||||
SRSLTE_API int srslte_precoding_pmi_select(cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
uint32_t nof_symbols,
|
||||
float noise_estimate,
|
||||
int nof_layers,
|
||||
uint32_t *pmi,
|
||||
float sinr[SRSLTE_MAX_CODEBOOKS]);
|
||||
|
||||
#endif /* PRECODING_H_ */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -52,14 +52,21 @@ add_test(precoding_single precoding_test -n 1000 -m single)
|
|||
add_test(precoding_diversity2 precoding_test -n 1000 -m diversity -l 2 -p 2)
|
||||
add_test(precoding_diversity4 precoding_test -n 1024 -m diversity -l 4 -p 4)
|
||||
|
||||
add_test(precoding_cdd_2x2 precoding_test -m cdd -l 2 -p 2 -r 2 -n 14000)
|
||||
add_test(precoding_cdd_2x2_zf precoding_test -m cdd -l 2 -p 2 -r 2 -n 14000 -d zf)
|
||||
add_test(precoding_cdd_2x2_mmse precoding_test -m cdd -l 2 -p 2 -r 2 -n 14000 -d mmse)
|
||||
|
||||
add_test(precoding_multiplex_1l_cb0 precoding_test -m multiplex -l 1 -p 2 -r 2 -n 14000 -c 0)
|
||||
add_test(precoding_multiplex_1l_cb1 precoding_test -m multiplex -l 1 -p 2 -r 2 -n 14000 -c 1)
|
||||
add_test(precoding_multiplex_1l_cb2 precoding_test -m multiplex -l 1 -p 2 -r 2 -n 14000 -c 2)
|
||||
add_test(precoding_multiplex_1l_cb3 precoding_test -m multiplex -l 1 -p 2 -r 2 -n 14000 -c 3)
|
||||
|
||||
add_test(precoding_multiplex_2l_cb0 precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 0)
|
||||
add_test(precoding_multiplex_2l_cb1 precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 1)
|
||||
add_test(precoding_multiplex_2l_cb2 precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 2)
|
||||
add_test(precoding_multiplex_2l_cb0_zf precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 0 -d zf)
|
||||
add_test(precoding_multiplex_2l_cb1_zf precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 1 -d zf)
|
||||
add_test(precoding_multiplex_2l_cb2_zf precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 2 -d zf)
|
||||
|
||||
|
||||
add_test(precoding_multiplex_2l_cb0_mmse precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 0 -d mmse)
|
||||
add_test(precoding_multiplex_2l_cb1_mmse precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 1 -d mmse)
|
||||
add_test(precoding_multiplex_2l_cb2_mmse precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 2 -d mmse)
|
||||
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "srslte/srslte.h"
|
||||
#include "srslte/phy/channel/ch_awgn.h"
|
||||
|
||||
#define MSE_THRESHOLD 0.0005
|
||||
|
||||
|
@ -41,18 +42,24 @@ int nof_symbols = 1000;
|
|||
uint32_t codebook_idx = 0;
|
||||
int nof_layers = 1, nof_tx_ports = 1, nof_rx_ports = 1, nof_re = 1;
|
||||
char *mimo_type_name = NULL;
|
||||
char decoder_type_name [16] = "zf";
|
||||
float snr_db = 100.0f;
|
||||
|
||||
void usage(char *prog) {
|
||||
printf(
|
||||
"Usage: %s -m [single|diversity|multiplex|cdd] -l [nof_layers] -p [nof_tx_ports]\n"
|
||||
" -r [nof_rx_ports]\n", prog);
|
||||
printf("\t-n num_symbols [Default %d]\n", nof_symbols);
|
||||
printf("\t-c codebook_idx [Default %d]\n\n", codebook_idx);
|
||||
printf("\t-c codebook_idx [Default %d]\n", codebook_idx);
|
||||
printf("\t-s SNR in dB [Default %.1fdB]*\n", snr_db);
|
||||
printf("\t-d decoder type [zf|mmse] [Default %s]\n", decoder_type_name);
|
||||
printf("\n");
|
||||
printf("* Performance test example:\n\t for snr in {0..20..1}; do ./precoding_test -m single -s $snr; done; \n\n", decoder_type_name);
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "mplnrc")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "mplnrcds")) != -1) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
nof_symbols = atoi(argv[optind]);
|
||||
|
@ -72,6 +79,12 @@ void parse_args(int argc, char **argv) {
|
|||
case 'c':
|
||||
codebook_idx = (uint32_t) atoi(argv[optind]);
|
||||
break;
|
||||
case 'd':
|
||||
strncpy(decoder_type_name, argv[optind], 16);
|
||||
break;
|
||||
case 's':
|
||||
snr_db = (float) atof(argv[optind]);
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(-1);
|
||||
|
@ -134,8 +147,17 @@ void populate_channel(srslte_mimo_type_t type, cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_
|
|||
}
|
||||
}
|
||||
|
||||
static void awgn(cf_t *y[SRSLTE_MAX_PORTS], uint32_t n, float snr) {
|
||||
int i;
|
||||
float std_dev = powf(10, - (snr + 3.0f) / 20.0f);
|
||||
|
||||
for (i = 0; i < nof_rx_ports; i++) {
|
||||
srslte_ch_awgn_c(y[i], y[i], std_dev, n);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i, j, k;
|
||||
int i, j, k, nof_errors = 0, ret = SRSLTE_SUCCESS;
|
||||
float mse;
|
||||
cf_t *x[SRSLTE_MAX_LAYERS], *r[SRSLTE_MAX_PORTS], *y[SRSLTE_MAX_PORTS], *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
|
||||
*xr[SRSLTE_MAX_LAYERS];
|
||||
|
@ -247,27 +269,48 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
awgn(r, (uint32_t) nof_re, snr_db);
|
||||
|
||||
/* If CDD or Spatial muliplex choose decoder */
|
||||
if (strncmp(decoder_type_name, "zf", 16) == 0) {
|
||||
srslte_predecoding_set_mimo_decoder(SRSLTE_MIMO_DECODER_ZF);
|
||||
} else if (strncmp(decoder_type_name, "mmse", 16) == 0) {
|
||||
srslte_predecoding_set_mimo_decoder(SRSLTE_MIMO_DECODER_MMSE);
|
||||
} else {
|
||||
ret = SRSLTE_ERROR;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
|
||||
/* predecoding / equalization */
|
||||
struct timeval t[3];
|
||||
gettimeofday(&t[1], NULL);
|
||||
srslte_predecoding_type_multi(r, h, xr, nof_rx_ports, nof_tx_ports, nof_layers,
|
||||
codebook_idx, nof_re, type, 0);
|
||||
codebook_idx, nof_re, type, powf(10, -snr_db/10));
|
||||
gettimeofday(&t[2], NULL);
|
||||
get_time_interval(t);
|
||||
printf("Execution Time: %ld us\n", t[0].tv_usec);
|
||||
|
||||
|
||||
/* check errors */
|
||||
mse = 0;
|
||||
for (i = 0; i < nof_layers; i++) {
|
||||
for (j = 0; j < nof_symbols; j++) {
|
||||
mse += cabsf(xr[i][j] - x[i][j]);
|
||||
|
||||
if ((crealf(xr[i][j]) > 0) != (crealf(x[i][j]) > 0)) {
|
||||
nof_errors ++;
|
||||
}
|
||||
if ((cimagf(xr[i][j]) > 0) != (cimagf(x[i][j]) > 0)) {
|
||||
nof_errors ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("MSE: %f\n", mse/ nof_layers / nof_symbols );
|
||||
printf("SNR: %5.1fdB;\tExecution time: %5ldus;\tMSE: %.6f;\tBER: %.6f\n", snr_db, t[0].tv_usec,
|
||||
mse / nof_layers / nof_symbols, (float) nof_errors / (4.0f * nof_re));
|
||||
if (mse / nof_layers / nof_symbols > MSE_THRESHOLD) {
|
||||
exit(-1);
|
||||
ret = SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
quit:
|
||||
/* Free all data */
|
||||
for (i = 0; i < nof_layers; i++) {
|
||||
free(x[i]);
|
||||
|
@ -284,6 +327,5 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
printf("Ok\n");
|
||||
exit(0);
|
||||
exit(ret);
|
||||
}
|
||||
|
|
|
@ -35,8 +35,10 @@
|
|||
#define HEST prhs[1]
|
||||
#define NEST prhs[2]
|
||||
#define NLAYERS prhs[3]
|
||||
#define TXSCHEME prhs[4]
|
||||
#define NOF_INPUTS 5
|
||||
#define NCW prhs[4]
|
||||
#define TXSCHEME prhs[5]
|
||||
#define CODEBOOK prhs[6]
|
||||
#define NOF_INPUTS 7
|
||||
|
||||
|
||||
void help()
|
||||
|
@ -58,6 +60,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
uint32_t nof_layers;
|
||||
uint32_t nof_tx_ports = 1;
|
||||
uint32_t nof_codewords = 1;
|
||||
uint32_t codebook_idx = 0;
|
||||
float noise_estimate = 0;
|
||||
cf_t *x[SRSLTE_MAX_LAYERS];
|
||||
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||
|
@ -81,6 +84,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
/* Read number of layers */
|
||||
nof_layers = (uint32_t) mxGetScalar(NLAYERS);
|
||||
|
||||
/* Read number of codewords */
|
||||
nof_codewords = (uint32_t) mxGetScalar(NCW);
|
||||
|
||||
if (nof_layers > SRSLTE_MAX_LAYERS) {
|
||||
mexErrMsgTxt("Too many layers\n");
|
||||
return;
|
||||
|
@ -109,7 +115,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
}
|
||||
|
||||
/* Print parameters trace */
|
||||
mexPrintf("nof_tx_ports=%d, nof_rx_ants=%d, nof_layers=%d, nof_symbols=%d\n", nof_tx_ports, nof_rx_ants, nof_layers, nof_symbols);
|
||||
mexPrintf("nof_tx_ports=%d, nof_rx_ants=%d, nof_layers=%d, nof_codewords=%d, codebook_idx=%d, nof_symbols=%d\n",
|
||||
nof_tx_ports, nof_rx_ants, nof_layers, nof_codewords, codebook_idx, nof_symbols);
|
||||
|
||||
/* Read noise estimate */
|
||||
if (nrhs >= NOF_INPUTS) {
|
||||
|
@ -134,7 +141,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
|
||||
/* Allocate memory for intermediate data */
|
||||
for (i = 0; i < nof_tx_ports; i++) {
|
||||
x[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols);
|
||||
x[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols*nof_layers);
|
||||
}
|
||||
|
||||
/* Allocate memory for channel estimate */
|
||||
|
@ -155,15 +162,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
mxGetString_700(TXSCHEME, txscheme, 32);
|
||||
}
|
||||
|
||||
if (!strcmp(txscheme, "Port0")) {
|
||||
type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
||||
} else if (!strcmp(txscheme, "TxDiversity")) {
|
||||
type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
|
||||
} else if (!strcmp(txscheme, "CDD")) {
|
||||
type = SRSLTE_MIMO_TYPE_CDD;
|
||||
} else if (!strcmp(txscheme, "SpatialMux")) {
|
||||
type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
|
||||
} else {
|
||||
codebook_idx = (uint32_t) mxGetScalar(CODEBOOK);
|
||||
|
||||
if (srslte_str2mimotype(txscheme, &type)) {
|
||||
mexPrintf("Unsupported TxScheme=%s\n", txscheme);
|
||||
return;
|
||||
}
|
||||
|
@ -176,18 +177,19 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
/* Set output pointer */
|
||||
cf_t *d[SRSLTE_MAX_CODEWORDS];
|
||||
for (i = 0; i<nof_codewords; i++) {
|
||||
d[i] = output;
|
||||
d[i] = &output[i*nof_symbols*nof_layers/nof_codewords];
|
||||
}
|
||||
|
||||
/* Pre-decode */
|
||||
srslte_predecoding_type_multi(y, h, x, nof_rx_ants, nof_tx_ports, nof_layers, nof_symbols, type, noise_estimate);
|
||||
srslte_predecoding_type_multi(y, h, x, nof_rx_ants, nof_tx_ports, nof_layers, codebook_idx, nof_symbols, type,
|
||||
noise_estimate);
|
||||
|
||||
/* Layer de-mapper */
|
||||
srslte_layerdemap_type(x, d, nof_layers, nof_codewords, nof_symbols, symbols_layers, type);
|
||||
|
||||
/* Write output */
|
||||
if (nlhs >= 1) {
|
||||
mexutils_write_cf(output, &plhs[0], nof_symbols*nof_layers*nof_rx_ants/nof_tx_ports, 1);
|
||||
mexutils_write_cf(output, &plhs[0], nof_symbols, nof_codewords);
|
||||
}
|
||||
|
||||
/* Free memory */
|
||||
|
|
Loading…
Reference in New Issue