Commit 64615dcc authored by Cedric Roux's avatar Cedric Roux

hotfix: correct PHICH generation

The PHICH generation is wrong.
HARQ process X is uplink scheduled at TTI n.
At TTI n+4 the eNB receives the data.
At TTI n+8 the eNB sends ACK/NACK on the PHICH.

The problem is that PHICH generation is done after scheduling.
And PHICH generation uses "first_rb" and "n_DMRS" to compute
"ngroup_PHICH" and "nseq_PHICH".

So at TTI n+8 if the eNB has reused the HARQ process X for
a new uplink scheduling the values "first_rb" and "n_DMRS"
may have changed.

We need to use the previous values.

One solution would have been to do PHICH generation before
scheduling. The problem is that "generate_phich_top" does more
than PHICH generation. It has to setup parameters to sort of
"emulate" a DCI0 in case of retransmission scheduled without
DCI0. So part of it has to be done after scheduling. We would
have to split the function.

The simple adopted fix is to store old values of "first_rb"
and "n_DMRS" and use those values in "generate_phich_top".

This fix has only been tested with FDD. TDD may miserably fail.
parent f116a10d
......@@ -360,6 +360,10 @@ typedef struct {
uint8_t TPC;
/// First Allocated RB
uint16_t first_rb;
/// First Allocated RB - previous scheduling
/// This is needed for PHICH generation which
/// is done after a new scheduling
uint16_t previous_first_rb;
/// Current Number of RBs
uint16_t nb_rb;
/// Transport block size
......@@ -444,6 +448,10 @@ typedef struct {
uint8_t Nsymb_initial;
/// n_DMRS for cyclic shift of DMRS (36.213 Table 9.1.2-2)
uint8_t n_DMRS;
/// n_DMRS for cyclic shift of DMRS (36.213 Table 9.1.2-2) - previous scheduling
/// This is needed for PHICH generation which
/// is done after a new scheduling
uint8_t previous_n_DMRS;
/// n_DMRS 2 for cyclic shift of DMRS (36.211 Table 5.5.1.1.-1)
uint8_t n_DMRS2;
/// Flag to indicate that this ULSCH is for calibration information sent from UE (i.e. no MAC SDU to pass up)
......
......@@ -1453,8 +1453,12 @@ void generate_phich_top(PHY_VARS_eNB *eNB,
LOG_D(PHY,"[eNB][PUSCH %d/%x] Frame %d subframe %d (pusch_subframe %d,pusch_frame %d) phich active %d\n",
harq_pid,ulsch[UE_id]->rnti,proc->frame_tx,subframe,pusch_subframe,pusch_frame,ulsch[UE_id]->harq_processes[harq_pid]->phich_active);
ngroup_PHICH = (ulsch[UE_id]->harq_processes[harq_pid]->first_rb +
ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS)%Ngroup_PHICH;
/* the HARQ process may have been reused by a new scheduling, so we use
* previous values of first_rb and n_DMRS to compute ngroup_PHICH and nseq_PHICH
*/
ngroup_PHICH = (ulsch[UE_id]->harq_processes[harq_pid]->previous_first_rb +
ulsch[UE_id]->harq_processes[harq_pid]->previous_n_DMRS)%Ngroup_PHICH;
if ((frame_parms->tdd_config == 0) && (frame_parms->frame_type == TDD) ) {
......@@ -1462,20 +1466,20 @@ void generate_phich_top(PHY_VARS_eNB *eNB,
ngroup_PHICH += Ngroup_PHICH;
}
nseq_PHICH = ((ulsch[UE_id]->harq_processes[harq_pid]->first_rb/Ngroup_PHICH) +
ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS)%(2*NSF_PHICH);
nseq_PHICH = ((ulsch[UE_id]->harq_processes[harq_pid]->previous_first_rb/Ngroup_PHICH) +
ulsch[UE_id]->harq_processes[harq_pid]->previous_n_DMRS)%(2*NSF_PHICH);
LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Generating PHICH, ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d dci_alloc %d)\n",
eNB->Mod_id,harq_pid,proc->frame_tx,
subframe,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH,
ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK,
ulsch[UE_id]->harq_processes[harq_pid]->first_rb,
ulsch[UE_id]->harq_processes[harq_pid]->previous_first_rb,
ulsch[UE_id]->harq_processes[harq_pid]->dci_alloc);
if (ulsch[UE_id]->Msg3_active == 1) {
LOG_D(PHY,"[eNB %d][PUSCH %d][RAPROC] Frame %d, subframe %d: Generating Msg3 PHICH for UE %d, ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d\n",
eNB->Mod_id,harq_pid,proc->frame_tx,subframe,
UE_id,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH,ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK,
ulsch[UE_id]->harq_processes[harq_pid]->first_rb);
ulsch[UE_id]->harq_processes[harq_pid]->previous_first_rb);
}
if (eNB->abstraction_flag == 0) {
......
......@@ -1206,6 +1206,38 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
}
/* save old HARQ information needed for PHICH generation */
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
if (eNB->ulsch[i]) {
/* Store first_rb and n_DMRS for correct PHICH generation below.
* For PHICH generation we need "old" values of last scheduling
* for this HARQ process. 'generate_eNB_dlsch_params' below will
* overwrite first_rb and n_DMRS and 'generate_phich_top', done
* after 'generate_eNB_dlsch_params', would use the "new" values
* instead of the "old" ones.
*
* This has been tested for FDD only, may be wrong for TDD.
*
* TODO: maybe we should restructure the code to be sure it
* is done correctly. The main concern is if the code
* changes and first_rb and n_DMRS are modified before
* we reach here, then the PHICH processing will be wrong,
* using wrong first_rb and n_DMRS values to compute
* ngroup_PHICH and nseq_PHICH.
*
* TODO: check if that works with TDD.
*/
if ((subframe_select(fp,ul_subframe)==SF_UL) ||
(fp->frame_type == FDD)) {
harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
eNB->ulsch[i]->harq_processes[harq_pid]->previous_first_rb =
eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
eNB->ulsch[i]->harq_processes[harq_pid]->previous_n_DMRS =
eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS;
}
}
}
num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
LOG_D(PHY,"num_pdcch_symbols %"PRIu8",(dci common %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,
......
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