From d443d9e915e16830f9120eb21b5d284ccd9b232f Mon Sep 17 00:00:00 2001
From: Raymond Knopp <raymond.knopp@eurecom.fr>
Date: Mon, 31 Aug 2020 13:43:16 +0200
Subject: [PATCH] added multi-antenna support for gNB RX (tested in ulsim)

---
 openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c |  2 +-
 .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c  | 72 ++++++++++++++++++-
 .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c     | 18 ++---
 openair1/PHY/defs_gNB.h                       |  1 +
 openair1/SCHED_NR/phy_procedures_nr_gNB.c     |  4 +-
 openair1/SIMULATION/NR_PHY/ulsim.c            |  2 +
 6 files changed, 84 insertions(+), 15 deletions(-)

diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
index f033941518b..d0dc6950c43 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
@@ -479,7 +479,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
     stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
 
 
-    LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n",
+    LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rvidx %d, round %d)...\n",
           harq_pid,r, G,
           Kr*3,
           harq_process->TBS,
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
index 4f25be5f7d0..8b6e67b8e7e 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
@@ -1046,6 +1046,69 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext,
 
 }
 
+void nr_ulsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
+			    int32_t **rxdataF_comp,
+			    int32_t **ul_ch_mag,
+			    int32_t **ul_ch_magb,
+			    uint8_t symbol,
+			    uint16_t nb_rb) {
+  int n_rx = frame_parms->nb_antennas_rx;
+#if defined(__x86_64__) || defined(__i386__)
+  __m128i *rxdataF_comp128[1+n_rx],*ul_ch_mag128[1+n_rx],*ul_ch_mag128b[1+n_rx];
+#elif defined(__arm__)
+  int16x8_t *rxdataF_comp128_0,*ul_ch_mag128_0,*ul_ch_mag128_0b;
+  int16x8_t *rxdataF_comp128_1,*ul_ch_mag128_1,*ul_ch_mag128_1b;
+#endif
+  int32_t i;
+
+#ifdef __AVX2__
+  int off = ((nb_rb&1) == 1)? 4:0;
+#else
+  int off = 0;
+#endif
+
+  if (frame_parms->nb_antennas_rx>1) {
+#if defined(__x86_64__) || defined(__i386__)
+    int nb_re = nb_rb*12;
+    for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
+      rxdataF_comp128[aa]   = (__m128i *)&rxdataF_comp[aa][(symbol*(nb_re + off))];
+      ul_ch_mag128[aa]      = (__m128i *)&ul_ch_mag[aa][(symbol*(nb_re + off))];
+      ul_ch_mag128b[aa]     = (__m128i *)&ul_ch_magb[aa][(symbol*(nb_re + off))];
+      
+      // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation)
+      for (i=0; i<nb_rb*3; i++) {
+	rxdataF_comp128[0][i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128[aa][i],1),_mm_srai_epi16(rxdataF_comp128[aa][i],1));
+	ul_ch_mag128[0][i]    = _mm_adds_epi16(_mm_srai_epi16(ul_ch_mag128[aa][i],1),_mm_srai_epi16(ul_ch_mag128[aa][i],1));
+	ul_ch_mag128b[0][i]   = _mm_adds_epi16(_mm_srai_epi16(ul_ch_mag128b[aa][i],1),_mm_srai_epi16(ul_ch_mag128b[aa][i],1));
+	//	rxdataF_comp128[0][i] = _mm_add_epi16(rxdataF_comp128_0[i],(*(__m128i *)&jitterc[0]));
+      }
+      
+#elif defined(__arm__)
+      rxdataF_comp128_0   = (int16x8_t *)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12];
+      rxdataF_comp128_1   = (int16x8_t *)&rxdataF_comp[1][symbol*frame_parms->N_RB_DL*12];
+      ul_ch_mag128_0      = (int16x8_t *)&ul_ch_mag[0][symbol*frame_parms->N_RB_DL*12];
+      ul_ch_mag128_1      = (int16x8_t *)&ul_ch_mag[1][symbol*frame_parms->N_RB_DL*12];
+      ul_ch_mag128_0b     = (int16x8_t *)&ul_ch_magb[0][symbol*frame_parms->N_RB_DL*12];
+      ul_ch_mag128_1b     = (int16x8_t *)&ul_ch_magb[1][symbol*frame_parms->N_RB_DL*12];
+      
+      // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation)
+      for (i=0; i<nb_rb*3; i++) {
+	rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]);
+	ul_ch_mag128_0[i]    = vhaddq_s16(ul_ch_mag128_0[i],ul_ch_mag128_1[i]);
+	ul_ch_mag128_0b[i]   = vhaddq_s16(ul_ch_mag128_0b[i],ul_ch_mag128_1b[i]);
+	rxdataF_comp128_0[i] = vqaddq_s16(rxdataF_comp128_0[i],(*(int16x8_t *)&jitterc[0]));
+      }
+      
+#endif
+    }
+  }
+
+#if defined(__x86_64__) || defined(__i386__)
+  _mm_empty();
+  _m_empty();
+#endif
+}
+
 int nr_rx_pusch(PHY_VARS_gNB *gNB,
                 uint8_t ulsch_id,
                 uint32_t frame,
@@ -1198,7 +1261,14 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB,
                                   gNB->pusch_vars[ulsch_id]->log2_maxh);
     stop_meas(&gNB->ulsch_channel_compensation_stats);
 
-
+    start_meas(&gNB->ulsch_mrc_stats);
+    nr_ulsch_detection_mrc(frame_parms,
+			   gNB->pusch_vars[ulsch_id]->rxdataF_comp,
+			   gNB->pusch_vars[ulsch_id]->ul_ch_mag,
+			   gNB->pusch_vars[ulsch_id]->ul_ch_magb,
+			   symbol,
+			   rel15_ul->rb_size);
+    stop_meas(&gNB->ulsch_mrc_stats);
 #ifdef NR_SC_FDMA
     nr_idft(&((uint32_t*)gNB->pusch_vars[ulsch_id]->rxdataF_ext[0])[symbol * rel15_ul->rb_size * NR_NB_SC_PER_RB], nb_re_pusch);
 #endif
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
index c02228bc9f9..6f5fba78129 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
@@ -424,19 +424,15 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
             }
     }
 
-#ifdef DEBUG_DLSCH_CODING
-    printf("Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d)...\n",
-        r,
-        G,
-        Kr*3,
-        mod_order,nb_rb);
-#endif
 
-    //start_meas(rm_stats);
-#ifdef DEBUG_DLSCH_CODING
-  printf("rvidx in encoding = %d\n", harq_process->pusch_pdu.pusch_data.rv_index);
-#endif
+    LOG_D(PHY,"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d, rvidx %d)...\n",
+	  r,
+	  G,
+	  Kr*3,
+	  mod_order,nb_rb,
+	  harq_process->pusch_pdu.pusch_data.rv_index);
 
+    //start_meas(rm_stats);
 ///////////////////////// d---->| Rate matching bit selection |---->e /////////////////////////
 ///////////
 
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index 5605a85287e..564d79158af 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -797,6 +797,7 @@ typedef struct PHY_VARS_gNB_s {
   time_stats_t ulsch_channel_estimation_stats;
   time_stats_t ulsch_channel_compensation_stats;
   time_stats_t ulsch_rbs_extraction_stats;
+  time_stats_t ulsch_mrc_stats;
   time_stats_t ulsch_llr_stats;
   /*
   time_stats_t rx_dft_stats;
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 0d87ff17384..40381421dc6 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -294,11 +294,11 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH
   stop_meas(&gNB->ulsch_decoding_stats);
 
   if (ret > gNB->ulsch[ULSCH_id][0]->max_ldpc_iterations){
-    LOG_I(PHY, "ULSCH %d in error\n",ULSCH_id);
+    LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id);
     nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1);
   }
   else if(gNB->ulsch[ULSCH_id][0]->harq_processes[harq_pid]->b!=NULL){
-    LOG_I(PHY, "ULSCH received ok \n");
+    LOG_D(PHY, "ULSCH received ok \n");
     nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 0);
   }
 }
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index 3a1e6b1c5c5..77fbfdd3153 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -721,6 +721,7 @@ int main(int argc, char **argv)
       reset_meas(&gNB->ulsch_unscrambling_stats);
       reset_meas(&gNB->ulsch_channel_estimation_stats);
       reset_meas(&gNB->ulsch_llr_stats);
+      reset_meas(&gNB->ulsch_mrc_stats);
       reset_meas(&gNB->ulsch_channel_compensation_stats);
       reset_meas(&gNB->ulsch_rbs_extraction_stats);
 
@@ -1046,6 +1047,7 @@ int main(int argc, char **argv)
       printStatIndent2(&gNB->ulsch_channel_estimation_stats,"ULSCH channel estimation time");
       printStatIndent2(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time");
       printStatIndent2(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time");
+      printStatIndent2(&gNB->ulsch_mrc_stats,"ULSCH mrc computation");
       printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation");
       printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling");
       printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time");
-- 
GitLab