Introduce group-based processing using FAPI groups

Refactor ULSCH_id based processing of the PUSCH PDUs to group based
processing using FAPI groups. This is required to process multiple
PUSCH PDUs jointly for MU-MIMO. This is an initial commit that
supports group size = 1 and will be extended to > 1 in the following
commits.

The flow of group information from MAC to PHY using FAPI is as follows:

- In MAC, nr_fill_pusch_fapi_groups() is introduced to fill UEs in
  groups. The FAPI groups consist of UE lists filled with a PDU index.
  Based on the parameter UL_tti_req->n_group, the number of unique groups are
  identified. In each group, the parameter group->n_ue defines the
  number of UEs present in the group along with their PDU indices.

- After receiving the FAPI message in the PHY from MAC, in
  nr_save_ul_tti_req(), a group number and group size for each
  PUSCH PDU is allocated in nr_fill_ulsch(), and a PUSCH job is created.

- Further, after a job is created, in phy_procedures_gNB_uespec_RX(),
  the PUSCH PDUs of the ULSCH_ids for each group are segregated based
  on the group index. They are processed jointly using
  handle_pusch_rx_group_trigger(), and the PUSCH DTX per UE in the
  group is calculated using handle_pusch_DTX().
Signed-off-by: default avatarRakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
parent f61d1834
...@@ -112,7 +112,9 @@ void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame); ...@@ -112,7 +112,9 @@ void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame);
void nr_fill_ulsch(PHY_VARS_gNB *gNB, void nr_fill_ulsch(PHY_VARS_gNB *gNB,
int frame, int frame,
int slot, int slot,
nfapi_nr_pusch_pdu_t *ulsch_pdu); nfapi_nr_pusch_pdu_t *ulsch_pdu,
int16_t mu_group_idx,
uint8_t mu_group_size);
void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu);
......
...@@ -89,8 +89,12 @@ static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_pusch_pdu ...@@ -89,8 +89,12 @@ static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_pusch_pdu
pusch_pdu->pusch_data.num_cb); pusch_pdu->pusch_data.num_cb);
} }
void nr_fill_ulsch(PHY_VARS_gNB *gNB,
void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t *ulsch_pdu) int frame,
int slot,
nfapi_nr_pusch_pdu_t *ulsch_pdu,
int16_t mu_group_idx,
uint8_t mu_group_size)
{ {
dump_pusch_pdu(gNB->Mod_id, frame, slot, ulsch_pdu); dump_pusch_pdu(gNB->Mod_id, frame, slot, ulsch_pdu);
LOG_D(NR_PHY, LOG_D(NR_PHY,
...@@ -101,7 +105,11 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t ...@@ -101,7 +105,11 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t
ulsch_pdu->pusch_data.harq_process_id, ulsch_pdu->pusch_data.harq_process_id,
ulsch_pdu->pusch_data.new_data_indicator); ulsch_pdu->pusch_data.new_data_indicator);
NR_gNB_PUSCH_job_t pusch = {.frame = frame, .slot = slot, .pusch_pdu = *ulsch_pdu}; NR_gNB_PUSCH_job_t pusch = {.frame = frame,
.slot = slot,
.pusch_pdu = *ulsch_pdu,
.mu_group_idx = mu_group_idx,
.mu_group_size = mu_group_size};
if (gNB->common_vars.beam_id) { if (gNB->common_vars.beam_id) {
int fapi_beam_idx = ulsch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; int fapi_beam_idx = ulsch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
int bitmap = SL_to_bitmap(ulsch_pdu->start_symbol_index, ulsch_pdu->nr_of_symbols); int bitmap = SL_to_bitmap(ulsch_pdu->start_symbol_index, ulsch_pdu->nr_of_symbols);
......
...@@ -181,6 +181,11 @@ typedef struct { ...@@ -181,6 +181,11 @@ typedef struct {
uint32_t slot; uint32_t slot;
/// ULSCH PDU /// ULSCH PDU
nfapi_nr_pusch_pdu_t pusch_pdu; nfapi_nr_pusch_pdu_t pusch_pdu;
// Multi-User (MU) group index
// -1 : unallocated
int16_t mu_group_idx;
// 1 for Single-User (SU) and > 1 is MU
uint8_t mu_group_size;
} NR_gNB_PUSCH_job_t; } NR_gNB_PUSCH_job_t;
typedef struct { typedef struct {
......
...@@ -28,6 +28,13 @@ ...@@ -28,6 +28,13 @@
//#define DEBUG_RXDATA //#define DEBUG_RXDATA
//#define SRS_IND_DEBUG //#define SRS_IND_DEBUG
typedef struct {
int jobs[MAX_UL_PDUS_PER_SLOT][MAX_UL_PDUS_PER_SLOT];
uint8_t size[MAX_UL_PDUS_PER_SLOT];
int16_t active_groups[MAX_UL_PDUS_PER_SLOT];
int n_active_groups;
} NR_MU_MIMO_job_groups_t;
static void nr_fill_indication(const PHY_VARS_gNB *gNB, static void nr_fill_indication(const PHY_VARS_gNB *gNB,
int frame, int frame,
int slot_rx, int slot_rx,
...@@ -951,8 +958,14 @@ static void handle_pucch(PHY_VARS_gNB *gNB, c16_t **rxdataF, const NR_gNB_PUCCH_ ...@@ -951,8 +958,14 @@ static void handle_pucch(PHY_VARS_gNB *gNB, c16_t **rxdataF, const NR_gNB_PUCCH_
} }
} }
static void handle_pusch_rx_trigger(PHY_VARS_gNB *gNB, NR_gNB_PUSCH *pusch_vars, NR_gNB_ULSCH_t *ulsch) static void handle_pusch_rx_group_trigger(PHY_VARS_gNB *gNB,
NR_gNB_PUSCH **pusch_vars_group,
NR_gNB_ULSCH_t **ulsch_group,
int group_size)
{ {
for (int u = 0; u < group_size; u++) {
NR_gNB_PUSCH *pusch_vars = pusch_vars_group[u];
NR_gNB_ULSCH_t *ulsch = ulsch_group[u];
NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process;
AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid);
const nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu; const nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu;
...@@ -975,7 +988,8 @@ static void handle_pusch_rx_trigger(PHY_VARS_gNB *gNB, NR_gNB_PUSCH *pusch_vars, ...@@ -975,7 +988,8 @@ static void handle_pusch_rx_trigger(PHY_VARS_gNB *gNB, NR_gNB_PUSCH *pusch_vars,
&ru->common.rxdata[0][slot_offset], &ru->common.rxdata[0][slot_offset],
frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) * sizeof(int32_t)); frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) * sizeof(int32_t));
gNB->common_vars.debugBuff_sample_offset += (frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) + 1000 + 4); gNB->common_vars.debugBuff_sample_offset += (frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) + 1000 + 4);
if (gNB->common_vars.debugBuff_sample_offset > ((frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) + 1000 + 2) * 20)) { if (gNB->common_vars.debugBuff_sample_offset
> ((frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) + 1000 + 2) * 20)) {
FILE *f; FILE *f;
f = fopen("rxdata_buff.raw", "w"); f = fopen("rxdata_buff.raw", "w");
if (f == NULL) if (f == NULL)
...@@ -999,6 +1013,7 @@ static void handle_pusch_rx_trigger(PHY_VARS_gNB *gNB, NR_gNB_PUSCH *pusch_vars, ...@@ -999,6 +1013,7 @@ static void handle_pusch_rx_trigger(PHY_VARS_gNB *gNB, NR_gNB_PUSCH *pusch_vars,
pusch_vars->ulsch_noise_power_tot += pusch_vars->ulsch_noise_power[aarx]; pusch_vars->ulsch_noise_power_tot += pusch_vars->ulsch_noise_power[aarx];
} }
stop_meas(&gNB->rx_pusch_stats); stop_meas(&gNB->rx_pusch_stats);
}
} }
static bool pusch_signal_detected(PHY_VARS_gNB *gNB, NR_gNB_PUSCH *pusch_vars, NR_gNB_ULSCH_t *ulsch) static bool pusch_signal_detected(PHY_VARS_gNB *gNB, NR_gNB_PUSCH *pusch_vars, NR_gNB_ULSCH_t *ulsch)
...@@ -1130,6 +1145,24 @@ static int handle_pusch_job_trigger(PHY_VARS_gNB *gNB, const NR_gNB_PUSCH_job_t ...@@ -1130,6 +1145,24 @@ static int handle_pusch_job_trigger(PHY_VARS_gNB *gNB, const NR_gNB_PUSCH_job_t
return ULSCH_id; return ULSCH_id;
} }
static NR_MU_MIMO_job_groups_t group_pusch_jobs(PHY_VARS_gNB *gNB, NR_gNB_PUSCH_job_t *pusch, int n_pusch_jobs)
{
NR_MU_MIMO_job_groups_t groups = {0};
for (int i = 0; i < n_pusch_jobs; ++i) {
int ULSCH_id = handle_pusch_job_trigger(gNB, &pusch[i]);
if (ULSCH_id < 0) {
continue;
}
int g = pusch[i].mu_group_idx;
AssertFatal(g >= 0, "Ungrouped ULSCH_id %d\n", ULSCH_id);
if (groups.size[g] == 0) {
groups.active_groups[groups.n_active_groups++] = g;
}
groups.jobs[g][groups.size[g]++] = ULSCH_id;
}
return groups;
}
int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO) int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO)
{ {
/* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */ /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */
...@@ -1198,13 +1231,30 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N ...@@ -1198,13 +1231,30 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
UL_INFO->rx_ind.pdu_list = UL_INFO->rx_pdu_list; UL_INFO->rx_ind.pdu_list = UL_INFO->rx_pdu_list;
int ulsch_idx_to_decode[MAX_UL_PDUS_PER_SLOT]; int ulsch_idx_to_decode[MAX_UL_PDUS_PER_SLOT];
int num_pusch = 0; int num_pusch = 0;
for (int i = 0; i < n_pusch_jobs; ++i) {
int ULSCH_id = handle_pusch_job_trigger(gNB, &pusch[i]); // Group the jobs using group index
if (ULSCH_id < 0) NR_MU_MIMO_job_groups_t pusch_groups = group_pusch_jobs(gNB, pusch, n_pusch_jobs);
continue;
for (int i = 0; i < pusch_groups.n_active_groups; i++) {
int g = pusch_groups.active_groups[i];
int gsz = pusch_groups.size[g];
AssertFatal(gsz == 1, "Cannot handle group size > 1\n");
NR_gNB_PUSCH *pusch_vars_group[gsz];
NR_gNB_ULSCH_t *ulsch_group[gsz];
// store pusch vars and ulsch pdu for group based processing
for (int u = 0; u < gsz; u++) {
int ulsch_id = pusch_groups.jobs[g][u];
pusch_vars_group[u] = &gNB->pusch_vars[ulsch_id];
ulsch_group[u] = &gNB->ulsch[ulsch_id];
}
handle_pusch_rx_group_trigger(gNB, pusch_vars_group, ulsch_group, gsz);
for (int u = 0; u < gsz; u++) {
int ULSCH_id = pusch_groups.jobs[g][u];
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id];
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
handle_pusch_rx_trigger(gNB, pusch_vars, ulsch);
if (pusch_signal_detected(gNB, pusch_vars, ulsch) || get_softmodem_params()->phy_test) { if (pusch_signal_detected(gNB, pusch_vars, ulsch) || get_softmodem_params()->phy_test) {
ulsch_idx_to_decode[num_pusch++] = ULSCH_id; ulsch_idx_to_decode[num_pusch++] = ULSCH_id;
...@@ -1219,6 +1269,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N ...@@ -1219,6 +1269,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX"); gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX");
} }
} }
}
/* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1 /* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1
* (valid for unitary physical simulators). ULSCH processing lopp is then executed * (valid for unitary physical simulators). ULSCH processing lopp is then executed
...@@ -1230,7 +1281,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N ...@@ -1230,7 +1281,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
if (num_pusch > 0) { if (num_pusch > 0) {
int ret_nr_ulsch_procedures = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ulsch_idx_to_decode, num_pusch, UL_INFO); int ret_nr_ulsch_procedures = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ulsch_idx_to_decode, num_pusch, UL_INFO);
if (ret_nr_ulsch_procedures != 0) if (ret_nr_ulsch_procedures != 0)
LOG_E(PHY,"Error in nr_ulsch_procedures, returned %d\n",ret_nr_ulsch_procedures); LOG_E(NR_PHY, "Error in nr_ulsch_procedures, returned %d\n", ret_nr_ulsch_procedures);
} }
/* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1 /* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1
...@@ -1271,6 +1322,19 @@ void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req ...@@ -1271,6 +1322,19 @@ void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req
int frame = UL_tti_req->SFN; int frame = UL_tti_req->SFN;
int slot = UL_tti_req->Slot; int slot = UL_tti_req->Slot;
int16_t pdu_group_idx[MAX_UL_PDUS_PER_SLOT] = {[0 ... MAX_UL_PDUS_PER_SLOT - 1] = -1};
uint8_t pdu_group_size[MAX_UL_PDUS_PER_SLOT] = {0};
for (int g = 0; g < UL_tti_req->n_group; g++) {
const nfapi_nr_ul_tti_request_number_of_groups_t *grp = &UL_tti_req->groups_list[g];
for (int u = 0; u < grp->n_ue; u++) {
int pdu_idx = grp->ue_list[u].pdu_idx;
if (pdu_idx >= 0 && pdu_idx < UL_tti_req->n_pdus) {
pdu_group_idx[pdu_idx] = g;
pdu_group_size[pdu_idx] = grp->n_ue;
}
}
}
for (int i = 0; i < UL_tti_req->n_pdus; i++) { for (int i = 0; i < UL_tti_req->n_pdus; i++) {
int type = UL_tti_req->pdus_list[i].pdu_type; int type = UL_tti_req->pdus_list[i].pdu_type;
LOG_D(NR_PHY, LOG_D(NR_PHY,
...@@ -1282,7 +1346,12 @@ void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req ...@@ -1282,7 +1346,12 @@ void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req
UL_tti_req->Slot); UL_tti_req->Slot);
switch (type) { switch (type) {
case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE:
nr_fill_ulsch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu); nr_fill_ulsch(gNB,
UL_tti_req->SFN,
UL_tti_req->Slot,
&UL_tti_req->pdus_list[i].pusch_pdu,
pdu_group_idx[i],
pdu_group_size[i]);
break; break;
case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE:
nr_fill_pucch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu); nr_fill_pucch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu);
......
...@@ -1326,6 +1326,12 @@ int main(int argc, char *argv[]) ...@@ -1326,6 +1326,12 @@ int main(int argc, char *argv[])
srs_pdu->beamforming.prg_size = 1; srs_pdu->beamforming.prg_size = 1;
} }
// Fill FAPI PUSCH groups for 1 UE
UL_tti_req->n_group = 1;
nfapi_nr_ul_tti_request_number_of_groups_t *group = &UL_tti_req->groups_list[0];
group->n_ue = 1;
group->ue_list[0].pdu_idx = 0;
/* load FAPI into RX of L1 */ /* load FAPI into RX of L1 */
nr_save_ul_tti_req(gNB, &Sched_INFO->UL_tti_req); nr_save_ul_tti_req(gNB, &Sched_INFO->UL_tti_req);
......
...@@ -115,6 +115,20 @@ static void copy_ul_tti_req(nfapi_nr_ul_tti_request_t *to, nfapi_nr_ul_tti_reque ...@@ -115,6 +115,20 @@ static void copy_ul_tti_req(nfapi_nr_ul_tti_request_t *to, nfapi_nr_ul_tti_reque
to->groups_list[i] = from->groups_list[i]; to->groups_list[i] = from->groups_list[i];
} }
static void nr_fill_pusch_fapi_groups(nfapi_nr_ul_tti_request_t *UL_tti_req)
{
// Single User MIMO
UL_tti_req->n_group = 0;
for (int i = 0; i < UL_tti_req->n_pdus; i++) {
if (UL_tti_req->pdus_list[i].pdu_type != NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE)
continue;
nfapi_nr_ul_tti_request_number_of_groups_t *group = &UL_tti_req->groups_list[UL_tti_req->n_group];
group->n_ue = 0;
group->ue_list[group->n_ue++].pdu_idx = i;
UL_tti_req->n_group++;
}
}
void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slot, NR_Sched_Rsp_t *sched_info) void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slot, NR_Sched_Rsp_t *sched_info)
{ {
protocol_ctxt_t ctxt = {0}; protocol_ctxt_t ctxt = {0};
...@@ -233,6 +247,8 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo ...@@ -233,6 +247,8 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo
const int current_index = ul_buffer_index(frame, slot, slots_frame, gNB->UL_tti_req_ahead_size); const int current_index = ul_buffer_index(frame, slot, slots_frame, gNB->UL_tti_req_ahead_size);
copy_ul_tti_req(&sched_info->UL_tti_req, &gNB->UL_tti_req_ahead[0][current_index]); copy_ul_tti_req(&sched_info->UL_tti_req, &gNB->UL_tti_req_ahead[0][current_index]);
nr_fill_pusch_fapi_groups(&sched_info->UL_tti_req);
stop_meas(&gNB->gNB_scheduler); stop_meas(&gNB->gNB_scheduler);
NR_SCHED_UNLOCK(&gNB->sched_lock); NR_SCHED_UNLOCK(&gNB->sched_lock);
} }
...@@ -486,6 +486,7 @@ void reset_sched_response(NR_Sched_Rsp_t *sched_response, int frame, int slot, i ...@@ -486,6 +486,7 @@ void reset_sched_response(NR_Sched_Rsp_t *sched_response, int frame, int slot, i
UL_tti_req->SFN = frame; UL_tti_req->SFN = frame;
UL_tti_req->Slot = slot; UL_tti_req->Slot = slot;
UL_tti_req->n_pdus = 0; UL_tti_req->n_pdus = 0;
UL_tti_req->n_group = 0;
nfapi_nr_tx_data_request_t *TX_req = &sched_response->TX_req; nfapi_nr_tx_data_request_t *TX_req = &sched_response->TX_req;
TX_req->SFN = frame; TX_req->SFN = frame;
......
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