Commit 1f69d15d authored by Robert Schmidt's avatar Robert Schmidt

Implement HARQ using NR_list_t

parent f08191ec
...@@ -427,9 +427,8 @@ void pf_dl(module_id_t module_id, ...@@ -427,9 +427,8 @@ void pf_dl(module_id_t module_id,
/* Loop UE_info->list to check retransmission */ /* Loop UE_info->list to check retransmission */
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];
// for now HARQ PID is fixed and should be the same as in post-processor /* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */
const int current_harq_pid = slot % 8; sched_ctrl->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
const rnti_t rnti = UE_info->rnti[UE_id]; const rnti_t rnti = UE_info->rnti[UE_id];
/* Calculate Throughput */ /* Calculate Throughput */
...@@ -438,7 +437,7 @@ void pf_dl(module_id_t module_id, ...@@ -438,7 +437,7 @@ void pf_dl(module_id_t module_id,
thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b; thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b;
/* retransmission */ /* retransmission */
if (harq->round != 0) { if (sched_ctrl->dl_harq_pid >= 0) {
/* Find a free CCE */ /* Find a free CCE */
bool freeCCEE = find_free_CCE(module_id, slot, UE_info, UE_id); bool freeCCEE = find_free_CCE(module_id, slot, UE_info, UE_id);
if (!freeCCEE) if (!freeCCEE)
...@@ -462,7 +461,7 @@ void pf_dl(module_id_t module_id, ...@@ -462,7 +461,7 @@ void pf_dl(module_id_t module_id,
return; return;
} }
/* Allocate retransmission */ /* Allocate retransmission */
bool r = allocate_retransmission(module_id, rballoc_mask, &n_rb_sched, UE_info, UE_id, current_harq_pid); bool r = allocate_retransmission(module_id, rballoc_mask, &n_rb_sched, UE_info, UE_id, sched_ctrl->dl_harq_pid);
if (!r) { if (!r) {
LOG_E(MAC, "%4d.%2d retransmission can NOT be allocated\n", frame, slot); LOG_E(MAC, "%4d.%2d retransmission can NOT be allocated\n", frame, slot);
return; return;
...@@ -693,11 +692,29 @@ void nr_schedule_ue_spec(module_id_t module_id, ...@@ -693,11 +692,29 @@ void nr_schedule_ue_spec(module_id_t module_id,
nrOfLayers) nrOfLayers)
>> 3; >> 3;
const int current_harq_pid = slot % 8; int current_harq_pid = sched_ctrl->dl_harq_pid;
if (current_harq_pid < 0) {
/* PP has not selected a specific HARQ Process, get a new one */
current_harq_pid = sched_ctrl->available_dl_harq.head;
AssertFatal(current_harq_pid >= 0,
"no free HARQ process available for UE %d\n",
UE_id);
remove_front_nr_list(&sched_ctrl->available_dl_harq);
} else {
/* PP selected a specific HARQ process. Check whether it will be a new
* transmission or a retransmission, and remove from the corresponding
* list */
if (sched_ctrl->harq_processes[current_harq_pid].round == 0)
remove_nr_list(&sched_ctrl->available_dl_harq, current_harq_pid);
else
remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid);
}
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
DevAssert(!harq->is_waiting);
add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid);
NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0]; NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0];
harq->feedback_slot = pucch->ul_slot; harq->feedback_slot = pucch->ul_slot;
harq->is_waiting = 1; harq->is_waiting = true;
UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++; UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++;
LOG_I(MAC, LOG_I(MAC,
......
...@@ -354,6 +354,8 @@ void nr_preprocessor_phytest(module_id_t module_id, ...@@ -354,6 +354,8 @@ void nr_preprocessor_phytest(module_id_t module_id,
sched_ctrl->mcsTableIdx = 0; sched_ctrl->mcsTableIdx = 0;
sched_ctrl->mcs = 9; sched_ctrl->mcs = 9;
sched_ctrl->numDmrsCdmGrpsNoData = 1; sched_ctrl->numDmrsCdmGrpsNoData = 1;
/* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */
sched_ctrl->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
/* mark the corresponding RBs as used */ /* mark the corresponding RBs as used */
for (int rb = 0; rb < sched_ctrl->rbSize; rb++) for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
......
...@@ -286,6 +286,31 @@ void nr_csi_meas_reporting(int Mod_idP, ...@@ -286,6 +286,31 @@ void nr_csi_meas_reporting(int Mod_idP,
} }
} }
inline void handle_dl_harq(module_id_t mod_id,
int UE_id,
int harq_pid,
bool success)
{
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
NR_UE_harq_t *harq = &UE_info->UE_sched_ctrl[UE_id].harq_processes[harq_pid];
harq->feedback_slot = -1;
harq->is_waiting = false;
if (success) {
add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].available_dl_harq, harq_pid);
harq->round = 0;
harq->ndi ^= 1;
} else if (harq->round == MAX_HARQ_ROUNDS) {
add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].available_dl_harq, harq_pid);
harq->round = 0;
harq->ndi ^= 1;
NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
stats->dlsch_errors++;
LOG_D(MAC, "retransmission error for UE %d (total %d)\n", UE_id, stats->dlsch_errors);
} else {
add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].retrans_dl_harq, harq_pid);
harq->round++;
}
}
void handle_nr_uci_pucch_0_1(module_id_t mod_id, void handle_nr_uci_pucch_0_1(module_id_t mod_id,
frame_t frame, frame_t frame,
...@@ -305,50 +330,17 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, ...@@ -305,50 +330,17 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
uci_01->ul_cqi, uci_01->ul_cqi,
30); 30);
// TODO
int max_harq_rounds = 4; // TODO define macro
if (((uci_01->pduBitmap >> 1) & 0x01)) { if (((uci_01->pduBitmap >> 1) & 0x01)) {
// handle harq
int harq_idx_s = 0;
// iterate over received harq bits // iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
// search for the right harq process const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value;
for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) { const uint8_t harq_confidence = uci_01->harq->harq_confidence_level;
// if the gNB received ack with a good confidence const int pid = sched_ctrl->feedback_dl_harq.head;
if ((slot - 1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { DevAssert(pid >= 0);
sched_ctrl->harq_processes[harq_idx].feedback_slot = -1; remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
if ((uci_01->harq->harq_list[harq_bit].harq_value == 1) && NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid];
(uci_01->harq->harq_confidence_level == 0)) { DevAssert(harq->feedback_slot == slot - 1);
// toggle NDI and reset round handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0);
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
else
sched_ctrl->harq_processes[harq_idx].round++;
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
harq_idx_s = harq_idx + 1;
// if the max harq rounds was reached
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
UE_info->mac_stats[UE_id].dlsch_errors++;
}
break;
}
// if feedback slot processing is aborted
else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1
&& (slot - 1) > sched_ctrl->harq_processes[harq_idx].feedback_slot
&& sched_ctrl->harq_processes[harq_idx].is_waiting) {
sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
sched_ctrl->harq_processes[harq_idx].round++;
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
}
}
} }
} }
} }
...@@ -371,50 +363,16 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, ...@@ -371,50 +363,16 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
uci_234->ul_cqi, uci_234->ul_cqi,
30); 30);
// TODO
int max_harq_rounds = 4; // TODO define macro
if ((uci_234->pduBitmap >> 1) & 0x01) { if ((uci_234->pduBitmap >> 1) & 0x01) {
int harq_idx_s = 0;
int acknack;
// iterate over received harq bits // iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
acknack = ((uci_234->harq.harq_payload[harq_bit>>3])>>harq_bit)&0x01; const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01;
for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) { const int pid = sched_ctrl->feedback_dl_harq.head;
// if the gNB received ack with a good confidence or if the max harq rounds was reached DevAssert(pid >= 0);
if ((slot - 1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
// TODO add some confidence level for when there is no CRC NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid];
sched_ctrl->harq_processes[harq_idx].feedback_slot = -1; DevAssert(harq->feedback_slot == slot - 1);
if ((uci_234->harq.harq_crc != 1) && acknack) { handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack);
// toggle NDI and reset round
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
else
sched_ctrl->harq_processes[harq_idx].round++;
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
harq_idx_s = harq_idx + 1;
// if the max harq rounds was reached
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
UE_info->mac_stats[UE_id].dlsch_errors++;
}
break;
}
// if feedback slot processing is aborted
else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1
&& (slot - 1) > sched_ctrl->harq_processes[harq_idx].feedback_slot
&& sched_ctrl->harq_processes[harq_idx].is_waiting) {
sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
sched_ctrl->harq_processes[harq_idx].round++;
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
}
}
} }
} }
} }
......
...@@ -73,6 +73,7 @@ ...@@ -73,6 +73,7 @@
#define MAX_NUM_BWP 2 #define MAX_NUM_BWP 2
#define MAX_NUM_CORESET 2 #define MAX_NUM_CORESET 2
#define MAX_NUM_CCE 90 #define MAX_NUM_CCE 90
#define MAX_HARQ_ROUNDS 4
/*!\brief Maximum number of random access process */ /*!\brief Maximum number of random access process */
#define NR_NB_RA_PROC_MAX 4 #define NR_NB_RA_PROC_MAX 4
#define MAX_NUM_OF_SSB 64 #define MAX_NUM_OF_SSB 64
...@@ -336,7 +337,7 @@ typedef struct NR_sched_pusch { ...@@ -336,7 +337,7 @@ typedef struct NR_sched_pusch {
} NR_sched_pusch_t; } NR_sched_pusch_t;
typedef struct NR_UE_harq { typedef struct NR_UE_harq {
uint8_t is_waiting; bool is_waiting;
uint8_t ndi; uint8_t ndi;
uint8_t round; uint8_t round;
uint16_t feedback_slot; uint16_t feedback_slot;
...@@ -428,6 +429,8 @@ typedef struct { ...@@ -428,6 +429,8 @@ typedef struct {
/// Retransmission-related information /// Retransmission-related information
NR_UE_ret_info_t retInfo[NR_MAX_NB_HARQ_PROCESSES]; NR_UE_ret_info_t retInfo[NR_MAX_NB_HARQ_PROCESSES];
/// DL HARQ PID to use for this UE, or -1 for "any new"
int dl_harq_pid;
uint16_t ta_frame; uint16_t ta_frame;
int16_t ta_update; int16_t ta_update;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment