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_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,11 +120,11 @@ 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,
|
||||||
uint32_t *pmi,
|
uint32_t *pmi,
|
||||||
float sinr[SRSLTE_MAX_CODEBOOKS]);
|
float sinr[SRSLTE_MAX_CODEBOOKS]);
|
||||||
|
|
||||||
#endif /* PRECODING_H_ */
|
#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_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…
Reference in New Issue