Commit d5c24eda authored by Robert Schmidt's avatar Robert Schmidt

Implement HARQ using NR_list_t

parent 97430b5d
...@@ -419,14 +419,14 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id, ...@@ -419,14 +419,14 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
} }
uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map; uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
// 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]; NR_UE_harq_t *harq = &sched_ctrl->harq_processes[sched_ctrl->dl_harq_pid];
NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[current_harq_pid];
const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275); const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275);
int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275); int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275);
if (harq->round != 0) { /* retransmission */ if (sched_ctrl->dl_harq_pid >= 0) { /* retransmission */
NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[sched_ctrl->dl_harq_pid];
sched_ctrl->time_domain_allocation = retInfo->time_domain_allocation; sched_ctrl->time_domain_allocation = retInfo->time_domain_allocation;
/* ensure that there is a free place for RB allocation */ /* ensure that there is a free place for RB allocation */
...@@ -564,11 +564,29 @@ void nr_schedule_ue_spec(module_id_t module_id, ...@@ -564,11 +564,29 @@ void nr_schedule_ue_spec(module_id_t module_id,
nrOfLayers) nrOfLayers)
>> 3; >> 3;
const int current_harq_pid = slot % 8; int8_t 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_D(MAC, LOG_D(MAC,
......
...@@ -360,6 +360,8 @@ void nr_preprocessor_phytest(module_id_t module_id, ...@@ -360,6 +360,8 @@ void nr_preprocessor_phytest(module_id_t module_id,
} }
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++)
......
...@@ -291,6 +291,31 @@ void nr_csi_meas_reporting(int Mod_idP, ...@@ -291,6 +291,31 @@ void nr_csi_meas_reporting(int Mod_idP,
} }
} }
inline void handle_dl_harq(module_id_t mod_id,
int UE_id,
int8_t 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,
...@@ -310,50 +335,23 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, ...@@ -310,50 +335,23 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
uci_01->ul_cqi, uci_01->ul_cqi,
30); 30);
// TODO NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
int max_harq_rounds = 4; // TODO define macro const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
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 int8_t 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)) { const int feedback_slot = (slot - 1 + num_slots) % num_slots;
// toggle NDI and reset round AssertFatal(harq->feedback_slot == feedback_slot,
sched_ctrl->harq_processes[harq_idx].ndi ^= 1; "expected feedback slot %d, but found %d instead\n",
sched_ctrl->harq_processes[harq_idx].round = 0; harq->feedback_slot, feedback_slot);
} DevAssert(harq->is_waiting);
else handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0);
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;
}
}
} }
} }
} }
...@@ -376,50 +374,21 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, ...@@ -376,50 +374,21 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
uci_234->ul_cqi, uci_234->ul_cqi,
30); 30);
// TODO NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
int max_harq_rounds = 4; // TODO define macro const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
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 int8_t 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; const int feedback_slot = (slot - 1 + num_slots) % num_slots;
if ((uci_234->harq.harq_crc != 1) && acknack) { AssertFatal(harq->feedback_slot == feedback_slot,
// toggle NDI and reset round "expected feedback slot %d, but found %d instead\n",
sched_ctrl->harq_processes[harq_idx].ndi ^= 1; harq->feedback_slot, feedback_slot);
sched_ctrl->harq_processes[harq_idx].round = 0; handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack);
}
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;
...@@ -423,6 +424,8 @@ typedef struct { ...@@ -423,6 +424,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"
int8_t 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