diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml
index 2c6dc73bfa..32876634c0 100755
--- a/cmake_targets/autotests/test_case_list.xml
+++ b/cmake_targets/autotests/test_case_list.xml
@@ -318,7 +318,8 @@
(Test25: Format 2 11-bit 2/273 PRB),
(Test26: Format 2 12-bit 8/273 PRB),
(Test27: Format 2 19-bit 8/273 PRB),
- (Test28: Format 2 64-bit 16/273 PRB)
+ (Test28: Format 2 64-bit 16/273 PRB),
+ (Test29: Format 2 64-bit 16/273 PRB Delay 2us)
nr_pucchsim
-R 106 -i 1 -P 0 -b 1 -s-2 -n1000
-R 106 -i 1 -P 0 -b 2 -s-2 -n1000
@@ -347,8 +348,9 @@
-R 273 -z8 -i 1 -P 2 -b 11 -s6 -n1000
-R 273 -z8 -i 1 -P 2 -q8 -b 12 -s-3 -n1000
-R 273 -z8 -i 1 -P 2 -q8 -b 19 -s-3 -n1000
- -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -n1000
- test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13 test14 test15 test16 test17 test18 test19 test20 test21 test22 test23 test24 test25 test26 test27 test28
+ -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -n1000
+ -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -d 2 -n1000
+ test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13 test14 test15 test16 test17 test18 test19 test20 test21 test22 test23 test24 test25 test26 test27 test28 test29
PUCCH test OK
segmentation fault|assertion|exiting|fatal
3
diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c
index 80244c0912..af6c30b858 100644
--- a/common/utils/LOG/log.c
+++ b/common/utils/LOG/log.c
@@ -651,6 +651,10 @@ void log_dump(int component,
wbuf=malloc((buffsize * 10) + 64 + MAX_LOG_TOTAL);
break;
+ case LOG_DUMP_C16:
+ wbuf = malloc((buffsize * 10) + 64 + MAX_LOG_TOTAL);
+ break;
+
case LOG_DUMP_CHAR:
default:
wbuf=malloc((buffsize * 3 ) + 64 + MAX_LOG_TOTAL);
@@ -669,6 +673,21 @@ void log_dump(int component,
pos = pos + sprintf(wbuf+pos,"%04.4lf ", (double)((double *)buffer)[i]);
break;
+ case LOG_DUMP_I16: {
+ int16_t *tmp = ((int16_t *)buffer) + i;
+ pos = pos + sprintf(wbuf + pos, "%d, ", *tmp);
+ } break;
+
+ case LOG_DUMP_C16: {
+ int16_t *tmp = ((int16_t *)buffer) + i * 2;
+ pos = pos + sprintf(wbuf + pos, "(%d,%d), ", *tmp, *(tmp + 1));
+ } break;
+
+ case LOG_DUMP_C32: {
+ int32_t *tmp = ((int32_t *)buffer) + i * 2;
+ pos = pos + sprintf(wbuf + pos, "(%d,%d), ", *tmp, *(tmp + 1));
+ } break;
+
case LOG_DUMP_CHAR:
default:
pos = pos + sprintf(wbuf+pos,"%02x ", (unsigned char)((unsigned char *)buffer)[i]);
diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h
index 1add78c6f1..f16ee296d4 100644
--- a/common/utils/LOG/log.h
+++ b/common/utils/LOG/log.h
@@ -335,6 +335,9 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
* @{*/
#define LOG_DUMP_CHAR 0
#define LOG_DUMP_DOUBLE 1
+#define LOG_DUMP_I16 2
+#define LOG_DUMP_C16 3
+#define LOG_DUMP_C32 4
// debugging macros
#define LOG_F LOG_I /* because LOG_F was originaly to dump a message or buffer but is also used as a regular level...., to dump use LOG_DUMPMSG */
diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index ca14ca99be..581338fa45 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -138,6 +138,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;
init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table);
+ init_delay_table(128, MAX_DELAY_COMP, 128, fp->delay_table128);
gNB->bad_pucch = 0;
if (gNB->TX_AMP == 0)
diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c
index e545766206..62c1564ede 100644
--- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c
+++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c
@@ -53,6 +53,7 @@
#include "SCHED_NR/sched_nr.h"
#include "T.h"
+#include "nr_phy_common.h"
//#define DEBUG_NR_PUCCH_RX 1
@@ -693,10 +694,6 @@ void nr_decode_pucch1(c16_t **rxdataF,
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols - 1]; // only if intra-slot hopping not enabled (PUCCH)
int N_SF_mprime_PUCCH_DMRS_1 =
table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols - 1]; // only if intra-slot hopping not enabled (DM-RS)
-#ifdef DEBUG_NR_PUCCH_RX
- printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n",
- w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1);
-#endif
if(l%2==1){
for (int m=0; m < N_SF_mprime_PUCCH_1; m++) {
@@ -860,164 +857,59 @@ void nr_decode_pucch1(c16_t **rxdataF,
}
}
-static simde__m256i pucch2_3bit[8 * 2];
-static simde__m256i pucch2_4bit[16 * 2];
-static simde__m256i pucch2_5bit[32 * 2];
-static simde__m256i pucch2_6bit[64 * 2];
-static simde__m256i pucch2_7bit[128 * 2];
-static simde__m256i pucch2_8bit[256 * 2];
-static simde__m256i pucch2_9bit[512 * 2];
-static simde__m256i pucch2_10bit[1024 * 2];
-static simde__m256i pucch2_11bit[2048 * 2];
+typedef struct {c16_t cw[16];} cw_t;
+static cw_t pucch2_3bit[8] __attribute__((aligned(32)));
+static cw_t pucch2_4bit[16] __attribute__((aligned(32)));
+static cw_t pucch2_5bit[32] __attribute__((aligned(32)));
+static cw_t pucch2_6bit[64] __attribute__((aligned(32)));
+static cw_t pucch2_7bit[128] __attribute__((aligned(32)));
+static cw_t pucch2_8bit[256] __attribute__((aligned(32)));
+static cw_t pucch2_9bit[512] __attribute__((aligned(32)));
+static cw_t pucch2_10bit[1024] __attribute__((aligned(32)));
+static cw_t pucch2_11bit[2048] __attribute__((aligned(32)));
-static simde__m256i *pucch2_lut[9] =
+static cw_t* pucch2_lut[9] =
{pucch2_3bit, pucch2_4bit, pucch2_5bit, pucch2_6bit, pucch2_7bit, pucch2_8bit, pucch2_9bit, pucch2_10bit, pucch2_11bit};
-static simde__m64 pucch2_polar_4bit[16];
-static simde__m128i pucch2_polar_llr_num_lut[256], pucch2_polar_llr_den_lut[256];
+typedef struct {
+ int16_t cw[4];
+} cw4bit_t;
+static cw4bit_t pucch2_polar_4bit[16] __attribute__((aligned(32)));
+static simde__m128i pucch2_polar_llr_num_lut[256];
-void init_pucch2_luts() {
-
- uint32_t out;
- int8_t bit;
-
+void init_pucch2_luts()
+{
for (int b=3;b<12;b++) {
- for (int i = 0; i < (1 << b); i++) {
- out = encodeSmallBlock(i, b);
-#ifdef DEBUG_NR_PUCCH_RX
- if (b==3) printf("in %d, out %x\n",i,out);
-#endif
- simde__m256i *lut_i=&pucch2_lut[b-3][i<<1];
- simde__m256i *lut_ip1=&pucch2_lut[b-3][1+(i<<1)];
- bit = (out&0x1) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,0);
- bit = (out&0x2) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,0);
- bit = (out&0x4) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,1);
- bit = (out&0x8) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,1);
- bit = (out&0x10) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,2);
- bit = (out&0x20) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,2);
- bit = (out&0x40) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,3);
- bit = (out&0x80) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,3);
- bit = (out&0x100) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,4);
- bit = (out&0x200) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,4);
- bit = (out&0x400) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,5);
- bit = (out&0x800) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,5);
- bit = (out&0x1000) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,6);
- bit = (out&0x2000) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,6);
- bit = (out&0x4000) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,7);
- bit = (out&0x8000) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,7);
- bit = (out&0x10000) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,8);
- bit = (out&0x20000) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,8);
- bit = (out&0x40000) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,9);
- bit = (out&0x80000) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,9);
- bit = (out&0x100000) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,10);
- bit = (out&0x200000) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,10);
- bit = (out&0x400000) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,11);
- bit = (out&0x800000) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,11);
- bit = (out&0x1000000) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,12);
- bit = (out&0x2000000) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,12);
- bit = (out&0x4000000) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,13);
- bit = (out&0x8000000) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,13);
- bit = (out&0x10000000) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,14);
- bit = (out&0x20000000) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,14);
- bit = (out&0x40000000) > 0 ? -1 : 1;
- *lut_i = simde_mm256_insert_epi16(*lut_i,bit,15);
- bit = (out&0x80000000) > 0 ? -1 : 1;
- *lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,15);
+ for (int cw = 0; cw < (1 << b); cw++) {
+ uint32_t out = encodeSmallBlock(cw, b);
+ uint16_t *tmp = (uint16_t *)pucch2_lut[b - 3][cw].cw;
+ for (int j = 0; j < 32; j++)
+ *tmp++ = (out & (1U< 0 ? -1 : 1;
}
}
for (int i = 0; i < 16; i++) {
- simde__m64 *lut_i=&pucch2_polar_4bit[i];
-
- bit = (i&0x1) > 0 ? -1 : 1;
- *lut_i = simde_mm_insert_pi16(*lut_i,bit,0);
- bit = (i&0x2) > 0 ? -1 : 1;
- *lut_i = simde_mm_insert_pi16(*lut_i,bit,1);
- bit = (i&0x4) > 0 ? -1 : 1;
- *lut_i = simde_mm_insert_pi16(*lut_i,bit,2);
- bit = (i&0x8) > 0 ? -1 : 1;
- *lut_i = simde_mm_insert_pi16(*lut_i,bit,3);
+ int16_t *lut_i = pucch2_polar_4bit[i].cw;
+ *lut_i++ = (i & 0x1) <= 0;
+ *lut_i++ = (i & 0x2) <= 0;
+ *lut_i++ = (i & 0x4) <= 0;
+ *lut_i++ = (i & 0x8) <= 0;
}
- for (int i=0;i<256;i++) {
- simde__m128i *lut_num_i=&pucch2_polar_llr_num_lut[i];
- simde__m128i *lut_den_i=&pucch2_polar_llr_den_lut[i];
- bit = (i&0x1) > 0 ? 0 : 1;
- *lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 0);
- *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 0);
-
- bit = (i&0x10) > 0 ? 0 : 1;
- *lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 1);
- *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 1);
-
- bit = (i&0x2) > 0 ? 0 : 1;
- *lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 2);
- *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 2);
-
- bit = (i&0x20) > 0 ? 0 : 1;
- *lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 3);
- *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 3);
-
- bit = (i&0x4) > 0 ? 0 : 1;
- *lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 4);
- *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 4);
-
- bit = (i&0x40) > 0 ? 0 : 1;
- *lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 5);
- *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 5);
-
- bit = (i&0x8) > 0 ? 0 : 1;
- *lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 6);
- *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 6);
-
- bit = (i&0x80) > 0 ? 0 : 1;
- *lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 7);
- *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 7);
-
+ for (int cw = 0; cw < 256; cw++) {
+ int16_t *lut_num_i = (int16_t *)&pucch2_polar_llr_num_lut[cw];
+ *lut_num_i++ = (cw & 0x1) <= 0;
+ *lut_num_i++ = (cw & 0x10) <= 0;
+ *lut_num_i++ = (cw & 0x2) <= 0;
+ *lut_num_i++ = (cw & 0x20) <= 0;
+ *lut_num_i++ = (cw & 0x4) <= 0;
+ *lut_num_i++ = (cw & 0x40) <= 0;
+ *lut_num_i++ = (cw & 0x8) <= 0;
+ *lut_num_i++ = (cw & 0x80) <= 0;
#ifdef DEBUG_NR_PUCCH_RX
- printf("i %d, lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
- i,
- ((int16_t *)lut_num_i)[0],
- ((int16_t *)lut_num_i)[1],
- ((int16_t *)lut_num_i)[2],
- ((int16_t *)lut_num_i)[3],
- ((int16_t *)lut_num_i)[4],
- ((int16_t *)lut_num_i)[5],
- ((int16_t *)lut_num_i)[6],
- ((int16_t *)lut_num_i)[7]);
+ log_dump(PHY, pucch2_polar_llr_num_lut, 8, LOG_DUMP_C16, "lut_num %d:", i);
#endif
}
}
-
void nr_decode_pucch2(PHY_VARS_gNB *gNB,
c16_t **rxdataF,
int frame,
@@ -1026,11 +918,14 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
nfapi_nr_pucch_pdu_t* pucch_pdu)
{
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
- //pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
+ const simde__m256i conj256 = simde_mm256_set_epi16(-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1);
- AssertFatal(pucch_pdu->nr_of_symbols == 1 || pucch_pdu->nr_of_symbols == 2,
+ //pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
+ const int nb_symbols=pucch_pdu->nr_of_symbols;
+
+ AssertFatal(nb_symbols == 1 || nb_symbols == 2,
"Illegal number of symbols for PUCCH 2 %d\n",
- pucch_pdu->nr_of_symbols);
+ nb_symbols);
AssertFatal((pucch_pdu->prb_start-((pucch_pdu->prb_start>>2)<<2))==0,
"Current pucch2 receiver implementation requires a PRB offset multiple of 4. The one selected is %d",
@@ -1040,35 +935,30 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
int l2 = pucch_pdu->start_symbol_index;
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
- int re_offset[2];
+ int re_offset[nb_symbols];
re_offset[0] =
(12 * (pucch_pdu->prb_start + pucch_pdu->bwp_start) + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size;
- if (pucch_pdu->freq_hop_flag == 0)
- re_offset[1] = re_offset[0];
- else {
- re_offset[1] = 12*(pucch_pdu->second_hop_prb+pucch_pdu->bwp_start) + frame_parms->first_carrier_offset;
- if (re_offset[1]>= frame_parms->ofdm_symbol_size)
- re_offset[1]-=frame_parms->ofdm_symbol_size;
+ if (nb_symbols==2) {
+ if (pucch_pdu->freq_hop_flag )
+ re_offset[1] = (12*(pucch_pdu->second_hop_prb+pucch_pdu->bwp_start) + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size ;
+ else
+ re_offset[1] = re_offset[0];
}
- AssertFatal(pucch_pdu->prb_size * pucch_pdu->nr_of_symbols > 1,
+ AssertFatal(pucch_pdu->prb_size * nb_symbols > 1,
"number of PRB*SYMB (%d,%d)< 2",
pucch_pdu->prb_size,
- pucch_pdu->nr_of_symbols);
+ nb_symbols);
int Prx = gNB->gNB_config.carrier_config.num_rx_ant.value;
// AssertFatal((pucch_pdu->prb_size&1) == 0,"prb_size %d is not a multiple of2\n",pucch_pdu->prb_size);
- int Prx2 = (Prx==1)?2:Prx;
// use 2 for Nb antennas in case of single antenna to allow the following allocations
- int nb_re_pucch = 12*pucch_pdu->prb_size;
- int prb_size_ext = pucch_pdu->prb_size+(pucch_pdu->prb_size&1);
-
- c16_t rp[Prx2][2][nb_re_pucch];
+ const int nb_re_pucch = 12 * pucch_pdu->prb_size;
+ c16_t rp[Prx][nb_symbols][nb_re_pucch];
memset(rp, 0, sizeof(rp));
int64_t pucch2_lev = 0;
-
for (int aa=0;aanr_of_symbols;symb++) {
+ for (int symb=0;symbofdm_symbol_size]);
if (re_offset[symb] + nb_re_pucch < frame_parms->ofdm_symbol_size) {
@@ -1084,23 +974,14 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
}
}
- pucch2_lev /= Prx * pucch_pdu->nr_of_symbols;
+ pucch2_lev /= Prx * nb_symbols;
int pucch2_levdB = dB_fixed(pucch2_lev);
- int scaling = 0;
- if (pucch2_levdB > 72)
- scaling = 4;
- else if (pucch2_levdB > 66)
- scaling = 3;
- else if (pucch2_levdB > 60)
- scaling = 2;
- else if (pucch2_levdB > 54)
- scaling = 1;
-
+ int scaling = max((log2_approx64(pucch2_lev) >> 1) - 8, 0);
LOG_D(NR_PHY,
"%d.%d Decoding pucch2 for %d symbols, %d PRB, nb_harq %d, nb_sr %d, nb_csi %d/%d, pucch2_lev %d dB (scaling %d)\n",
frame,
slot,
- pucch_pdu->nr_of_symbols,
+ nb_symbols,
pucch_pdu->prb_size,
pucch_pdu->bit_len_harq,
pucch_pdu->sr_flag,
@@ -1109,68 +990,87 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
pucch2_levdB,
scaling);
+ int prb_size_ext = pucch_pdu->prb_size + (pucch_pdu->prb_size & 1);
int nc_group_size=1; // 2 PRB
int ngroup = prb_size_ext/nc_group_size/2;
- int32_t corr32_re[2][ngroup][Prx2],corr32_im[2][ngroup][Prx2];
- memset(corr32_re, 0, sizeof(corr32_re));
- memset(corr32_im, 0, sizeof(corr32_im));
+ c32_t corr32[nb_symbols][ngroup][Prx];
+ memset(corr32, 0, sizeof(corr32));
+ const int nb_re_data = 8 * prb_size_ext;
+ const int nb_re_dmrs = 4 * prb_size_ext;
+ c16_t r_ext[Prx][nb_symbols][nb_re_data] __attribute__((aligned(32)));
+ c16_t r_ext2[Prx][nb_symbols][nb_re_data] __attribute__((aligned(32)));
+ const simde__m256i swap = simde_mm256_set_epi8(29,
+ 28,
+ 31,
+ 30,
+ 25,
+ 24,
+ 27,
+ 26,
+ 21,
+ 20,
+ 23,
+ 22,
+ 17,
+ 16,
+ 19,
+ 18,
+ 13,
+ 12,
+ 15,
+ 14,
+ 9,
+ 8,
+ 11,
+ 10,
+ 5,
+ 4,
+ 7,
+ 6,
+ 1,
+ 0,
+ 3,
+ 2);
+ // prepare scrambling sequence for data
+ uint32_t x2 = ((pucch_pdu->rnti) << 15) + pucch_pdu->data_scrambling_id;
+#ifdef DEBUG_NR_PUCCH_RX
+ printf("x2 %x\n", x2);
+#endif
+ c16_t scramb_data[nb_re_data] __attribute__((aligned(32)));
- int16_t r_re_ext[Prx2][2][8 * prb_size_ext] __attribute__((aligned(32)));
- int16_t r_im_ext[Prx2][2][8 * prb_size_ext] __attribute__((aligned(32)));
- int16_t r_re_ext2[Prx2][2][8 * prb_size_ext] __attribute__((aligned(32)));
- int16_t r_im_ext2[Prx2][2][8 * prb_size_ext] __attribute__((aligned(32)));
- int16_t rd_re_ext[Prx2][2][4 * prb_size_ext] __attribute__((aligned(32)));
- int16_t rd_im_ext[Prx2][2][4 * prb_size_ext] __attribute__((aligned(32)));
+ uint32_t *sGold = gold_cache(x2, nb_symbols * nb_re_data/2);
+ uint8_t *sGold8 = (uint8_t *)sGold;
+ for (int i = 0; i < nb_re_data; i += 4)
+ *(simde__m128i *)(scramb_data + i) = byte2m128i[*sGold8++];
+
- if (pucch_pdu->prb_size != prb_size_ext) {
- // if the number of PRBs is odd
- // we fill the unsed part of the arrays
- for (int aa = 0; aa < Prx; aa++) {
- for (int symb = 0; symb < pucch_pdu->nr_of_symbols; symb++) {
- const int sz = pucch_pdu->prb_size;
- memset(r_re_ext[aa][symb] + 8 * sz, 0, 8 * sizeof(int16_t));
- memset(r_im_ext[aa][symb] + 8 * sz, 0, 8 * sizeof(int16_t));
- memset(rd_re_ext[aa][symb] + 4 * sz, 0, 4 * sizeof(int16_t));
- memset(rd_im_ext[aa][symb] + 4 * sz, 0, 4 * sizeof(int16_t));
- }
- }
- }
+ for (int symb=0; symbnr_of_symbols;symb++) {
- // 24 REs contains 48x16-bit, so 6x8x16-bit
+ // extract DMRS
for (int aa = 0; aa < Prx; aa++) {
+ c16_t *rdmrs_ext_p = rdmrs_ext[aa];
+ c16_t *rp_base = rp[aa][symb];
for (int prb = 0; prb < pucch_pdu->prb_size; prb++) {
- int16_t *r_re_ext_p = &r_re_ext[aa][symb][8 * prb];
- int16_t *r_im_ext_p = &r_im_ext[aa][symb][8 * prb];
- int16_t *rd_re_ext_p = &rd_re_ext[aa][symb][4 * prb];
- int16_t *rd_im_ext_p = &rd_im_ext[aa][symb][4 * prb];
-
for (int idx = 0; idx < 4; idx++) {
- c16_t *rp_base = rp[aa][symb] + prb * 12 + 3 * idx;
- AssertFatal(prb * 12 + 3 * idx + 2 < nb_re_pucch, "");
- r_re_ext_p[idx << 1] = rp_base->r >> scaling;
- r_im_ext_p[idx << 1] = rp_base->i >> scaling;
rp_base++;
- rd_re_ext_p[idx] = rp_base->r >> scaling;
- rd_im_ext_p[idx] = rp_base->i >> scaling;
+ *rdmrs_ext_p++ = *rp_base++;
rp_base++;
- r_re_ext_p[1 + (idx << 1)] = rp_base->r >> scaling;
- r_im_ext_p[1 + (idx << 1)] = rp_base->i >> scaling;
}
+ }
+ if (pucch_pdu->prb_size != prb_size_ext)
+ // if the number of PRBs is odd
+ // we fill the unsed part of the arrays
+ memset(rdmrs_ext[aa] + pucch_pdu->prb_size * 4, 0, 4 * sizeof(c16_t));
+ }
#ifdef DEBUG_NR_PUCCH_RX
- for (int i = 0; i < 8; i++)
- printf("Ant %d PRB %d dmrs[%d] -> (%d,%d)\n", aa, prb + (i >> 2), i, rd_re_ext_p[i], rd_im_ext_p[i]);
- for (int i = 0; i < 16; i++)
- printf("Ant %d PRB %d data[%d] -> (%d,%d)\n", aa, prb + (i >> 3), i, r_re_ext_p[i], r_im_ext_p[i]);
+ for (int aa = 0; aa < Prx; aa++)
+ log_dump(PHY, rdmrs_ext[aa], nb_re_dmrs, LOG_DUMP_C16, "Ant %d dmrs:\n", aa);
#endif
- }
- }
// first compute DMRS component
-
const int scramble = pucch_pdu->dmrs_scrambling_id * 2;
- // fixme: when MR2754 will be merged, use the gold sequence cache instead of regenerate each time
uint32_t x2 =
((1ULL << 17) * ((NR_NUMBER_OF_SYMBOLS_PER_SLOT * slot + pucch_pdu->start_symbol_index + symb + 1) * (scramble + 1))
+ scramble)
@@ -1180,453 +1080,210 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
slot,pucch_pdu->start_symbol_index,symb,pucch_pdu->dmrs_scrambling_id);
#endif
uint32_t *sGold = gold_cache(x2, pucch_pdu->prb_start / 4 + ngroup / 2);
- for (int group = 0, goldIdx = pucch_pdu->prb_start / 4; group < ngroup; group++) {
- // each group has 8*nc_group_size elements, compute 1 complex correlation with DMRS per group
- // non-coherent combining across groups
- uint8_t *sGold8 = (uint8_t *)&sGold[goldIdx];
- simde__m64 dmrs_re = byte2m64_re[sGold8[(group & 1) << 1]];
- int16_t *dmrs_re16 = (int16_t *)&dmrs_re;
- simde__m64 dmrs_im = byte2m64_im[sGold8[(group & 1) << 1]];
- int16_t *dmrs_im16 = (int16_t *)&dmrs_im;
-#ifdef DEBUG_NR_PUCCH_RX
- printf("Group %d: x2 %x ((%d,%d),(%d,%d),(%d,%d),(%d,%d))\n",
- group,
- x2,
- dmrs_re16[0],
- dmrs_im16[0],
- dmrs_re16[1],
- dmrs_im16[1],
- dmrs_re16[2],
- dmrs_im16[2],
- dmrs_re16[3],
- dmrs_im16[3]);
-#endif
- for (int aa=0;aaprb_start / 4);
+ for (int group = 0; group < nb_re_dmrs; group += 4)
+ *(simde__m128i *)(pil_dmrs + group) = simde_mm_sign_epi16(byte2m128i[*sGold8++], *(simde__m128i *)&conj256);
-#ifdef DEBUG_NR_PUCCH_RX
- printf("Group %d: rd ((%d,%d),(%d,%d),(%d,%d),(%d,%d))\n",
- group,
- rd_re_ext_p[0],rd_im_ext_p[0],
- rd_re_ext_p[1],rd_im_ext_p[1],
- rd_re_ext_p[2],rd_im_ext_p[2],
- rd_re_ext_p[3],rd_im_ext_p[3]);
-#endif
- for (int z = 0; z < 4; z++) {
- corr32_re[symb][group][aa] += rd_re_ext_p[z] * dmrs_re16[z] + rd_im_ext_p[z] * dmrs_im16[z];
- corr32_im[symb][group][aa] += -rd_re_ext_p[z] * dmrs_im16[z] + rd_im_ext_p[z] * dmrs_re16[z];
- }
+ // Compute delay
+ c16_t ch_ls[128] __attribute__((aligned(32))) = {0};
+ {
+ c16_t rdmrs_gold[nb_re_dmrs] __attribute__((aligned(32)));
+ for (int aa = 0; aa < Prx; aa++) {
+ mult_complex_vectors(rdmrs_ext[aa], pil_dmrs, rdmrs_gold, nb_re_dmrs, 0);
+ c16_t *ch_ls_ptr = ch_ls;
+ c16_t *end = ch_ls_ptr + 128;
+ for (int i = 0; i < nb_re_dmrs; i++)
+ for (int k = 0; k < 3 && ch_ls_ptr < end; k++)
+ *ch_ls_ptr++ = rdmrs_gold[i];
}
- dmrs_re = byte2m64_re[sGold8[1 + ((group & 1) << 1)]];
- dmrs_im = byte2m64_im[sGold8[1 + ((group & 1) << 1)]];
-#ifdef DEBUG_NR_PUCCH_RX
- printf("Group %d: s %x ((%d,%d),(%d,%d),(%d,%d),(%d,%d))\n",
- group,
- ((uint16_t *)&sGold)[1],
- dmrs_re16[0],
- dmrs_im16[0],
- dmrs_re16[1],
- dmrs_im16[1],
- dmrs_re16[2],
- dmrs_im16[2],
- dmrs_re16[3],
- dmrs_im16[3]);
-#endif
- for (int aa=0;aa>=5;
- corr32_im[group][aa]>>=5;*/
-#ifdef DEBUG_NR_PUCCH_RX
- printf("Group %d: corr32 (%d,%d)\n",group,corr32_re[symb][group][aa],corr32_im[symb][group][aa]);
-#endif
- } //aa
-
- if ((group & 1) == 1)
- goldIdx++;
- } // group
- } // symb
-
- // unscrambling
- uint32_t x2 = ((pucch_pdu->rnti) << 15) + pucch_pdu->data_scrambling_id;
-#ifdef DEBUG_NR_PUCCH_RX
- printf("x2 %x\n", x2);
-#endif
- uint32_t *sGold = gold_cache(x2, pucch_pdu->nr_of_symbols * prb_size_ext / 2);
- int goldIdx = 0;
- for (int symb=0;symbnr_of_symbols;symb++) {
- simde__m64 c_re[4], c_im[4];
- int re_off=0;
- for (int prb=0;prbbit_len_harq+pucch_pdu->sr_flag+pucch_pdu->bit_len_csi_part1+pucch_pdu->bit_len_csi_part2;
- AssertFatal(nb_bit > 2 && nb_bit< 65,"illegal length (%d : %d,%d,%d,%d)\n",nb_bit,pucch_pdu->bit_len_harq,pucch_pdu->sr_flag,pucch_pdu->bit_len_csi_part1,pucch_pdu->bit_len_csi_part2);
+ c16_t ch_temp[128] __attribute__((aligned(32))) = {0};
+ delay_t delay = {0};
+ nr_est_delay(128, ch_ls, ch_temp, &delay);
- uint64_t decodedPayload[2];
+ // Apply delay compensation on the input
+ if (delay.est_delay != 0) {
+ int delay_idx = get_delay_idx(delay.est_delay, MAX_DELAY_COMP);
+ c16_t *delay_table = frame_parms->delay_table128[delay_idx];
+ for (int aa = 0; aa < Prx; aa++)
+ mult_complex_vectors(rp[aa][symb], delay_table, rp[aa][symb], nb_re_pucch, 8);
+ }
+
+ // extract again DMRS, and signal, after delay compensation
+ for (int aa = 0; aa < Prx; aa++) {
+ c16_t *r_ext_p = r_ext[aa][symb];
+ c16_t *rdmrs_ext_p = rdmrs_ext[aa];
+ c16_t *rp_base = rp[aa][symb];
+ for (int prb = 0; prb < pucch_pdu->prb_size; prb++) {
+ for (int idx = 0; idx < 4; idx++) {
+ *r_ext_p++ = *rp_base++;
+ *rdmrs_ext_p++ = *rp_base++;
+ *r_ext_p++ = *rp_base++;
+ }
+ }
+ if (pucch_pdu->prb_size != prb_size_ext) {
+ // if the number of PRBs is odd
+ // we fill the unsed part of the arrays
+ memset(rdmrs_ext[aa] + pucch_pdu->prb_size * 4, 0, 4 * sizeof(c16_t));
+ memset(r_ext[aa][symb] + pucch_pdu->prb_size * 8, 0, 8 * sizeof(c16_t));
+ }
+ }
+#ifdef DEBUG_NR_PUCCH_RX
+ for (int aa = 0; aa < Prx; aa++) {
+ log_dump(PHY, rdmrs_ext[aa], nb_re_dmrs, LOG_DUMP_C16, "after delay compensation ant %d dmrs:\n", aa);
+ log_dump(PHY, r_ext[aa], nb_re_data, LOG_DUMP_C16, "after delay compensation ant %d data:\n", aa);
+ }
+#endif
+ c16_t rdmrs_gold[Prx][nb_re_dmrs] __attribute__((aligned(32)));
+ for (int aa = 0; aa < Prx; aa++)
+ mult_complex_vectors(rdmrs_ext[aa], pil_dmrs, rdmrs_gold[aa], nb_re_dmrs, 0);
+ for (int aa=0;aabit_len_harq+pucch_pdu->sr_flag+pucch_pdu->bit_len_csi_part1+pucch_pdu->bit_len_csi_part2;
+ AssertFatal(nb_bit > 2 && nb_bit < 65,
+ "illegal length (%d : %d,%d,%d,%d)\n",
+ nb_bit,
+ pucch_pdu->bit_len_harq,
+ pucch_pdu->sr_flag,
+ pucch_pdu->bit_len_csi_part1,
+ pucch_pdu->bit_len_csi_part2);
+
+ uint64_t decodedPayload[nb_symbols];
+ memset(decodedPayload,0,sizeof(decodedPayload));
uint8_t corr_dB;
int decoderState = 2;
if (pucch2_levdB < gNB->measurements.n0_subband_power_avg_dB + (gNB->pucch0_thres / 10))
decoderState = 1; // assuming missed detection, only attempt to decode for polar case (with CRC)
LOG_D(NR_PHY, "n0+thres %d decoderState %d\n", gNB->measurements.n0_subband_power_avg_dB + (gNB->pucch0_thres / 10), decoderState);
+
if (nb_bit < 12 && decoderState == 2) { // short blocklength case
- simde__m256i *rp_re[Prx2][2];
- simde__m256i *rp2_re[Prx2][2];
- simde__m256i *rp_im[Prx2][2];
- simde__m256i *rp2_im[Prx2][2];
- for (int aa=0;aanr_of_symbols;symb++) {
- rp_re[aa][symb] = (simde__m256i*)r_re_ext[aa][symb];
- rp_im[aa][symb] = (simde__m256i*)r_im_ext[aa][symb];
- rp2_re[aa][symb] = (simde__m256i*)r_re_ext2[aa][symb];
- rp2_im[aa][symb] = (simde__m256i*)r_im_ext2[aa][symb];
- }
- }
- simde__m256i prod_re[Prx2],prod_im[Prx2];
uint64_t corr=0;
int cw_ML=0;
-
- for (int cw=0;cw<1<> 1],
- ((int16_t *)&pucch2_lut[nb_bit - 3][cw << 1])[1 + (i >> 1)]);
- }
- printf("\n");
-#endif
+ for (int cw = 0; cw < 1 << nb_bit; cw++) {
uint64_t corr_tmp = 0;
-
- for (int symb=0;symbnr_of_symbols;symb++) {
+ for (int symb=0;symb (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",aa,
- ((int16_t*)&prod_re[aa])[0],((int16_t*)&prod_re[aa])[1],((int16_t*)&prod_re[aa])[2],((int16_t*)&prod_re[aa])[3],
- ((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7],
- ((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11],
- ((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]);
- printf("prod_im[%d] => (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",aa,
- ((int16_t*)&prod_im[aa])[0],((int16_t*)&prod_im[aa])[1],((int16_t*)&prod_im[aa])[2],((int16_t*)&prod_im[aa])[3],
- ((int16_t*)&prod_im[aa])[4],((int16_t*)&prod_im[aa])[5],((int16_t*)&prod_im[aa])[6],((int16_t*)&prod_im[aa])[7],
- ((int16_t*)&prod_im[aa])[8],((int16_t*)&prod_im[aa])[9],((int16_t*)&prod_im[aa])[10],((int16_t*)&prod_im[aa])[11],
- ((int16_t*)&prod_im[aa])[12],((int16_t*)&prod_im[aa])[13],((int16_t*)&prod_im[aa])[14],((int16_t*)&prod_im[aa])[15]);
-
-#endif
- prod_re[aa] = simde_mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1
-#ifdef DEBUG_NR_PUCCH_RX
- printf("0.prod_re[%d] => (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",aa,
- ((int16_t*)&prod_re[aa])[0],((int16_t*)&prod_re[aa])[1],((int16_t*)&prod_re[aa])[2],((int16_t*)&prod_re[aa])[3],
- ((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7],
- ((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11],
- ((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]);
-#endif
- prod_im[aa] = simde_mm256_hadds_epi16(prod_im[aa],prod_im[aa]);
- prod_re[aa] = simde_mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3
-#ifdef DEBUG_NR_PUCCH_RX
- printf("1.prod_re[%d] => (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",aa,
- ((int16_t*)&prod_re[aa])[0],((int16_t*)&prod_re[aa])[1],((int16_t*)&prod_re[aa])[2],((int16_t*)&prod_re[aa])[3],
- ((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7],
- ((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11],
- ((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]);
-#endif
- prod_im[aa] = simde_mm256_hadds_epi16(prod_im[aa],prod_im[aa]);
- prod_re[aa] = simde_mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3+4+5+6+7
-#ifdef DEBUG_NR_PUCCH_RX
- printf("2.prod_re[%d] => (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",aa,
- ((int16_t*)&prod_re[aa])[0],((int16_t*)&prod_re[aa])[1],((int16_t*)&prod_re[aa])[2],((int16_t*)&prod_re[aa])[3],
- ((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7],
- ((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11],
- ((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]);
-#endif
- prod_im[aa] = simde_mm256_hadds_epi16(prod_im[aa],prod_im[aa]);
- }
- int64_t corr_re=0,corr_im=0;
-
-
- for (int aa=0;aa corr) {
corr = corr_tmp;
cw_ML = cw;
-#ifdef DEBUG_NR_PUCCH_RX
+#ifdef DEBUG_NR_PUCCH_RX
printf("slot %d PUCCH2 cw_ML %d, corr %lu\n", slot, cw_ML, corr);
#endif
}
} // cw loop
- corr_dB = dB_fixed64((uint64_t)corr);
+ corr_dB = dB_fixed64(corr);
#ifdef DEBUG_NR_PUCCH_RX
printf("slot %d PUCCH2 cw_ML %d, metric %d \n",slot,cw_ML,corr_dB);
#endif
decodedPayload[0]=(uint64_t)cw_ML;
- } else if (nb_bit >= 12) { // polar coded case
- simde__m64 *rp_re[Prx2][2];
- simde__m64 *rp2_re[Prx2][2];
- simde__m64 *rp_im[Prx2][2];
- simde__m64 *rp2_im[Prx2][2];
- simde__m128i llrs[pucch_pdu->prb_size*2*pucch_pdu->nr_of_symbols];
-
- for (int aa=0;aanr_of_symbols;symb++) {
- rp_re[aa][symb] = (simde__m64*)r_re_ext[aa][symb];
- rp_im[aa][symb] = (simde__m64*)r_im_ext[aa][symb];
- rp2_re[aa][symb] = (simde__m64*)r_re_ext2[aa][symb];
- rp2_im[aa][symb] = (simde__m64*)r_im_ext2[aa][symb];
- }
- }
- simde__m64 prod_re[Prx2],prod_im[Prx2];
-
-#ifdef DEBUG_NR_PUCCH_RX
- for (int cw=0;cw<16;cw++) {
-
- printf("cw %d:",cw);
- for (int i=0;i<4;i++) {
- printf("%d,", ((int16_t *)&pucch2_polar_4bit[cw])[i >> 1]);
- }
- printf("\n");
- }
-#endif
+ } else if (nb_bit >= 12) { // polar coded case
+
+ simde__m128i llrs[pucch_pdu->prb_size * 2 * nb_symbols];
// non-coherent LLR computation on groups of 4 REs (half-PRBs)
- int32_t corr_re,corr_im,corr_tmp;
- simde__m128i corr16,llr_num,llr_den;
uint64_t corr = 0;
- for (int symb=0;symbnr_of_symbols;symb++) {
+ const simde__m128i ones = simde_mm_set1_epi16(1);
+ for (int symb=0;symbprb_size);half_prb++) {
- llr_num=simde_mm_set1_epi16(0);llr_den=simde_mm_set1_epi16(0);
+ simde__m128i llr_num = simde_mm_set1_epi16(0);
+ simde__m128i llr_den = simde_mm_set1_epi16(0);
for (int cw=0;cw<256;cw++) {
- corr_tmp=0;
+ int32_t corr_tmp=0;
for (int aa=0;aa> 4], rp_im[aa][symb][half_prb])),
- 5);
- prod_im[aa] =
- simde_mm_srai_pi16(simde_mm_subs_pi16(simde_mm_mullo_pi16(pucch2_polar_4bit[cw & 15], rp2_im[aa][symb][half_prb]),
- simde_mm_mullo_pi16(pucch2_polar_4bit[cw >> 4], rp2_re[aa][symb][half_prb])),
- 5);
- prod_re[aa] = simde_mm_hadds_pi16(prod_re[aa],prod_re[aa]);// 0+1
- prod_im[aa] = simde_mm_hadds_pi16(prod_im[aa],prod_im[aa]);
- prod_re[aa] = simde_mm_hadds_pi16(prod_re[aa],prod_re[aa]);// 0+1+2+3
- prod_im[aa] = simde_mm_hadds_pi16(prod_im[aa],prod_im[aa]);
-
+ simde__m128i part1 = simde_mm_set_epi64x(0ULL, *(int64_t *)&pucch2_polar_4bit[cw & 15].cw);
+ simde__m128i part2 = simde_mm_set_epi64x(0ULL, *(int64_t *)&pucch2_polar_4bit[cw >> 4].cw);
+ simde__m128i factor = simde_mm_unpacklo_epi16(part1, part2);
+ simde__m128i re = *(simde__m128i *)&r_ext[aa][symb][half_prb * 4];
+ simde__m128i im = *(simde__m128i *)&r_ext2[aa][symb][half_prb * 4];
+ simde__m128i prod_re = simde_mm_madd_epi16(re, factor);
+ simde__m128i prod_im = simde_mm_madd_epi16(im, factor);
+ prod_re = simde_mm_hadd_epi32(prod_re, prod_re);
+ prod_im = simde_mm_hadd_epi32(prod_im, prod_im);
+ prod_re = simde_mm_hadd_epi32(prod_re, prod_re);
+ prod_im = simde_mm_hadd_epi32(prod_im, prod_im);
+ simde__m128i prod = simde_mm_srai_epi32(simde_mm_unpacklo_epi32(prod_re, prod_im), 5);
+ c64_t corr64 = (c64_t){corr32[symb][half_prb >> 2][aa].r / (2 * nc_group_size * 4 / 2),
+ corr32[symb][half_prb >> 2][aa].i / (2 * nc_group_size * 4 / 2)};
+ // _mm_srai_epi64 is missing in SIMDE package, we need to update it
+ c64_t prod2 = {simde_mm_extract_epi32(prod, 0), simde_mm_extract_epi32(prod, 1)};
+ csum(prod2, prod2, corr64);
+ corr_tmp += squaredMod(prod2) >> (Prx / 2);
// this is for UL CQI measurement
- if (cw==0) corr += ((int64_t)corr32_re[symb][half_prb>>2][aa]*corr32_re[symb][half_prb>>2][aa])+
- ((int64_t)corr32_im[symb][half_prb>>2][aa]*corr32_im[symb][half_prb>>2][aa]);
-
-
- corr_re = ( corr32_re[symb][half_prb>>2][aa]/(2*nc_group_size*4/2)+((int16_t*)(&prod_re[aa]))[0]);
- corr_im = ( corr32_im[symb][half_prb>>2][aa]/(2*nc_group_size*4/2)+((int16_t*)(&prod_im[aa]))[0]);
- corr_tmp += (corr_re*corr_re + corr_im*corr_im)>>(Prx/2);
-
- LOG_D(PHY,
- "pucch2 half_prb %d cw %d (%d,%d) aa %d: (%d,%d,%d,%d,%d,%d,%d,%d)x(%d,%d,%d,%d,%d,%d,%d,%d) (%d,%d)+(%d,%d) = "
- "(%d,%d) => %d\n",
- half_prb,
- cw,
- cw & 15,
- cw >> 4,
- aa,
- ((int16_t *)&pucch2_polar_4bit[cw & 15])[0],
- ((int16_t *)&pucch2_polar_4bit[cw >> 4])[0],
- ((int16_t *)&pucch2_polar_4bit[cw & 15])[1],
- ((int16_t *)&pucch2_polar_4bit[cw >> 4])[1],
- ((int16_t *)&pucch2_polar_4bit[cw & 15])[2],
- ((int16_t *)&pucch2_polar_4bit[cw >> 4])[2],
- ((int16_t *)&pucch2_polar_4bit[cw & 15])[3],
- ((int16_t *)&pucch2_polar_4bit[cw >> 4])[3],
- ((int16_t *)&rp_re[aa][half_prb])[0],
- ((int16_t *)&rp_im[aa][half_prb])[0],
- ((int16_t *)&rp_re[aa][half_prb])[1],
- ((int16_t *)&rp_im[aa][half_prb])[1],
- ((int16_t *)&rp_re[aa][half_prb])[2],
- ((int16_t *)&rp_im[aa][half_prb])[2],
- ((int16_t *)&rp_re[aa][half_prb])[3],
- ((int16_t *)&rp_im[aa][half_prb])[3],
- corr32_re[symb][half_prb >> 2][aa] / (2 * nc_group_size * 4 / 2),
- corr32_im[symb][half_prb >> 2][aa] / (2 * nc_group_size * 4 / 2),
- ((int16_t *)(&prod_re[aa]))[0],
- ((int16_t *)(&prod_im[aa]))[0],
- corr_re,
- corr_im,
- corr_tmp);
+ if (cw == 0)
+ corr += squaredMod(corr32[symb][half_prb >> 2][aa]);
}
- corr16 = simde_mm_set1_epi16((int16_t)(corr_tmp >> 8));
-
- LOG_D(PHY, "half_prb %d cw %d corr16 %d\n", half_prb, cw, corr_tmp >> 8);
-
+ simde__m128i corr16 = simde_mm_set1_epi16((int16_t)(corr_tmp >> 8));
+ simde__m128i den = simde_mm_xor_si128(pucch2_polar_llr_num_lut[cw], ones);
llr_num = simde_mm_max_epi16(simde_mm_mullo_epi16(corr16, pucch2_polar_llr_num_lut[cw]), llr_num);
- llr_den = simde_mm_max_epi16(simde_mm_mullo_epi16(corr16, pucch2_polar_llr_den_lut[cw]), llr_den);
-
- LOG_D(PHY,
- "lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
- ((int16_t *)&pucch2_polar_llr_num_lut[cw])[0],
- ((int16_t *)&pucch2_polar_llr_num_lut[cw])[1],
- ((int16_t *)&pucch2_polar_llr_num_lut[cw])[2],
- ((int16_t *)&pucch2_polar_llr_num_lut[cw])[3],
- ((int16_t *)&pucch2_polar_llr_num_lut[cw])[4],
- ((int16_t *)&pucch2_polar_llr_num_lut[cw])[5],
- ((int16_t *)&pucch2_polar_llr_num_lut[cw])[6],
- ((int16_t *)&pucch2_polar_llr_num_lut[cw])[7]);
-
- LOG_D(PHY,
- "llr_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
- ((int16_t *)&llr_num)[0],
- ((int16_t *)&llr_num)[1],
- ((int16_t *)&llr_num)[2],
- ((int16_t *)&llr_num)[3],
- ((int16_t *)&llr_num)[4],
- ((int16_t *)&llr_num)[5],
- ((int16_t *)&llr_num)[6],
- ((int16_t *)&llr_num)[7]);
- LOG_D(PHY,
- "llr_den (%d,%d,%d,%d,%d,%d,%d,%d)\n",
- ((int16_t *)&llr_den)[0],
- ((int16_t *)&llr_den)[1],
- ((int16_t *)&llr_den)[2],
- ((int16_t *)&llr_den)[3],
- ((int16_t *)&llr_den)[4],
- ((int16_t *)&llr_den)[5],
- ((int16_t *)&llr_den)[6],
- ((int16_t *)&llr_den)[7]);
+ llr_den = simde_mm_max_epi16(simde_mm_mullo_epi16(corr16, den), llr_den);
}
// compute llrs
- llrs[half_prb + (symb*2*pucch_pdu->prb_size)] = simde_mm_subs_epi16(llr_num,llr_den);
- LOG_D(PHY,"llrs[%d] : (%d,%d,%d,%d,%d,%d,%d,%d)\n",
- half_prb,
- ((int16_t*)&llrs[half_prb])[0],
- ((int16_t*)&llrs[half_prb])[1],
- ((int16_t*)&llrs[half_prb])[2],
- ((int16_t*)&llrs[half_prb])[3],
- ((int16_t*)&llrs[half_prb])[4],
- ((int16_t*)&llrs[half_prb])[5],
- ((int16_t*)&llrs[half_prb])[6],
- ((int16_t*)&llrs[half_prb])[7]);
+ llrs[half_prb + symb * 2 * pucch_pdu->prb_size] = simde_mm_subs_epi16(llr_num, llr_den);
+ LOG_DDUMP(PHY, llrs+half_prb + symb * 2 * pucch_pdu->prb_size, 8, LOG_DUMP_I16, "llrs:");
} // half_prb
} // symb
@@ -1636,10 +1293,12 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
// Decoder reversal
decodedPayload[0] = reverse_bits(decodedPayload[0], nb_bit);
- if (decoderState>0) decoderState=1;
+ if (decoderState > 0)
+ decoderState = 1;
corr_dB = dB_fixed64(corr);
- LOG_D(PHY,"metric %d dB\n",corr_dB);
- }
+ LOG_D(PHY, "metric %d dB\n", corr_dB);
+ } else
+ LOG_E(PHY, "PUCCH not processed: nb_bit %d decoderState %d\n", nb_bit, decoderState);
LOG_D(PHY, "UCI decoderState %d, payload[0] %llu\n", decoderState, (unsigned long long)decodedPayload[0]);
@@ -1647,42 +1306,46 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
// TODO this computation is wrong -> to be ignored at MAC for now
int cqi = 0xff;
/*int SNRtimes10 =
- dB_fixed_times10(signal_energy_nodc((int32_t *)&rxdataF[0][soffset + (l2 * frame_parms->ofdm_symbol_size) + re_offset[0]],
- 12 * pucch_pdu->prb_size))
- - (10 * gNB->measurements.n0_power_tot_dB);
- int cqi,bit_left;
- if (SNRtimes10 < -640) cqi=0;
- else if (SNRtimes10 > 635) cqi=255;
- else cqi=(640+SNRtimes10)/5;*/
+ dB_fixed_times10(signal_energy_nodc((int32_t *)&rxdataF[0][soffset + (l2 * frame_parms->ofdm_symbol_size) + re_offset[0]],
+ 12 * pucch_pdu->prb_size))
+ - (10 * gNB->measurements.n0_power_tot_dB);
+ int cqi,bit_left;
+ if (SNRtimes10 < -640) cqi=0;
+ else if (SNRtimes10 > 635) cqi=255;
+ else cqi=(640+SNRtimes10)/5;*/
uci_pdu->harq.harq_bit_len = pucch_pdu->bit_len_harq;
- uci_pdu->pduBitmap=0;
- uci_pdu->rnti=pucch_pdu->rnti;
- uci_pdu->handle=pucch_pdu->handle;
- uci_pdu->pucch_format=0;
- uci_pdu->ul_cqi=cqi;
- uci_pdu->timing_advance=0xffff; // currently not valid
- uci_pdu->rssi=1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(signal_energy_nodc(&rxdataF[0][soffset+(l2*frame_parms->ofdm_symbol_size)+re_offset[0]],12*pucch_pdu->prb_size)));
- if (pucch_pdu->bit_len_harq>0) {
- int harq_bytes=pucch_pdu->bit_len_harq>>3;
- if ((pucch_pdu->bit_len_harq&7) > 0) harq_bytes++;
- uci_pdu->pduBitmap|=2;
- uci_pdu->harq.harq_payload = (uint8_t*)malloc(harq_bytes);
+ uci_pdu->pduBitmap = 0;
+ uci_pdu->rnti = pucch_pdu->rnti;
+ uci_pdu->handle = pucch_pdu->handle;
+ uci_pdu->pucch_format = 0;
+ uci_pdu->ul_cqi = cqi;
+ uci_pdu->timing_advance = 0xffff; // currently not valid
+ uci_pdu->rssi =
+ 1280
+ - (10 * dB_fixed(32767 * 32767)
+ - dB_fixed_times10(signal_energy_nodc(&rxdataF[0][soffset + (l2 * frame_parms->ofdm_symbol_size) + re_offset[0]],
+ 12 * pucch_pdu->prb_size)));
+ if (pucch_pdu->bit_len_harq > 0) {
+ int harq_bytes = pucch_pdu->bit_len_harq >> 3;
+ if ((pucch_pdu->bit_len_harq & 7) > 0)
+ harq_bytes++;
+ uci_pdu->pduBitmap |= 2;
+ uci_pdu->harq.harq_payload = (uint8_t *)malloc(harq_bytes);
uci_pdu->harq.harq_crc = decoderState;
- LOG_D(PHY,"[DLSCH/PDSCH/PUCCH2] %d.%d HARQ bytes (%d) Decoder state %d\n",
- frame,slot,harq_bytes,decoderState);
- int i=0;
- for (;iharq.harq_payload[i] = decodedPayload[0] & 255;
LOG_D(PHY, "[DLSCH/PDSCH/PUCCH2] %d.%d HARQ payload (%d) = %d\n", frame, slot, i, uci_pdu->harq.harq_payload[i]);
- decodedPayload[0]>>=8;
+ decodedPayload[0] >>= 8;
}
int bit_left = pucch_pdu->bit_len_harq - ((harq_bytes - 1) << 3);
uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1 << bit_left) - 1);
LOG_D(PHY, "[DLSCH/PDSCH/PUCCH2] %d.%d HARQ payload (%d) = %d\n", frame, slot, i, uci_pdu->harq.harq_payload[i]);
decodedPayload[0] >>= pucch_pdu->bit_len_harq;
}
-
+
if (pucch_pdu->sr_flag == 1) {
uci_pdu->pduBitmap|=1;
uci_pdu->sr.sr_bit_len = 1;
diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h
index 64f3ef303c..f6f18eb942 100644
--- a/openair1/PHY/defs_nr_common.h
+++ b/openair1/PHY/defs_nr_common.h
@@ -217,6 +217,8 @@ struct NR_DL_FRAME_PARMS {
c16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16)));
/// Table used to apply the delay compensation in DL/UL
c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE];
+ /// Table used to apply the delay compensation in PUCCH2
+ c16_t delay_table128[2 * MAX_DELAY_COMP + 1][128];
/// SRS configuration from TS 38.331 RRC
SRS_NR srs_nr;
/// Power used by SSB in order to estimate signal strength and path loss
diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c
index c543f5a630..9aa45e20b3 100644
--- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c
+++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c
@@ -25,6 +25,8 @@
#define USE_128BIT
#endif
+#define PEAK_DETECT_THRESHOLD 15
+
int16_t saturating_sub(int16_t a, int16_t b)
{
int32_t result = (int32_t)a - (int32_t)b;
@@ -367,20 +369,28 @@ void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates
int max_val = delay->delay_max_val;
const int sync_pos = 0;
+ uint64_t mean_val = 0;
for (int i = 0; i < ofdm_symbol_size; i++) {
int temp = c16amp2(ch_estimates_time[i]) >> 1;
+ mean_val += temp;
if (temp > max_val) {
max_pos = i;
max_val = temp;
}
}
+ mean_val /= ofdm_symbol_size;
if (max_pos > ofdm_symbol_size / 2)
max_pos = max_pos - ofdm_symbol_size;
delay->delay_max_pos = max_pos;
delay->delay_max_val = max_val;
- delay->est_delay = max_pos - sync_pos;
+
+ // The peak in general is quite clear. It only gives a small peak when the noise is high, generally obtaining an incorrect
+ // estimated delay, and causing the delay compensation to worsen the result instead of improving it. After analyzing several
+ // peaks, and doing many tests, a PEAK_DETECT_THRESHOLD = 15 is an adequate value, to apply delay compensation only when there is
+ // clearly a peak
+ delay->est_delay = mean_val > 0 && max_val / mean_val > PEAK_DETECT_THRESHOLD ? max_pos - sync_pos : 0;
}
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb)
diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c
index 81d6fff9b3..ab73a13626 100644
--- a/openair1/SIMULATION/NR_PHY/pucchsim.c
+++ b/openair1/SIMULATION/NR_PHY/pucchsim.c
@@ -144,6 +144,7 @@ int main(int argc, char **argv)
int sr_flag = 0;
int pucch_DTX_thres = 0;
cpuf = get_cpu_freq_GHz();
+ bool print_perf = false;
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
exit_fun("[NR_PUCCHSIM] Error, configuration module init failed\n");
@@ -153,8 +154,7 @@ int main(int argc, char **argv)
logInit();
int c;
- while ((c = getopt (argc, argv, "--:O:f:hA:f:g:i:I:P:B:b:t:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:cd:")) != -1) {
-
+ while ((c = getopt(argc, argv, "--:O:f:hA:f:g:i:I:P:B:b:t:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:cd:C")) != -1) {
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
if (c == 1 || c == '-' || c == 'O')
@@ -349,6 +349,10 @@ int main(int argc, char **argv)
//nacktoack_flag=(uint8_t)atoi(optarg);
target_error_rate=0.001;
break;
+ case 'C':
+ print_perf = 1;
+ cpu_meas_enabled = 1;
+ break;
default:
case 'h':
printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", argv[0]);
@@ -381,6 +385,7 @@ int main(int argc, char **argv)
printf("-x Transmission mode (1,2,6 for the moment)\n");
printf("-y Number of TX antennas used in eNB\n");
printf("-z Number of RX antennas used in UE\n");
+ printf("-C print CPU cost\n");
exit (-1);
break;
}
@@ -406,8 +411,8 @@ int main(int argc, char **argv)
if ((format < 2) && (actual_payload == 4)) do_DTX=1;
if (random_payload) {
- srand(time(NULL)); // Initialization, should only be called once.
- actual_payload = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX.
+ double tmp = uniformrandom();
+ memcpy(&actual_payload, &tmp, sizeof(actual_payload));
}
actual_payload &= nr_bit < 64 ? (1UL << nr_bit) - 1: 0xffffffffffffffff;
@@ -638,6 +643,7 @@ int main(int argc, char **argv)
// noise measurement (all PRBs)
gNB_I0_measurements(gNB, nr_slot_tx, 0, gNB->frame_parms.symbols_per_slot, rb_mask_ul);
+ start_meas(&gNB->phy_proc_rx);
if (n_trials==1) printf("noise rxlev %d (%d dB), rxlev pucch %d dB sigma2 %f dB, SNR %f, TX %f, I0 (pucch) %d, I0 (avg) %d\n",rxlev,dB_fixed(rxlev),dB_fixed(rxlev_pucch),sigma2_dB,SNR,10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/12),gNB->measurements.n0_subband_power_tot_dB[startingPRB],gNB->measurements.n0_subband_power_avg_dB);
if(format==0){
@@ -731,10 +737,21 @@ int main(int argc, char **argv)
free(uci_pdu.csi_part1.csi_part1_payload);
}
+ stop_meas(&gNB->phy_proc_rx);
+
n_errors=((actual_payload^payload_received)&1)+(((actual_payload^payload_received)&2)>>1)+(((actual_payload^payload_received)&4)>>2)+n_errors;
}
if (sr_flag == 1)
printf("SR: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,sr_errors);
+ if (print_perf) {
+ time_stats_t *ts = &gNB->phy_proc_rx;
+ printf("cpu time for pucch format %d: per block %.2f us; nb blocks %d, max time %.2f;\n",
+ format,
+ ts->diff / ts->trials / cpuf / 1000.0,
+ ts->trials,
+ ts->max / cpuf / 1000.0);
+ reset_meas(ts);
+ }
if(nr_bit > 0)
printf("ACK/NACK: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors);
if((float)(ack_nack_errors+sr_errors)/(float)(n_trials)<=target_error_rate){