|
|
|
@ -30,6 +30,8 @@
|
|
|
|
|
|
|
|
|
|
#include "srslte/srslte.h"
|
|
|
|
|
|
|
|
|
|
#define MAX_DATABUFFER_SIZE (6144 * 16 * 3 / 8)
|
|
|
|
|
|
|
|
|
|
srslte_cell_t cell = {
|
|
|
|
|
.nof_prb = 100,
|
|
|
|
|
.nof_ports = 1,
|
|
|
|
@ -39,14 +41,14 @@ srslte_cell_t cell = {
|
|
|
|
|
.phich_length = SRSLTE_PHICH_NORM
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
uint32_t tm = 0;
|
|
|
|
|
uint32_t transmission_mode = 1;
|
|
|
|
|
srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
|
|
|
|
|
uint32_t sf_idx = 5;
|
|
|
|
|
uint32_t cfi = 3;
|
|
|
|
|
uint32_t cfi = 1;
|
|
|
|
|
uint32_t nof_rx_ant = 1;
|
|
|
|
|
uint32_t nof_subframes = 10;
|
|
|
|
|
uint32_t nof_subframes = 100;
|
|
|
|
|
uint16_t rnti = 0x1234;
|
|
|
|
|
bool print_dci_table;
|
|
|
|
|
uint32_t mcs = 28;
|
|
|
|
|
|
|
|
|
|
void usage(char *prog) {
|
|
|
|
|
printf("Usage: %s [cfpndvs]\n", prog);
|
|
|
|
@ -56,12 +58,13 @@ void usage(char *prog) {
|
|
|
|
|
printf("\t-s number of subframes to simulate [Default %d]\n", nof_subframes);
|
|
|
|
|
printf("\t-d Print DCI table [Default %s]\n", print_dci_table ? "yes" : "no");
|
|
|
|
|
printf("\t-x MIMO Type: single, diversity, cdd, multiplex [Default %s]\n", srslte_mimotype2str(mimo_type));
|
|
|
|
|
printf("\t-m mcs [Default %d]\n", mcs);
|
|
|
|
|
printf("\t-v [set srslte_verbose to debug, default none]\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void parse_args(int argc, char **argv) {
|
|
|
|
|
int opt;
|
|
|
|
|
while ((opt = getopt(argc, argv, "cfpndvsx")) != -1) {
|
|
|
|
|
while ((opt = getopt(argc, argv, "cfpndvsxm")) != -1) {
|
|
|
|
|
switch (opt) {
|
|
|
|
|
case 'x':
|
|
|
|
|
if (srslte_str2mimotype(argv[optind], &mimo_type)) {
|
|
|
|
@ -72,18 +75,25 @@ void parse_args(int argc, char **argv) {
|
|
|
|
|
if (mimo_type == SRSLTE_MIMO_TYPE_SINGLE_ANTENNA) {
|
|
|
|
|
cell.nof_ports = 1;
|
|
|
|
|
nof_rx_ant = 1;
|
|
|
|
|
tm = 0;
|
|
|
|
|
transmission_mode = 1;
|
|
|
|
|
} else {
|
|
|
|
|
cell.nof_ports = 2;
|
|
|
|
|
nof_rx_ant = 2;
|
|
|
|
|
if (mimo_type == SRSLTE_MIMO_TYPE_TX_DIVERSITY) {
|
|
|
|
|
tm = 2;
|
|
|
|
|
transmission_mode = 2;
|
|
|
|
|
} else if (mimo_type == SRSLTE_MIMO_TYPE_CDD) {
|
|
|
|
|
transmission_mode = 3;
|
|
|
|
|
} else {
|
|
|
|
|
transmission_mode = 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
cfi = (uint32_t) atoi(argv[optind]);
|
|
|
|
|
break;
|
|
|
|
|
case 'm':
|
|
|
|
|
mcs = (uint32_t) atoi(argv[optind]);
|
|
|
|
|
break;
|
|
|
|
|
case 'p':
|
|
|
|
|
cell.nof_prb = (uint32_t) atoi(argv[optind]);
|
|
|
|
|
break;
|
|
|
|
@ -109,6 +119,53 @@ void parse_args(int argc, char **argv) {
|
|
|
|
|
int prbset_num = 1, last_prbset_num = 1;
|
|
|
|
|
int prbset_orig = 0;
|
|
|
|
|
|
|
|
|
|
int work_enb(srslte_enb_dl_t *enb_dl,
|
|
|
|
|
srslte_dci_format_t dci_format,
|
|
|
|
|
srslte_ra_dl_dci_t *dci,
|
|
|
|
|
srslte_ra_dl_grant_t *grant,
|
|
|
|
|
srslte_softbuffer_tx_t **softbuffer_tx,
|
|
|
|
|
uint32_t sf_idx, uint8_t **data_tx) {
|
|
|
|
|
int ret = SRSLTE_ERROR;
|
|
|
|
|
|
|
|
|
|
srslte_dci_location_t location = {
|
|
|
|
|
.ncce = 8,
|
|
|
|
|
.L = 3
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
srslte_enb_dl_clear_sf(enb_dl);
|
|
|
|
|
|
|
|
|
|
srslte_enb_dl_put_base(enb_dl, sf_idx);
|
|
|
|
|
|
|
|
|
|
if (srslte_enb_dl_put_pdcch_dl(enb_dl,
|
|
|
|
|
dci,
|
|
|
|
|
dci_format,
|
|
|
|
|
location,
|
|
|
|
|
rnti,
|
|
|
|
|
sf_idx % 10) < 0) {
|
|
|
|
|
fprintf(stderr, "Error putting PDCCH\n");
|
|
|
|
|
goto quit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (srslte_enb_dl_put_pdsch(enb_dl,
|
|
|
|
|
grant,
|
|
|
|
|
softbuffer_tx,
|
|
|
|
|
rnti,
|
|
|
|
|
(int[SRSLTE_MAX_CODEWORDS]) {dci->rv_idx, dci->rv_idx_1},
|
|
|
|
|
sf_idx % 10,
|
|
|
|
|
data_tx,
|
|
|
|
|
mimo_type) < 0) {
|
|
|
|
|
fprintf(stderr, "Error putting PDSCH\n");
|
|
|
|
|
goto quit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srslte_enb_dl_gen_signal(enb_dl);
|
|
|
|
|
|
|
|
|
|
ret = SRSLTE_SUCCESS;
|
|
|
|
|
|
|
|
|
|
quit:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
|
reverse(register unsigned int x) {
|
|
|
|
|
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
|
|
|
|
@ -131,13 +188,17 @@ uint32_t prbset_to_bitmask() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
|
struct timeval t[3] = {};
|
|
|
|
|
size_t tx_nof_bits = 0, rx_nof_bits = 0;
|
|
|
|
|
srslte_enb_dl_t enb_dl = {};
|
|
|
|
|
srslte_ue_dl_t ue_dl = {};
|
|
|
|
|
srslte_softbuffer_tx_t *softbuffer_tx[SRSLTE_MAX_TB] = {};
|
|
|
|
|
srslte_softbuffer_rx_t *softbuffer_rx[SRSLTE_MAX_TB] = {};
|
|
|
|
|
uint8_t *data_tx[SRSLTE_MAX_TB] = {};
|
|
|
|
|
uint8_t *data_rx[SRSLTE_MAX_TB] = {};
|
|
|
|
|
uint32_t count_failures = 0;
|
|
|
|
|
uint32_t count_failures = 0, count_tbs = 0;
|
|
|
|
|
size_t pdsch_decode_us = 0;
|
|
|
|
|
size_t pdsch_encode_us = 0;
|
|
|
|
|
|
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
|
@ -179,13 +240,13 @@ int main(int argc, char **argv) {
|
|
|
|
|
goto quit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * 150000);
|
|
|
|
|
data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * MAX_DATABUFFER_SIZE);
|
|
|
|
|
if (!data_tx[i]) {
|
|
|
|
|
fprintf(stderr, "Error allocating data tx\n");
|
|
|
|
|
goto quit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data_rx[i] = srslte_vec_malloc(sizeof(uint8_t) * 150000);
|
|
|
|
|
data_rx[i] = srslte_vec_malloc(sizeof(uint8_t) * MAX_DATABUFFER_SIZE);
|
|
|
|
|
if (!data_rx[i]) {
|
|
|
|
|
fprintf(stderr, "Error allocating data tx\n");
|
|
|
|
|
goto quit;
|
|
|
|
@ -223,42 +284,53 @@ int main(int argc, char **argv) {
|
|
|
|
|
|
|
|
|
|
srslte_ue_dl_set_rnti(&ue_dl, rnti);
|
|
|
|
|
|
|
|
|
|
srslte_chest_dl_average_subframe(&ue_dl.chest, true);
|
|
|
|
|
//srslte_chest_dl_set_smooth_filter_gauss(&ue_dl.chest, 4, 1.0f);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Loop
|
|
|
|
|
*/
|
|
|
|
|
INFO("--- Starting test ---\n");
|
|
|
|
|
for (uint32_t sf_idx = 0; sf_idx < nof_subframes; sf_idx++) {
|
|
|
|
|
bool acks[SRSLTE_MAX_TB] = {};
|
|
|
|
|
|
|
|
|
|
/* Run eNodeB */
|
|
|
|
|
srslte_enb_dl_clear_sf(&enb_dl);
|
|
|
|
|
|
|
|
|
|
srslte_enb_dl_put_base(&enb_dl, sf_idx);
|
|
|
|
|
/* Generate random data */
|
|
|
|
|
for (int t = 0; t < SRSLTE_MAX_TB; t++) {
|
|
|
|
|
for (int i = 0; i < MAX_DATABUFFER_SIZE; i++) {
|
|
|
|
|
data_tx[t][i] = (uint8_t) (rand() & 0xff);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Run eNodeB
|
|
|
|
|
*/
|
|
|
|
|
srslte_ra_dl_dci_t dci = {};
|
|
|
|
|
srslte_dci_format_t dci_format = SRSLTE_DCI_FORMAT1A;
|
|
|
|
|
srslte_ra_dl_grant_t grant = {};
|
|
|
|
|
|
|
|
|
|
prbset_num = (int) ceilf((float) cell.nof_prb / srslte_ra_type0_P(cell.nof_prb));
|
|
|
|
|
last_prbset_num = prbset_num;
|
|
|
|
|
|
|
|
|
|
/* Pupulate TB Common */
|
|
|
|
|
dci.harq_process = 0;
|
|
|
|
|
|
|
|
|
|
/* Pupulate TB0 */
|
|
|
|
|
dci.mcs_idx = 0;
|
|
|
|
|
dci.mcs_idx = mcs;
|
|
|
|
|
dci.ndi = 0;
|
|
|
|
|
dci.rv_idx = 0;
|
|
|
|
|
dci.tb_en[0] = true;
|
|
|
|
|
|
|
|
|
|
if (mimo_type == SRSLTE_MIMO_TYPE_CDD || mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
|
|
|
|
|
dci_format = SRSLTE_DCI_FORMAT2B;
|
|
|
|
|
dci_format = (transmission_mode == 3) ? SRSLTE_DCI_FORMAT2A : SRSLTE_DCI_FORMAT2;
|
|
|
|
|
|
|
|
|
|
/* Pupulate TB1 */
|
|
|
|
|
dci.mcs_idx_1 = 0;
|
|
|
|
|
dci.mcs_idx_1 = mcs;
|
|
|
|
|
dci.ndi_1 = 0;
|
|
|
|
|
dci.rv_idx_1 = 0;
|
|
|
|
|
dci.tb_en[1] = true;
|
|
|
|
|
|
|
|
|
|
/* Pupulate Allocation */
|
|
|
|
|
dci.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
|
|
|
|
|
dci.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
|
|
|
|
|
dci.type0_alloc.rbg_bitmask = prbset_to_bitmask();
|
|
|
|
|
} else {
|
|
|
|
|
dci_format = SRSLTE_DCI_FORMAT1A;
|
|
|
|
@ -275,62 +347,62 @@ int main(int argc, char **argv) {
|
|
|
|
|
dci.dci_is_1c = (dci_format == SRSLTE_DCI_FORMAT1C);
|
|
|
|
|
|
|
|
|
|
srslte_ra_dl_dci_to_grant(&dci, cell.nof_prb, rnti, &grant);
|
|
|
|
|
INFO("--- Process Uplink ---\n");
|
|
|
|
|
|
|
|
|
|
srslte_dci_location_t location = {
|
|
|
|
|
.ncce = 0,
|
|
|
|
|
.L = 2
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (int t = 0; t < SRSLTE_RA_DL_GRANT_NOF_TB(&grant); t++) {
|
|
|
|
|
for (int i = 0; i < grant.mcs->tbs; i++) {
|
|
|
|
|
data_tx[t][i] = (uint8_t) (rand() & 0xff);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (srslte_enb_dl_put_pdcch_dl(&enb_dl,
|
|
|
|
|
&dci,
|
|
|
|
|
dci_format,
|
|
|
|
|
location,
|
|
|
|
|
rnti,
|
|
|
|
|
sf_idx % 10) < 0) {
|
|
|
|
|
fprintf(stderr, "Error putting PDCCH\n");
|
|
|
|
|
gettimeofday(&t[1], NULL);
|
|
|
|
|
if (work_enb(&enb_dl, dci_format, &dci, &grant, softbuffer_tx, sf_idx, data_tx)) {
|
|
|
|
|
goto quit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (srslte_enb_dl_put_pdsch(&enb_dl,
|
|
|
|
|
&grant,
|
|
|
|
|
softbuffer_tx,
|
|
|
|
|
rnti,
|
|
|
|
|
(int[SRSLTE_MAX_CODEWORDS]) {dci.rv_idx, dci.rv_idx_1},
|
|
|
|
|
sf_idx % 10,
|
|
|
|
|
data_tx,
|
|
|
|
|
mimo_type) < 0) {
|
|
|
|
|
fprintf(stderr, "Error putting PDSCH\n");
|
|
|
|
|
goto quit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srslte_enb_dl_gen_signal(&enb_dl);
|
|
|
|
|
|
|
|
|
|
/* Run UE */
|
|
|
|
|
int n = srslte_ue_dl_decode(&ue_dl, data_rx, tm, sf_idx, acks);
|
|
|
|
|
gettimeofday(&t[2], NULL);
|
|
|
|
|
get_time_interval(t);
|
|
|
|
|
pdsch_encode_us += t[0].tv_sec * 1e6 + t[0].tv_usec;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Run UE
|
|
|
|
|
*/
|
|
|
|
|
INFO("--- Process Downlink ---\n");
|
|
|
|
|
gettimeofday(&t[1], NULL);
|
|
|
|
|
int n = srslte_ue_dl_decode(&ue_dl, data_rx, transmission_mode - 1, sf_idx, acks);
|
|
|
|
|
if (n < 0) {
|
|
|
|
|
fprintf(stderr, "Error decoding PDSCH\n");
|
|
|
|
|
goto quit;
|
|
|
|
|
}
|
|
|
|
|
gettimeofday(&t[2], NULL);
|
|
|
|
|
get_time_interval(t);
|
|
|
|
|
pdsch_decode_us += t[0].tv_sec * 1e6 + t[0].tv_usec;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < SRSLTE_RA_DL_GRANT_NOF_TB(&grant); i++) {
|
|
|
|
|
if (!acks[i]) {
|
|
|
|
|
INFO("UE Failed decoding subframe %d\n", sf_idx);
|
|
|
|
|
if (!acks[i] || memcmp(data_tx[i], data_rx[i], grant.mcs[i].tbs / 8) != 0) {
|
|
|
|
|
printf("UE Failed decoding tb %d in subframe %d\n", i, sf_idx);
|
|
|
|
|
srslte_vec_fprint_hex(stdout, data_tx[i], grant.mcs[i].tbs / 8);
|
|
|
|
|
srslte_vec_fprint_hex(stdout, data_rx[i], grant.mcs[i].tbs / 8);
|
|
|
|
|
count_failures++;
|
|
|
|
|
}
|
|
|
|
|
count_tbs++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tx_nof_bits += (enb_dl.pdsch_cfg.grant.tb_en[0] ? enb_dl.pdsch_cfg.grant.mcs[0].tbs : 0);
|
|
|
|
|
tx_nof_bits += (enb_dl.pdsch_cfg.grant.tb_en[1] ? enb_dl.pdsch_cfg.grant.mcs[1].tbs : 0);
|
|
|
|
|
rx_nof_bits += (acks[0] ? ue_dl.pdsch_cfg.grant.mcs[0].tbs : 0);
|
|
|
|
|
rx_nof_bits += (acks[1] ? ue_dl.pdsch_cfg.grant.mcs[1].tbs : 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("Finished! The UE failed decoding %d of %d.\n", count_failures, nof_subframes);
|
|
|
|
|
printf("Finished! The UE failed decoding %d of %d transport blocks.\n", count_failures, count_tbs);
|
|
|
|
|
if (!count_failures) {
|
|
|
|
|
ret = SRSLTE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("%ld were transmitted, %ld bits were received.\n", tx_nof_bits, rx_nof_bits);
|
|
|
|
|
printf("[Rates in Mbps] Granted Processed\n");
|
|
|
|
|
printf(" eNb: %5.1f %5.1f\n",
|
|
|
|
|
(float) tx_nof_bits / (float) nof_subframes / 1000.0f,
|
|
|
|
|
(float) rx_nof_bits / pdsch_encode_us);
|
|
|
|
|
printf(" UE: %5.1f %5.1f\n",
|
|
|
|
|
(float) rx_nof_bits / (float) nof_subframes / 1000.0f,
|
|
|
|
|
(float) rx_nof_bits / pdsch_decode_us);
|
|
|
|
|
|
|
|
|
|
printf("BLER: %5.1f%%\n", (float) count_failures / (float) count_tbs * 100.0f);
|
|
|
|
|
|
|
|
|
|
quit:
|
|
|
|
|
srslte_enb_dl_free(&enb_dl);
|
|
|
|
|
srslte_ue_dl_free(&ue_dl);
|
|
|
|
|