Commit f3daf0ed authored by Romain Beurdouche's avatar Romain Beurdouche

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.
parent bbbbda70
......@@ -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<E2;i+=32,i2++) {
if (i<E) {
for (int j=0; j < E2_first_segment; j++) {
for (i=0; i < E2; i += 32, i2++) {
if (i < E) {
for (int j = 0; j < E2_first_segment; j++) {
// Note: Here and below, we are using the 64-bit SIMD instruction
// instead of C >>/<< 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++;
}
......
......@@ -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];
}
}
......
......@@ -24,8 +24,6 @@
#include <stdint.h>
#define NR_NULL 2
/**
* \brief interleave a code segment after encoding and rate matching
* \param E size of the code segment in bits
......
......@@ -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];
......
......@@ -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);
......
......@@ -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);
......
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