Extending DL scheduling to multiple LCIDs
This commit is contained in:
committed by
Robert Schmidt
parent
6fbfa3b066
commit
68471d0525
@@ -466,76 +466,49 @@ void nr_store_dlsch_buffer(module_id_t module_id,
|
|||||||
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||||
|
|
||||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||||
|
|
||||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||||
|
|
||||||
sched_ctrl->num_total_bytes = 0;
|
sched_ctrl->num_total_bytes = 0;
|
||||||
|
sched_ctrl->dl_pdus_total = 0;
|
||||||
|
|
||||||
int lcid;
|
/* loop over all activated logical channels */
|
||||||
const uint16_t rnti = UE_info->rnti[UE_id];
|
// Note: DL_SCH_LCID_DCCH, DL_SCH_LCID_DCCH1, DL_SCH_LCID_DTCH
|
||||||
LOG_D(NR_MAC,"UE %d/%x : lcid_mask %x\n",UE_id,rnti,sched_ctrl->lcid_mask);
|
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) {
|
||||||
if ((sched_ctrl->lcid_mask&(1<<2)) > 0)
|
|
||||||
sched_ctrl->rlc_status[DL_SCH_LCID_DCCH1] = mac_rlc_status_ind(module_id,
|
const int lcid = sched_ctrl->dl_lc_ids[i];
|
||||||
|
const uint16_t rnti = UE_info->rnti[UE_id];
|
||||||
|
LOG_D(NR_MAC, "In %s: UE %d/%x: LCID %d\n", __FUNCTION__, UE_id, rnti, lcid);
|
||||||
|
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||||
|
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id,
|
||||||
rnti,
|
rnti,
|
||||||
module_id,
|
module_id,
|
||||||
frame,
|
frame,
|
||||||
slot,
|
slot,
|
||||||
ENB_FLAG_YES,
|
ENB_FLAG_YES,
|
||||||
MBMS_FLAG_NO,
|
MBMS_FLAG_NO,
|
||||||
DL_SCH_LCID_DCCH1,
|
lcid,
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
if ((sched_ctrl->lcid_mask&(1<<1)) > 0)
|
stop_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||||
sched_ctrl->rlc_status[DL_SCH_LCID_DCCH] = mac_rlc_status_ind(module_id,
|
|
||||||
rnti,
|
|
||||||
module_id,
|
|
||||||
frame,
|
|
||||||
slot,
|
|
||||||
ENB_FLAG_YES,
|
|
||||||
MBMS_FLAG_NO,
|
|
||||||
DL_SCH_LCID_DCCH,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
if ((sched_ctrl->lcid_mask&(1<<4)) > 0) {
|
|
||||||
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
|
||||||
sched_ctrl->rlc_status[DL_SCH_LCID_DTCH] = mac_rlc_status_ind(module_id,
|
|
||||||
rnti,
|
|
||||||
module_id,
|
|
||||||
frame,
|
|
||||||
slot,
|
|
||||||
ENB_FLAG_YES,
|
|
||||||
MBMS_FLAG_NO,
|
|
||||||
DL_SCH_LCID_DTCH,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
stop_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
|
||||||
}
|
|
||||||
if(sched_ctrl->rlc_status[DL_SCH_LCID_DCCH].bytes_in_buffer > 0){
|
|
||||||
lcid = DL_SCH_LCID_DCCH;
|
|
||||||
}
|
|
||||||
else if (sched_ctrl->rlc_status[DL_SCH_LCID_DCCH1].bytes_in_buffer > 0)
|
|
||||||
{
|
|
||||||
lcid = DL_SCH_LCID_DCCH1;
|
|
||||||
}else{
|
|
||||||
lcid = DL_SCH_LCID_DTCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
|
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
|
||||||
//later multiplex here. Just select DCCH/SRB before DTCH/DRB
|
continue;
|
||||||
sched_ctrl->lcid_to_schedule = lcid;
|
|
||||||
|
|
||||||
if (sched_ctrl->num_total_bytes == 0
|
sched_ctrl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer;
|
||||||
&& !sched_ctrl->ta_apply) /* If TA should be applied, give at least one RB */
|
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
|
||||||
continue;
|
LOG_D(MAC,
|
||||||
|
"[gNB %d][%4d.%2d] %s%d->DLSCH, RLC status for UE %d: %d bytes in buffer, total DL buffer size = %d bytes, %d total PDU bytes, %s TA command\n",
|
||||||
LOG_D(NR_MAC,
|
module_id,
|
||||||
"[%s][%d.%d], %s%d->DLSCH, RLC status %d bytes TA %d\n",
|
frame,
|
||||||
__func__,
|
slot,
|
||||||
frame,
|
lcid < 4 ? "DCCH":"DTCH",
|
||||||
slot,
|
lcid,
|
||||||
lcid<4?"DCCH":"DTCH",
|
UE_id,
|
||||||
lcid,
|
sched_ctrl->rlc_status[lcid].bytes_in_buffer,
|
||||||
sched_ctrl->rlc_status[lcid].bytes_in_buffer,
|
sched_ctrl->num_total_bytes,
|
||||||
sched_ctrl->ta_apply);
|
sched_ctrl->dl_pdus_total,
|
||||||
|
sched_ctrl->ta_apply ? "send":"do not send");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -882,7 +855,7 @@ void pf_dl(module_id_t module_id,
|
|||||||
sched_pdsch->pucch_allocation = alloc;
|
sched_pdsch->pucch_allocation = alloc;
|
||||||
uint32_t TBS = 0;
|
uint32_t TBS = 0;
|
||||||
uint16_t rbSize;
|
uint16_t rbSize;
|
||||||
const int oh = 3 + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
|
const int oh = 3*sched_ctrl->dl_pdus_total + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
|
||||||
nr_find_nb_rb(sched_pdsch->Qm,
|
nr_find_nb_rb(sched_pdsch->Qm,
|
||||||
sched_pdsch->R,
|
sched_pdsch->R,
|
||||||
ps->nrOfLayers,
|
ps->nrOfLayers,
|
||||||
@@ -1326,68 +1299,70 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
|||||||
buf += written;
|
buf += written;
|
||||||
int size = TBS - written;
|
int size = TBS - written;
|
||||||
DevAssert(size >= 0);
|
DevAssert(size >= 0);
|
||||||
|
|
||||||
/* next, get RLC data */
|
/* next, get RLC data */
|
||||||
|
|
||||||
// const int lcid = DL_SCH_LCID_DTCH;
|
|
||||||
const int lcid = sched_ctrl->lcid_to_schedule;
|
|
||||||
int dlsch_total_bytes = 0;
|
|
||||||
start_meas(&gNB_mac->rlc_data_req);
|
start_meas(&gNB_mac->rlc_data_req);
|
||||||
if (sched_ctrl->num_total_bytes > 0) {
|
if (sched_ctrl->num_total_bytes > 0) {
|
||||||
tbs_size_t len = 0;
|
|
||||||
while (size > 3) {
|
|
||||||
// we do not know how much data we will get from RLC, i.e., whether it
|
|
||||||
// will be longer than 256B or not. Therefore, reserve space for long header, then
|
|
||||||
// fetch data, then fill real length
|
|
||||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
|
||||||
buf += 3;
|
|
||||||
size -= 3;
|
|
||||||
|
|
||||||
/* limit requested number of bytes to what preprocessor specified, or
|
/* loop over all activated logical channels */
|
||||||
* such that TBS is full */
|
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) {
|
||||||
const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, size);
|
|
||||||
|
|
||||||
len = mac_rlc_data_req(module_id,
|
const int lcid = sched_ctrl->dl_lc_ids[i];
|
||||||
rnti,
|
int dlsch_total_bytes = 0;
|
||||||
module_id,
|
|
||||||
frame,
|
|
||||||
ENB_FLAG_YES,
|
|
||||||
MBMS_FLAG_NO,
|
|
||||||
lcid,
|
|
||||||
ndata,
|
|
||||||
(char *)buf,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
|
|
||||||
LOG_D(NR_MAC,
|
while (size > 3) {
|
||||||
"%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %d)\n",
|
// we do not know how much data we will get from RLC, i.e., whether it
|
||||||
frame,
|
// will be longer than 256B or not. Therefore, reserve space for long header, then
|
||||||
slot,
|
// fetch data, then fill real length
|
||||||
rnti,
|
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
||||||
len,
|
buf += 3;
|
||||||
lcid < 4 ? "DCCH" : "DTCH",
|
size -= 3;
|
||||||
lcid,
|
|
||||||
ndata,
|
|
||||||
size);
|
|
||||||
if (len == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
header->R = 0;
|
/* limit requested number of bytes to what preprocessor specified, or
|
||||||
header->F = 1;
|
* such that TBS is full */
|
||||||
header->LCID = lcid;
|
const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, size);
|
||||||
header->L1 = (len >> 8) & 0xff;
|
tbs_size_t len = mac_rlc_data_req(module_id,
|
||||||
header->L2 = len & 0xff;
|
rnti,
|
||||||
size -= len;
|
module_id,
|
||||||
buf += len;
|
frame,
|
||||||
dlsch_total_bytes += len;
|
ENB_FLAG_YES,
|
||||||
|
MBMS_FLAG_NO,
|
||||||
|
lcid,
|
||||||
|
ndata,
|
||||||
|
(char *)buf,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
LOG_D(NR_MAC,
|
||||||
|
"%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %d)\n",
|
||||||
|
frame,
|
||||||
|
slot,
|
||||||
|
rnti,
|
||||||
|
len,
|
||||||
|
lcid < 4 ? "DCCH" : "DTCH",
|
||||||
|
lcid,
|
||||||
|
ndata,
|
||||||
|
size);
|
||||||
|
if (len == 0) {
|
||||||
|
/* RLC did not have data anymore, mark buffer as unused */
|
||||||
|
buf -= 3;
|
||||||
|
size += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
header->R = 0;
|
||||||
|
header->F = 1;
|
||||||
|
header->LCID = lcid;
|
||||||
|
header->L1 = (len >> 8) & 0xff;
|
||||||
|
header->L2 = len & 0xff;
|
||||||
|
size -= len;
|
||||||
|
buf += len;
|
||||||
|
dlsch_total_bytes += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += dlsch_total_bytes;
|
||||||
}
|
}
|
||||||
if (len == 0) {
|
} else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) {
|
||||||
/* RLC did not have data anymore, mark buffer as unused */
|
|
||||||
buf -= 3;
|
|
||||||
size += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra || get_softmodem_params()->sa) {
|
|
||||||
/* we will need the large header, phy-test typically allocates all
|
/* we will need the large header, phy-test typically allocates all
|
||||||
* resources and fills to the last byte below */
|
* resources and fills to the last byte below */
|
||||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
||||||
@@ -1405,7 +1380,6 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
|||||||
header->L2 = size & 0xff;
|
header->L2 = size & 0xff;
|
||||||
size -= size;
|
size -= size;
|
||||||
buf += size;
|
buf += size;
|
||||||
dlsch_total_bytes += size;
|
|
||||||
}
|
}
|
||||||
stop_meas(&gNB_mac->rlc_data_req);
|
stop_meas(&gNB_mac->rlc_data_req);
|
||||||
|
|
||||||
@@ -1425,7 +1399,6 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
|||||||
|
|
||||||
UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS;
|
UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS;
|
||||||
UE_info->mac_stats[UE_id].dlsch_current_bytes = TBS;
|
UE_info->mac_stats[UE_id].dlsch_current_bytes = TBS;
|
||||||
UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += dlsch_total_bytes;
|
|
||||||
|
|
||||||
/* save retransmission information */
|
/* save retransmission information */
|
||||||
harq->sched_pdsch = *sched_pdsch;
|
harq->sched_pdsch = *sched_pdsch;
|
||||||
|
|||||||
@@ -597,8 +597,9 @@ typedef struct {
|
|||||||
|
|
||||||
/// total amount of data awaiting for this UE
|
/// total amount of data awaiting for this UE
|
||||||
uint32_t num_total_bytes;
|
uint32_t num_total_bytes;
|
||||||
|
uint16_t dl_pdus_total;
|
||||||
/// per-LC status data
|
/// per-LC status data
|
||||||
mac_rlc_status_resp_t rlc_status[MAX_NUM_LCID];
|
mac_rlc_status_resp_t rlc_status[NR_MAX_NUM_LCID];
|
||||||
|
|
||||||
/// Estimation of HARQ from BLER
|
/// Estimation of HARQ from BLER
|
||||||
NR_DL_bler_stats_t dl_bler_stats;
|
NR_DL_bler_stats_t dl_bler_stats;
|
||||||
@@ -638,6 +639,12 @@ typedef struct {
|
|||||||
/// UL HARQ processes that await retransmission
|
/// UL HARQ processes that await retransmission
|
||||||
NR_list_t retrans_ul_harq;
|
NR_list_t retrans_ul_harq;
|
||||||
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information
|
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information
|
||||||
|
|
||||||
|
/// number of active DL LCs
|
||||||
|
uint8_t dl_lc_num;
|
||||||
|
/// order in which DLSCH scheduler should allocate LCs
|
||||||
|
uint8_t dl_lc_ids[NR_MAX_NUM_LCID];
|
||||||
|
|
||||||
} NR_UE_sched_ctrl_t;
|
} NR_UE_sched_ctrl_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user