Commit 02e329a3 authored by Ahmed Hussein's avatar Ahmed Hussein Committed by Thomas Schlichter
Browse files

SC-FDMA working for 1 SNR loop (enabled using "NR_SC_FDMA" MACRO)

- Added nr_dft at UE side and nr_idft at gNB side
- NR_SC_FDMA can be found in "PHY/defs_nr_common.h"
- For 1 SNR loop, the code executes correctly
- For more loops, it gives a segmentation fault in the LDPC decoder
- The segmentation fault is caused when nr_idft is used
- The code works fine when the "NR_SC_FDMA" is disabled
parent d34868e6
......@@ -119,4 +119,183 @@ void nr_layer_mapping(int16_t **mod_symbs,
default:
AssertFatal(0, "Invalid number of layers %d\n", n_layers);
}
}
\ No newline at end of file
}
void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH)
{
#if defined(__x86_64__) || defined(__i386__)
__m128i dft_in128[1][1200], dft_out128[1][1200];
#elif defined(__arm__)
int16x8_t dft_in128[1][1200], dft_out128[1][1200];
#endif
uint32_t *dft_in0 = (uint32_t*)dft_in128[0], *dft_out0 = (uint32_t*)dft_out128[0];
uint32_t i, ip;
#if defined(__x86_64__) || defined(__i386__)
__m128i norm128;
#elif defined(__arm__)
int16x8_t norm128;
#endif
for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) {
dft_in0[ip] = d[i];
}
switch (Msc_PUSCH) {
case 12:
dft12((int16_t *)dft_in0, (int16_t *)dft_out0);
#if defined(__x86_64__) || defined(__i386__)
norm128 = _mm_set1_epi16(9459);
#elif defined(__arm__)
norm128 = vdupq_n_s16(9459);
#endif
for (i=0; i<12; i++) {
#if defined(__x86_64__) || defined(__i386__)
((__m128i*)dft_out0)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)dft_out0)[i], norm128), 1);
#elif defined(__arm__)
((int16x8_t*)dft_out0)[i] = vqdmulhq_s16(((int16x8_t*)dft_out0)[i], norm128);
#endif
}
break;
case 24:
dft24((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 36:
dft36((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 48:
dft48((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 60:
dft60((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 72:
dft72((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 96:
dft96((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 108:
dft108((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 120:
dft120((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 144:
dft144((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 180:
dft180((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 192:
dft192((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 216:
dft216((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 240:
dft240((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 288:
dft288((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 300:
dft300((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 324:
dft324((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 360:
dft360((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 384:
dft384((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 432:
dft432((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 480:
dft480((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 540:
dft540((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 576:
dft576((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 600:
dft600((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 648:
dft648((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 720:
dft720((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 768:
dft768((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 864:
dft864((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 900:
dft900((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 960:
dft960((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 972:
dft972((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 1080:
dft1080((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 1152:
dft1152((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
case 1200:
dft1200((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
break;
}
for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) {
z[i] = dft_out0[ip];
}
}
......@@ -68,4 +68,12 @@ int nr_slot_fep_ul(PHY_VARS_gNB *phy_vars_gNB,
int sample_offset,
int no_prefix);
/*!
\brief This function implements the dft transform precoding in PUSCH
\param z Pointer to output in frequnecy domain
\param d Pointer to input in time domain
\param Msc_PUSCH number of allocated data subcarriers
*/
void nr_dft(int32_t *z,int32_t *d, uint32_t Msc_PUSCH);
#endif
\ No newline at end of file
......@@ -73,6 +73,12 @@ void nr_ulsch_extract_rbs_single(int **rxdataF,
unsigned short nb_rb_pusch,
NR_DL_FRAME_PARMS *frame_parms);
/*!
\brief This function implements the idft transform precoding in PUSCH
\param z Pointer to input in frequnecy domain, and it is also the output in time domain
\param Msc_PUSCH number of allocated data subcarriers
*/
void nr_idft(uint32_t *z, uint32_t Msc_PUSCH);
/** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms.
@param rxdataF_comp Compensated channel output
......
......@@ -2,7 +2,219 @@
#include "nr_transport_proto.h"
#include "PHY/impl_defs_top.h"
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
#include "PHY/defs_nr_common.h"
short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1};
void nr_idft(uint32_t *z, uint32_t Msc_PUSCH)
{
#if defined(__x86_64__) || defined(__i386__)
__m128i idft_in128[1][1200], idft_out128[1][1200];
__m128i norm128;
#elif defined(__arm__)
int16x8_t idft_in128[1][1200], idft_out128[1][1200];
int16x8_t norm128;
#endif
int16_t *idft_in0 = (int16_t*)idft_in128[0], *idft_out0 = (int16_t*)idft_out128[0];
int i, ip;
LOG_T(PHY,"Doing lte_idft for Msc_PUSCH %d\n",Msc_PUSCH);
// conjugate input
for (i = 0; i < (Msc_PUSCH>>2); i++) {
#if defined(__x86_64__)||defined(__i386__)
*&(((__m128i*)z)[i]) = _mm_sign_epi16(*&(((__m128i*)z)[i]), *(__m128i*)&conjugate2[0]);
#elif defined(__arm__)
*&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]);
#endif
}
for (i=0,ip=0; i<Msc_PUSCH; i++, ip+=4) {
((uint32_t*)idft_in0)[ip+0] = z[i];
}
switch (Msc_PUSCH) {
case 12:
dft12((int16_t *)idft_in0, (int16_t *)idft_out0);
#if defined(__x86_64__)||defined(__i386__)
norm128 = _mm_set1_epi16(9459);
#elif defined(__arm__)
norm128 = vdupq_n_s16(9459);
#endif
for (i = 0; i < 12; i++) {
#if defined(__x86_64__)||defined(__i386__)
((__m128i*)idft_out0)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)idft_out0)[i], norm128), 1);
#elif defined(__arm__)
((int16x8_t*)idft_out0)[i] = vqdmulhq_s16(((int16x8_t*)idft_out0)[i], norm128);
#endif
}
break;
case 24:
dft24(idft_in0, idft_out0, 1);
break;
case 36:
dft36(idft_in0, idft_out0, 1);
break;
case 48:
dft48(idft_in0, idft_out0, 1);
break;
case 60:
dft60(idft_in0, idft_out0, 1);
break;
case 72:
dft72(idft_in0, idft_out0, 1);
break;
case 96:
dft96(idft_in0, idft_out0, 1);
break;
case 108:
dft108(idft_in0, idft_out0, 1);
break;
case 120:
dft120(idft_in0, idft_out0, 1);
break;
case 144:
dft144(idft_in0, idft_out0, 1);
break;
case 180:
dft180(idft_in0, idft_out0, 1);
break;
case 192:
dft192(idft_in0, idft_out0, 1);
break;
case 216:
dft216(idft_in0, idft_out0, 1);
break;
case 240:
dft240(idft_in0, idft_out0, 1);
break;
case 288:
dft288(idft_in0, idft_out0, 1);
break;
case 300:
dft300(idft_in0, idft_out0, 1);
break;
case 324:
dft324((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 360:
dft360((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 384:
dft384((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 432:
dft432((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 480:
dft480((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 540:
dft540((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 576:
dft576((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 600:
dft600((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 648:
dft648((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 720:
dft720((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 768:
dft768((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 864:
dft864((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 900:
dft900((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 960:
dft960((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 972:
dft972((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 1080:
dft1080((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 1152:
dft1152((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
break;
case 1200:
dft1200(idft_in0, idft_out0, 1);
break;
default:
// should not be reached
LOG_E( PHY, "Unsupported Msc_PUSCH value of %"PRIu16"\n", Msc_PUSCH );
return;
}
for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) {
z[i] = ((uint32_t*)idft_out0)[ip];
}
// conjugate output
for (i = 0; i < (Msc_PUSCH>>2); i++) {
#if defined(__x86_64__) || defined(__i386__)
((__m128i*)z)[i] = _mm_sign_epi16(((__m128i*)z)[i], *(__m128i*)&conjugate2[0]);
#elif defined(__arm__)
*&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]);
#endif
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty();
_m_empty();
#endif
}
void nr_ulsch_extract_rbs_single(int **rxdataF,
int **rxdataF_ext,
......@@ -51,18 +263,18 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
unsigned char symbol,
unsigned char harq_pid)
{
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
nfapi_nr_ul_config_ulsch_pdu_rel15_t *rel15_ul = &gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->ulsch_pdu.ulsch_pdu_rel15;
uint32_t nb_re;
uint32_t nb_re_pusch;
if(symbol == rel15_ul->start_symbol)
gNB->pusch_vars[UE_id]->rxdataF_ext_offset = 0;
if (symbol == 2) // [hna] here it is assumed that symbol 2 carries 6 DMRS REs (dmrs-type 1)
nb_re = rel15_ul->number_rbs * 6;
nb_re_pusch = rel15_ul->number_rbs * 6;
else
nb_re = rel15_ul->number_rbs * 12;
nb_re_pusch = rel15_ul->number_rbs * NR_NB_SC_PER_RB;
//----------------------------------------------------------
//--------------------- RBs extraction ---------------------
......@@ -76,8 +288,11 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
rel15_ul->start_rb,
rel15_ul->number_rbs,
frame_parms);
#ifdef NR_SC_FDMA
nr_idft(&((uint32_t*)gNB->pusch_vars[UE_id]->rxdataF_ext[0])[gNB->pusch_vars[UE_id]->rxdataF_ext_offset], nb_re_pusch);
#endif
//----------------------------------------------------------
//-------------------- LLRs computation --------------------
//----------------------------------------------------------
......@@ -86,10 +301,10 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
gNB->pusch_vars[UE_id]->ul_ch_mag,
gNB->pusch_vars[UE_id]->ul_ch_magb,
&gNB->pusch_vars[UE_id]->llr[gNB->pusch_vars[UE_id]->rxdataF_ext_offset * rel15_ul->Qm],
nb_re,
nb_re_pusch,
symbol,
rel15_ul->Qm);
gNB->pusch_vars[UE_id]->rxdataF_ext_offset = gNB->pusch_vars[UE_id]->rxdataF_ext_offset + nb_re;
gNB->pusch_vars[UE_id]->rxdataF_ext_offset = gNB->pusch_vars[UE_id]->rxdataF_ext_offset + nb_re_pusch;
}
\ No newline at end of file
......@@ -1082,10 +1082,6 @@ void nr_pusch_codeword_scrambling(uint8_t *in,
uint32_t n_RNTI,
uint32_t* out);
void pusch_transform_precoding(NR_UE_ULSCH_t *ulsch,
NR_DL_FRAME_PARMS *frame_parms,
int harq_pid);
/** \brief Perform the following functionalities:
- encoding
- scrambling
......
......@@ -204,7 +204,7 @@ typedef struct {
/// Modulated "d"-sequences (for definition see 36-211 V8.6 2009-03, p.14)
uint32_t d_mod[MAX_NUM_NR_RE] __attribute__ ((aligned(16)));
/// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4)
uint32_t y[MAX_NUM_NR_RE];
uint32_t y[MAX_NUM_NR_RE] __attribute__ ((aligned(16)));
/*
/// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27)
uint8_t q[MAX_CQI_PAYLOAD];
......
......@@ -41,11 +41,6 @@
//#define DEBUG_SCFDMA
#ifdef DEBUG_SCFDMA
FILE *debug_scfdma;
#endif
int generate_ue_ulsch_params(PHY_VARS_NR_UE *UE,
uint8_t thread_id,
......@@ -152,105 +147,6 @@ void nr_pusch_codeword_scrambling(uint8_t *in,
}
void pusch_transform_precoding(NR_UE_ULSCH_t *ulsch, NR_DL_FRAME_PARMS *frame_parms, int harq_pid){
NR_UL_UE_HARQ_t *harq_process;
int x[8192]__attribute__ ((aligned (32))); // 8192 is the maximum number of fft bins
uint32_t *dmod;
int sc, pusch_symb, pusch_sc;
int symb, k, l, num_mod_symb;
harq_process = ulsch->harq_processes[harq_pid];
#ifdef DEBUG_SCFDMA
debug_scfdma = fopen("debug_scfdma.txt","w");
#endif
dmod = ulsch->d_mod;
pusch_symb = ulsch->Nsymb_pusch;
pusch_sc = ulsch->Nsc_pusch;
num_mod_symb = harq_process->num_of_mod_symbols;
void (*dft)(int16_t *,int16_t *, int);
switch (frame_parms->ofdm_symbol_size) {
case 128:
dft = dft128;
break;
case 256:
dft = dft256;
break;
case 512:
dft = dft512;
break;
case 1024:
dft = dft1024;
break;
case 1536:
dft = dft1536;
break;
case 2048:
dft = dft2048;
break;
case 4096:
dft = dft4096;
break;
case 8192:
dft = dft8192;
break;
default:
dft = dft512;
break;
}
k = 0;
symb = 0;
for(l = 0; l < pusch_symb; l++){
for (sc = 0; sc < pusch_sc; sc++){
((int16_t *)x)[sc*2] = (symb<num_mod_symb)?(AMP*((int16_t *)dmod)[symb*2])>>15:0;
((int16_t *)x)[sc*2 + 1] = (symb<num_mod_symb)?(AMP*((int16_t *)dmod)[symb*2 + 1])>>15:0;
#ifdef DEBUG_SCFDMA
fprintf(debug_scfdma, "x[%d] = %d\n", symb*2, ((int16_t *)x)[sc*2] );
fprintf(debug_scfdma, "x[%d] = %d\n", symb*2 + 1, ((int16_t *)x)[sc*2 + 1] );
#endif
symb++;