Now working with variable HARQ scheduling

master
Ismael Gomez 7 years ago
parent fb0a918f7a
commit ca0cf017d6

@ -44,13 +44,15 @@
#define SRSLTE_N_DRB 8 #define SRSLTE_N_DRB 8
#define SRSLTE_N_RADIO_BEARERS 11 #define SRSLTE_N_RADIO_BEARERS 11
#define HARQ_DELAY_MS 4 #define HARQ_DELAY_MS 6
#define MSG3_DELAY_MS 6 #define MSG3_DELAY_MS 6
#define HARQ_TX(tti) ((tti+HARQ_DELAY_MS)%10240) #define TTI_TX(tti) ((tti+HARQ_DELAY_MS)%10240)
#define HARQ_RX(tti) ((tti+(2*HARQ_DELAY_MS))%10240) #define TTI_RX_ACK(tti) ((tti+(2*HARQ_DELAY_MS))%10240)
#define TTIMOD_SZ 10 #define TTIMOD_SZ 20
#define TTIMOD(tti) (tti%TTIMOD_SZ) #define TTIMOD(tti) (tti%TTIMOD_SZ)
#define ASYNC_DL_SCHED (HARQ_DELAY_MS <= 4)
// Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI // Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI
// 3GPP 36.306 Table 4.1.1 // 3GPP 36.306 Table 4.1.1

@ -89,9 +89,9 @@ private:
cf_t *signal_buffer_rx; cf_t *signal_buffer_rx;
cf_t *signal_buffer_tx; cf_t *signal_buffer_tx;
uint32_t tti_rx, tti_tx, tti_sched_ul; uint32_t tti_rx, tti_tx_dl, tti_tx_ul;
uint32_t sf_rx, sf_tx, tx_mutex_cnt; uint32_t sf_rx, sf_tx, tx_mutex_cnt;
uint32_t t_rx, t_tx, t_sched_ul; uint32_t t_rx, t_tx_dl, t_tx_ul;
srslte_enb_dl_t enb_dl; srslte_enb_dl_t enb_dl;
srslte_enb_ul_t enb_ul; srslte_enb_ul_t enb_ul;

@ -677,14 +677,14 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
/* If dl_sched() not yet called this tti (this tti is +4ms advanced), reset CCE state */ /* If dl_sched() not yet called this tti (this tti is +4ms advanced), reset CCE state */
if (HARQ_TX(current_tti) != tti) { if (TTI_TX(current_tti) != tti) {
bzero(used_cce, MAX_CCE*sizeof(bool)); bzero(used_cce, MAX_CCE*sizeof(bool));
} }
/* Initialize variables */ /* Initialize variables */
current_tti = tti; current_tti = tti;
sfn = tti/10; sfn = tti/10;
if (tti > 4) { if (tti > HARQ_DELAY_MS) {
sf_idx = (tti-HARQ_DELAY_MS)%10; sf_idx = (tti-HARQ_DELAY_MS)%10;
} else { } else {
sf_idx = (tti+10240-HARQ_DELAY_MS)%10; sf_idx = (tti+10240-HARQ_DELAY_MS)%10;

@ -142,8 +142,12 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user)
dl_harq_proc *h = user->get_pending_dl_harq(current_tti); dl_harq_proc *h = user->get_pending_dl_harq(current_tti);
// Time-domain RR scheduling // Time-domain RR scheduling
#if ASYNC_DL_SCHED
if (pending_data || h) { if (pending_data || h) {
if (nof_users_with_data) { #else
if (pending_data || (h && !h->is_empty())) {
#endif
if (nof_users_with_data) {
if (nof_users_with_data == 2) { if (nof_users_with_data == 2) {
} }
if ((current_tti%nof_users_with_data) != user->ue_idx) { if ((current_tti%nof_users_with_data) != user->ue_idx) {
@ -153,7 +157,11 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user)
} }
// Schedule retx if we have space // Schedule retx if we have space
#if ASYNC_DL_SCHED
if (h) { if (h) {
#else
if (h && !h->is_empty()) {
#endif
uint32_t retx_mask = h->get_rbgmask(); uint32_t retx_mask = h->get_rbgmask();
// If can schedule the same mask, do it // If can schedule the same mask, do it
if (!allocation_is_valid(retx_mask)) { if (!allocation_is_valid(retx_mask)) {
@ -170,10 +178,14 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user)
} }
} }
} }
// If could not schedule the reTx, or there wasn't any pending retx, find an empty PID // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID
#if ASYNC_DL_SCHED
h = user->get_empty_dl_harq(); h = user->get_empty_dl_harq();
if (h) { if (h) {
// Allocate resources based on pending data #else
if (h && h->is_empty()) {
#endif
// Allocate resources based on pending data
if (pending_data) { if (pending_data) {
uint32_t pending_rb = user->get_required_prb_dl(pending_data, nof_ctrl_symbols); uint32_t pending_rb = user->get_required_prb_dl(pending_data, nof_ctrl_symbols);
uint32_t newtx_mask = 0; uint32_t newtx_mask = 0;

@ -248,7 +248,7 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2])
// First check if it has pending ACKs // First check if it has pending ACKs
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) { for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
if (HARQ_TX(dl_harq[i].get_tti()) == current_tti) { if (TTI_TX(dl_harq[i].get_tti()) == current_tti) {
uint32_t n_pucch = srslte_pucch_get_npucch(dl_harq[i].get_n_cce(), SRSLTE_PUCCH_FORMAT_1A, has_sr, &pucch_sched); uint32_t n_pucch = srslte_pucch_get_npucch(dl_harq[i].get_n_cce(), SRSLTE_PUCCH_FORMAT_1A, has_sr, &pucch_sched);
if (prb_idx) { if (prb_idx) {
for (int i=0;i<2;i++) { for (int i=0;i<2;i++) {
@ -288,7 +288,7 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2])
int sched_ue::set_ack_info(uint32_t tti, bool ack) int sched_ue::set_ack_info(uint32_t tti, bool ack)
{ {
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) { for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
if (HARQ_TX(dl_harq[i].get_tti()) == tti) { if (TTI_TX(dl_harq[i].get_tti()) == tti) {
Debug("SCHED: Set ACK=%d for rnti=0x%x, pid=%d, tti=%d\n", ack, rnti, i, tti); Debug("SCHED: Set ACK=%d for rnti=0x%x, pid=%d, tti=%d\n", ack, rnti, i, tti);
dl_harq[i].set_ack(ack); dl_harq[i].set_ack(ack);
return dl_harq[i].get_tbs(); return dl_harq[i].get_tbs();
@ -656,6 +656,7 @@ bool sched_ue::is_sr_triggered()
/* Gets HARQ process with oldest pending retx */ /* Gets HARQ process with oldest pending retx */
dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti) dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti)
{ {
#if ASYNC_DL_SCHED
int oldest_idx=-1; int oldest_idx=-1;
uint32_t oldest_tti = 0; uint32_t oldest_tti = 0;
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) { for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
@ -671,7 +672,10 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti)
return &dl_harq[oldest_idx]; return &dl_harq[oldest_idx];
} else { } else {
return NULL; return NULL;
} }
#else
return &dl_harq[tti%SCHED_MAX_HARQ_PROC];
#endif
} }
dl_harq_proc* sched_ue::get_empty_dl_harq() dl_harq_proc* sched_ue::get_empty_dl_harq()
@ -681,7 +685,7 @@ dl_harq_proc* sched_ue::get_empty_dl_harq()
return &dl_harq[i]; return &dl_harq[i];
} }
} }
return NULL; return NULL;
} }
ul_harq_proc* sched_ue::get_ul_harq(uint32_t tti) ul_harq_proc* sched_ue::get_ul_harq(uint32_t tti)

@ -104,7 +104,7 @@ void phch_common::ack_clear(uint32_t sf_idx)
void phch_common::ack_add_rnti(uint16_t rnti) void phch_common::ack_add_rnti(uint16_t rnti)
{ {
for (int sf_idx=0;sf_idx<10;sf_idx++) { for (int sf_idx=0;sf_idx<TTIMOD_SZ;sf_idx++) {
pending_ack[rnti].is_pending[sf_idx] = false; pending_ack[rnti].is_pending[sf_idx] = false;
} }
} }
@ -126,14 +126,18 @@ bool phch_common::ack_is_pending(uint32_t sf_idx, uint16_t rnti, uint32_t *last_
{ {
if (pending_ack.count(rnti)) { if (pending_ack.count(rnti)) {
bool ret = pending_ack[rnti].is_pending[sf_idx]; bool ret = pending_ack[rnti].is_pending[sf_idx];
pending_ack[rnti].is_pending[sf_idx] = false; pending_ack[rnti].is_pending[sf_idx] = false;
if (ret) {
}
if (ret && last_n_pdcch) { if (ret && last_n_pdcch) {
*last_n_pdcch = pending_ack[rnti].n_pdcch[sf_idx]; *last_n_pdcch = pending_ack[rnti].n_pdcch[sf_idx];
} }
return ret; return ret;
} else { } else {
return false; return false;
} }
} }

@ -176,16 +176,16 @@ cf_t* phch_worker::get_buffer_rx()
void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_) void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_)
{ {
tti_rx = tti_; tti_rx = tti_;
tti_tx = HARQ_TX(tti_rx); tti_tx_dl = TTI_TX(tti_rx);
tti_sched_ul = HARQ_RX(tti_rx); tti_tx_ul = TTI_RX_ACK(tti_rx);
sf_rx = tti_rx%10; sf_rx = tti_rx%10;
sf_tx = tti_tx%10; sf_tx = tti_tx_dl%10;
t_tx = TTIMOD(tti_tx); t_tx_dl = TTIMOD(tti_tx_dl);
t_rx = TTIMOD(tti_rx); t_rx = TTIMOD(tti_rx);
t_sched_ul = TTIMOD(tti_sched_ul); t_tx_ul = TTIMOD(tti_tx_ul);
tx_mutex_cnt = tx_mutex_cnt_; tx_mutex_cnt = tx_mutex_cnt_;
memcpy(&tx_time, &tx_time_, sizeof(srslte_timestamp_t)); memcpy(&tx_time, &tx_time_, sizeof(srslte_timestamp_t));
} }
@ -194,16 +194,16 @@ int phch_worker::add_rnti(uint16_t rnti)
{ {
if (srslte_enb_dl_add_rnti(&enb_dl, rnti)) { if (srslte_enb_dl_add_rnti(&enb_dl, rnti)) {
return -1; return -1;
} }
if (srslte_enb_ul_add_rnti(&enb_ul, rnti)) { if (srslte_enb_ul_add_rnti(&enb_ul, rnti)) {
return -1; return -1;
} }
// Create user // Create user
ue_db[rnti].rnti = rnti; ue_db[rnti].rnti = rnti;
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -211,61 +211,61 @@ uint32_t phch_worker::get_nof_rnti() {
return ue_db.size(); return ue_db.size();
} }
void phch_worker::set_config_dedicated(uint16_t rnti, void phch_worker::set_config_dedicated(uint16_t rnti,
srslte_uci_cfg_t *uci_cfg, srslte_uci_cfg_t *uci_cfg,
srslte_pucch_sched_t *pucch_sched, srslte_pucch_sched_t *pucch_sched,
srslte_refsignal_srs_cfg_t *srs_cfg, srslte_refsignal_srs_cfg_t *srs_cfg,
uint32_t I_sr, bool pucch_cqi, uint32_t pmi_idx, bool pucch_cqi_ack) uint32_t I_sr, bool pucch_cqi, uint32_t pmi_idx, bool pucch_cqi_ack)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (ue_db.count(rnti)) { if (ue_db.count(rnti)) {
pucch_sched->N_pucch_1 = phy->pucch_cfg.n1_pucch_an; pucch_sched->N_pucch_1 = phy->pucch_cfg.n1_pucch_an;
srslte_enb_ul_cfg_ue(&enb_ul, rnti, uci_cfg, pucch_sched, srs_cfg); srslte_enb_ul_cfg_ue(&enb_ul, rnti, uci_cfg, pucch_sched, srs_cfg);
ue_db[rnti].I_sr = I_sr; ue_db[rnti].I_sr = I_sr;
ue_db[rnti].I_sr_en = true; ue_db[rnti].I_sr_en = true;
if (pucch_cqi) { if (pucch_cqi) {
ue_db[rnti].pmi_idx = pmi_idx; ue_db[rnti].pmi_idx = pmi_idx;
ue_db[rnti].cqi_en = true; ue_db[rnti].cqi_en = true;
ue_db[rnti].pucch_cqi_ack = pucch_cqi_ack; ue_db[rnti].pucch_cqi_ack = pucch_cqi_ack;
} else { } else {
ue_db[rnti].pmi_idx = 0; ue_db[rnti].pmi_idx = 0;
ue_db[rnti].cqi_en = false; ue_db[rnti].cqi_en = false;
} }
} else { } else {
Error("Setting config dedicated: rnti=0x%x does not exist\n"); Error("Setting config dedicated: rnti=0x%x does not exist\n");
} }
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
void phch_worker::rem_rnti(uint16_t rnti) void phch_worker::rem_rnti(uint16_t rnti)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (ue_db.count(rnti)) { if (ue_db.count(rnti)) {
ue_db.erase(rnti); ue_db.erase(rnti);
srslte_enb_dl_rem_rnti(&enb_dl, rnti); srslte_enb_dl_rem_rnti(&enb_dl, rnti);
srslte_enb_ul_rem_rnti(&enb_ul, rnti); srslte_enb_ul_rem_rnti(&enb_ul, rnti);
// remove any pending grant for each subframe // remove any pending grant for each subframe
for (uint32_t i=0;i<TTIMOD_SZ;i++) { for (uint32_t i=0;i<TTIMOD_SZ;i++) {
for (uint32_t j=0;j<phy->ul_grants[i].nof_grants;j++) { for (uint32_t j=0;j<phy->ul_grants[i].nof_grants;j++) {
if (phy->ul_grants[i].sched_grants[j].rnti == rnti) { if (phy->ul_grants[i].sched_grants[j].rnti == rnti) {
phy->ul_grants[i].sched_grants[j].rnti = 0; phy->ul_grants[i].sched_grants[j].rnti = 0;
} }
} }
for (uint32_t j=0;j<phy->dl_grants[i].nof_grants;j++) { for (uint32_t j=0;j<phy->dl_grants[i].nof_grants;j++) {
if (phy->dl_grants[i].sched_grants[j].rnti == rnti) { if (phy->dl_grants[i].sched_grants[j].rnti == rnti) {
phy->dl_grants[i].sched_grants[j].rnti = 0; phy->dl_grants[i].sched_grants[j].rnti = 0;
} }
} }
} }
} else { } else {
Error("Removing user: rnti=0x%x does not exist\n", rnti); Error("Removing user: rnti=0x%x does not exist\n", rnti);
} }
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
void phch_worker::work_imp() void phch_worker::work_imp()
@ -275,18 +275,18 @@ void phch_worker::work_imp()
} }
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants; mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants;
mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants; mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants;
mac_interface_phy *mac = phy->mac; mac_interface_phy *mac = phy->mac;
log_h->step(tti_rx); log_h->step(tti_rx);
Debug("Worker %d running\n", get_id()); Debug("Worker %d running\n", get_id());
for(std::map<uint16_t, ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { for(std::map<uint16_t, ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) {
uint16_t rnti = (uint16_t) iter->first; uint16_t rnti = (uint16_t) iter->first;
ue_db[rnti].has_grant_tti = -1; ue_db[rnti].has_grant_tti = -1;
} }
// Process UL signal // Process UL signal
@ -294,51 +294,51 @@ void phch_worker::work_imp()
// Decode pending UL grants for the tti they were scheduled // Decode pending UL grants for the tti they were scheduled
decode_pusch(ul_grants[t_rx].sched_grants, ul_grants[t_rx].nof_grants); decode_pusch(ul_grants[t_rx].sched_grants, ul_grants[t_rx].nof_grants);
// Decode remaining PUCCH ACKs not associated with PUSCH transmission and SR signals // Decode remaining PUCCH ACKs not associated with PUSCH transmission and SR signals
decode_pucch(); decode_pucch();
// Get DL scheduling for the TX TTI from MAC // Get DL scheduling for the TX TTI from MAC
if (mac->get_dl_sched(tti_tx, &dl_grants[t_tx]) < 0) { if (mac->get_dl_sched(tti_tx_dl, &dl_grants[t_tx_dl]) < 0) {
Error("Getting DL scheduling from MAC\n"); Error("Getting DL scheduling from MAC\n");
goto unlock; goto unlock;
} }
if (dl_grants[t_tx].cfi < 1 || dl_grants[t_tx].cfi > 3) { if (dl_grants[t_tx_dl].cfi < 1 || dl_grants[t_tx_dl].cfi > 3) {
Error("Invalid CFI=%d\n", dl_grants[t_tx].cfi); Error("Invalid CFI=%d\n", dl_grants[t_tx_dl].cfi);
goto unlock; goto unlock;
} }
// Get UL scheduling for the TX TTI from MAC // Get UL scheduling for the TX TTI from MAC
if (mac->get_ul_sched(tti_sched_ul, &ul_grants[t_sched_ul]) < 0) { if (mac->get_ul_sched(tti_tx_ul, &ul_grants[t_tx_ul]) < 0) {
Error("Getting UL scheduling from MAC\n"); Error("Getting UL scheduling from MAC\n");
goto unlock; goto unlock;
} }
// Put base signals (references, PBCH, PCFICH and PSS/SSS) into the resource grid // Put base signals (references, PBCH, PCFICH and PSS/SSS) into the resource grid
srslte_enb_dl_clear_sf(&enb_dl); srslte_enb_dl_clear_sf(&enb_dl);
srslte_enb_dl_set_cfi(&enb_dl, dl_grants[t_tx].cfi); srslte_enb_dl_set_cfi(&enb_dl, dl_grants[t_tx_dl].cfi);
srslte_enb_dl_put_base(&enb_dl, tti_tx); srslte_enb_dl_put_base(&enb_dl, tti_tx_dl);
// Put UL/DL grants to resource grid. PDSCH data will be encoded as well.
encode_pdcch_dl(dl_grants[t_tx_dl].sched_grants, dl_grants[t_tx_dl].nof_grants);
encode_pdcch_ul(ul_grants[t_tx_ul].sched_grants, ul_grants[t_tx_ul].nof_grants);
encode_pdsch(dl_grants[t_tx_dl].sched_grants, dl_grants[t_tx_dl].nof_grants);
// Put UL/DL grants to resource grid. PDSCH data will be encoded as well.
encode_pdcch_dl(dl_grants[t_tx].sched_grants, dl_grants[t_tx].nof_grants);
encode_pdcch_ul(ul_grants[t_sched_ul].sched_grants, ul_grants[t_sched_ul].nof_grants);
encode_pdsch(dl_grants[t_tx].sched_grants, dl_grants[t_tx].nof_grants);
// Put pending PHICH HARQ ACK/NACK indications into subframe // Put pending PHICH HARQ ACK/NACK indications into subframe
encode_phich(ul_grants[t_sched_ul].phich, ul_grants[t_sched_ul].nof_phich); encode_phich(ul_grants[t_tx_ul].phich, ul_grants[t_tx_ul].nof_phich);
// Prepare for receive ACK for DL grants in t_tx+4 // Prepare for receive ACK for DL grants in t_tx_dl+4
phy->ack_clear(TTIMOD(HARQ_TX(sf_tx))); phy->ack_clear(TTIMOD(TTI_TX(t_tx_dl)));
for (uint32_t i=0;i<dl_grants[t_tx].nof_grants;i++) { for (uint32_t i=0;i<dl_grants[t_tx_dl].nof_grants;i++) {
// SI-RNTI and RAR-RNTI do not have ACK // SI-RNTI and RAR-RNTI do not have ACK
if (dl_grants[t_tx].sched_grants[i].rnti >= SRSLTE_CRNTI_START && dl_grants[t_tx].sched_grants[i].rnti <= SRSLTE_CRNTI_END) { if (dl_grants[t_tx_dl].sched_grants[i].rnti >= SRSLTE_CRNTI_START && dl_grants[t_tx_dl].sched_grants[i].rnti <= SRSLTE_CRNTI_END) {
phy->ack_set_pending(TTIMOD(HARQ_TX(sf_tx)), dl_grants[t_tx].sched_grants[i].rnti, dl_grants[t_tx].sched_grants[i].location.ncce); phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), dl_grants[t_tx_dl].sched_grants[i].rnti, dl_grants[t_tx_dl].sched_grants[i].location.ncce);
} }
} }
// Generate signal and transmit // Generate signal and transmit
srslte_enb_dl_gen_signal(&enb_dl, signal_buffer_tx); srslte_enb_dl_gen_signal(&enb_dl, signal_buffer_tx);
Debug("Sending to radio\n"); Debug("Sending to radio\n");
phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time); phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time);
@ -347,35 +347,35 @@ void phch_worker::work_imp()
#endif #endif
#ifdef DEBUG_WRITE_FILE #ifdef DEBUG_WRITE_FILE
if (tti_tx == 10) { if (tti_tx_dl == 10) {
fclose(f); fclose(f);
exit(-1); exit(-1);
} }
#endif #endif
/* Tell the plotting thread to draw the plots */ /* Tell the plotting thread to draw the plots */
#ifdef ENABLE_GUI #ifdef ENABLE_GUI
if ((int) get_id() == plot_worker_id) { if ((int) get_id() == plot_worker_id) {
sem_post(&plot_sem); sem_post(&plot_sem);
} }
#endif #endif
unlock: unlock:
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
{ {
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
uint32_t wideband_cqi_value = 0; uint32_t wideband_cqi_value = 0;
uint32_t n_rb_ho = 0; uint32_t n_rb_ho = 0;
for (uint32_t i=0;i<nof_pusch;i++) { for (uint32_t i=0;i<nof_pusch;i++) {
uint16_t rnti = grants[i].rnti; uint16_t rnti = grants[i].rnti;
if (rnti) { if (rnti) {
#ifdef LOG_EXECTIME #ifdef LOG_EXECTIME
@ -386,27 +386,27 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
// Get pending ACKs with an associated PUSCH transmission // Get pending ACKs with an associated PUSCH transmission
if (phy->ack_is_pending(t_rx, rnti)) { if (phy->ack_is_pending(t_rx, rnti)) {
uci_data.uci_ack_len = 1; uci_data.uci_ack_len = 1;
} }
// Configure PUSCH CQI channel // Configure PUSCH CQI channel
srslte_cqi_value_t cqi_value; srslte_cqi_value_t cqi_value;
bool cqi_enabled = false; bool cqi_enabled = false;
if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
cqi_enabled = true; cqi_enabled = true;
} else if (grants[i].grant.cqi_request) { } else if (grants[i].grant.cqi_request) {
cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL; cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL;
cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0; cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0;
cqi_enabled = true; cqi_enabled = true;
} }
if (cqi_enabled) { if (cqi_enabled) {
uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value);
} }
// mark this tti as having an ul grant to avoid pucch // mark this tti as having an ul grant to avoid pucch
ue_db[rnti].has_grant_tti = tti_rx; ue_db[rnti].has_grant_tti = tti_rx;
srslte_ra_ul_grant_t phy_grant; srslte_ra_ul_grant_t phy_grant;
int res = -1; int res = -1;
if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant, tti_rx%8)) { if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant, tti_rx%8)) {
if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) { if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) {
@ -414,27 +414,27 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
} }
phy_grant.Qm = SRSLTE_MIN(phy_grant.Qm, 4); phy_grant.Qm = SRSLTE_MIN(phy_grant.Qm, 4);
res = srslte_enb_ul_get_pusch(&enb_ul, &phy_grant, grants[i].softbuffer, res = srslte_enb_ul_get_pusch(&enb_ul, &phy_grant, grants[i].softbuffer,
rnti, grants[i].rv_idx, rnti, grants[i].rv_idx,
grants[i].current_tx_nb, grants[i].current_tx_nb,
grants[i].data, grants[i].data,
&uci_data, &uci_data,
sf_rx); sf_rx);
} else { } else {
Error("Computing PUSCH grant\n"); Error("Computing PUSCH grant\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
#ifdef LOG_EXECTIME #ifdef LOG_EXECTIME
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec); snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec);
#endif #endif
bool crc_res = (res == 0); bool crc_res = (res == 0);
// Save PHICH scheduling for this user. Each user can have just 1 PUSCH grant per TTI // Save PHICH scheduling for this user. Each user can have just 1 PUSCH grant per TTI
ue_db[rnti].phich_info.n_prb_lowest = enb_ul.pusch_cfg.grant.n_prb_tilde[0]; ue_db[rnti].phich_info.n_prb_lowest = enb_ul.pusch_cfg.grant.n_prb_tilde[0];
ue_db[rnti].phich_info.n_dmrs = phy_grant.ncs_dmrs; ue_db[rnti].phich_info.n_dmrs = phy_grant.ncs_dmrs;
char cqi_str[64]; char cqi_str[64];
if (cqi_enabled) { if (cqi_enabled) {
@ -446,8 +446,8 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
} }
snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value); snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value);
} }
float snr_db = 10*log10(srslte_chest_ul_get_snr(&enb_ul.chest)); float snr_db = 10*log10(srslte_chest_ul_get_snr(&enb_ul.chest));
/* /*
if (!crc_res && enb_ul.pusch_cfg.grant.L_prb == 1 && enb_ul.pusch_cfg.grant.n_prb[0] == 0 && snr_db > 5) { if (!crc_res && enb_ul.pusch_cfg.grant.L_prb == 1 && enb_ul.pusch_cfg.grant.n_prb[0] == 0 && snr_db > 5) {
@ -456,8 +456,8 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
srslte_vec_save_file("d", enb_ul.pusch.d, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re); srslte_vec_save_file("d", enb_ul.pusch.d, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re);
srslte_vec_save_file("ce2", enb_ul.pusch.ce, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re); srslte_vec_save_file("ce2", enb_ul.pusch.ce, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re);
srslte_vec_save_file("z", enb_ul.pusch.z, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re); srslte_vec_save_file("z", enb_ul.pusch.z, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re);
printf("saved sf_idx=%d, mcs=%d, tbs=%d, rnti=%d, rv=%d, snr=%.1f\n", tti%10, printf("saved sf_idx=%d, mcs=%d, tbs=%d, rnti=%d, rv=%d, snr=%.1f\n", tti%10,
grants[i].grant.mcs_idx, enb_ul.pusch_cfg.cb_segm.tbs, rnti, grants[i].rv_idx, snr_db); grants[i].grant.mcs_idx, enb_ul.pusch_cfg.cb_segm.tbs, rnti, grants[i].rv_idx, snr_db);
exit(-1); exit(-1);
} }
*/ */
@ -465,120 +465,121 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
"PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s\n", "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s\n",
rnti, phy_grant.n_prb[0], phy_grant.n_prb[0]+phy_grant.L_prb, rnti, phy_grant.n_prb[0], phy_grant.n_prb[0]+phy_grant.L_prb,
phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx, phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx,
snr_db, snr_db,
srslte_pusch_last_noi(&enb_ul.pusch), srslte_pusch_last_noi(&enb_ul.pusch),
crc_res?"OK":"KO", crc_res?"OK":"KO",
uci_data.uci_ack_len>0?(uci_data.uci_ack?", ack=1":", ack=0"):"", uci_data.uci_ack_len>0?(uci_data.uci_ack?", ack=1":", ack=0"):"",
uci_data.uci_cqi_len>0?cqi_str:"", uci_data.uci_cqi_len>0?cqi_str:"",
timestr); timestr);
// Notify MAC of RL status // Notify MAC of RL status
if (grants[i].grant.rv_idx == 0) { if (grants[i].grant.rv_idx == 0) {
if (res && snr_db < PUSCH_RL_SNR_DB_TH) { if (res && snr_db < PUSCH_RL_SNR_DB_TH) {
Debug("PUSCH: Radio-Link failure snr=%.1f dB\n", snr_db); Debug("PUSCH: Radio-Link failure snr=%.1f dB\n", snr_db);
phy->mac->rl_failure(rnti); phy->mac->rl_failure(rnti);
} else { } else {
phy->mac->rl_ok(rnti); phy->mac->rl_ok(rnti);
} }
} }
// Notify MAC new received data and HARQ Indication value // Notify MAC new received data and HARQ Indication value
phy->mac->crc_info(tti_rx, rnti, phy_grant.mcs.tbs/8, crc_res); phy->mac->crc_info(tti_rx, rnti, phy_grant.mcs.tbs/8, crc_res);
if (uci_data.uci_ack_len) { if (uci_data.uci_ack_len) {
phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (crc_res || snr_db > PUSCH_RL_SNR_DB_TH)); phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (crc_res || snr_db > PUSCH_RL_SNR_DB_TH));
} }
// Notify MAC of UL SNR and DL CQI // Notify MAC of UL SNR and DL CQI
if (snr_db >= PUSCH_RL_SNR_DB_TH) { if (snr_db >= PUSCH_RL_SNR_DB_TH) {
phy->mac->snr_info(tti_rx, rnti, snr_db); phy->mac->snr_info(tti_rx, rnti, snr_db);
} }
if (uci_data.uci_cqi_len>0 && crc_res) { if (uci_data.uci_cqi_len>0 && crc_res) {
phy->mac->cqi_info(tti_rx, rnti, wideband_cqi_value); phy->mac->cqi_info(tti_rx, rnti, wideband_cqi_value);
} }
// Save metrics stats // Save metrics stats
ue_db[rnti].metrics_ul(phy_grant.mcs.idx, 0, snr_db, srslte_pusch_last_noi(&enb_ul.pusch)); ue_db[rnti].metrics_ul(phy_grant.mcs.idx, 0, snr_db, srslte_pusch_last_noi(&enb_ul.pusch));
} }
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
int phch_worker::decode_pucch() int phch_worker::decode_pucch()
{ {
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
for(std::map<uint16_t, ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { for(std::map<uint16_t, ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) {
uint16_t rnti = (uint16_t) iter->first; uint16_t rnti = (uint16_t) iter->first;
if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) { if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) {
// Check if user needs to receive PUCCH // Check if user needs to receive PUCCH
bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false; bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false;
uint32_t last_n_pdcch = 0; uint32_t last_n_pdcch = 0;
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
if (ue_db[rnti].I_sr_en) { if (ue_db[rnti].I_sr_en) {
if (srslte_ue_ul_sr_send_tti(ue_db[rnti].I_sr, tti_rx)) { if (srslte_ue_ul_sr_send_tti(ue_db[rnti].I_sr, tti_rx)) {
needs_pucch = true; needs_pucch = true;
needs_sr = true; needs_sr = true;
uci_data.scheduling_request = true; uci_data.scheduling_request = true;
} }
} }
if (phy->ack_is_pending(t_rx, rnti, &last_n_pdcch)) { if (phy->ack_is_pending(t_rx, rnti, &last_n_pdcch)) {
needs_pucch = true; needs_pucch = true;
needs_ack = true; needs_ack = true;
uci_data.uci_ack_len = 1; uci_data.uci_ack_len = 1;
} }
srslte_cqi_value_t cqi_value; srslte_cqi_value_t cqi_value;
if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack)) { if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack)) {
if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
needs_pucch = true; needs_pucch = true;
needs_cqi = true; needs_cqi = true;
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value);
} }
} }
if (needs_pucch) { if (needs_pucch) {
if (srslte_enb_ul_get_pucch(&enb_ul, rnti, last_n_pdcch, t_rx, &uci_data)) { if (srslte_enb_ul_get_pucch(&enb_ul, rnti, last_n_pdcch, sf_rx, &uci_data)) {
fprintf(stderr, "Error getting PUCCH\n"); fprintf(stderr, "Error getting PUCCH\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (uci_data.uci_ack_len > 0) { if (uci_data.uci_ack_len > 0) {
phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH)); phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH));
} }
if (uci_data.scheduling_request) { if (uci_data.scheduling_request) {
phy->mac->sr_detected(tti_rx, rnti); phy->mac->sr_detected(tti_rx, rnti);
} }
char cqi_str[64]; char cqi_str[64];
if (uci_data.uci_cqi_len) { if (uci_data.uci_cqi_len) {
srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value);
phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi);
sprintf(cqi_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); sprintf(cqi_str, ", cqi=%d", cqi_value.wideband.wideband_cqi);
} }
log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n", log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n",
rnti, rnti,
srslte_pucch_get_last_corr(&enb_ul.pucch), srslte_pucch_get_last_corr(&enb_ul.pucch),
enb_ul.pucch.last_n_pucch, enb_ul.pucch.last_n_prb, enb_ul.pucch.last_n_pucch, enb_ul.pucch.last_n_prb,
needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"", needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"",
needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"", needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"",
needs_cqi?cqi_str:""); needs_cqi?cqi_str:"");
// Notify MAC of RL status // Notify MAC of RL status
if (!needs_sr) { if (!needs_sr) {
if (srslte_pucch_get_last_corr(&enb_ul.pucch) < PUCCH_RL_CORR_TH) { if (srslte_pucch_get_last_corr(&enb_ul.pucch) < PUCCH_RL_CORR_TH) {
Debug("PUCCH: Radio-Link failure corr=%.1f\n", srslte_pucch_get_last_corr(&enb_ul.pucch)); Debug("PUCCH: Radio-Link failure corr=%.1f\n", srslte_pucch_get_last_corr(&enb_ul.pucch));
phy->mac->rl_failure(rnti); phy->mac->rl_failure(rnti);
} else { } else {
phy->mac->rl_ok(rnti); phy->mac->rl_ok(rnti);
} }
} }
} }
} }
} }
return 0; return 0;
} }
@ -587,15 +588,15 @@ int phch_worker::encode_phich(srslte_enb_dl_phich_t *acks, uint32_t nof_acks)
for (uint32_t i=0;i<nof_acks;i++) { for (uint32_t i=0;i<nof_acks;i++) {
uint16_t rnti = acks[i].rnti; uint16_t rnti = acks[i].rnti;
if (rnti) { if (rnti) {
srslte_enb_dl_put_phich(&enb_dl, acks[i].ack, srslte_enb_dl_put_phich(&enb_dl, acks[i].ack,
ue_db[rnti].phich_info.n_prb_lowest, ue_db[rnti].phich_info.n_prb_lowest,
ue_db[rnti].phich_info.n_dmrs, ue_db[rnti].phich_info.n_dmrs,
sf_tx); sf_tx);
Info("PHICH: rnti=0x%x, hi=%d, I_lowest=%d, n_dmrs=%d, tti_tx=%d\n", Info("PHICH: rnti=0x%x, hi=%d, I_lowest=%d, n_dmrs=%d, tti_tx_dl=%d\n",
rnti, acks[i].ack, rnti, acks[i].ack,
ue_db[rnti].phich_info.n_prb_lowest, ue_db[rnti].phich_info.n_prb_lowest,
ue_db[rnti].phich_info.n_dmrs, tti_tx); ue_db[rnti].phich_info.n_dmrs, tti_tx_dl);
} }
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
@ -609,14 +610,14 @@ int phch_worker::encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_gra
if (grants[i].needs_pdcch && rnti) { if (grants[i].needs_pdcch && rnti) {
if (srslte_enb_dl_put_pdcch_ul(&enb_dl, &grants[i].grant, grants[i].location, rnti, sf_tx)) { if (srslte_enb_dl_put_pdcch_ul(&enb_dl, &grants[i].grant, grants[i].location, rnti, sf_tx)) {
fprintf(stderr, "Error putting PUSCH %d\n",i); fprintf(stderr, "Error putting PUSCH %d\n",i);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
Info("PDCCH: UL DCI Format0 rnti=0x%x, cce_index=%d, L=%d, tpc=%d, tti_tx=%d\n", Info("PDCCH: UL DCI Format0 rnti=0x%x, cce_index=%d, L=%d, tpc=%d, tti_tx_dl=%d\n",
rnti, grants[i].location.ncce, (1<<grants[i].location.L), grants[i].grant.tpc_pusch, tti_tx); rnti, grants[i].location.ncce, (1<<grants[i].location.L), grants[i].grant.tpc_pusch, tti_tx_dl);
} }
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants) int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants)
@ -624,28 +625,28 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra
for (uint32_t i=0;i<nof_grants;i++) { for (uint32_t i=0;i<nof_grants;i++) {
uint16_t rnti = grants[i].rnti; uint16_t rnti = grants[i].rnti;
if (rnti) { if (rnti) {
srslte_dci_format_t format = SRSLTE_DCI_FORMAT1; srslte_dci_format_t format = SRSLTE_DCI_FORMAT1;
switch(grants[i].grant.alloc_type) { switch(grants[i].grant.alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0: case SRSLTE_RA_ALLOC_TYPE0:
case SRSLTE_RA_ALLOC_TYPE1: case SRSLTE_RA_ALLOC_TYPE1:
format = SRSLTE_DCI_FORMAT1; format = SRSLTE_DCI_FORMAT1;
break; break;
case SRSLTE_RA_ALLOC_TYPE2: case SRSLTE_RA_ALLOC_TYPE2:
format = SRSLTE_DCI_FORMAT1A; format = SRSLTE_DCI_FORMAT1A;
break; break;
} }
if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, format, grants[i].location, rnti, sf_tx)) { if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, format, grants[i].location, rnti, sf_tx)) {
fprintf(stderr, "Error putting PDCCH %d\n",i); fprintf(stderr, "Error putting PDCCH %d\n",i);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (LOG_THIS(rnti)) { if (LOG_THIS(rnti)) {
Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx=%d\n", srslte_dci_format_string(format), Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx_dl=%d\n", srslte_dci_format_string(format),
rnti, grants[i].location.ncce, (1<<grants[i].location.L), tti_tx); rnti, grants[i].location.ncce, (1<<grants[i].location.L), tti_tx_dl);
} }
} }
} }
return 0; return 0;
} }
int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants) int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants)
@ -654,14 +655,14 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
uint16_t rnti = grants[i].rnti; uint16_t rnti = grants[i].rnti;
if (rnti) { if (rnti) {
bool rnti_is_user = true; bool rnti_is_user = true;
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || rnti == SRSLTE_MRNTI) { if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || rnti == SRSLTE_MRNTI) {
rnti_is_user = false; rnti_is_user = false;
} }
srslte_ra_dl_grant_t phy_grant; srslte_ra_dl_grant_t phy_grant;
srslte_ra_dl_dci_to_grant(&grants[i].grant, enb_dl.cell.nof_prb, rnti, &phy_grant); srslte_ra_dl_dci_to_grant(&grants[i].grant, enb_dl.cell.nof_prb, rnti, &phy_grant);
char grant_str[64]; char grant_str[64];
switch(grants[i].grant.alloc_type) { switch(grants[i].grant.alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0: case SRSLTE_RA_ALLOC_TYPE0:
@ -674,19 +675,19 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
sprintf(grant_str, "rb_start=%d",grants[i].grant.type2_alloc.RB_start); sprintf(grant_str, "rb_start=%d",grants[i].grant.type2_alloc.RB_start);
break; break;
} }
if (LOG_THIS(rnti)) { if (LOG_THIS(rnti)) {
uint8_t x = 0; uint8_t x = 0;
uint8_t *ptr = grants[i].data; uint8_t *ptr = grants[i].data;
uint32_t len = phy_grant.mcs[0].tbs / (uint32_t) 8; uint32_t len = phy_grant.mcs[0].tbs / (uint32_t) 8;
if (!ptr) { if (!ptr) {
ptr = &x; ptr = &x;
len = 1; len = 1;
} }
log_h->info_hex(ptr, len, log_h->info_hex(ptr, len,
"PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n", "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx_dl=%d\n",
rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process,
phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx); phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx_dl);
} }
srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS] = {grants[i].softbuffer, NULL}; srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS] = {grants[i].softbuffer, NULL};

@ -115,7 +115,7 @@ void txrx::run_thread()
/* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */
srslte_timestamp_copy(&tx_time, &rx_time); srslte_timestamp_copy(&tx_time, &rx_time);
srslte_timestamp_add(&tx_time, 0, 4e-3); srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3);
Debug("Settting TTI=%d, tx_mutex=%d, tx_time=%d:%f to worker %d\n", Debug("Settting TTI=%d, tx_mutex=%d, tx_time=%d:%f to worker %d\n",
tti, tx_mutex_cnt, tti, tx_mutex_cnt,

@ -82,8 +82,7 @@ private:
const static int MIN_RLC_SDU_LEN = 0; const static int MIN_RLC_SDU_LEN = 0;
const static int MAX_NOF_SUBHEADERS = 20; const static int MAX_NOF_SUBHEADERS = 20;
const static int MAX_HARQ_PROC = 8;
std::vector<lchid_t> lch; std::vector<lchid_t> lch;
// Keep track of the PIDs that transmitted BSR reports // Keep track of the PIDs that transmitted BSR reports

@ -136,12 +136,16 @@ srslte::radio* phch_common::get_radio()
void phch_common::set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) void phch_common::set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN])
{ {
srslte_dci_rar_grant_unpack(&rar_grant, grant_payload); srslte_dci_rar_grant_unpack(&rar_grant, grant_payload);
rar_grant_pending = true; rar_grant_pending = true;
// PUSCH is at n+6 or n+7 and phch_worker assumes default delay of 4 ttis int delay = MSG3_DELAY_MS-HARQ_DELAY_MS;
if (delay < 0) {
fprintf(stderr, "Error MSG3_DELAY_MS can't be lower than HARQ_DELAY_MS\n");
delay = 0;
}
if (rar_grant.ul_delay) { if (rar_grant.ul_delay) {
rar_grant_tti = (tti + 3) % 10240; rar_grant_tti = (tti + delay + 1) % 10240;
} else { } else {
rar_grant_tti = (tti + 2) % 10240; rar_grant_tti = (tti + delay) % 10240;
} }
} }

@ -292,6 +292,13 @@ void phch_worker::work_imp()
} }
} }
} }
// Process RAR before UL to enable zero-delay Msg3
bool rar_delivered = false;
if (HARQ_DELAY_MS == MSG3_DELAY_MS && dl_mac_grant.rnti_type == SRSLTE_RNTI_RAR) {
rar_delivered = true;
phy->mac->tb_decoded(dl_ack[0], 0, dl_mac_grant.rnti_type, dl_mac_grant.pid);
}
// Decode PHICH // Decode PHICH
bool ul_ack = false; bool ul_ack = false;
@ -313,8 +320,8 @@ void phch_worker::work_imp()
set_uci_periodic_cqi(); set_uci_periodic_cqi();
} }
/* TTI offset for UL is always 4 for LTE */ /* TTI offset for UL */
ul_action.tti_offset = 4; ul_action.tti_offset = HARQ_DELAY_MS;
/* Send UL grant or HARQ information (from PHICH) to MAC */ /* Send UL grant or HARQ information (from PHICH) to MAC */
if (ul_grant_available && ul_ack_available) { if (ul_grant_available && ul_ack_available) {
@ -335,7 +342,7 @@ void phch_worker::work_imp()
&ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar);
signal_ready = true; signal_ready = true;
if (ul_action.expect_ack) { if (ul_action.expect_ack) {
phy->set_pending_ack(HARQ_RX(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs);
} }
} else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0) { } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0) {
@ -357,7 +364,7 @@ void phch_worker::work_imp()
if (!dl_action.generate_ack_callback) { if (!dl_action.generate_ack_callback) {
if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH && dl_action.decode_enabled[0]) { if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH && dl_action.decode_enabled[0]) {
phy->mac->pch_decoded_ok(dl_mac_grant.n_bytes[0]); phy->mac->pch_decoded_ok(dl_mac_grant.n_bytes[0]);
} else { } else if (!rar_delivered) {
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
if (dl_action.decode_enabled[tb]) { if (dl_action.decode_enabled[tb]) {
phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid); phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid);
@ -475,7 +482,7 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
/* Fill MAC grant structure */ /* Fill MAC grant structure */
grant->ndi[0] = dci_unpacked.ndi; grant->ndi[0] = dci_unpacked.ndi;
grant->ndi[1] = dci_unpacked.ndi_1; grant->ndi[1] = dci_unpacked.ndi_1;
grant->pid = dci_unpacked.harq_process; grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS));
grant->n_bytes[0] = grant->phy_grant.dl.mcs[0].tbs / (uint32_t) 8; grant->n_bytes[0] = grant->phy_grant.dl.mcs[0].tbs / (uint32_t) 8;
grant->n_bytes[1] = grant->phy_grant.dl.mcs[1].tbs / (uint32_t) 8; grant->n_bytes[1] = grant->phy_grant.dl.mcs[1].tbs / (uint32_t) 8;
grant->tti = tti; grant->tti = tti;
@ -663,7 +670,7 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
char timestr[64]; char timestr[64];
timestr[0]='\0'; timestr[0]='\0';
phy->reset_pending_ack(HARQ_RX(tti)); phy->reset_pending_ack(TTI_RX_ACK(tti));
srslte_dci_msg_t dci_msg; srslte_dci_msg_t dci_msg;
srslte_ra_ul_dci_t dci_unpacked; srslte_ra_ul_dci_t dci_unpacked;
@ -776,7 +783,7 @@ void phch_worker::set_uci_sr()
{ {
uci_data.scheduling_request = false; uci_data.scheduling_request = false;
if (phy->sr_enabled) { if (phy->sr_enabled) {
uint32_t sr_tx_tti = HARQ_TX(tti); uint32_t sr_tx_tti = TTI_TX(tti);
// Get I_sr parameter // Get I_sr parameter
if (srslte_ue_ul_sr_send_tti(I_sr, sr_tx_tti)) { if (srslte_ue_ul_sr_send_tti(I_sr, sr_tx_tti)) {
Info("PUCCH: SR transmission at TTI=%d, I_sr=%d\n", sr_tx_tti, I_sr); Info("PUCCH: SR transmission at TTI=%d, I_sr=%d\n", sr_tx_tti, I_sr);
@ -793,7 +800,7 @@ void phch_worker::set_uci_periodic_cqi()
int cqi_max = phy->args->cqi_max; int cqi_max = phy->args->cqi_max;
if (period_cqi.configured && rnti_is_set) { if (period_cqi.configured && rnti_is_set) {
if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, HARQ_TX(tti))) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) {
if (uci_data.uci_ri_len) { if (uci_data.uci_ri_len) {
uci_data.uci_cqi[0] = uci_data.uci_ri; uci_data.uci_cqi[0] = uci_data.uci_ri;
uci_data.uci_cqi_len = uci_data.uci_ri_len; uci_data.uci_cqi_len = uci_data.uci_ri_len;
@ -802,7 +809,7 @@ void phch_worker::set_uci_periodic_cqi()
uci_data.uci_pmi_len = 0; uci_data.uci_pmi_len = 0;
Info("PUCCH: Periodic RI=%d\n", uci_data.uci_cqi[0]); Info("PUCCH: Periodic RI=%d\n", uci_data.uci_cqi[0]);
} }
} else if (srslte_cqi_send(period_cqi.pmi_idx, HARQ_TX(tti))) { } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) {
srslte_cqi_value_t cqi_report; srslte_cqi_value_t cqi_report;
if (period_cqi.format_is_subband) { if (period_cqi.format_is_subband) {
// TODO: Implement subband periodic reports // TODO: Implement subband periodic reports
@ -868,8 +875,8 @@ void phch_worker::set_uci_aperiodic_cqi()
bool phch_worker::srs_is_ready_to_send() { bool phch_worker::srs_is_ready_to_send() {
if (srs_cfg.configured) { if (srs_cfg.configured) {
if (srslte_refsignal_srs_send_cs(srs_cfg.subframe_config, HARQ_RX(tti)%10) == 1 && if (srslte_refsignal_srs_send_cs(srs_cfg.subframe_config, TTI_TX(tti)%10) == 1 &&
srslte_refsignal_srs_send_ue(srs_cfg.I_srs, HARQ_TX(tti)) == 1) srslte_refsignal_srs_send_ue(srs_cfg.I_srs, TTI_TX(tti)) == 1)
{ {
return true; return true;
} }
@ -889,7 +896,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
char timestr[64]; char timestr[64];
timestr[0]='\0'; timestr[0]='\0';
if (srslte_ue_ul_cfg_grant(&ue_ul, grant, HARQ_TX(tti), rv, current_tx_nb)) { if (srslte_ue_ul_cfg_grant(&ue_ul, grant, TTI_TX(tti), rv, current_tx_nb)) {
Error("Configuring UL grant\n"); Error("Configuring UL grant\n");
} }
@ -919,7 +926,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
#endif #endif
Info("PUSCH: tti_tx=%d, n_prb=%d, rb_start=%d, tbs=%d, mod=%d, mcs=%d, rv_idx=%d, ack=%s, ri=%s, cfo=%.1f Hz%s\n", Info("PUSCH: tti_tx=%d, n_prb=%d, rb_start=%d, tbs=%d, mod=%d, mcs=%d, rv_idx=%d, ack=%s, ri=%s, cfo=%.1f Hz%s\n",
HARQ_TX(tti), TTI_TX(tti),
grant->L_prb, grant->n_prb[0], grant->L_prb, grant->n_prb[0],
grant->mcs.tbs/8, grant->mcs.mod, grant->mcs.idx, rv, grant->mcs.tbs/8, grant->mcs.mod, grant->mcs.idx, rv,
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",
@ -950,7 +957,7 @@ void phch_worker::encode_pucch()
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
#endif #endif
if (srslte_ue_ul_pucch_encode(&ue_ul, uci_data, last_dl_pdcch_ncce, HARQ_TX(tti), signal_buffer[0])) { if (srslte_ue_ul_pucch_encode(&ue_ul, uci_data, last_dl_pdcch_ncce, TTI_TX(tti), signal_buffer[0])) {
Error("Encoding PUCCH\n"); Error("Encoding PUCCH\n");
} }
@ -966,7 +973,7 @@ void phch_worker::encode_pucch()
float gain = set_power(tx_power); float gain = set_power(tx_power);
Info("PUCCH: tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, pmi=%s%s, sr=%s, cfo=%.1f Hz%s\n", Info("PUCCH: tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, pmi=%s%s, sr=%s, cfo=%.1f Hz%s\n",
HARQ_TX(tti), TTI_TX(tti),
last_dl_pdcch_ncce, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb, last_dl_pdcch_ncce, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb,
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",
uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"", uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"",
@ -987,7 +994,7 @@ void phch_worker::encode_srs()
char timestr[64]; char timestr[64];
timestr[0]='\0'; timestr[0]='\0';
if (srslte_ue_ul_srs_encode(&ue_ul, HARQ_TX(tti), signal_buffer[0])) if (srslte_ue_ul_srs_encode(&ue_ul, TTI_TX(tti), signal_buffer[0]))
{ {
Error("Encoding SRS\n"); Error("Encoding SRS\n");
} }
@ -1002,7 +1009,7 @@ void phch_worker::encode_srs()
float gain = set_power(tx_power); float gain = set_power(tx_power);
uint32_t fi = srslte_vec_max_fi((float*) signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)); uint32_t fi = srslte_vec_max_fi((float*) signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb));
float *f = (float*) signal_buffer; float *f = (float*) signal_buffer;
Info("SRS: power=%.2f dBm, tti_tx=%d%s\n", tx_power, HARQ_TX(tti), timestr); Info("SRS: power=%.2f dBm, tti_tx=%d%s\n", tx_power, TTI_TX(tti), timestr);
} }

Loading…
Cancel
Save