Added 2nd Codeword interface in scheduler, plus pmi close loop reporting

master
Xavier Arteaga 7 years ago
parent af669a6cbb
commit 6985682ef0

@ -65,6 +65,7 @@ public:
virtual int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv) = 0;
virtual int ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) = 0;
virtual int pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) = 0;
virtual int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) = 0;
virtual int snr_info(uint32_t tti, uint16_t rnti, float snr_db) = 0;
virtual int ack_info(uint32_t tti, uint16_t rnti, bool ack) = 0;
@ -113,6 +114,7 @@ public:
/* Manages UE bearers and associated configuration */
virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t *cfg) = 0;
virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0;
virtual int set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) = 0;
virtual void phy_config_enabled(uint16_t rnti, bool enabled) = 0;
};

@ -131,9 +131,10 @@ public:
typedef struct {
uint32_t rnti;
srslte_dci_format_t dci_format;
srslte_ra_dl_dci_t dci;
srslte_dci_location_t dci_location;
uint32_t tbs;
uint32_t tbs[SRSLTE_MAX_TB];
bool mac_ce_ta;
bool mac_ce_rnti;
uint32_t nof_pdu_elems;
@ -228,6 +229,7 @@ public:
virtual int dl_ack_info(uint32_t tti, uint16_t rnti, bool ack) = 0;
virtual int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size) = 0;
virtual int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) = 0;
virtual int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) = 0;
virtual int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) = 0;
/* UL information */

@ -95,6 +95,7 @@ typedef struct SRSLTE_API {
typedef struct {
uint16_t rnti;
srslte_dci_format_t dci_format;
srslte_ra_dl_dci_t grant;
srslte_dci_location_t location;
srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_TB];
@ -162,8 +163,7 @@ SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q,
int rv_idx[SRSLTE_MAX_CODEWORDS],
uint32_t sf_idx,
uint8_t *data[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t mimo_type,
uint32_t pmi);
srslte_mimo_type_t mimo_type);
SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q,
srslte_ra_dl_dci_t *grant,

@ -326,8 +326,30 @@ int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant,
int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS],
uint16_t rnti, int rv_idx[SRSLTE_MAX_CODEWORDS], uint32_t sf_idx,
uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type, uint32_t pmi)
uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type)
{
uint32_t pmi = 0;
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant);
/* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */
if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
if (nof_tb == 1) {
if (grant->pinfo > 0 && grant->pinfo < 5) {
pmi = grant->pinfo - 1;
} else {
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
return SRSLTE_ERROR;
}
} else {
if (grant->pinfo < 2) {
pmi = grant->pinfo;
} else {
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
return SRSLTE_ERROR;
}
}
}
/* Configure pdsch_cfg parameters */
if (srslte_pdsch_cfg_mimo(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx, mimo_type, pmi)) {
fprintf(stderr, "Error configuring PDSCH\n");

@ -323,9 +323,17 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti,
memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t));
}
if (uci_data->uci_dif_cqi_len) {
memcpy(uci_data->uci_dif_cqi, pucch_bits + uci_data->uci_cqi_len, uci_data->uci_dif_cqi_len*sizeof(uint8_t));
}
if (uci_data->uci_pmi_len) {
memcpy(uci_data->uci_pmi, pucch_bits + uci_data->uci_cqi_len + uci_data->uci_dif_cqi_len,
uci_data->uci_pmi_len*sizeof(uint8_t));
}
if (uci_data->uci_ri_len) {
uint8_t *ptr = pucch_bits;
uci_data->uci_ri = (uint8_t) srslte_bit_pack(&ptr, uci_data->uci_ri_len);
uci_data->uci_ri = pucch_bits[0]; /* Assume only one bit of RI */
}
if (uci_data->uci_cqi_len || uci_data->uci_ri_len) {

@ -677,6 +677,7 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, flo
}
/* Set RI */
q->ri = best_ri;
if (ri != NULL) {
*ri = best_ri;
}
@ -712,9 +713,10 @@ int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint8_t *ri, float *cn) {
*cn = _cn;
}
q->ri = (uint8_t)((_cn < 17.0f)? 1:0);
/* Set rank indicator */
if (!ret && ri) {
*ri = (uint8_t)((_cn < 17.0f)? 1:0);
*ri = (uint8_t) q->ri;
}
return ret;

@ -281,8 +281,9 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format
}
if (format >= SRSLTE_PUCCH_FORMAT_2) {
/* Append RI */
uint8_t *ptr = uci_buffer;
srslte_bit_unpack(uci_data->uci_ri, &ptr, uci_data->uci_ri_len);
if (uci_data->uci_ri_len) {
uci_data->uci_ri = uci_buffer[0]; // It assumes only 1 bit of RI
}
uci_buffer_len += uci_data->uci_ri_len;
/* Append CQI */

@ -72,7 +72,10 @@ public:
int sr_detected(uint32_t tti, uint16_t rnti);
int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv);
int set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info);
int ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value);
int pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value);
int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value);
int snr_info(uint32_t tti, uint16_t rnti, float snr);
int ack_info(uint32_t tti, uint16_t rnti, bool ack);

@ -45,6 +45,7 @@ struct mac_metrics_t
int dl_buffer;
float dl_cqi;
float dl_ri;
float dl_pmi;
float phr;
};

@ -103,9 +103,11 @@ public:
int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue);
int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code);
int dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dedicated);
int dl_ack_info(uint32_t tti, uint16_t rnti, bool ack);
int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size);
int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value);
int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value);
int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value);
int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc);

@ -38,50 +38,50 @@ class harq_proc
public:
void config(uint32_t id, uint32_t max_retx, srslte::log* log_h);
void set_max_retx(uint32_t max_retx);
void reset();
void reset(uint32_t tb_idx);
uint32_t get_id();
bool is_empty();
bool is_empty(uint32_t tb_idx);
void new_retx(uint32_t tti, int *mcs, int *tbs);
void new_retx(uint32_t tb_idx, uint32_t tti, int *mcs, int *tbs);
bool get_ack();
void set_ack(bool ack);
bool get_ack(uint32_t tb_idx);
void set_ack(uint32_t tb_idx, bool ack);
uint32_t nof_tx();
uint32_t nof_retx();
uint32_t nof_tx(uint32_t tb_idx);
uint32_t nof_retx(uint32_t tb_idx);
uint32_t get_tti();
bool get_ndi();
bool get_ndi(uint32_t tb_idx);
protected:
void new_tx_common(uint32_t tti, int mcs, int tbs);
bool has_pending_retx_common();
void new_tx_common(uint32_t tb_idx, uint32_t tti, int mcs, int tbs);
bool has_pending_retx_common(uint32_t tb_idx);
bool ack;
bool ack[SRSLTE_MAX_TB];
bool active;
bool ndi;
bool ndi[SRSLTE_MAX_TB];
uint32_t id;
uint32_t max_retx;
uint32_t n_rtx;
uint32_t tx_cnt;
uint32_t n_rtx[SRSLTE_MAX_TB];
uint32_t tx_cnt[SRSLTE_MAX_TB];
int tti;
int last_mcs;
int last_tbs;
int last_mcs[SRSLTE_MAX_TB];
int last_tbs[SRSLTE_MAX_TB];
srslte::log* log_h;
private:
bool ack_received;
bool ack_received[SRSLTE_MAX_TB];
};
class dl_harq_proc : public harq_proc
{
public:
void new_tx(uint32_t tti, int mcs, int tbs, uint32_t n_cce);
void new_tx(uint32_t tb_idx, uint32_t tti, int mcs, int tbs, uint32_t n_cce);
uint32_t get_rbgmask();
void set_rbgmask(uint32_t new_mask);
bool has_pending_retx(uint32_t tti);
int get_tbs();
bool has_pending_retx(uint32_t tb_idx, uint32_t tti);
int get_tbs(uint32_t tb_idx);
uint32_t get_n_cce();
private:
uint32_t rbgmask;

@ -68,8 +68,10 @@ public:
void ul_phr(int phr);
void mac_buffer_state(uint32_t ce_code);
void ul_recv_len(uint32_t lcid, uint32_t len);
void set_dl_ant_info(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dedicated);
void set_ul_cqi(uint32_t tti, uint32_t cqi, uint32_t ul_ch_code);
void set_dl_ri(uint32_t tti, uint32_t ri);
void set_dl_pmi(uint32_t tti, uint32_t ri);
void set_dl_cqi(uint32_t tti, uint32_t cqi);
int set_ack_info(uint32_t tti, bool ack);
void set_ul_crc(uint32_t tti, bool crc_res);
@ -108,8 +110,11 @@ public:
void unset_sr();
int generate_format1(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi);
int generate_format2a(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi);
int generate_format2(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi);
int generate_format0(ul_harq_proc *h, sched_interface::ul_sched_data_t *data, uint32_t tti, bool cqi_request);
srslte_dci_format_t get_dci_format();
uint32_t get_aggr_level(uint32_t nof_bits);
sched_dci_cce_t *get_locations(uint32_t current_cfi, uint32_t sf_idx);
@ -158,6 +163,8 @@ private:
int power_headroom;
uint32_t dl_ri;
uint32_t dl_ri_tti;
uint32_t dl_pmi;
uint32_t dl_pmi_tti;
uint32_t dl_cqi;
uint32_t dl_cqi_tti;
uint32_t cqi_request_tti;
@ -180,6 +187,7 @@ private:
ul_harq_proc ul_harq[SCHED_MAX_HARQ_PROC];
bool phy_config_dedicated_enabled;
LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT dl_ant_info;
};

@ -94,6 +94,7 @@ public:
void metrics_tx(bool crc, uint32_t tbs);
void metrics_phr(float phr);
void metrics_dl_ri(uint32_t dl_cqi);
void metrics_dl_pmi(uint32_t dl_cqi);
void metrics_dl_cqi(uint32_t dl_cqi);
@ -110,6 +111,7 @@ private:
uint32_t phr_counter;
uint32_t dl_cqi_counter;
uint32_t dl_ri_counter;
uint32_t dl_pmi_counter;
mac_metrics_t metrics;
srslte::mac_pcap* pcap;

@ -305,6 +305,18 @@ int mac::crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc)
}
}
int mac::set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) {
log_h->step(tti);
if (ue_db.count(rnti)) {
scheduler.dl_ant_info(rnti, dl_ant_info);
} else {
Error("User rnti=0x%x not found\n", rnti);
return -1;
}
return 0;
}
int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value)
{
log_h->step(tti);
@ -319,6 +331,20 @@ int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value)
return 0;
}
int mac::pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value)
{
log_h->step(tti);
if (ue_db.count(rnti)) {
scheduler.dl_pmi_info(tti, rnti, pmi_value);
ue_db[rnti]->metrics_dl_pmi(pmi_value);
} else {
Error("User rnti=0x%x not found\n", rnti);
return -1;
}
return 0;
}
int mac::cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value)
{
log_h->step(tti);
@ -445,6 +471,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res)
// Copy grant info
dl_sched_res->sched_grants[n].rnti = rnti;
dl_sched_res->sched_grants[n].dci_format = sched_result.data[i].dci_format;
memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.data[i].dci, sizeof(srslte_ra_dl_dci_t));
memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.data[i].dci_location, sizeof(srslte_dci_location_t));
@ -454,10 +481,10 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res)
if (sched_result.data[i].nof_pdu_elems > 0) {
dl_sched_res->sched_grants[n].data[0] = ue_db[rnti]->generate_pdu(sched_result.data[i].pdu,
sched_result.data[i].nof_pdu_elems,
sched_result.data[i].tbs);
sched_result.data[i].tbs[0]);
if (pcap) {
pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs, rnti, true, tti);
pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs[0], rnti, true, tti);
}
} else {
@ -470,6 +497,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res)
for (uint32_t i=0;i<sched_result.nof_rar_elems;i++) {
// Copy grant info
dl_sched_res->sched_grants[n].rnti = sched_result.rar[i].rarnti;
dl_sched_res->sched_grants[n].dci_format = SRSLTE_DCI_FORMAT1A; // Force Format 1A
memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.rar[i].dci, sizeof(srslte_ra_dl_dci_t));
memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.rar[i].dci_location, sizeof(srslte_dci_location_t));
@ -481,7 +509,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res)
if (pcap) {
pcap->write_dl_ranti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs, dl_sched_res->sched_grants[n].rnti, true, tti);
pcap->write_dl_ranti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs[0], dl_sched_res->sched_grants[n].rnti, true, tti);
}
n++;
@ -491,6 +519,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res)
for (uint32_t i=0;i<sched_result.nof_bc_elems;i++) {
// Copy grant info
dl_sched_res->sched_grants[n].rnti = (sched_result.bc[i].type == sched_interface::dl_sched_bc_t::BCCH ) ? SRSLTE_SIRNTI : SRSLTE_PRNTI;
dl_sched_res->sched_grants[n].dci_format = SRSLTE_DCI_FORMAT1A; // Force Format 1A
memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.bc[i].dci, sizeof(srslte_ra_dl_dci_t));
memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.bc[i].dci_location, sizeof(srslte_dci_location_t));

@ -238,6 +238,19 @@ int sched::dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code)
return ret;
}
int sched::dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) {
pthread_mutex_lock(&mutex);
int ret = 0;
if (ue_db.count(rnti)) {
ue_db[rnti].set_dl_ant_info(dl_ant_info);
} else {
Error("User rnti=0x%x not found\n", rnti);
ret = -1;
}
pthread_mutex_unlock(&mutex);
return ret;
}
int sched::dl_ack_info(uint32_t tti, uint16_t rnti, bool ack)
{
pthread_mutex_lock(&mutex);
@ -280,6 +293,20 @@ int sched::dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value)
return ret;
}
int sched::dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value)
{
pthread_mutex_lock(&mutex);
int ret = 0;
if (ue_db.count(rnti)) {
ue_db[rnti].set_dl_pmi(tti, pmi_value);
} else {
Error("User rnti=0x%x not found\n", rnti);
ret = -1;
}
pthread_mutex_unlock(&mutex);
return ret;
}
int sched::dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value)
{
pthread_mutex_lock(&mutex);
@ -611,19 +638,34 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST])
uint16_t rnti = (uint16_t) iter->first;
dl_harq_proc *h = dl_metric->get_user_allocation(user);
srslte_dci_format_t dci_format = user->get_dci_format();
data[nof_data_elems].dci_format = dci_format;
if (h) {
// Try to schedule DCI first
if (generate_dci(&data[nof_data_elems].dci_location,
user->get_locations(current_cfi, sf_idx),
user->get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, cfg.cell.nof_prb, cfg.cell.nof_ports)), user))
user->get_aggr_level(srslte_dci_format_sizeof(dci_format, cfg.cell.nof_prb, cfg.cell.nof_ports)), user))
{
bool is_newtx = h->is_empty();
int tbs = user->generate_format1(h, &data[nof_data_elems], current_tti, current_cfi);
bool is_newtx = h->is_empty(0);
int tbs = 0;
switch(dci_format) {
case SRSLTE_DCI_FORMAT1:
tbs = user->generate_format1(h, &data[nof_data_elems], current_tti, current_cfi);
break;
case SRSLTE_DCI_FORMAT2:
tbs = user->generate_format2(h, &data[nof_data_elems], current_tti, current_cfi);
break;
case SRSLTE_DCI_FORMAT2A:
tbs = user->generate_format2a(h, &data[nof_data_elems], current_tti, current_cfi);
break;
default:
Error("DCI format (%d) not implemented\n", dci_format);
}
if (tbs >= 0) {
log_h->info("SCHED: DL %s rnti=0x%x, pid=%d, mask=0x%x, dci=%d,%d, n_rtx=%d, tbs=%d, buffer=%d\n",
!is_newtx?"retx":"tx", rnti, h->get_id(), h->get_rbgmask(),
data[nof_data_elems].dci_location.L, data[nof_data_elems].dci_location.ncce, h->nof_retx(),
data[nof_data_elems].dci_location.L, data[nof_data_elems].dci_location.ncce, h->nof_retx(0),
tbs, user->get_pending_dl_new_data(current_tti));
nof_data_elems++;
} else {
@ -633,7 +675,7 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST])
tbs, user->get_pending_dl_new_data(current_tti));
}
} else {
h->reset();
h->reset(0);
Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d\n", rnti, h->get_id());
}
}
@ -721,7 +763,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
/* Indicate PHICH acknowledgment if needed */
if (h->has_pending_ack()) {
sched_result->phich[nof_phich_elems].phich = h->get_ack()?ul_sched_phich_t::ACK:ul_sched_phich_t::NACK;
sched_result->phich[nof_phich_elems].phich = h->get_ack(0)?ul_sched_phich_t::ACK:ul_sched_phich_t::NACK;
sched_result->phich[nof_phich_elems].rnti = rnti;
nof_phich_elems++;
}
@ -778,7 +820,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
if (h)
{
ul_harq_proc::ul_alloc_t alloc = h->get_alloc();
bool is_newtx = h->is_empty();
bool is_newtx = h->is_empty(0);
bool needs_pdcch = !h->is_adaptive_retx() && !is_rar;
// Set number of retx
@ -797,7 +839,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
user->get_locations(current_cfi, sf_idx),
aggr_level))
{
h->reset();
h->reset(0);
log_h->warning("SCHED: Could not schedule UL DCI rnti=0x%x, pid=%d, L=%d\n",
rnti, h->get_id(), aggr_level);
sched_result->pusch[nof_dci_elems].needs_pdcch = false;
@ -824,7 +866,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
is_newtx?"tx":"retx",
rnti, h->get_id(),
sched_result->pusch[nof_dci_elems].dci_location.L, sched_result->pusch[nof_dci_elems].dci_location.ncce,
alloc.RB_start, alloc.RB_start+alloc.L, h->nof_retx(), sched_result->pusch[nof_dci_elems].tbs,
alloc.RB_start, alloc.RB_start+alloc.L, h->nof_retx(0), sched_result->pusch[nof_dci_elems].tbs,
user->get_pending_ul_new_data(current_tti),pending_data_before, user->get_pending_ul_old_data());
nof_dci_elems++;

@ -50,7 +50,9 @@ void harq_proc::config(uint32_t id_, uint32_t max_retx_, srslte::log* log_h_)
log_h = log_h_;
id = id_;
max_retx = max_retx_;
ndi = false;
for (int i = 0; i < SRSLTE_MAX_TB; i++) {
ndi[i] = false;
}
}
void harq_proc::set_max_retx(uint32_t max_retx_) {
@ -63,57 +65,57 @@ uint32_t harq_proc::get_id()
return id;
}
void harq_proc::reset()
void harq_proc::reset(uint32_t tb_idx)
{
active = false;
ack = true;
ack_received = false;
n_rtx = 0;
ack[tb_idx] = true;
ack_received[tb_idx] = false;
n_rtx[tb_idx] = 0;
tti = 0;
last_mcs = -1;
last_tbs = -1;
tx_cnt = 0;
last_mcs[tb_idx] = -1;
last_tbs[tb_idx] = -1;
tx_cnt[tb_idx] = 0;
}
bool harq_proc::is_empty()
bool harq_proc::is_empty(uint32_t tb_idx)
{
return !active || (active && ack && ack_received);
return !active || (active && ack[tb_idx] && ack_received[tb_idx]);
}
bool harq_proc::has_pending_retx_common()
bool harq_proc::has_pending_retx_common(uint32_t tb_idx)
{
return !ack && n_rtx < max_retx;
return !ack[tb_idx] && n_rtx[tb_idx] < max_retx;
}
uint32_t harq_proc::get_tti()
{
return tti;
return (uint32_t) tti;
}
bool harq_proc::get_ack()
bool harq_proc::get_ack(uint32_t tb_idx)
{
return ack;
return ack[tb_idx];
}
void harq_proc::set_ack(bool ack_)
void harq_proc::set_ack(uint32_t tb_idx, bool ack_)
{
ack = ack_;
ack_received = true;
log_h->debug("ACK=%d received pid=%d, n_rtx=%d, max_retx=%d\n", ack_, id, n_rtx, max_retx);
if (n_rtx + 1 >= max_retx) {
Warning("SCHED: discarting TB pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", id, tti, max_retx);
ack[tb_idx] = ack_;
ack_received[tb_idx] = true;
log_h->debug("ACK=%d received pid=%d, tb_idx=%d, n_rtx=%d, max_retx=%d\n", ack_, id, tb_idx, n_rtx[tb_idx], max_retx);
if (n_rtx[tb_idx] + 1 >= max_retx) {
Warning("SCHED: discarting TB %d pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", tb_idx, id, tti, max_retx);
active = false;
}
}
void harq_proc::new_tx_common(uint32_t tti_, int mcs, int tbs)
void harq_proc::new_tx_common(uint32_t tb_idx, uint32_t tti_, int mcs, int tbs)
{
reset();
ndi = !ndi;
reset(tb_idx);
ndi[tb_idx] = !ndi[tb_idx];
tti = tti_;
tx_cnt++;
last_mcs = mcs;
last_tbs = tbs;
tx_cnt[tb_idx]++;
last_mcs[tb_idx] = mcs;
last_tbs[tb_idx] = tbs;
if (max_retx) {
active = true;
@ -122,42 +124,42 @@ void harq_proc::new_tx_common(uint32_t tti_, int mcs, int tbs)
}
}
void harq_proc::new_retx(uint32_t tti_, int *mcs, int *tbs)
void harq_proc::new_retx(uint32_t tb_idx, uint32_t tti_, int *mcs, int *tbs)
{
ack_received = false;
ack_received[tb_idx] = false;
tti = tti_;
n_rtx++;
n_rtx[tb_idx]++;
if (mcs) {
*mcs = last_mcs;
*mcs = last_mcs[tb_idx];
}
if (tbs) {
*tbs = last_tbs;
*tbs = last_tbs[tb_idx];
}
}
uint32_t harq_proc::nof_tx()
uint32_t harq_proc::nof_tx(uint32_t tb_idx)
{
return tx_cnt;
return tx_cnt[tb_idx];
}
uint32_t harq_proc::nof_retx()
uint32_t harq_proc::nof_retx(uint32_t tb_idx)
{
return n_rtx;
return n_rtx[tb_idx];
}
bool harq_proc::get_ndi()
bool harq_proc::get_ndi(uint32_t tb_idx)
{
return ndi;
return ndi[tb_idx];
}
/******************************************************
* UE::DL HARQ class *
******************************************************/
void dl_harq_proc::new_tx(uint32_t tti, int mcs, int tbs, uint32_t n_cce_)
void dl_harq_proc::new_tx(uint32_t tb_idx, uint32_t tti, int mcs, int tbs, uint32_t n_cce_)
{
n_cce = n_cce_;
new_tx_common(tti, mcs, tbs);
new_tx_common(tb_idx, tti, mcs, tbs);
}
uint32_t dl_harq_proc::get_n_cce()
@ -175,14 +177,14 @@ void dl_harq_proc::set_rbgmask(uint32_t new_mask)
rbgmask = new_mask;
}
bool dl_harq_proc::has_pending_retx(uint32_t current_tti)
bool dl_harq_proc::has_pending_retx(uint32_t tb_idx, uint32_t current_tti)
{
return srslte_tti_interval(current_tti, tti) >= 8 && has_pending_retx_common();
return srslte_tti_interval(current_tti, tti) >= 8 && has_pending_retx_common(tb_idx);
}
int dl_harq_proc::get_tbs()
int dl_harq_proc::get_tbs(uint32_t tb_idx)
{
return last_tbs;
return last_tbs[tb_idx];
}
@ -215,7 +217,7 @@ bool ul_harq_proc::is_adaptive_retx()
void ul_harq_proc::new_tx(uint32_t tti_, int mcs, int tbs)
{
need_ack = true;
new_tx_common(tti_, mcs, tbs);
new_tx_common(0, tti_, mcs, tbs);
pending_data = tbs;
}
@ -225,7 +227,7 @@ bool ul_harq_proc::has_pending_ack()
bool ret = need_ack;
// Reset if already received a positive ACK
if (active && ack) {
if (active && ack[0]) {
active = false;
}
if (!active) {
@ -244,9 +246,9 @@ void ul_harq_proc::reset_pending_data()
}
uint32_t ul_harq_proc::get_pending_data()
uint32_t ul_harq_proc::get_pending_data()
{
return pending_data;
return (uint32_t) pending_data;
}
void ul_harq_proc::set_rar_mcs(uint32_t mcs)

@ -212,7 +212,7 @@ void ul_metric_rr::new_tti(std::map<uint16_t,sched_ue> &ue_db, uint32_t nof_rb_,
nof_users_with_data = 0;
for(std::map<uint16_t, sched_ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) {
sched_ue *user = (sched_ue*) &iter->second;
if (user->get_pending_ul_new_data(current_tti) || !user->get_ul_harq(current_tti)->is_empty()) {
if (user->get_pending_ul_new_data(current_tti) || !user->get_ul_harq(current_tti)->is_empty(0)) {
user->ue_idx = nof_users_with_data;
nof_users_with_data++;
}
@ -284,7 +284,7 @@ ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user)
uint32_t pending_data = user->get_pending_ul_new_data(current_tti);
ul_harq_proc *h = user->get_ul_harq(current_tti);
if (pending_data || !h->is_empty()) {
if (pending_data || !h->is_empty(0)) {
if (nof_users_with_data) {
if ((current_tti%nof_users_with_data) != user->ue_idx) {
return NULL;
@ -294,7 +294,7 @@ ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user)
// Schedule retx if we have space
if (!h->is_empty()) {
if (!h->is_empty(0)) {
ul_harq_proc::ul_alloc_t alloc = h->get_alloc();
@ -313,7 +313,7 @@ ul_harq_proc* ul_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 (h->is_empty()) {
if (h->is_empty(0)) {
// Allocate resources based on pending data
if (pending_data) {
uint32_t pending_rb = user->get_required_prb_ul(pending_data);

@ -109,8 +109,8 @@ void sched_ue::reset()
ul_cqi_tti = 0;
cqi_request_tti = 0;
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
dl_harq[i].reset();
ul_harq[i].reset();
dl_harq[i].reset(0);
ul_harq[i].reset(0);
}
for (int i=0;i<sched_interface::MAX_LC; i++) {
rem_bearer(i);
@ -291,8 +291,8 @@ int sched_ue::set_ack_info(uint32_t tti, bool ack)
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
if (((dl_harq[i].get_tti()+4)%10240) == 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);
return dl_harq[i].get_tbs();
dl_harq[i].set_ack(0, ack);
return dl_harq[i].get_tbs(0);
}
}
Warning("SCHED: Received ACK info for unknown TTI=%d\n", tti);
@ -320,7 +320,7 @@ void sched_ue::ul_recv_len(uint32_t lcid, uint32_t len)
void sched_ue::set_ul_crc(uint32_t tti, bool crc_res)
{
get_ul_harq(tti)->set_ack(crc_res);
get_ul_harq(tti)->set_ack(0, crc_res);
}
void sched_ue::set_dl_ri(uint32_t tti, uint32_t ri)
@ -329,12 +329,23 @@ void sched_ue::set_dl_ri(uint32_t tti, uint32_t ri)
dl_ri_tti = tti;
}
void sched_ue::set_dl_pmi(uint32_t tti, uint32_t pmi)
{
dl_pmi = pmi;
dl_pmi_tti = tti;
}
void sched_ue::set_dl_cqi(uint32_t tti, uint32_t cqi)
{
dl_cqi = cqi;
dl_cqi_tti = tti;
}
void sched_ue::set_dl_ant_info(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *d)
{
memcpy(&dl_ant_info, d, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT));
}
void sched_ue::set_ul_cqi(uint32_t tti, uint32_t cqi, uint32_t ul_ch_code)
{
ul_cqi = cqi;
@ -385,7 +396,7 @@ int sched_ue::generate_format1(dl_harq_proc *h,
if (is_first_dl_tx()) {
need_conres_ce = true;
}
if (h->is_empty()) {
if (h->is_empty(0)) {
uint32_t req_bytes = get_pending_dl_new_data(tti);
@ -401,11 +412,11 @@ int sched_ue::generate_format1(dl_harq_proc *h,
mcs = fixed_mcs_dl;
}
h->new_tx(tti, mcs, tbs, data->dci_location.ncce);
h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce);
Debug("SCHED: Alloc format1 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes);
} else {
h->new_retx(tti, &mcs, &tbs);
h->new_retx(0, tti, &mcs, &tbs);
Debug("SCHED: Alloc format1 previous mcs=%d, tbs=%d\n", mcs, tbs);
}
@ -431,11 +442,151 @@ int sched_ue::generate_format1(dl_harq_proc *h,
if (tbs > 0) {
dci->harq_process = h->get_id();
dci->mcs_idx = mcs;
dci->rv_idx = sched::get_rvidx(h->nof_retx());
dci->ndi = h->get_ndi();
dci->rv_idx = sched::get_rvidx(h->nof_retx(0));
dci->ndi = h->get_ndi(0);
dci->tpc_pucch = next_tpc_pucch;
next_tpc_pucch = 1;
data->tbs[0] = tbs;
dci->tb_en[0] = true;
dci->tb_en[1] = false;
}
return tbs;
}
// Generates a Format2a grant
int sched_ue::generate_format2a(dl_harq_proc *h,
sched_interface::dl_sched_data_t *data,
uint32_t tti,
uint32_t cfi)
{
srslte_ra_dl_dci_t *dci = &data->dci;
bzero(dci, sizeof(srslte_ra_dl_dci_t));
uint32_t sf_idx = tti%10;
int mcs = 0;
int tbs = 0;
dci->alloc_type = SRSLTE_RA_ALLOC_TYPE0;
dci->type0_alloc.rbg_bitmask = h->get_rbgmask();
if (h->is_empty(0)) {
uint32_t req_bytes = get_pending_dl_new_data(tti);
uint32_t nof_prb = format1_count_prb(h->get_rbgmask(), cell.nof_prb);
srslte_ra_dl_grant_t grant;
srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb);
uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0);
uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols);
if (fixed_mcs_dl < 0) {
tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs);
} else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb)/8;
mcs = fixed_mcs_dl;
}
h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce);
Debug("SCHED: Alloc format1 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes);
} else {
h->new_retx(0, tti, &mcs, &tbs);
Debug("SCHED: Alloc format1 previous mcs=%d, tbs=%d\n", mcs, tbs);
}
int rem_tbs = tbs;
int x = 0;
do {
x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]);
rem_tbs -= x;
if (x) {
data->nof_pdu_elems++;
}
} while(rem_tbs > 0 && x > 0);
data->rnti = rnti;
if (tbs > 0) {
dci->harq_process = h->get_id();
dci->mcs_idx = mcs;
dci->rv_idx = sched::get_rvidx(h->nof_retx(0));
dci->ndi = h->get_ndi(0);
dci->tpc_pucch = next_tpc_pucch;
next_tpc_pucch = 1;
data->tbs = tbs;
data->tbs[0] = tbs;
dci->tb_en[0] = true;
dci->tb_en[1] = false;
}
return tbs;
}
// Generates a Format2 grant
int sched_ue::generate_format2(dl_harq_proc *h,
sched_interface::dl_sched_data_t *data,
uint32_t tti,
uint32_t cfi)
{
srslte_ra_dl_dci_t *dci = &data->dci;
bzero(dci, sizeof(srslte_ra_dl_dci_t));
uint32_t sf_idx = tti%10;
int mcs = 0;
int tbs = 0;
dci->alloc_type = SRSLTE_RA_ALLOC_TYPE0;
dci->type0_alloc.rbg_bitmask = h->get_rbgmask();
if (h->is_empty(0)) {
uint32_t req_bytes = get_pending_dl_new_data(tti);
uint32_t nof_prb = format1_count_prb(h->get_rbgmask(), cell.nof_prb);
srslte_ra_dl_grant_t grant;
srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb);
uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0);
uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols);
if (fixed_mcs_dl < 0) {
tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs);
} else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb)/8;
mcs = fixed_mcs_dl;
}
h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce);
Debug("SCHED: Alloc format2 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes);
} else {
h->new_retx(0, tti, &mcs, &tbs);
Debug("SCHED: Alloc format2 previous mcs=%d, tbs=%d\n", mcs, tbs);
}
int rem_tbs = tbs;
int x = 0;
do {
x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]);
rem_tbs -= x;
if (x) {
data->nof_pdu_elems++;
}
} while(rem_tbs > 0 && x > 0);
data->rnti = rnti;
if (tbs > 0) {
dci->pinfo = (uint8_t) (dl_pmi + 1);
/* if (SRSLTE_RA_DL_GRANT_NOF_TB(dci) == 1) {
dci->pinfo = (uint8_t) (dl_pmi + 1);
} else {
dci->pinfo = (uint8_t) (dl_pmi & 1);
}*/
dci->harq_process = h->get_id();
dci->mcs_idx = mcs;
dci->rv_idx = sched::get_rvidx(h->nof_retx(0));
dci->ndi = h->get_ndi(0);
dci->tpc_pucch = next_tpc_pucch;
next_tpc_pucch = 1;
data->tbs[0] = tbs;
dci->tb_en[0] = true;
dci->tb_en[1] = false;
}
@ -459,7 +610,7 @@ int sched_ue::generate_format0(ul_harq_proc *h,
if (h->get_rar_mcs(&mcs)) {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8;
h->new_tx(tti, mcs, tbs);
} else if (h->is_empty()) {
} else if (h->is_empty(0)) {
uint32_t req_bytes = get_pending_ul_new_data(tti);
@ -475,7 +626,7 @@ int sched_ue::generate_format0(ul_harq_proc *h,
h->new_tx(tti, mcs, tbs);
} else {
h->new_retx(tti, &mcs, NULL);
h->new_retx(0, tti, &mcs, NULL);
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8;
}
@ -486,8 +637,8 @@ int sched_ue::generate_format0(ul_harq_proc *h,
dci->type2_alloc.L_crb = allocation.L;
dci->type2_alloc.RB_start = allocation.RB_start;
dci->mcs_idx = mcs;
dci->rv_idx = sched::get_rvidx(h->nof_retx());
dci->ndi = h->get_ndi();
dci->rv_idx = sched::get_rvidx(h->nof_retx(0));
dci->ndi = h->get_ndi(0);
dci->cqi_request = cqi_request;
dci->freq_hop_fl = srslte_ra_ul_dci_t::SRSLTE_RA_PUSCH_HOP_DISABLED;
dci->tpc_pusch = next_tpc_pusch;
@ -518,7 +669,7 @@ uint32_t sched_ue::get_max_retx() {
bool sched_ue::is_first_dl_tx()
{
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
if (dl_harq[i].nof_tx() > 0) {
if (dl_harq[i].nof_tx(0) > 0) {
return false;
}
}
@ -666,7 +817,7 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti)
int oldest_idx=-1;
uint32_t oldest_tti = 0;
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
if (dl_harq[i].has_pending_retx(tti)) {
if (dl_harq[i].has_pending_retx(0, tti)) {
uint32_t x = srslte_tti_interval(tti, dl_harq[i].get_tti());
if (x > oldest_tti) {
oldest_idx = i;
@ -684,7 +835,7 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti)
dl_harq_proc* sched_ue::get_empty_dl_harq()
{
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
if (dl_harq[i].is_empty()) {
if (dl_harq[i].is_empty(0)) {
return &dl_harq[i];
}
}
@ -696,6 +847,36 @@ ul_harq_proc* sched_ue::get_ul_harq(uint32_t tti)
return &ul_harq[tti%SCHED_MAX_HARQ_PROC];
}
srslte_dci_format_t sched_ue::get_dci_format() {
srslte_dci_format_t ret = SRSLTE_DCI_FORMAT1;
if (phy_config_dedicated_enabled) {
/* FIXME: Assumes UE-Specific Search Space (Not common) */
switch (dl_ant_info.tx_mode) {
case LIBLTE_RRC_TRANSMISSION_MODE_1:
case LIBLTE_RRC_TRANSMISSION_MODE_2:
ret = SRSLTE_DCI_FORMAT1;
break;
case LIBLTE_RRC_TRANSMISSION_MODE_3:
ret = SRSLTE_DCI_FORMAT2A;
break;
case LIBLTE_RRC_TRANSMISSION_MODE_4:
ret = SRSLTE_DCI_FORMAT2;
break;
case LIBLTE_RRC_TRANSMISSION_MODE_5:
case LIBLTE_RRC_TRANSMISSION_MODE_6:
case LIBLTE_RRC_TRANSMISSION_MODE_7:
case LIBLTE_RRC_TRANSMISSION_MODE_8:
case LIBLTE_RRC_TRANSMISSION_MODE_N_ITEMS:
default:
Warning("Incorrect transmission mode (rnti=%04x)\n", rnti);
}
}
return ret;
}
/* Find lowest DCI aggregation level supported by the UE spectral efficiency */
uint32_t sched_ue::get_aggr_level(uint32_t nof_bits)
{

@ -412,6 +412,11 @@ void ue::metrics_dl_ri(uint32_t dl_ri) {
dl_ri_counter++;
}
void ue::metrics_dl_pmi(uint32_t dl_ri) {
metrics.dl_pmi = SRSLTE_VEC_CMA((float) dl_ri, metrics.dl_pmi, dl_pmi_counter);
dl_pmi_counter++;
}
void ue::metrics_dl_cqi(uint32_t dl_cqi) {
metrics.dl_cqi = SRSLTE_VEC_CMA((float) dl_cqi, metrics.dl_cqi, dl_cqi_counter);
dl_cqi_counter++;

@ -99,6 +99,7 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
fprintf(stderr, "Error allocating memory\n");
return;
}
bzero(signal_buffer_tx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t));
}
if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) {
fprintf(stderr, "Error initiating ENB DL\n");
@ -566,6 +567,10 @@ int phch_worker::decode_pucch(uint32_t tti_rx)
needs_cqi = true;
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value);
if (tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
//uci_data.uci_dif_cqi_len = 3;
uci_data.uci_pmi_len = 2;
}
}
}
@ -589,6 +594,17 @@ int phch_worker::decode_pucch(uint32_t tti_rx)
srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value);
phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi);
sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi);
if (uci_data.uci_pmi_len) {
uint8_t *ptr = uci_data.uci_pmi;
uint32_t packed_pmi = uci_data.uci_pmi[0];
if (uci_data.uci_pmi_len > 1) {
packed_pmi = (packed_pmi << 1) + uci_data.uci_pmi[1];
}
phy->mac->pmi_info(tti_rx, rnti, packed_pmi);
sprintf(cqi_ri_str, "%s, pmi=%c", cqi_ri_str, packed_pmi + 0x30);
}
}
log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n",
rnti,
@ -656,35 +672,16 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra
{
/* For each grant... */
for (uint32_t i=0;i<nof_grants;i++) {
uint16_t rnti = grants[i].rnti;
srslte_enb_dl_pdsch_t *grant = &grants[i];
uint16_t rnti = grant->rnti;
if (rnti) {
bool dedicated_acknowledged = ue_db[grants[i].rnti].dedicated_ack;
bool antenna_info_present = ue_db[grants[i].rnti].dedicated.antenna_info_present;
LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = ue_db[grants[i].rnti].dedicated.antenna_info_explicit_value.tx_mode;
srslte_dci_format_t format = SRSLTE_DCI_FORMAT1;
switch(grants[i].grant.alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0:
case SRSLTE_RA_ALLOC_TYPE1:
if (dedicated_acknowledged && antenna_info_present && tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) {
format = SRSLTE_DCI_FORMAT2A;
} else if (dedicated_acknowledged && antenna_info_present && tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
format = SRSLTE_DCI_FORMAT2;
} else {
format = SRSLTE_DCI_FORMAT1;
}
break;
case SRSLTE_RA_ALLOC_TYPE2:
format = SRSLTE_DCI_FORMAT1A;
break;
}
if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, format, grants[i].location, rnti, sf_idx)) {
if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, grant->dci_format, grants[i].location, rnti, sf_idx)) {
fprintf(stderr, "Error putting PDCCH %d\n",i);
return SRSLTE_ERROR;
}
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=%d\n", srslte_dci_format_string(grant->dci_format),
rnti, grants[i].location.ncce, (1<<grants[i].location.L), tti_tx);
}
}
@ -694,18 +691,16 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra
int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants, uint32_t sf_idx)
{
/* FIXME: currently, it assumes TM1, TM2 or TM3 */
srslte_mimo_type_t mimo_type = (enb_dl.cell.nof_ports == 1) ? SRSLTE_MIMO_TYPE_SINGLE_ANTENNA : SRSLTE_MIMO_TYPE_TX_DIVERSITY;
for (uint32_t i=0;i<nof_grants;i++) {
uint16_t rnti = grants[i].rnti;
if (rnti) {
bool rnti_is_user = true;
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || rnti == SRSLTE_MRNTI) {
rnti_is_user = false;
}
/* Mimo type (tx scheme) shall be single or tx diversity by default */
srslte_mimo_type_t mimo_type = (enb_dl.cell.nof_ports == 1) ? SRSLTE_MIMO_TYPE_SINGLE_ANTENNA
: SRSLTE_MIMO_TYPE_TX_DIVERSITY;
srslte_ra_dl_grant_t phy_grant;
srslte_ra_dl_dci_to_grant(&grants[i].grant, enb_dl.cell.nof_prb, rnti, &phy_grant);
@ -717,11 +712,41 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
case SRSLTE_RA_ALLOC_TYPE1:
sprintf(grant_str, "mask=0x%x",grants[i].grant.type1_alloc.vrb_bitmask);
break;
case SRSLTE_RA_ALLOC_TYPE2:
default:
sprintf(grant_str, "rb_start=%d",grants[i].grant.type2_alloc.RB_start);
break;
}
srslte_dci_format_t dci_format = grants[i].dci_format;
switch (dci_format) {
case SRSLTE_DCI_FORMAT1:
case SRSLTE_DCI_FORMAT1A:
/* Do nothing, it keeps default */
break;
case SRSLTE_DCI_FORMAT2A:
break;
case SRSLTE_DCI_FORMAT2:
if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1) {
if (phy_grant.pinfo == 0) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else {
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
}
} else if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1 && phy_grant.pinfo == 0) {
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
}
break;
case SRSLTE_DCI_FORMAT0:
case SRSLTE_DCI_FORMAT1C:
case SRSLTE_DCI_FORMAT1B:
case SRSLTE_DCI_FORMAT1D:
case SRSLTE_DCI_FORMAT2B:
default:
Error("Not implemented/Undefined DCI format (%d)\n", dci_format);
}
if (LOG_THIS(rnti)) {
uint8_t x = 0;
uint8_t *ptr = grants[i].data[0];
@ -730,15 +755,19 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
ptr = &x;
len = 1;
}
char pinfo_str[16] = {0};
if (dci_format == SRSLTE_DCI_FORMAT2) {
snprintf(pinfo_str, 15, ", pinfo=%x", phy_grant.pinfo);
}
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=%d, tx_scheme=%s%s\n",
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, srslte_mimotype2str(mimo_type), pinfo_str);
}
int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1};
if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_idx, grants[i].data, mimo_type, 0)) {
if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_idx, grants[i].data, mimo_type)) {
fprintf(stderr, "Error putting PDSCH %d\n",i);
return SRSLTE_ERROR;
}

@ -864,6 +864,7 @@ void rrc::ue::handle_rrc_con_setup_complete(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE
// Acknowledge Dedicated Configuration
parent->phy->set_conf_dedicated_ack(rnti, true);
parent->mac->phy_config_enabled(rnti, true);
if(has_tmsi) {
parent->s1ap->initial_ue(rnti, pdu, m_tmsi, mmec);
@ -1211,7 +1212,8 @@ void rrc::ue::send_connection_setup(bool is_setup)
// Configure PHY layer
parent->phy->set_config_dedicated(rnti, phy_cfg);
parent->phy->set_conf_dedicated_ack(rnti, false);
parent->mac->phy_config_enabled(rnti, true);
parent->mac->set_dl_ant_info(rnti, &phy_cfg->antenna_info_explicit_value);
parent->mac->phy_config_enabled(rnti, false);
rr_cfg->drb_to_add_mod_list_size = 0;
rr_cfg->drb_to_release_list_size = 0;

@ -374,7 +374,6 @@ void phch_worker::compute_ri() {
float sinr = 0.0f;
uint8 packed_pmi = 0;
srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr);
srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, 2);
if (uci_data.uci_ri == 0) {
uci_data.uci_pmi_len = 2;
uci_data.uci_dif_cqi_len = 0;
@ -382,6 +381,8 @@ void phch_worker::compute_ri() {
uci_data.uci_pmi_len = 1;
uci_data.uci_dif_cqi_len = 3;
}
srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, uci_data.uci_pmi_len);
Info("pmi=%d\n", packed_pmi);
/* If only one antenna in TM4 print limitation warning */
if (ue_dl.nof_rx_antennas < 2) {
@ -615,9 +616,13 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL
snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec);
#endif
snprintf(commonstr, 128, "PDSCH: l_crb=%2d, harq=%d, snr=%.1f dB, tx_scheme=%s", grant->nof_prb, harq_pid,
10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), srslte_mimotype2str(mimo_type));
char pinfo_str[16] = {0};
if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
snprintf(pinfo_str, 15, ", pinfo=%x", grant->pinfo);
}
snprintf(commonstr, 128, "PDSCH: l_crb=%2d, harq=%d, snr=%.1f dB, tx_scheme=%s%s", grant->nof_prb, harq_pid,
10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), srslte_mimotype2str(mimo_type), pinfo_str);
for (int i=0;i<SRSLTE_MAX_CODEWORDS;i++) {
if (grant->tb_en[i]) {
snprintf(tbstr[i], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d, crc=%s, it=%d",
@ -826,6 +831,16 @@ void phch_worker::set_uci_periodic_cqi()
}
Info("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db);
}
if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
if (ue_dl.ri == 0) {
uci_data.uci_pmi_len = 2;
} else {
uci_data.uci_pmi_len = 1;
uci_data.uci_dif_cqi_len = 3;
}
uint8_t *ptr = uci_data.uci_pmi;
srslte_bit_unpack(ue_dl.pmi[ue_dl.ri], &ptr, uci_data.uci_pmi_len);
}
uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi);
rar_cqi_request = false;
}

Loading…
Cancel
Save