Added MMSE in SSE and AVX plus subroutines refactor

master
Xavier Arteaga 7 years ago
parent d1709e06af
commit a9d9c92205

@ -175,6 +175,11 @@ typedef enum SRSLTE_API {
SRSLTE_MIMO_TYPE_CDD SRSLTE_MIMO_TYPE_CDD
} srslte_mimo_type_t; } srslte_mimo_type_t;
typedef enum SRSLTE_API {
SRSLTE_MIMO_DECODER_ZF,
SRSLTE_MIMO_DECODER_MMSE
} srslte_mimo_decoder_t;
typedef enum SRSLTE_API { typedef enum SRSLTE_API {
SRSLTE_MOD_BPSK = 0, SRSLTE_MOD_BPSK = 0,
SRSLTE_MOD_QPSK, SRSLTE_MOD_QPSK,

@ -107,6 +107,8 @@ SRSLTE_API int srslte_predecoding_type(cf_t *y,
srslte_mimo_type_t type, srslte_mimo_type_t type,
float noise_estimate); 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], SRSLTE_API int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS],
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
cf_t *x[SRSLTE_MAX_LAYERS], cf_t *x[SRSLTE_MAX_LAYERS],
@ -118,7 +120,7 @@ SRSLTE_API int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS],
srslte_mimo_type_t type, srslte_mimo_type_t type,
float noise_estimate); float noise_estimate);
int srslte_precoding_pmi_select (cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], SRSLTE_API int srslte_precoding_pmi_select(cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
uint32_t nof_symbols, uint32_t nof_symbols,
float noise_estimate, float noise_estimate,
int nof_layers, int nof_layers,

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_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_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_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_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_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_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_cb0_zf precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 0 -d zf)
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_cb1_zf precoding_test -m multiplex -l 2 -p 2 -r 2 -n 14000 -c 1 -d zf)
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_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 <stdbool.h>
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srslte/phy/channel/ch_awgn.h"
#define MSE_THRESHOLD 0.0005 #define MSE_THRESHOLD 0.0005
@ -41,18 +42,24 @@ int nof_symbols = 1000;
uint32_t codebook_idx = 0; uint32_t codebook_idx = 0;
int nof_layers = 1, nof_tx_ports = 1, nof_rx_ports = 1, nof_re = 1; int nof_layers = 1, nof_tx_ports = 1, nof_rx_ports = 1, nof_re = 1;
char *mimo_type_name = NULL; char *mimo_type_name = NULL;
char decoder_type_name [16] = "zf";
float snr_db = 100.0f;
void usage(char *prog) { void usage(char *prog) {
printf( printf(
"Usage: %s -m [single|diversity|multiplex|cdd] -l [nof_layers] -p [nof_tx_ports]\n" "Usage: %s -m [single|diversity|multiplex|cdd] -l [nof_layers] -p [nof_tx_ports]\n"
" -r [nof_rx_ports]\n", prog); " -r [nof_rx_ports]\n", prog);
printf("\t-n num_symbols [Default %d]\n", nof_symbols); 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) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "mplnrc")) != -1) { while ((opt = getopt(argc, argv, "mplnrcds")) != -1) {
switch (opt) { switch (opt) {
case 'n': case 'n':
nof_symbols = atoi(argv[optind]); nof_symbols = atoi(argv[optind]);
@ -72,6 +79,12 @@ void parse_args(int argc, char **argv) {
case 'c': case 'c':
codebook_idx = (uint32_t) atoi(argv[optind]); codebook_idx = (uint32_t) atoi(argv[optind]);
break; break;
case 'd':
strncpy(decoder_type_name, argv[optind], 16);
break;
case 's':
snr_db = (float) atof(argv[optind]);
break;
default: default:
usage(argv[0]); usage(argv[0]);
exit(-1); 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 main(int argc, char **argv) {
int i, j, k; int i, j, k, nof_errors = 0, ret = SRSLTE_SUCCESS;
float mse; float mse;
cf_t *x[SRSLTE_MAX_LAYERS], *r[SRSLTE_MAX_PORTS], *y[SRSLTE_MAX_PORTS], *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], 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]; *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 */ /* predecoding / equalization */
struct timeval t[3]; struct timeval t[3];
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
srslte_predecoding_type_multi(r, h, xr, nof_rx_ports, nof_tx_ports, nof_layers, 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); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
printf("Execution Time: %ld us\n", t[0].tv_usec);
/* check errors */ /* check errors */
mse = 0; mse = 0;
for (i = 0; i < nof_layers; i++) { for (i = 0; i < nof_layers; i++) {
for (j = 0; j < nof_symbols; j++) { for (j = 0; j < nof_symbols; j++) {
mse += cabsf(xr[i][j] - x[i][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) { if (mse / nof_layers / nof_symbols > MSE_THRESHOLD) {
exit(-1); ret = SRSLTE_ERROR;
} }
quit:
/* Free all data */ /* Free all data */
for (i = 0; i < nof_layers; i++) { for (i = 0; i < nof_layers; i++) {
free(x[i]); free(x[i]);
@ -284,6 +327,5 @@ int main(int argc, char **argv) {
} }
} }
printf("Ok\n"); exit(ret);
exit(0);
} }

@ -35,8 +35,10 @@
#define HEST prhs[1] #define HEST prhs[1]
#define NEST prhs[2] #define NEST prhs[2]
#define NLAYERS prhs[3] #define NLAYERS prhs[3]
#define TXSCHEME prhs[4] #define NCW prhs[4]
#define NOF_INPUTS 5 #define TXSCHEME prhs[5]
#define CODEBOOK prhs[6]
#define NOF_INPUTS 7
void help() void help()
@ -58,6 +60,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
uint32_t nof_layers; uint32_t nof_layers;
uint32_t nof_tx_ports = 1; uint32_t nof_tx_ports = 1;
uint32_t nof_codewords = 1; uint32_t nof_codewords = 1;
uint32_t codebook_idx = 0;
float noise_estimate = 0; float noise_estimate = 0;
cf_t *x[SRSLTE_MAX_LAYERS]; cf_t *x[SRSLTE_MAX_LAYERS];
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; 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 */ /* Read number of layers */
nof_layers = (uint32_t) mxGetScalar(NLAYERS); nof_layers = (uint32_t) mxGetScalar(NLAYERS);
/* Read number of codewords */
nof_codewords = (uint32_t) mxGetScalar(NCW);
if (nof_layers > SRSLTE_MAX_LAYERS) { if (nof_layers > SRSLTE_MAX_LAYERS) {
mexErrMsgTxt("Too many layers\n"); mexErrMsgTxt("Too many layers\n");
return; return;
@ -109,7 +115,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
/* Print parameters trace */ /* 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 */ /* Read noise estimate */
if (nrhs >= NOF_INPUTS) { if (nrhs >= NOF_INPUTS) {
@ -134,7 +141,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
/* Allocate memory for intermediate data */ /* Allocate memory for intermediate data */
for (i = 0; i < nof_tx_ports; i++) { 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 */ /* 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); mxGetString_700(TXSCHEME, txscheme, 32);
} }
if (!strcmp(txscheme, "Port0")) { codebook_idx = (uint32_t) mxGetScalar(CODEBOOK);
type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
} else if (!strcmp(txscheme, "TxDiversity")) { if (srslte_str2mimotype(txscheme, &type)) {
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 {
mexPrintf("Unsupported TxScheme=%s\n", txscheme); mexPrintf("Unsupported TxScheme=%s\n", txscheme);
return; return;
} }
@ -176,18 +177,19 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
/* Set output pointer */ /* Set output pointer */
cf_t *d[SRSLTE_MAX_CODEWORDS]; cf_t *d[SRSLTE_MAX_CODEWORDS];
for (i = 0; i<nof_codewords; i++) { for (i = 0; i<nof_codewords; i++) {
d[i] = output; d[i] = &output[i*nof_symbols*nof_layers/nof_codewords];
} }
/* Pre-decode */ /* 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 */ /* Layer de-mapper */
srslte_layerdemap_type(x, d, nof_layers, nof_codewords, nof_symbols, symbols_layers, type); srslte_layerdemap_type(x, d, nof_layers, nof_codewords, nof_symbols, symbols_layers, type);
/* Write output */ /* Write output */
if (nlhs >= 1) { 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 */ /* Free memory */

Loading…
Cancel
Save