|
|
@ -35,11 +35,14 @@ static uint32_t mcs = 30; // Set to 30 for steering
|
|
|
|
static srslte_pdsch_cfg_nr_t pdsch_cfg = {};
|
|
|
|
static srslte_pdsch_cfg_nr_t pdsch_cfg = {};
|
|
|
|
static srslte_pdsch_grant_nr_t pdsch_grant = {};
|
|
|
|
static srslte_pdsch_grant_nr_t pdsch_grant = {};
|
|
|
|
static uint16_t rnti = 0x1234;
|
|
|
|
static uint16_t rnti = 0x1234;
|
|
|
|
|
|
|
|
static uint32_t nof_slots = 10;
|
|
|
|
|
|
|
|
|
|
|
|
void usage(char* prog)
|
|
|
|
void usage(char* prog)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
printf("Usage: %s [pTL] \n", prog);
|
|
|
|
printf("Usage: %s [pTL] \n", prog);
|
|
|
|
|
|
|
|
printf("\t-P Number of BWP (Carrier) PRB [Default %d]\n", carrier.nof_prb);
|
|
|
|
printf("\t-p Number of grant PRB, set to 0 for steering [Default %d]\n", n_prb);
|
|
|
|
printf("\t-p Number of grant PRB, set to 0 for steering [Default %d]\n", n_prb);
|
|
|
|
|
|
|
|
printf("\t-n Number of slots to simulate [Default %d]\n", nof_slots);
|
|
|
|
printf("\t-m MCS PRB, set to >28 for steering [Default %d]\n", mcs);
|
|
|
|
printf("\t-m MCS PRB, set to >28 for steering [Default %d]\n", mcs);
|
|
|
|
printf("\t-T Provide MCS table (64qam, 256qam, 64qamLowSE) [Default %s]\n",
|
|
|
|
printf("\t-T Provide MCS table (64qam, 256qam, 64qamLowSE) [Default %s]\n",
|
|
|
|
srslte_mcs_table_to_str(pdsch_cfg.sch_cfg.mcs_table));
|
|
|
|
srslte_mcs_table_to_str(pdsch_cfg.sch_cfg.mcs_table));
|
|
|
@ -50,11 +53,17 @@ void usage(char* prog)
|
|
|
|
int parse_args(int argc, char** argv)
|
|
|
|
int parse_args(int argc, char** argv)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int opt;
|
|
|
|
int opt;
|
|
|
|
while ((opt = getopt(argc, argv, "pmTLv")) != -1) {
|
|
|
|
while ((opt = getopt(argc, argv, "PpmnTLv")) != -1) {
|
|
|
|
switch (opt) {
|
|
|
|
switch (opt) {
|
|
|
|
|
|
|
|
case 'P':
|
|
|
|
|
|
|
|
carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
case 'p':
|
|
|
|
n_prb = (uint32_t)strtol(argv[optind], NULL, 10);
|
|
|
|
n_prb = (uint32_t)strtol(argv[optind], NULL, 10);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
|
|
|
|
nof_slots = (uint32_t)strtol(argv[optind], NULL, 10);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
case 'm':
|
|
|
|
mcs = (uint32_t)strtol(argv[optind], NULL, 10);
|
|
|
|
mcs = (uint32_t)strtol(argv[optind], NULL, 10);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -76,6 +85,62 @@ int parse_args(int argc, char** argv)
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int work_gnb_dl(srslte_enb_dl_nr_t* enb_dl,
|
|
|
|
|
|
|
|
srslte_dl_slot_cfg_t* slot,
|
|
|
|
|
|
|
|
srslte_search_space_t* search_space,
|
|
|
|
|
|
|
|
srslte_dci_dl_nr_t* dci_dl,
|
|
|
|
|
|
|
|
srslte_dci_location_t* dci_location,
|
|
|
|
|
|
|
|
uint8_t** data_tx)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (srslte_enb_dl_nr_base_zero(enb_dl) < SRSLTE_SUCCESS) {
|
|
|
|
|
|
|
|
ERROR("Error setting base to zero\n");
|
|
|
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Put actual DCI
|
|
|
|
|
|
|
|
if (srslte_enb_dl_nr_pdcch_put(enb_dl, slot, search_space, dci_dl, dci_location, rnti) < SRSLTE_SUCCESS) {
|
|
|
|
|
|
|
|
ERROR("Error putting PDCCH\n");
|
|
|
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Put PDSCH transmission
|
|
|
|
|
|
|
|
if (srslte_enb_dl_nr_pdsch_put(enb_dl, slot, &pdsch_cfg, &pdsch_grant, data_tx) < SRSLTE_SUCCESS) {
|
|
|
|
|
|
|
|
ERROR("Error putting PDSCH\n");
|
|
|
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
srslte_enb_dl_nr_gen_signal(enb_dl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int work_ue_dl(srslte_ue_dl_nr_t* ue_dl,
|
|
|
|
|
|
|
|
srslte_dl_slot_cfg_t* slot,
|
|
|
|
|
|
|
|
srslte_search_space_t* search_space,
|
|
|
|
|
|
|
|
srslte_pdsch_res_nr_t* pdsch_res)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
srslte_ue_dl_nr_estimate_fft(ue_dl, slot);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
srslte_dci_dl_nr_t dci_dl_rx = {};
|
|
|
|
|
|
|
|
int nof_found_dci = srslte_ue_dl_nr_find_dl_dci(ue_dl, search_space, slot, rnti, &dci_dl_rx, 1);
|
|
|
|
|
|
|
|
if (nof_found_dci < SRSLTE_SUCCESS) {
|
|
|
|
|
|
|
|
ERROR("Error decoding\n");
|
|
|
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nof_found_dci < 1) {
|
|
|
|
|
|
|
|
ERROR("Error DCI not found\n");
|
|
|
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (srslte_ue_dl_nr_pdsch_get(ue_dl, slot, &pdsch_cfg, &pdsch_grant, pdsch_res) < SRSLTE_SUCCESS) {
|
|
|
|
|
|
|
|
ERROR("Error decoding\n");
|
|
|
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char** argv)
|
|
|
|
int main(int argc, char** argv)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int ret = SRSLTE_ERROR;
|
|
|
|
int ret = SRSLTE_ERROR;
|
|
|
@ -84,6 +149,10 @@ int main(int argc, char** argv)
|
|
|
|
srslte_pdsch_res_nr_t pdsch_res[SRSLTE_MAX_TB] = {};
|
|
|
|
srslte_pdsch_res_nr_t pdsch_res[SRSLTE_MAX_TB] = {};
|
|
|
|
srslte_random_t rand_gen = srslte_random_init(1234);
|
|
|
|
srslte_random_t rand_gen = srslte_random_init(1234);
|
|
|
|
srslte_dl_slot_cfg_t slot = {};
|
|
|
|
srslte_dl_slot_cfg_t slot = {};
|
|
|
|
|
|
|
|
struct timeval t[3] = {};
|
|
|
|
|
|
|
|
uint64_t pdsch_encode_us = 0;
|
|
|
|
|
|
|
|
uint64_t pdsch_decode_us = 0;
|
|
|
|
|
|
|
|
uint64_t nof_bits = 0;
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t* data_tx[SRSLTE_MAX_TB] = {};
|
|
|
|
uint8_t* data_tx[SRSLTE_MAX_TB] = {};
|
|
|
|
uint8_t* data_rx[SRSLTE_MAX_CODEWORDS] = {};
|
|
|
|
uint8_t* data_rx[SRSLTE_MAX_CODEWORDS] = {};
|
|
|
@ -97,15 +166,16 @@ int main(int argc, char** argv)
|
|
|
|
|
|
|
|
|
|
|
|
srslte_ue_dl_nr_args_t ue_dl_args = {};
|
|
|
|
srslte_ue_dl_nr_args_t ue_dl_args = {};
|
|
|
|
ue_dl_args.nof_rx_antennas = 1;
|
|
|
|
ue_dl_args.nof_rx_antennas = 1;
|
|
|
|
ue_dl_args.nof_max_prb = MAX_PRB;
|
|
|
|
ue_dl_args.pdsch.sch.disable_simd = false;
|
|
|
|
ue_dl_args.pdsch.sch.disable_simd = true;
|
|
|
|
ue_dl_args.pdsch.sch.decoder_use_flooded = false;
|
|
|
|
ue_dl_args.pdsch.measure_evm = true;
|
|
|
|
ue_dl_args.pdsch.measure_evm = true;
|
|
|
|
ue_dl_args.pdsch.measure_time = true;
|
|
|
|
ue_dl_args.pdcch.disable_simd = false;
|
|
|
|
|
|
|
|
ue_dl_args.pdcch.measure_evm = true;
|
|
|
|
|
|
|
|
|
|
|
|
srslte_enb_dl_nr_args_t enb_dl_args = {};
|
|
|
|
srslte_enb_dl_nr_args_t enb_dl_args = {};
|
|
|
|
enb_dl_args.nof_tx_antennas = 1;
|
|
|
|
enb_dl_args.nof_tx_antennas = 1;
|
|
|
|
enb_dl_args.nof_max_prb = MAX_PRB;
|
|
|
|
enb_dl_args.pdsch.sch.disable_simd = false;
|
|
|
|
enb_dl_args.pdsch.sch.disable_simd = true;
|
|
|
|
enb_dl_args.pdcch.disable_simd = false;
|
|
|
|
|
|
|
|
|
|
|
|
// Set default PDSCH configuration
|
|
|
|
// Set default PDSCH configuration
|
|
|
|
pdsch_cfg.sch_cfg.mcs_table = srslte_mcs_table_64qam;
|
|
|
|
pdsch_cfg.sch_cfg.mcs_table = srslte_mcs_table_64qam;
|
|
|
@ -113,21 +183,17 @@ int main(int argc, char** argv)
|
|
|
|
goto clean_exit;
|
|
|
|
goto clean_exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
srslte_pdsch_nr_args_t pdsch_args = {};
|
|
|
|
|
|
|
|
pdsch_args.sch.disable_simd = true;
|
|
|
|
|
|
|
|
pdsch_args.measure_evm = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Configure CORESET
|
|
|
|
// Configure CORESET
|
|
|
|
srslte_coreset_t coreset = {};
|
|
|
|
srslte_coreset_t coreset = {};
|
|
|
|
coreset.duration = 2;
|
|
|
|
coreset.duration = 2;
|
|
|
|
for (uint32_t i = 0; i < SRSLTE_CORESET_FREQ_DOMAIN_RES_SIZE; i++) {
|
|
|
|
for (uint32_t i = 0; i < SRSLTE_CORESET_FREQ_DOMAIN_RES_SIZE; i++) {
|
|
|
|
coreset.freq_resources[i] = i < carrier.nof_prb;
|
|
|
|
coreset.freq_resources[i] = i < carrier.nof_prb / 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Configure Search Space
|
|
|
|
// Configure Search Space
|
|
|
|
srslte_search_space_t search_space = {};
|
|
|
|
srslte_search_space_t search_space = {};
|
|
|
|
search_space.type = srslte_search_space_type_ue;
|
|
|
|
search_space.type = srslte_search_space_type_ue;
|
|
|
|
for (uint32_t L = 0; L < SRSLTE_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR; L++) {
|
|
|
|
for (uint32_t L = 0; L < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; L++) {
|
|
|
|
search_space.nof_candidates[L] = srslte_pdcch_nr_max_candidates_coreset(&coreset, L);
|
|
|
|
search_space.nof_candidates[L] = srslte_pdcch_nr_max_candidates_coreset(&coreset, L);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -210,8 +276,10 @@ int main(int argc, char** argv)
|
|
|
|
mcs_end = SRSLTE_MIN(mcs + 1, mcs_end);
|
|
|
|
mcs_end = SRSLTE_MIN(mcs + 1, mcs_end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t slot_count = 0;
|
|
|
|
|
|
|
|
for (slot.idx = 0; slot.idx < nof_slots; slot.idx++) {
|
|
|
|
for (n_prb = n_prb_start; n_prb < n_prb_end; n_prb++) {
|
|
|
|
for (n_prb = n_prb_start; n_prb < n_prb_end; n_prb++) {
|
|
|
|
for (mcs = mcs_start; mcs < mcs_end; mcs++) {
|
|
|
|
for (mcs = mcs_start; mcs < mcs_end; mcs++, slot_count++) {
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t n = 0; n < SRSLTE_MAX_PRB_NR; n++) {
|
|
|
|
for (uint32_t n = 0; n < SRSLTE_MAX_PRB_NR; n++) {
|
|
|
|
pdsch_grant.prb_idx[n] = (n < n_prb);
|
|
|
|
pdsch_grant.prb_idx[n] = (n < n_prb);
|
|
|
@ -252,43 +320,28 @@ int main(int argc, char** argv)
|
|
|
|
// Setup DCI
|
|
|
|
// Setup DCI
|
|
|
|
srslte_dci_dl_nr_t dci_dl = {};
|
|
|
|
srslte_dci_dl_nr_t dci_dl = {};
|
|
|
|
|
|
|
|
|
|
|
|
// Put actual DCI
|
|
|
|
gettimeofday(&t[1], NULL);
|
|
|
|
if (srslte_enb_dl_nr_pdcch_put(&enb_dl, &slot, &search_space, &dci_dl, &dci_location, rnti) < SRSLTE_SUCCESS) {
|
|
|
|
if (work_gnb_dl(&enb_dl, &slot, &search_space, &dci_dl, &dci_location, data_tx) < SRSLTE_ERROR) {
|
|
|
|
ERROR("Error putting PDCCH\n");
|
|
|
|
ERROR("Error running eNb DL\n");
|
|
|
|
goto clean_exit;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Put PDSCH transmission
|
|
|
|
|
|
|
|
if (srslte_enb_dl_nr_pdsch_put(&enb_dl, &slot, &pdsch_cfg, &pdsch_grant, data_tx) < SRSLTE_SUCCESS) {
|
|
|
|
|
|
|
|
ERROR("Error putting PDSCH\n");
|
|
|
|
|
|
|
|
goto clean_exit;
|
|
|
|
goto clean_exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gettimeofday(&t[2], NULL);
|
|
|
|
srslte_enb_dl_nr_gen_signal(&enb_dl);
|
|
|
|
get_time_interval(t);
|
|
|
|
|
|
|
|
pdsch_encode_us += (size_t)(t[0].tv_sec * 1e6 + t[0].tv_usec);
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
|
|
|
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
|
|
|
|
pdsch_grant.tb[tb].softbuffer.rx = &softbuffer_rx;
|
|
|
|
pdsch_grant.tb[tb].softbuffer.rx = &softbuffer_rx;
|
|
|
|
srslte_softbuffer_rx_reset(pdsch_grant.tb[tb].softbuffer.rx);
|
|
|
|
srslte_softbuffer_rx_reset(pdsch_grant.tb[tb].softbuffer.rx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
srslte_ue_dl_nr_estimate_fft(&ue_dl, &slot);
|
|
|
|
gettimeofday(&t[1], NULL);
|
|
|
|
|
|
|
|
if (work_ue_dl(&ue_dl, &slot, &search_space, pdsch_res) < SRSLTE_SUCCESS) {
|
|
|
|
srslte_dci_dl_nr_t dci_dl_rx = {};
|
|
|
|
ERROR("Error running UE DL\n");
|
|
|
|
int nof_found_dci = srslte_ue_dl_nr_find_dl_dci(&ue_dl, &search_space, &slot, rnti, &dci_dl_rx, 1);
|
|
|
|
|
|
|
|
if (nof_found_dci < SRSLTE_SUCCESS) {
|
|
|
|
|
|
|
|
ERROR("Error decoding\n");
|
|
|
|
|
|
|
|
goto clean_exit;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nof_found_dci < 1) {
|
|
|
|
|
|
|
|
ERROR("Error DCI not found\n");
|
|
|
|
|
|
|
|
goto clean_exit;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (srslte_ue_dl_nr_pdsch_get(&ue_dl, &slot, &pdsch_cfg, &pdsch_grant, pdsch_res) < SRSLTE_SUCCESS) {
|
|
|
|
|
|
|
|
ERROR("Error decoding\n");
|
|
|
|
|
|
|
|
goto clean_exit;
|
|
|
|
goto clean_exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gettimeofday(&t[2], NULL);
|
|
|
|
|
|
|
|
get_time_interval(t);
|
|
|
|
|
|
|
|
pdsch_decode_us += (size_t)(t[0].tv_sec * 1e6 + t[0].tv_usec);
|
|
|
|
|
|
|
|
|
|
|
|
if (pdsch_res->evm > 0.001f) {
|
|
|
|
if (pdsch_res->evm > 0.001f) {
|
|
|
|
ERROR("Error PDSCH EVM is too high %f\n", pdsch_res->evm);
|
|
|
|
ERROR("Error PDSCH EVM is too high %f\n", pdsch_res->evm);
|
|
|
@ -309,9 +362,21 @@ int main(int argc, char** argv)
|
|
|
|
goto clean_exit;
|
|
|
|
goto clean_exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pdsch_grant.tb[0].tbs, pdsch_res[0].evm);
|
|
|
|
INFO("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pdsch_grant.tb[0].tbs, pdsch_res[0].evm);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Count the Tx/Rx'd number of bits
|
|
|
|
|
|
|
|
nof_bits += pdsch_grant.tb[0].tbs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("[Rates in Mbps] Granted Processed\n");
|
|
|
|
|
|
|
|
printf(" eNb: %5.1f %5.1f\n",
|
|
|
|
|
|
|
|
(double)nof_bits / (double)slot_count / 1000.0f,
|
|
|
|
|
|
|
|
(double)nof_bits / pdsch_encode_us);
|
|
|
|
|
|
|
|
printf(" UE: %5.1f %5.1f\n",
|
|
|
|
|
|
|
|
(double)nof_bits / (double)slot_count / 1000.0f,
|
|
|
|
|
|
|
|
(double)nof_bits / pdsch_decode_us);
|
|
|
|
|
|
|
|
|
|
|
|
ret = SRSLTE_SUCCESS;
|
|
|
|
ret = SRSLTE_SUCCESS;
|
|
|
|
|
|
|
|
|
|
|
|