From f3daf0ed833f950c8b766290da79f271029e1495 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 5 Mar 2025 09:32:32 +0000 Subject: [PATCH] fix(nrLDPC_coding): Miscellaneous fixes 1. nrLDPC_coding_segment_encoder: pointer not aligned on 64 bits An undefined behavior was happening because of a shift on a __m64 which was actually a uint32_t which was not aligned on 64 bits. This commit suggests a fix by properly loading into a __m64 with _mm_set_pi32 before performing the shift. 2. nr_rate_matching: Filler bits detection Previously, if the bit selection was reaching Ncb and restarting selection from the beginning of encoded data, the filler bits were detected by testing the bytes again NR_NULL which was equal to 2. But on this branch the bits of up to 8 segments are stored in one byte while doing rate matching so that one byte could be tested to be a filler while it is not. So this commit changes the way to test filler bits. Instead of relying on NR_NULL, bit selection now relies on the offset and size of filler bits. 3. nr_ulsch_coding: missing filling f with zeros The array `f` of the UE UL HARQ process was not filled with zeros between transmissions. This is a problem if the encoder does not properly overwrite its output. In order to avoid such situation, this commit adds a memset to fill `f` with zeros before passing it to the encoder. 4. nrLDPC_coding_segment_encoder: missing init of f to zeros In the encoder, `f` is not filled with zeros before being used. `f` is instead somehow filled with arbitrary values. When writing to `output` by 64 bit vectors, some arbitrary bits may be added after the segment. Then the arbitrary added ones are not overwritten when writing the next segment because of writing with a logical or. This commit properly fills `f` and `f2` with zeros. 5. nr_ulschsim & nr_dlschsim: Adapt modulation to new encoder output The QPSK symbols that are feed to the channel model of nr_dlschsim were determined based on the bytes of the encoder output. With the new output of the encoder, it had to be reworked to determine the QPSK symbols based on the bits of the encoder output. --- .../nrLDPC_coding_segment_encoder.c | 50 +++++++++---------- .../nrLDPC_coding_segment/nr_rate_matching.c | 7 ++- .../nrLDPC_coding_segment/nr_rate_matching.h | 2 - .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 4 ++ openair1/SIMULATION/NR_PHY/dlschsim.c | 6 +-- openair1/SIMULATION/NR_PHY/ulschsim.c | 2 +- 6 files changed, 38 insertions(+), 33 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c index c962074560..da4502d657 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c @@ -80,12 +80,6 @@ static void ldpc8blocks(void *p) stop_meas(&nrLDPC_TB_encoding_parameters->segments[impp->macro_num * 8].ts_ldpc_encode); // Compute where to place in output buffer that is concatenation of all segments - - if (impp->F>0) { - // writing into positions d[k-2Zc] as in clause 5.3.2 step 2) in 38.212 - memset(&d[impp->K - impp->F - 2 * impp->Zc], NR_NULL, impp->F); - } - #ifdef DEBUG_LDPC_ENCODING LOG_D(PHY, "rvidx in encoding = %d\n", nrLDPC_TB_encoding_parameters->rv_index); #endif @@ -135,7 +129,11 @@ static void ldpc8blocks(void *p) uint8_t e2[E2] __attribute__((aligned(64))); uint8_t f2[E2+64] __attribute__((aligned(64))); bzero(e, E); - if (Eshift) bzero(e2,E2); + bzero(f, E + 64); + if (Eshift) { + bzero(e2, E2); + bzero(f2, E2 + 64); + } start_meas(&nrLDPC_TB_encoding_parameters->segments[macro_segment].ts_rate_match); nr_rate_matching_ldpc(Tbslbrm, impp->BG, @@ -460,32 +458,34 @@ static void ldpc8blocks(void *p) Eoffset2_bit[n] = Eoffset&31; //printf("E2 %d (macro_segment_end %d, macro_segment %d) : n %d, Eoffset %d, Eoffset2 %d, Eoffset2_bit %d\n",E2,macro_segment_end,macro_segment,n,Eoffset,Eoffset2[n],Eoffset2_bit[n]); } - int i2=0; + int i2 = 0; int tmp; - __m64 tmp64,tmp64b,tmp64c; + __m64 tmp64, tmp64b, tmp64c, out64; - for (i=0;i>/<< because when the Eoffset2_bit is 64 or 0, the << // and >> operations are undefined and in fact don't give "0" which is // what we want here. The SIMD version do give 0 when the shift is 64 - tmp = _mm256_movemask_epi8(_mm256_slli_epi16(((__m256i *)f)[i2],7-j)); - tmp64=_mm_set1_pi32(tmp); - tmp64b = _mm_or_si64(*(__m64*)(output_p + Eoffset2[j]),_mm_slli_pi32(tmp64,Eoffset2_bit[j])); - tmp64c = _mm_or_si64(*(__m64*)(output_p + Eoffset2[j]),_mm_srli_pi32(tmp64,(32-Eoffset2_bit[j]))); - *(output_p + Eoffset2[j]) = _m_to_int(tmp64b); - *(output_p + Eoffset2[j]+1) = _m_to_int(_mm_srli_si64(tmp64c,32)); + tmp = _mm256_movemask_epi8(_mm256_slli_epi16(((__m256i *)f)[i2], 7 - j)); + tmp64 = _mm_set1_pi32(tmp); + out64 = _mm_set_pi32(*(output_p + Eoffset2[j] + 1), *(output_p + Eoffset2[j])); + tmp64b = _mm_or_si64(out64, _mm_slli_pi32(tmp64, Eoffset2_bit[j])); + tmp64c = _mm_or_si64(out64, _mm_srli_pi32(tmp64, (32 - Eoffset2_bit[j]))); + *(output_p + Eoffset2[j]) = _m_to_int(tmp64b); + *(output_p + Eoffset2[j] + 1) = _m_to_int(_mm_srli_si64(tmp64c, 32)); } } - for (int j=E2_first_segment; j < macro_segment_end-macro_segment; j++) { - tmp = _mm256_movemask_epi8(_mm256_slli_epi16(((__m256i *)f2)[i2],7-j)); - tmp64=_mm_set1_pi32(tmp); - tmp64b = _mm_or_si64(*(__m64*)(output_p + Eoffset2[j]),_mm_slli_pi32(tmp64,Eoffset2_bit[j])); - tmp64c = _mm_or_si64(*(__m64*)(output_p + Eoffset2[j]),_mm_srli_pi32(tmp64,(32-Eoffset2_bit[j]))); - *(output_p + Eoffset2[j]) = _m_to_int(tmp64b); - *(output_p + Eoffset2[j]+1) = _m_to_int(_mm_srli_si64(tmp64c,32)); + for (int j = E2_first_segment; j < macro_segment_end - macro_segment; j++) { + tmp = _mm256_movemask_epi8(_mm256_slli_epi16(((__m256i *)f2)[i2], 7 - j)); + tmp64 = _mm_set1_pi32(tmp); + out64 = _mm_set_pi32(*(output_p + Eoffset2[j] + 1), *(output_p + Eoffset2[j])); + tmp64b = _mm_or_si64(out64, _mm_slli_pi32(tmp64, Eoffset2_bit[j])); + tmp64c = _mm_or_si64(out64, _mm_srli_pi32(tmp64, (32 - Eoffset2_bit[j]))); + *(output_p + Eoffset2[j]) = _m_to_int(tmp64b); + *(output_p + Eoffset2[j] + 1) = _m_to_int(_mm_srli_si64(tmp64c, 32)); } output_p++; } diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.c index 8f111b5308..4e5a31f31f 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.c @@ -626,8 +626,11 @@ int nr_rate_matching_ldpc(uint32_t Tbslbrm, printf("RM_TX k%u Ind: %u (%d)\n", k, ind, d[ind]); #endif - if (d[ind] != NR_NULL) - e[k++] = d[ind]; + if (ind == Foffset) + ind = F + Foffset; // skip filler bits + + e[k++] = d[ind]; + } } diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.h b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.h index ac6a496801..597a53070a 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.h +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.h @@ -24,8 +24,6 @@ #include -#define NR_NULL 2 - /** * \brief interleave a code segment after encoding and rate matching * \param E size of the code segment in bits diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index bed86bf852..dcf18ceff5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -156,6 +156,10 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid]; TB_parameters->segments = segments[pusch_id]; + const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch->pusch_pdu; + uint16_t nb_rb = pusch_pdu->rb_size; + memset(harq_process->f, 0, 14 * nb_rb * 12 * 16); + int r_offset = 0; for (int r = 0; r < TB_parameters->C; r++) { nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index f7b10e5fb1..c475bfc039 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -512,8 +512,8 @@ int main(int argc, char **argv) //printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32)); // generate signal - unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS] __attribute__((aligned(64))); - bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * NR_MAX_NB_LAYERS] __attribute__((aligned(64))); + bzero(output, sizeof(output)); if (input_fd == NULL) { msgDataTx.num_pdsch_slot = 1; nr_dlsch_encoding(gNB, &msgDataTx, frame, slot, frame_parms, output, NULL, NULL, NULL, NULL, NULL, NULL, NULL); @@ -533,7 +533,7 @@ int main(int argc, char **argv) //if (i<16) // printf("encoder output f[%d] = %d\n",i,dlsch->harq_processes[0]->f[i]); - if ((output[i]&1) == 0) + if ((output[i >> 3] & (1 << (i & 7))) == 0) modulated_input[i] = 1.0; ///sqrt(2); //QPSK else modulated_input[i] = -1.0; ///sqrt(2); diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index f68f6885a6..ef6fd34ee4 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -542,7 +542,7 @@ int main(int argc, char **argv) } */ - if (harq_process_ul_ue->f[i] == 0) + if ((harq_process_ul_ue->f[i >> 3] & (1 << (i & 7))) == 0) modulated_input[i] = 1.0; ///sqrt(2); //QPSK else modulated_input[i] = -1.0; ///sqrt(2);