From afde7f6c51e43806b637c2867ab13f0acff8cfa2 Mon Sep 17 00:00:00 2001
From: francescomani <email@francescomani.it>
Date: Mon, 25 Mar 2024 13:09:31 +0100
Subject: [PATCH] improvements in precoding initialization at MAC

---
 common/utils/nr/nr_common.c                   |  12 --
 common/utils/nr/nr_common.h                   |   1 -
 openair2/LAYER2/NR_MAC_gNB/config.c           | 107 +++++++++++-------
 .../NR_MAC_gNB/gNB_scheduler_primitives.c     |  19 +---
 openair2/LAYER2/NR_MAC_gNB/mac_proto.h        |   1 +
 5 files changed, 75 insertions(+), 65 deletions(-)

diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c
index 4006fbb8580..e61fe01c8be 100644
--- a/common/utils/nr/nr_common.c
+++ b/common/utils/nr/nr_common.c
@@ -827,18 +827,6 @@ void get_samplerate_and_bw(int mu,
   }
 }
 
-void get_K1_K2(int N1, int N2, int *K1, int *K2)
-{
-  // num of allowed k1 and k2 according to 5.2.2.2.1-3 and -4 in 38.214
-  if(N2 == N1 || N1 == 2)
-    *K1 = 2;
-  else if (N2 == 1)
-    *K1 = 5;
-  else
-    *K1 = 3;
-  *K2 = N2 > 1 ? 2 : 1;
-}
-
 // from start symbol index and nb or symbols to symbol occupation bitmap in a slot
 uint16_t SL_to_bitmap(int startSymbolIndex, int nrOfSymbols) {
  return ((1<<nrOfSymbols)-1)<<startSymbolIndex;
diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h
index a18b1cecc9a..8456ec48a27 100644
--- a/common/utils/nr/nr_common.h
+++ b/common/utils/nr/nr_common.h
@@ -188,7 +188,6 @@ int get_dmrs_port(int nl, uint16_t dmrs_ports);
 uint16_t SL_to_bitmap(int startSymbolIndex, int nrOfSymbols);
 int get_nb_periods_per_frame(uint8_t tdd_period);
 long rrc_get_max_nr_csrs(const int max_rbs, long b_SRS);
-void get_K1_K2(int N1, int N2, int *K1, int *K2);
 bool compare_relative_ul_channel_bw(int nr_band, int scs, int nb_ul, frame_type_t frame_type);
 int get_supported_bw_mhz(frequency_range_t frequency_range, int bw_index);
 int get_supported_band_index(int scs, frequency_range_t freq_range, int n_rbs);
diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c
index 5b7b24b9dd2..95b5c6cbecd 100644
--- a/openair2/LAYER2/NR_MAC_gNB/config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/config.c
@@ -67,6 +67,36 @@ c16_t convert_precoder_weight(double complex c_in)
   return (c16_t) {.r = (short)cr, .i = (short)ci};
 }
 
+void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers)
+{
+  // num of allowed k1 and k2 according to 5.2.2.2.1-3 and -4 in 38.214
+  switch (layers) {
+    case 1:
+      *K1 = 1;
+      *K2 = 1;
+      break;
+    case 2:
+      *K2 = N2 == 1 ? 1 : 2;
+      if(N2 == N1 || N1 == 2)
+        *K1 = 2;
+      else if (N2 == 1)
+        *K1 = 4;
+      else
+        *K1 = 3;
+      break;
+    case 3:
+    case 4:
+      *K2 = N2 == 1 ? 1 : 2;
+      if (N1 == 6)
+        *K1 = 5;
+      else
+        *K1 = N1;
+      break;
+    default:
+      AssertFatal(false, "Number of layers %d not supported\n", layers);
+  }
+}
+
 nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPorts_t antenna_ports)
 {
   int num_antenna_ports = antenna_ports.N1 * antenna_ports.N2 * antenna_ports.XP;
@@ -88,16 +118,20 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
   int O2 = N2 > 1 ? 4 : 1; //Vertical beam oversampling (1 or 4)
   int O1 = num_antenna_ports > 2 ? 4 : 1; //Horizontal beam oversampling (1 or 4)
 
-  int K1, K2;
-  get_K1_K2(N1, N2, &K1, &K2);
-
   int max_mimo_layers = (num_antenna_ports < NR_MAX_NB_LAYERS) ? num_antenna_ports : NR_MAX_NB_LAYERS;
   AssertFatal(max_mimo_layers <= 4, "Max number of layers supported is 4\n");
+  AssertFatal(num_antenna_ports < 16, "Max number of antenna ports supported is currently 16\n");
+
+  int K1[max_mimo_layers];
+  memset(K1, 0, sizeof(K1));
+  int K2[max_mimo_layers];
+  memset(K2, 0, sizeof(K2));
 
-  gNB->precoding_matrix_size[0] = N1 * O1 * N2 * O2 * 4;
-  nfapi_nr_pm_list_t mat = {.num_pm_idx = gNB->precoding_matrix_size[0]};
-  for (int i = 1; i < max_mimo_layers; i++) {
-    gNB->precoding_matrix_size[i] = 2 * N1 * O1 * N2 * O2 * K1 * K2;
+  nfapi_nr_pm_list_t mat = {.num_pm_idx = 0};
+  for (int i = 0; i < max_mimo_layers; i++) {
+    get_K1_K2(N1, N2, &K1[i], &K2[i], i + 1);
+    int i2_size = i == 0 ? 4 : 2;
+    gNB->precoding_matrix_size[i] = i2_size * N1 * O1 * N2 * O2 * K1[i] * K2[i];
     mat.num_pm_idx += gNB->precoding_matrix_size[i];
   }
 
@@ -106,10 +140,10 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
   mat.pmi_pdu = pmi_pdu;
 
   // Generation of codebook Type1 with codebookMode 1 (num_antenna_ports < 16)
-  AssertFatal(num_antenna_ports < 16, "Max number of antenna ports supported is currently 16\n");
+
   // Generate DFT vertical beams
   // ll: index of a vertical beams vector (represented by i1_1 in TS 38.214)
-  const int max_l = N1 * O1 + (K1 - 1) * O1;
+  const int max_l = N1 * O1 + 4 * O1;  // max k1 is 4*O1
   double complex v[max_l][N1];
   for (int ll = 0; ll < max_l; ll++) { // i1_1
     for (int nn = 0; nn < N1; nn++) {
@@ -119,7 +153,7 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
   }
   // Generate DFT Horizontal beams
   // mm: index of a Horizontal beams vector (represented by i1_2 in TS 38.214)
-  const int max_m = N2 * O2 + (K2 - 1) * O2;
+  const int max_m = N2 * O2 + O2; // max k2 is O2
   double complex u[max_m][N2];
   for (int mm = 0; mm < max_m; mm++) { // i1_2
     for (int nn = 0; nn < N2; nn++) {
@@ -158,12 +192,12 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
   double complex res_code;
 
   // Table 5.2.2.2.1-5:
-  int pmiq = 0;
+  int pmiq = -1;
   // Codebook for 1-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
-  for (int ll = 0; ll < N1 * O1; ll++) { // i_1_1
-    for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2
+  for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2
+    for (int ll = 0; ll < N1 * O1; ll++) { // i_1_1
       for (int nn = 0; nn < 4; nn++) {
-        pmiq = ll * N2 * O2 * 4 + mm * 4 + nn;
+        pmiq++;
         pmi_pdu[pmiq].pm_idx = pmiq + 1; // index 0 is the identity matrix
         pmi_pdu[pmiq].numLayers = 1;
         pmi_pdu[pmiq].num_ant_ports = num_antenna_ports;
@@ -175,7 +209,7 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
           weights->precoder_weight_Re = precoder_weight.r;
           weights->precoder_weight_Im = precoder_weight.i;
           LOG_D(PHY,
-                "1 Layer Precoding Matrix[0][pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n",
+                "1 Layer Precoding Matrix[pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n",
                 pmiq,
                 len,
                 creal(res_code),
@@ -191,7 +225,7 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
           weights->precoder_weight_Re = precoder_weight.r;
           weights->precoder_weight_Im = precoder_weight.i;
           LOG_D(PHY,
-                "1 Layer Precoding Matrix[0][pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n",
+                "1 Layer Precoding Matrix[pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n",
                 pmiq,
                 len,
                 creal(res_code),
@@ -208,12 +242,11 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
   // Table 5.2.2.2.1-6:
   // Codebook for 2-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
   // Compute the code book size for generating 2 layers out of Tx antenna ports
-
   // pmi=1,...,pmi_size, we construct
-  for (int ll = 0; ll < N1 * O1; ll++) { // i_1_1
-    for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2
-      for (int k1 = 0; k1 < K1; k1++) {
-        for (int k2 = 0; k2 < K2; k2++) {
+  for (int k2 = 0; k2 < K2[1]; k2++) {
+    for (int k1 = 0; k1 < K1[1]; k1++) {
+      for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2
+        for (int ll = 0; ll < N1 * O1; ll++) { // i_1_1
           for (int nn = 0; nn < 2; nn++) { // i_2
             pmiq++;
             pmi_pdu[pmiq].pm_idx = pmiq + 1; // index 0 is the identity matrix
@@ -238,7 +271,7 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
                 weights->precoder_weight_Re = precoder_weight.r;
                 weights->precoder_weight_Im = precoder_weight.i;
                 LOG_D(PHY,
-                      "2 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
+                      "2 Layer Precoding Matrix[pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                       pmiq,
                       i_rows,
                       j_col,
@@ -254,7 +287,7 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
                 weights->precoder_weight_Re = precoder_weight.r;
                 weights->precoder_weight_Im = precoder_weight.i;
                 LOG_D(PHY,
-                      "2 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
+                      "2 Layer Precoding Matrix[pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                       pmiq,
                       i_rows,
                       j_col,
@@ -272,15 +305,13 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
 
   if (max_mimo_layers < 3)
     return mat;
-
   // Table 5.2.2.2.1-7:
   // Codebook for 3-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
-
   // pmi=1,...,pmi_size are computed as follows
-  for (int ll = 0; ll < N1 * O1; ll++) { // i_1_1
-    for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2
-      for (int k1 = 0; k1 < K1; k1++) {
-        for (int k2 = 0; k2 < K2; k2++) {
+  for (int k2 = 0; k2 < K2[2]; k2++) {
+    for (int k1 = 0; k1 < K1[2]; k1++) {
+      for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2
+        for (int ll = 0; ll < N1 * O1; ll++) { // i_1_1
           for (int nn = 0; nn < 2; nn++) { // i_2
             pmiq++;
             pmi_pdu[pmiq].pm_idx = pmiq + 1; // index 0 is the identity matrix
@@ -310,7 +341,7 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
                 weights->precoder_weight_Re = precoder_weight.r;
                 weights->precoder_weight_Im = precoder_weight.i;
                 LOG_D(PHY,
-                      "3 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
+                      "3 Layer Precoding Matrix[pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                       pmiq,
                       i_rows,
                       j_col,
@@ -326,7 +357,7 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
                 weights->precoder_weight_Re = precoder_weight.r;
                 weights->precoder_weight_Im = precoder_weight.i;
                 LOG_D(PHY,
-                      "3 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
+                      "3 Layer Precoding Matrix[pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                       pmiq,
                       i_rows,
                       j_col,
@@ -344,14 +375,12 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
 
   if (max_mimo_layers < 4)
     return mat;
-
   // Table 5.2.2.2.1-8:
   // Codebook for 4-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
-
-  for (int ll = 0; ll < N1 * O1; ll++) { // i_1_1
-    for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2
-      for (int k1 = 0; k1 < K1; k1++) {
-        for (int k2 = 0; k2 < K2; k2++) {
+  for (int k2 = 0; k2 < K2[3]; k2++) {
+    for (int k1 = 0; k1 < K1[3]; k1++) {
+      for (int mm = 0; mm < N2 * O2; mm++) { // i_1_2
+        for (int ll = 0; ll < N1 * O1; ll++) { // i_1_1
           for (int nn = 0; nn < 2; nn++) { // i_2
             pmiq++;
             pmi_pdu[pmiq].pm_idx = pmiq + 1; // index 0 is the identity matrix
@@ -386,7 +415,7 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
                 weights->precoder_weight_Re = precoder_weight.r;
                 weights->precoder_weight_Im = precoder_weight.i;
                 LOG_D(PHY,
-                      "4 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
+                      "4 Layer Precoding Matrix[pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                       pmiq,
                       i_rows,
                       j_col,
@@ -402,7 +431,7 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
                 weights->precoder_weight_Re = precoder_weight.r;
                 weights->precoder_weight_Im = precoder_weight.i;
                 LOG_D(PHY,
-                      "4 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
+                      "4 Layer Precoding Matrix[pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
                       pmiq,
                       i_rows,
                       j_col,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
index e01c0861d0d..3d7179d04cf 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
@@ -223,21 +223,14 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac,
     int k1, k2;
     get_k1_k2_indices(layers, N1, N2, i13, &k1, &k2); // get indices k1 and k2 for PHY matrix (not actual k1 and k2 values)
     const int O2 = N2 == 1 ? 1 : 4;
+    int O1 = 4; //Horizontal beam oversampling = 4 for more than 2 antenna ports
     int max_i2 = 0;
     int lay_index = 0;
-    if (layers == 1) {
-      max_i2 = 4;
-      // computing precoding matrix index according to rule set in allocation function init_codebook_gNB
-      lay_index = i2 + (i12 * max_i2) + (i11 * max_i2 * N2 * O2);
-    }
-    else {
-      max_i2 = 2;
-      // num of allowed k1 and k2 according to 5.2.2.2.1-3 and -4 in 38.214
-      int K1, K2;
-      get_K1_K2(N1, N2, &K1, &K2);
-      // computing precoding matrix index according to rule set in allocation function init_codebook_gNB
-      lay_index = i2 + (k2 * max_i2) + (k1 * max_i2 * K2) + (i12 * max_i2 * K2 * K1) + (i11 * max_i2 * K2 * K1 * N2 * O2);
-    }
+    max_i2 = layers == 1 ? 4 : 2;
+    int K1, K2;
+    get_K1_K2(N1, N2, &K1, &K2, layers);
+    // computing precoding matrix index according to rule set in allocation function init_codebook_gNB
+    lay_index = i2 + (i11 * max_i2) + (i12 * max_i2 * N1 * O1) + (k1 * max_i2 * N1 * O1 * N2 * O2) + (k2 * max_i2 * N1 * O1 * N2 * O2 * K1);
     return 1 + prev_layers_size + lay_index;
   }
 }
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index 62289989427..6e38f491f64 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -36,6 +36,7 @@
 #include "common/ngran_types.h"
 
 void set_cset_offset(uint16_t);
+void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers);
 
 void mac_top_init_gNB(ngran_node_t node_type,
                       NR_ServingCellConfigCommon_t *scc,
-- 
GitLab