Commit 3bd7cd2d authored by laurent's avatar laurent

initial

parent 91dd7ed4
...@@ -1825,6 +1825,7 @@ add_definitions(-DASN1_MINIMUM_VERSION=924) ...@@ -1825,6 +1825,7 @@ add_definitions(-DASN1_MINIMUM_VERSION=924)
# lte-softmodem is both eNB and UE implementation # lte-softmodem is both eNB and UE implementation
################################################### ###################################################
include_directories (${OPENAIR_TARGETS}/tcri)
add_executable(lte-softmodem add_executable(lte-softmodem
${rrc_h} ${rrc_h}
${s1ap_h} ${s1ap_h}
...@@ -1849,6 +1850,7 @@ add_executable(lte-softmodem ...@@ -1849,6 +1850,7 @@ add_executable(lte-softmodem
${T_SOURCE} ${T_SOURCE}
${CONFIG_SOURCES} ${CONFIG_SOURCES}
${SHLIB_LOADER_SOURCES} ${SHLIB_LOADER_SOURCES}
${OPENAIR_TARGETS}/tcri/thread-pool.c
) )
target_link_libraries (lte-softmodem target_link_libraries (lte-softmodem
...@@ -2323,3 +2325,10 @@ ADD_CUSTOM_TARGET(oarf ...@@ -2323,3 +2325,10 @@ ADD_CUSTOM_TARGET(oarf
DEPENDS ${OCT_FILES} DEPENDS ${OCT_FILES}
) )
add_executable(test_tcri
${OPENAIR_TARGETS}/tcri/thread-pool.c
${CONFIG_SOURCES}
${SHLIB_LOADER_SOURCES}
)
target_compile_definitions(test_tcri PRIVATE TESTMAIN)
target_link_libraries(test_tcri pthread PHY UTIL ${ITTI_LIB} LFDS config rt dl)
...@@ -463,7 +463,21 @@ int32_t rate_matching_lte(uint32_t N_coded, ...@@ -463,7 +463,21 @@ int32_t rate_matching_lte(uint32_t N_coded,
uint8_t *inPtr, uint8_t *inPtr,
uint32_t off); uint32_t off);
typedef uint8_t (turboDecoder)(int16_t *y,
uint8_t *,
uint16_t,
uint16_t,
uint16_t,
uint8_t,
uint8_t,
uint8_t,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *);
/*! /*!
\brief This routine performs max-logmap detection for the 3GPP turbo code (with termination). It is optimized for SIMD processing and 16-bit \brief This routine performs max-logmap detection for the 3GPP turbo code (with termination). It is optimized for SIMD processing and 16-bit
LLR arithmetic, and requires SSE2,SSSE3 and SSE4.1 (gcc >=4.3 and appropriate CPU) LLR arithmetic, and requires SSE2,SSSE3 and SSE4.1 (gcc >=4.3 and appropriate CPU)
...@@ -477,21 +491,7 @@ LLR arithmetic, and requires SSE2,SSSE3 and SSE4.1 (gcc >=4.3 and appropriate CP ...@@ -477,21 +491,7 @@ LLR arithmetic, and requires SSE2,SSSE3 and SSE4.1 (gcc >=4.3 and appropriate CP
@param F Number of filler bits at start of packet @param F Number of filler bits at start of packet
@returns number of iterations used (this is 1+max if incorrect crc or if crc_len=0) @returns number of iterations used (this is 1+max if incorrect crc or if crc_len=0)
*/ */
uint8_t phy_threegpplte_turbo_decoder16(int16_t *y, turboDecoder phy_threegpplte_turbo_decoder16;
uint8_t *decoded_bytes,
uint16_t n,
uint16_t interleaver_f1,
uint16_t interleaver_f2,
uint8_t max_iterations,
uint8_t crc_type,
uint8_t F,
time_stats_t *init_stats,
time_stats_t *alpha_stats,
time_stats_t *beta_stats,
time_stats_t *gamma_stats,
time_stats_t *ext_stats,
time_stats_t *intl1_stats,
time_stats_t *intl2_stats);
uint8_t phy_threegpplte_turbo_decoder16avx2(int16_t *y, uint8_t phy_threegpplte_turbo_decoder16avx2(int16_t *y,
int16_t *y2, int16_t *y2,
...@@ -524,21 +524,7 @@ LLR arithmetic, and requires SSE2,SSSE3 and SSE4.1 (gcc >=4.3 and appropriate CP ...@@ -524,21 +524,7 @@ LLR arithmetic, and requires SSE2,SSSE3 and SSE4.1 (gcc >=4.3 and appropriate CP
@param F Number of filler bits at start of packet @param F Number of filler bits at start of packet
@returns number of iterations used (this is 1+max if incorrect crc or if crc_len=0) @returns number of iterations used (this is 1+max if incorrect crc or if crc_len=0)
*/ */
uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, turboDecoder phy_threegpplte_turbo_decoder8;
uint8_t *decoded_bytes,
uint16_t n,
uint16_t interleaver_f1,
uint16_t interleaver_f2,
uint8_t max_iterations,
uint8_t crc_type,
uint8_t F,
time_stats_t *init_stats,
time_stats_t *alpha_stats,
time_stats_t *beta_stats,
time_stats_t *gamma_stats,
time_stats_t *ext_stats,
time_stats_t *intl1_stats,
time_stats_t *intl2_stats);
uint8_t phy_threegpplte_turbo_decoder_scalar(int16_t *y, uint8_t phy_threegpplte_turbo_decoder_scalar(int16_t *y,
uint8_t *decoded_bytes, uint8_t *decoded_bytes,
......
...@@ -155,7 +155,7 @@ typedef struct { ...@@ -155,7 +155,7 @@ typedef struct {
/// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
uint8_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); uint8_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32)));
/// Turbo-code outputs (36-212 V8.6 2009-03, p.12 /// Turbo-code outputs (36-212 V8.6 2009-03, p.12
uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))]; //uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))];
/// Sub-block interleaver outputs (36-212 V8.6 2009-03, p.16-17) /// Sub-block interleaver outputs (36-212 V8.6 2009-03, p.16-17)
uint8_t w[MAX_NUM_DLSCH_SEGMENTS][3*6144]; uint8_t w[MAX_NUM_DLSCH_SEGMENTS][3*6144];
/// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9) /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9)
...@@ -461,7 +461,7 @@ typedef struct { ...@@ -461,7 +461,7 @@ typedef struct {
/// Pointer to the payload /// Pointer to the payload
uint8_t *b; uint8_t *b;
/// Pointers to transport block segments /// Pointers to transport block segments
uint8_t *c[MAX_NUM_ULSCH_SEGMENTS]; //uint8_t *c[MAX_NUM_ULSCH_SEGMENTS];
/// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15) /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15)
uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS]; uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS];
/// Current Number of Symbols /// Current Number of Symbols
...@@ -477,9 +477,12 @@ typedef struct { ...@@ -477,9 +477,12 @@ typedef struct {
/// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) /// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
int16_t w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; int16_t w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)];
/// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
int16_t *d[MAX_NUM_ULSCH_SEGMENTS]; //int16_t *d[MAX_NUM_ULSCH_SEGMENTS];
/// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9) /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9)
uint32_t C; uint32_t C;
uint32_t processedSegments;
uint32_t processedBadSegment;
/// Number of "small" code segments (for definition see 36-212 V8.6 2009-03, p.10) /// Number of "small" code segments (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t Cminus; uint32_t Cminus;
/// Number of "large" code segments (for definition see 36-212 V8.6 2009-03, p.10) /// Number of "large" code segments (for definition see 36-212 V8.6 2009-03, p.10)
......
...@@ -95,20 +95,15 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) ...@@ -95,20 +95,15 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch)
if (dlsch->harq_processes[i]->c[r]) { if (dlsch->harq_processes[i]->c[r]) {
free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768); free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768);
dlsch->harq_processes[i]->c[r] = NULL; dlsch->harq_processes[i]->c[r] = NULL;
} }
if (dlsch->harq_processes[i]->d[r]) { }
free16(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144))); free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t));
dlsch->harq_processes[i]->d[r] = NULL; dlsch->harq_processes[i] = NULL;
} }
}
}
free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t));
dlsch->harq_processes[i] = NULL;
}
}
free16(dlsch,sizeof(LTE_eNB_DLSCH_t)); free16(dlsch,sizeof(LTE_eNB_DLSCH_t));
dlsch = NULL; dlsch = NULL;
} }
} }
...@@ -116,9 +111,9 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) ...@@ -116,9 +111,9 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch)
LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms) LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms)
{ {
LTE_eNB_DLSCH_t *dlsch; LTE_eNB_DLSCH_t *dlsch;
unsigned char exit_flag = 0,i,j,r,aa,layer; unsigned char exit_flag = 0,i,r,aa,layer;
int re; int re;
unsigned char bw_scaling =1; unsigned char bw_scaling =1;
switch (N_RB_DL) { switch (N_RB_DL) {
...@@ -191,39 +186,24 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ ...@@ -191,39 +186,24 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_
for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) { for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) {
// account for filler in first segment and CRCs for multiple segment case // account for filler in first segment and CRCs for multiple segment case
dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+ 768); dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+ 768);
dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16((96+12+3+(3*6144))); if (dlsch->harq_processes[i]->c[r]) {
if (dlsch->harq_processes[i]->c[r]) { bzero(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+ 768);
bzero(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+ 768); } else {
} else { printf("Can't get c\n");
printf("Can't get c\n"); exit_flag=2;
exit_flag=2; }
} }
if (dlsch->harq_processes[i]->d[r]) { }
bzero(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144)));
} else { } else {
printf("Can't get d\n"); printf("Can't get harq_p %d\n",i);
exit_flag=2; exit_flag=3;
} }
}
} }
} else {
printf("Can't get harq_p %d\n",i);
exit_flag=3;
}
}
if (exit_flag==0) {
for (i=0; i<Mdlharq; i++) {
dlsch->harq_processes[i]->round=0;
for (j=0; j<96; j++)
for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) {
// printf("dlsch->harq_processes[%d]->d[%d] %p\n",i,r,dlsch->harq_processes[i]->d[r]);
if (dlsch->harq_processes[i]->d[r])
dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
}
} if (exit_flag==0) {
for (i=0; i<Mdlharq; i++) {
dlsch->harq_processes[i]->round=0;
}
return(dlsch); return(dlsch);
} }
...@@ -240,30 +220,25 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ ...@@ -240,30 +220,25 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_
void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch)
{ {
unsigned char Mdlharq; unsigned char Mdlharq;
unsigned char i,j,r;
if (dlsch) { if (dlsch) {
Mdlharq = dlsch->Mdlharq; Mdlharq = dlsch->Mdlharq;
dlsch->rnti = 0; dlsch->rnti = 0;
dlsch->active = 0; dlsch->active = 0;
for (i=0; i<10; i++) for (int i=0; i<10; i++)
dlsch->harq_ids[i] = Mdlharq; dlsch->harq_ids[i] = Mdlharq;
for (i=0; i<Mdlharq; i++) { for (int i=0; i<Mdlharq; i++) {
if (dlsch->harq_processes[i]) { if (dlsch->harq_processes[i]) {
// dlsch->harq_processes[i]->Ndi = 0; // dlsch->harq_processes[i]->Ndi = 0;
dlsch->harq_processes[i]->status = 0; dlsch->harq_processes[i]->status = 0;
dlsch->harq_processes[i]->round = 0; dlsch->harq_processes[i]->round = 0;
for (j=0; j<96; j++)
for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++)
if (dlsch->harq_processes[i]->d[r])
dlsch->harq_processes[i]->d[r][j] = LTE_NULL;
} }
} }
} }
} }
...@@ -309,18 +284,21 @@ int dlsch_encoding_2threads0(te_params *tep) { ...@@ -309,18 +284,21 @@ int dlsch_encoding_2threads0(te_params *tep) {
} }
uint8_t tmp[96+12+3+3*6144]= {0};
threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r], for (int j=0; j<96; j++)
Kr>>3, tmp[j] = LTE_NULL;
&dlsch->harq_processes[harq_pid]->d[r][96],
(r==0) ? dlsch->harq_processes[harq_pid]->F : 0, threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r],
f1f2mat_old[iind*2], // f1 (see 36121-820, page 14) Kr>>3,
f1f2mat_old[(iind*2)+1] // f2 (see 36121-820, page 14) tmp+96, //&dlsch->harq_processes[harq_pid]->d[r][96],
); (r==0) ? dlsch->harq_processes[harq_pid]->F : 0,
dlsch->harq_processes[harq_pid]->RTC[r] = f1f2mat_old[iind*2], // f1 (see 36121-820, page 14)
sub_block_interleaving_turbo(4+(Kr_bytes*8), f1f2mat_old[(iind*2)+1] // f2 (see 36121-820, page 14)
&dlsch->harq_processes[harq_pid]->d[r][96], );
dlsch->harq_processes[harq_pid]->w[r]); dlsch->harq_processes[harq_pid]->RTC[r] =
sub_block_interleaving_turbo(4+(Kr_bytes*8),
tmp+96, //&dlsch->harq_processes[harq_pid]->d[r][96],
dlsch->harq_processes[harq_pid]->w[r]);
} }
} }
...@@ -481,23 +459,26 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, ...@@ -481,23 +459,26 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
} }
start_meas(te_stats); start_meas(te_stats);
threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r], uint8_t tmp[96+12+3+3*6144]= {0};
Kr>>3, for (int j=0; j<96; j++)
&dlsch->harq_processes[harq_pid]->d[r][96], tmp[j] = LTE_NULL;
(r==0) ? dlsch->harq_processes[harq_pid]->F : 0, threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r],
f1f2mat_old[iind*2], // f1 (see 36121-820, page 14) Kr>>3,
f1f2mat_old[(iind*2)+1] // f2 (see 36121-820, page 14) tmp+96, //&dlsch->harq_processes[harq_pid]->d[r][96],
); (r==0) ? dlsch->harq_processes[harq_pid]->F : 0,
stop_meas(te_stats); f1f2mat_old[iind*2], // f1 (see 36121-820, page 14)
f1f2mat_old[(iind*2)+1] // f2 (see 36121-820, page 14)
start_meas(i_stats); );
dlsch->harq_processes[harq_pid]->RTC[r] = stop_meas(te_stats);
sub_block_interleaving_turbo(4+(Kr_bytes*8),
&dlsch->harq_processes[harq_pid]->d[r][96], start_meas(i_stats);
dlsch->harq_processes[harq_pid]->w[r]); dlsch->harq_processes[harq_pid]->RTC[r] =
stop_meas(i_stats); sub_block_interleaving_turbo(4+(Kr_bytes*8),
} tmp+96, //&dlsch->harq_processes[harq_pid]->d[r][96],
dlsch->harq_processes[harq_pid]->w[r]);
stop_meas(i_stats);
}
} }
else { else {
...@@ -572,49 +553,14 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, ...@@ -572,49 +553,14 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
time_stats_t *i_stats) time_stats_t *i_stats)
{ {
unsigned int G; unsigned char harq_pid = dlsch->harq_ids[subframe];
unsigned int crc=1; unsigned int A=dlsch->harq_processes[harq_pid]->TBS;//6228
unsigned short iind; // unsigned short m=dlsch->harq_processes[harq_pid]->mcs;
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
unsigned char harq_pid = dlsch->harq_ids[subframe];
unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb;
unsigned int A;
unsigned char mod_order;
unsigned int Kr=0,Kr_bytes,r,r_offset=0;
// unsigned short m=dlsch->harq_processes[harq_pid]->mcs;
uint8_t beamforming_mode=0;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
A = dlsch->harq_processes[harq_pid]->TBS; //6228
// printf("Encoder: A: %d\n",A);
mod_order = dlsch->harq_processes[harq_pid]->Qm;
if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7)
beamforming_mode = 7;
else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8)
beamforming_mode = 8;
else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10)
beamforming_mode = 9;
G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
// if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet
if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet
#ifdef DEBUG_DLSCH_CODING
printf("encoding thinks this is a new packet \n");
#endif
/*
int i;
printf("dlsch (tx): \n");
for (i=0;i<(A>>3);i++)
printf("%02x.",a[i]);
printf("\n");
*/
// Add 24-bit crc (polynomial A) to payload // Add 24-bit crc (polynomial A) to payload
crc = crc24a(a, unsigned int crc = crc24a(a, A)>>8;
A)>>8;
a[A>>3] = ((uint8_t*)&crc)[2]; a[A>>3] = ((uint8_t*)&crc)[2];
a[1+(A>>3)] = ((uint8_t*)&crc)[1]; a[1+(A>>3)] = ((uint8_t*)&crc)[1];
a[2+(A>>3)] = ((uint8_t*)&crc)[0]; a[2+(A>>3)] = ((uint8_t*)&crc)[0];
...@@ -633,75 +579,108 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, ...@@ -633,75 +579,108 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
&dlsch->harq_processes[harq_pid]->Kplus, &dlsch->harq_processes[harq_pid]->Kplus,
&dlsch->harq_processes[harq_pid]->Kminus, &dlsch->harq_processes[harq_pid]->Kminus,
&dlsch->harq_processes[harq_pid]->F)<0) &dlsch->harq_processes[harq_pid]->F)<0)
return(-1);
for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
if (r<dlsch->harq_processes[harq_pid]->Cminus)
Kr = dlsch->harq_processes[harq_pid]->Kminus;
else
Kr = dlsch->harq_processes[harq_pid]->Kplus;
Kr_bytes = Kr>>3;
// get interleaver index for Turbo code (lookup in Table 5.1.3-3 36-212, V8.6 2009-03, p. 13-14)
if (Kr_bytes<=64)
iind = (Kr_bytes-5);
else if (Kr_bytes <=128)
iind = 59 + ((Kr_bytes-64)>>1);
else if (Kr_bytes <= 256)
iind = 91 + ((Kr_bytes-128)>>2);
else if (Kr_bytes <= 768)
iind = 123 + ((Kr_bytes-256)>>3);
else {
printf("dlsch_coding: Illegal codeword size %d!!!\n",Kr_bytes);
return(-1); return(-1);
} unsigned int Kr=0,Kr_bytes;
for (int r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
#ifdef DEBUG_DLSCH_CODING
printf("Generating Code Segment %d (%d bits)\n",r,Kr); if (r<dlsch->harq_processes[harq_pid]->Cminus)
// generate codewords Kr = dlsch->harq_processes[harq_pid]->Kminus;
else
printf("bits_per_codeword (Kr)= %d, A %d\n",Kr,A); Kr = dlsch->harq_processes[harq_pid]->Kplus;
printf("N_RB = %d\n",nb_rb);
printf("Ncp %d\n",frame_parms->Ncp); Kr_bytes = Kr>>3;
printf("mod_order %d\n",mod_order);
#endif // get interleaver index for Turbo code (lookup in Table 5.1.3-3 36-212, V8.6 2009-03, p. 13-14)
unsigned short iind;
if (Kr_bytes<=64)
#ifdef DEBUG_DLSCH_CODING iind = (Kr_bytes-5);
printf("Encoding ... iind %d f1 %d, f2 %d\n",iind,f1f2mat_old[iind*2],f1f2mat_old[(iind*2)+1]); else if (Kr_bytes <=128)
#endif iind = 59 + ((Kr_bytes-64)>>1);
start_meas(te_stats); else if (Kr_bytes <= 256)
threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r], iind = 91 + ((Kr_bytes-128)>>2);
Kr>>3, else if (Kr_bytes <= 768)
&dlsch->harq_processes[harq_pid]->d[r][96], iind = 123 + ((Kr_bytes-256)>>3);
(r==0) ? dlsch->harq_processes[harq_pid]->F : 0, else {
f1f2mat_old[iind*2], // f1 (see 36121-820, page 14) printf("dlsch_coding: Illegal codeword size %d!!!\n",Kr_bytes);
f1f2mat_old[(iind*2)+1] // f2 (see 36121-820, page 14) return(-1);
); }
stop_meas(te_stats); request_t *req=createRequest(ENCODE,sizeof(turboEncode_t));
#ifdef DEBUG_DLSCH_CODING union turboReqUnion id={.s={dlsch->rnti,frame,subframe,r,0}};
req->id= id.p;
if (r==0) req->decodeIterations=0;
write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4); turboEncode_t * rdata=(turboEncode_t *) req->data;
rdata->input=dlsch->harq_processes[harq_pid]->c[r];
#endif rdata->Kr_bytes=Kr>>3;
start_meas(i_stats); rdata->filler=(r==0) ? dlsch->harq_processes[harq_pid]->F : 0;
dlsch->harq_processes[harq_pid]->RTC[r] = rdata->iind=iind;
sub_block_interleaving_turbo(4+(Kr_bytes*8), rdata->r=r;
&dlsch->harq_processes[harq_pid]->d[r][96], rdata->harq_pid=harq_pid;
dlsch->harq_processes[harq_pid]->w[r]); rdata->dlsch=dlsch;
stop_meas(i_stats); if ( eNB->proc.threadPool.activated) {
add_request(req, &eNB->proc.threadPool);
} else {
memset(rdata->output,LTE_NULL, TURBO_SIMD_SOFTBITS);
start_meas(te_stats);
req->creationTime=req->startProcessingTime=rdtsc();
threegpplte_turbo_encoder(rdata->input,
rdata->Kr_bytes,
rdata->output+96,//&dlsch->harq_processes[harq_pid]->d[r][96],
rdata->filler,
f1f2mat_old[rdata->iind*2], // f1 (see 36121-820, page 14)
f1f2mat_old[(rdata->iind*2)+1] // f2 (see 36121-820, page 14)
);
stop_meas(te_stats);
req->returnTime=req->endProcessingTime=rdtsc();
req->decodeIterations=0;
req->coreId=0;
req->processedBy[0]=0;
req->decodeIterations=0;
// Ignore write error (if no trace listner)
if (write(eNB->proc.threadPool.traceFd, req, sizeof(request_t)- 2*sizeof(void*))) {}; start_meas(i_stats);
rdata->dlsch->harq_processes[rdata->harq_pid]->RTC[rdata->r] =
sub_block_interleaving_turbo(4+(rdata->Kr_bytes*8),
rdata->output+96, //&dlsch->harq_processes[harq_pid]->d[r][96],
rdata->dlsch->harq_processes[rdata->harq_pid]->w[rdata->r]);
stop_meas(i_stats);
free(req);
}
} }
return 0;
}
} int dlsch_encoding2(PHY_VARS_eNB *eNB,
unsigned char *a,
uint8_t num_pdcch_symbols,
LTE_eNB_DLSCH_t *dlsch,
int frame,
uint8_t subframe,
time_stats_t *rm_stats,
time_stats_t *te_stats,
time_stats_t *i_stats)
{
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
unsigned char harq_pid = dlsch->harq_ids[subframe];
unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb;
// Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the
// outputs for each code segment, see Section 5.1.5 p.20
int r_offset=0;
unsigned int G;
{
unsigned char mod_order=dlsch->harq_processes[harq_pid]->Qm;
uint8_t beamforming_mode=0;
if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7)
beamforming_mode = 7;
else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8)
beamforming_mode = 8;
else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10)
beamforming_mode = 9;
G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode);
}
// Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the for (int r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
// outputs for each code segment, see Section 5.1.5 p.20
for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
#ifdef DEBUG_DLSCH_CODING #ifdef DEBUG_DLSCH_CODING
printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n", printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n",
r, r,
...@@ -855,27 +834,30 @@ int dlsch_encoding_SIC(PHY_VARS_UE *ue, ...@@ -855,27 +834,30 @@ int dlsch_encoding_SIC(PHY_VARS_UE *ue,
#ifdef DEBUG_DLSCH_CODING #ifdef DEBUG_DLSCH_CODING
printf("Encoding ... iind %d f1 %d, f2 %d\n",iind,f1f2mat_old[iind*2],f1f2mat_old[(iind*2)+1]); printf("Encoding ... iind %d f1 %d, f2 %d\n",iind,f1f2mat_old[iind*2],f1f2mat_old[(iind*2)+1]);
#endif #endif
start_meas(te_stats); start_meas(te_stats);
threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r], uint8_t tmp[96+12+3+3*6144]= {0};
Kr>>3, for (int j=0; j<96; j++)
&dlsch->harq_processes[harq_pid]->d[r][96], tmp[j] = LTE_NULL;
(r==0) ? dlsch->harq_processes[harq_pid]->F : 0, threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r],
f1f2mat_old[iind*2], // f1 (see 36121-820, page 14) Kr>>3,
f1f2mat_old[(iind*2)+1] // f2 (see 36121-820, page 14) tmp+96, //&dlsch->harq_processes[harq_pid]->d[r][96],
); (r==0) ? dlsch->harq_processes[harq_pid]->F : 0,
stop_meas(te_stats); f1f2mat_old[iind*2], // f1 (see 36121-820, page 14)
f1f2mat_old[(iind*2)+1] // f2 (see 36121-820, page 14)
);
stop_meas(te_stats);
#ifdef DEBUG_DLSCH_CODING #ifdef DEBUG_DLSCH_CODING
if (r==0) if (r==0)
write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4); write_output("enc_output0.m","enc0",tmp, 0); //&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4);
#endif #endif
start_meas(i_stats); start_meas(i_stats);
dlsch->harq_processes[harq_pid]->RTC[r] = dlsch->harq_processes[harq_pid]->RTC[r] =
sub_block_interleaving_turbo(4+(Kr_bytes*8), sub_block_interleaving_turbo(4+(Kr_bytes*8),
&dlsch->harq_processes[harq_pid]->d[r][96], tmp+96, //&dlsch->harq_processes[harq_pid]->d[r][96],
dlsch->harq_processes[harq_pid]->w[r]); dlsch->harq_processes[harq_pid]->w[r]);
stop_meas(i_stats); stop_meas(i_stats);
} }
} }
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include "PHY/defs.h" #include "PHY/defs.h"
#include <math.h> #include <math.h>
#include "nfapi_interface.h" #include "nfapi_interface.h"
#include <thread-pool.h>
// Functions below implement 36-211 and 36-212 // Functions below implement 36-211 and 36-212
/** @addtogroup _PHY_TRANSPORT_ /** @addtogroup _PHY_TRANSPORT_
...@@ -122,6 +122,16 @@ int32_t dlsch_encoding(PHY_VARS_eNB *eNB, ...@@ -122,6 +122,16 @@ int32_t dlsch_encoding(PHY_VARS_eNB *eNB,
time_stats_t *te_stats, time_stats_t *te_stats,
time_stats_t *i_stats); time_stats_t *i_stats);
int32_t dlsch_encoding2(PHY_VARS_eNB *eNB,
uint8_t *a,
uint8_t num_pdcch_symbols,
LTE_eNB_DLSCH_t *dlsch,
int frame,
uint8_t subframe,
time_stats_t *rm_stats,
time_stats_t *te_stats,
time_stats_t *i_stats);
int32_t dlsch_encoding_SIC(PHY_VARS_UE *ue, int32_t dlsch_encoding_SIC(PHY_VARS_UE *ue,
uint8_t *a, uint8_t *a,
uint8_t num_pdcch_symbols, uint8_t num_pdcch_symbols,
...@@ -1884,12 +1894,8 @@ int32_t ulsch_encoding_emul(uint8_t *ulsch_buffer, ...@@ -1884,12 +1894,8 @@ int32_t ulsch_encoding_emul(uint8_t *ulsch_buffer,
@param llr8_flag If 1, indicate that the 8-bit turbo decoder should be used @param llr8_flag If 1, indicate that the 8-bit turbo decoder should be used
@returns 0 on success @returns 0 on success
*/ */
unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB,
eNB_rxtx_proc_t *proc, ulsch_decoding_t ulsch_decoding;
uint8_t UE_id,
uint8_t control_only_flag,
uint8_t Nbundled,
uint8_t llr8_flag);
/*! /*!
\brief Decoding of ULSCH data component from 36-212. This one spawns 1 worker thread in parallel,half of the segments in each thread. \brief Decoding of ULSCH data component from 36-212. This one spawns 1 worker thread in parallel,half of the segments in each thread.
...@@ -1912,10 +1918,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB, ...@@ -1912,10 +1918,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,
@param llr8_flag If 1, indicate that the 8-bit turbo decoder should be used @param llr8_flag If 1, indicate that the 8-bit turbo decoder should be used
@returns 0 on success @returns 0 on success
*/ */
int ulsch_decoding_data(PHY_VARS_eNB *eNB, ulsch_decoding_data_t ulsch_decoding_data;
int UE_id,
int harq_pid,
int llr8_flag);
uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB, uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB,
eNB_rxtx_proc_t *proc, eNB_rxtx_proc_t *proc,
......
...@@ -50,48 +50,35 @@ ...@@ -50,48 +50,35 @@
#endif #endif
#include "UTIL/LOG/vcd_signal_dumper.h" #include "UTIL/LOG/vcd_signal_dumper.h"
#include <thread-pool.h>
//#define DEBUG_ULSCH_DECODING //#define DEBUG_ULSCH_DECODING
void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch) void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch)
{ {
int i,r; if (ulsch) {
for (int i=0; i<8; i++) {
if (ulsch) { if (ulsch->harq_processes[i]) {
for (i=0; i<8; i++) { if (ulsch->harq_processes[i]->b) {
if (ulsch->harq_processes[i]) { free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES);
if (ulsch->harq_processes[i]->b) { ulsch->harq_processes[i]->b = NULL;
free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES); }
ulsch->harq_processes[i]->b = NULL; free16(ulsch->harq_processes[i],sizeof(LTE_UL_eNB_HARQ_t));
ulsch->harq_processes[i] = NULL;
}
} }
for (r=0; r<MAX_NUM_ULSCH_SEGMENTS; r++) { free16(ulsch,sizeof(LTE_eNB_ULSCH_t));
free16(ulsch->harq_processes[i]->c[r],((r==0)?8:0) + 768); ulsch = NULL;
ulsch->harq_processes[i]->c[r] = NULL;
}
for (r=0; r<MAX_NUM_ULSCH_SEGMENTS; r++)
if (ulsch->harq_processes[i]->d[r]) {
free16(ulsch->harq_processes[i]->d[r],((3*8*6144)+12+96)*sizeof(short));
ulsch->harq_processes[i]->d[r] = NULL;
}
free16(ulsch->harq_processes[i],sizeof(LTE_UL_eNB_HARQ_t));
ulsch->harq_processes[i] = NULL;
}
} }
free16(ulsch,sizeof(LTE_eNB_ULSCH_t));
ulsch = NULL;
}
} }
LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag) LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag)
{ {
LTE_eNB_ULSCH_t *ulsch; LTE_eNB_ULSCH_t *ulsch;
uint8_t exit_flag = 0,i,r; uint8_t exit_flag = 0;
unsigned char bw_scaling =1; unsigned char bw_scaling;
switch (N_RB_UL) { switch (N_RB_UL) {
case 6: case 6:
...@@ -116,45 +103,28 @@ LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uin ...@@ -116,45 +103,28 @@ LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uin
if (ulsch) { if (ulsch) {
memset(ulsch,0,sizeof(LTE_eNB_ULSCH_t)); memset(ulsch,0,sizeof(LTE_eNB_ULSCH_t));
ulsch->max_turbo_iterations = max_turbo_iterations; ulsch->max_turbo_iterations = max_turbo_iterations;
ulsch->Mlimit = 4; ulsch->Mlimit = 4;
for (i=0; i<8; i++) { for (int i=0; i<8; i++) {
// printf("new_ue_ulsch: Harq process %d\n",i); // printf("new_ue_ulsch: Harq process %d\n",i);
ulsch->harq_processes[i] = (LTE_UL_eNB_HARQ_t *)malloc16(sizeof(LTE_UL_eNB_HARQ_t)); ulsch->harq_processes[i] = (LTE_UL_eNB_HARQ_t *)malloc16(sizeof(LTE_UL_eNB_HARQ_t));
if (ulsch->harq_processes[i]) { if (ulsch->harq_processes[i]) {
memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t)); memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t));
ulsch->harq_processes[i]->b = (uint8_t*)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); ulsch->harq_processes[i]->b = (uint8_t*)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
if (ulsch->harq_processes[i]->b) if (ulsch->harq_processes[i]->b)
memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
else else
exit_flag=3; exit_flag=3;
} else {
if (abstraction_flag==0) { exit_flag=1;
for (r=0; r<MAX_NUM_ULSCH_SEGMENTS/bw_scaling; r++) { }
ulsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+768);
if (ulsch->harq_processes[i]->c[r])
memset(ulsch->harq_processes[i]->c[r],0,((r==0)?8:0) + 3+768);
else
exit_flag=2;
ulsch->harq_processes[i]->d[r] = (short*)malloc16(((3*8*6144)+12+96)*sizeof(short));
if (ulsch->harq_processes[i]->d[r])
memset(ulsch->harq_processes[i]->d[r],0,((3*8*6144)+12+96)*sizeof(short));
else
exit_flag=2;
}
} }
} else {
exit_flag=1;
}
}
if (exit_flag==0) if (exit_flag==0)
return(ulsch); return(ulsch);
} }
LOG_E(PHY,"new_ue_ulsch: exit_flag = %d\n",exit_flag); LOG_E(PHY,"new_ue_ulsch: exit_flag = %d\n",exit_flag);
free_eNB_ulsch(ulsch); free_eNB_ulsch(ulsch);
...@@ -247,28 +217,9 @@ int ulsch_decoding_data_2thread0(td_params* tdp) { ...@@ -247,28 +217,9 @@ int ulsch_decoding_data_2thread0(td_params* tdp) {
uint32_t Gp,GpmodC,Nl=1; uint32_t Gp,GpmodC,Nl=1;
uint32_t C = ulsch_harq->C; uint32_t C = ulsch_harq->C;
uint8_t (*tc)(int16_t *y, turboDecoder * tc=llr8_flag?
uint8_t *, phy_threegpplte_turbo_decoder8:
uint16_t, phy_threegpplte_turbo_decoder16 ;
uint16_t,
uint16_t,
uint8_t,
uint8_t,
uint8_t,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *);
if (llr8_flag == 0)
tc = phy_threegpplte_turbo_decoder16;
else
tc = phy_threegpplte_turbo_decoder8;
// go through first half of segments to get r_offset // go through first half of segments to get r_offset
for (r=0; r<(ulsch_harq->C/2); r++) { for (r=0; r<(ulsch_harq->C/2); r++) {
...@@ -378,18 +329,20 @@ int ulsch_decoding_data_2thread0(td_params* tdp) { ...@@ -378,18 +329,20 @@ int ulsch_decoding_data_2thread0(td_params* tdp) {
r_offset += E; r_offset += E;
sub_block_deinterleaving_turbo(4+Kr, int16_t soft_bits[3*8*6144+12+96] __attribute__((aligned(32)));
&ulsch_harq->d[r][96], sub_block_deinterleaving_turbo(4+Kr,
ulsch_harq->w[r]); soft_bits+96,
ulsch_harq->w[r]);
if (ulsch_harq->C == 1) if (ulsch_harq->C == 1)
crc_type = CRC24_A; crc_type = CRC24_A;
else else
crc_type = CRC24_B; crc_type = CRC24_B;
ret = tc(&ulsch_harq->d[r][96], uint8_t decoded_bytes[3+768] __attribute__((aligned(32)));
ulsch_harq->c[r], ret = tc(soft_bits+96,
decoded_bytes,
Kr, Kr,
f1f2mat_old[iind*2], f1f2mat_old[iind*2],
f1f2mat_old[(iind*2)+1], f1f2mat_old[(iind*2)+1],
...@@ -415,7 +368,7 @@ int ulsch_decoding_data_2thread0(td_params* tdp) { ...@@ -415,7 +368,7 @@ int ulsch_decoding_data_2thread0(td_params* tdp) {
Kr_bytes = Kr>>3; Kr_bytes = Kr>>3;
memcpy(ulsch_harq->b+offset, memcpy(ulsch_harq->b+offset,
ulsch_harq->c[r], decoded_bytes,
Kr_bytes - ((ulsch_harq->C>1)?3:0)); Kr_bytes - ((ulsch_harq->C>1)?3:0));
offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
...@@ -468,32 +421,13 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr ...@@ -468,32 +421,13 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr
unsigned int E; unsigned int E;
int Cby2; int Cby2;
uint8_t (*tc)(int16_t *y, struct timespec wait;
uint8_t *,
uint16_t, wait.tv_sec=0;
uint16_t, wait.tv_nsec=5000000L;
uint16_t, turboDecoder * tc=llr8_flag?
uint8_t, phy_threegpplte_turbo_decoder8:
uint8_t, phy_threegpplte_turbo_decoder16 ;
uint8_t,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *);
struct timespec wait;
wait.tv_sec=0;
wait.tv_nsec=5000000L;
if (llr8_flag == 0)
tc = phy_threegpplte_turbo_decoder16;
else
tc = phy_threegpplte_turbo_decoder8;
if (ulsch_harq->C>1) { // wakeup worker if more than 1 segment if (ulsch_harq->C>1) { // wakeup worker if more than 1 segment
if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) { if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) {
...@@ -596,55 +530,57 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr ...@@ -596,55 +530,57 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr
} }
stop_meas(&eNB->ulsch_rate_unmatching_stats); stop_meas(&eNB->ulsch_rate_unmatching_stats);
r_offset += E; r_offset += E;
start_meas(&eNB->ulsch_deinterleaving_stats); int16_t soft_bits[3*8*6144+12+96] __attribute__((aligned(32)));
sub_block_deinterleaving_turbo(4+Kr, start_meas(&eNB->ulsch_deinterleaving_stats);
&ulsch_harq->d[r][96], sub_block_deinterleaving_turbo(4+Kr,
ulsch_harq->w[r]); soft_bits+96,
stop_meas(&eNB->ulsch_deinterleaving_stats); ulsch_harq->w[r]);
stop_meas(&eNB->ulsch_deinterleaving_stats);
if (ulsch_harq->C == 1) if (ulsch_harq->C == 1)
crc_type = CRC24_A; crc_type = CRC24_A;
else else
crc_type = CRC24_B; crc_type = CRC24_B;
start_meas(&eNB->ulsch_turbo_decoding_stats); start_meas(&eNB->ulsch_turbo_decoding_stats);
ret = tc(&ulsch_harq->d[r][96], uint8_t decoded_bytes[3+768] __attribute__((aligned(32)));
ulsch_harq->c[r], ret = tc(soft_bits+96,
Kr, decoded_bytes,
f1f2mat_old[iind*2], Kr,
f1f2mat_old[(iind*2)+1], f1f2mat_old[iind*2],
ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, f1f2mat_old[(iind*2)+1],
crc_type, ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS,
(r==0) ? ulsch_harq->F : 0, crc_type,
&eNB->ulsch_tc_init_stats, (r==0) ? ulsch_harq->F : 0,
&eNB->ulsch_tc_alpha_stats, &eNB->ulsch_tc_init_stats,
&eNB->ulsch_tc_beta_stats, &eNB->ulsch_tc_alpha_stats,
&eNB->ulsch_tc_gamma_stats, &eNB->ulsch_tc_beta_stats,
&eNB->ulsch_tc_ext_stats, &eNB->ulsch_tc_gamma_stats,
&eNB->ulsch_tc_intl1_stats, &eNB->ulsch_tc_ext_stats,
&eNB->ulsch_tc_intl2_stats); &eNB->ulsch_tc_intl1_stats,
&eNB->ulsch_tc_intl2_stats);
// Reassembly of Transport block here
if (ret != (1+ulsch->max_turbo_iterations)) {
if (r<ulsch_harq->Cminus)
Kr = ulsch_harq->Kminus;
else
Kr = ulsch_harq->Kplus;
// Reassembly of Transport block here Kr_bytes = Kr>>3;
if (ret != (1+ulsch->max_turbo_iterations)) { if (r==0) {
if (r<ulsch_harq->Cminus) memcpy(ulsch_harq->b,
Kr = ulsch_harq->Kminus; decoded_bytes+(ulsch_harq->F>>3),
else Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0));
Kr = ulsch_harq->Kplus;
Kr_bytes = Kr>>3;
if (r==0) {
memcpy(ulsch_harq->b,
&ulsch_harq->c[0][(ulsch_harq->F>>3)],
Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0));
offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0);
} else { } else {
memcpy(ulsch_harq->b+offset, memcpy(ulsch_harq->b+offset,
ulsch_harq->c[r], decoded_bytes,
Kr_bytes - ((ulsch_harq->C>1)?3:0)); Kr_bytes - ((ulsch_harq->C>1)?3:0));
offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
} }
...@@ -662,167 +598,131 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr ...@@ -662,167 +598,131 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr
return( (ret>proc->tdp.ret) ? ret : proc->tdp.ret ); return( (ret>proc->tdp.ret) ? ret : proc->tdp.ret );
} }
int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { request_t * ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag, int frame, int subframe) {
request_t * req=NULL;
unsigned int r,r_offset=0,Kr,Kr_bytes,iind; unsigned int r_offset=0;
uint8_t crc_type; int offset = 0;
int offset = 0; LTE_UL_eNB_HARQ_t *ulsch_harq = eNB->ulsch[UE_id]->harq_processes[harq_pid];
int ret = 1; int G = ulsch_harq->G;
int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; unsigned int E;
LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; turboDecoder * td=llr8_flag?
LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; phy_threegpplte_turbo_decoder8:
phy_threegpplte_turbo_decoder16 ;
int G = ulsch_harq->G;
unsigned int E; for (int r=0; r<ulsch_harq->C; r++) {
// Get Turbo interleaver parameters
uint8_t (*tc)(int16_t *y, int Kr=r<ulsch_harq->Cminus?ulsch_harq->Kminus:ulsch_harq->Kplus;
uint8_t *, int Kr_bytes = Kr>>3;
uint16_t, int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)];
uint16_t, memset(dummy_w, 0, sizeof(dummy_w));
uint16_t, ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
uint8_t, (uint8_t*)&dummy_w[r][0],
uint8_t, (r==0) ? ulsch_harq->F : 0);
uint8_t, start_meas(&eNB->ulsch_rate_unmatching_stats);
time_stats_t *, if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r],
time_stats_t *, G,
time_stats_t *, ulsch_harq->w[r],
time_stats_t *, (uint8_t*) &dummy_w[r][0],
time_stats_t *, ulsch_harq->e+r_offset,
time_stats_t *, ulsch_harq->C,
time_stats_t *); NSOFT,
0, //Uplink
if (llr8_flag == 0) 1,
tc = phy_threegpplte_turbo_decoder16; ulsch_harq->rvidx,
else (ulsch_harq->round==0)?1:0, // clear
tc = phy_threegpplte_turbo_decoder8; ulsch_harq->Qm,
1,
r,
for (r=0; r<ulsch_harq->C; r++) { &E)==-1) {
LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
// printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); return NULL;
// Get Turbo interleaver parameters }
if (r<ulsch_harq->Cminus)
Kr = ulsch_harq->Kminus;
else
Kr = ulsch_harq->Kplus;
Kr_bytes = Kr>>3;
if (Kr_bytes<=64)
iind = (Kr_bytes-5);
else if (Kr_bytes <=128)
iind = 59 + ((Kr_bytes-64)>>1);
else if (Kr_bytes <= 256)
iind = 91 + ((Kr_bytes-128)>>2);
else if (Kr_bytes <= 768)
iind = 123 + ((Kr_bytes-256)>>3);
else {
LOG_E(PHY,"ulsch_decoding: Illegal codeword size %d!!!\n",Kr_bytes);
return(-1);
}
#ifdef DEBUG_ULSCH_DECODING
printf("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? ulsch_harq->F : 0);
#endif
memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short));
ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
(uint8_t*)&dummy_w[r][0],
(r==0) ? ulsch_harq->F : 0);
#ifdef DEBUG_ULSCH_DECODING
printf("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %d, Q_m %d, nb_rb %d, Nl %d)...\n",
r, G,
Kr*3,
Q_m,
nb_rb,
ulsch_harq->Nl);
#endif
start_meas(&eNB->ulsch_rate_unmatching_stats);
if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r],
G,
ulsch_harq->w[r],
(uint8_t*) &dummy_w[r][0],
ulsch_harq->e+r_offset,
ulsch_harq->C,
NSOFT,
0, //Uplink
1,
ulsch_harq->rvidx,
(ulsch_harq->round==0)?1:0, // clear
ulsch_harq->Qm,
1,
r,
&E)==-1) {
LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
return(-1);
}
stop_meas(&eNB->ulsch_rate_unmatching_stats);
r_offset += E;
start_meas(&eNB->ulsch_deinterleaving_stats);
sub_block_deinterleaving_turbo(4+Kr,
&ulsch_harq->d[r][96],
ulsch_harq->w[r]);
stop_meas(&eNB->ulsch_deinterleaving_stats);
if (ulsch_harq->C == 1) stop_meas(&eNB->ulsch_rate_unmatching_stats);
crc_type = CRC24_A; r_offset += E;
else start_meas(&eNB->ulsch_deinterleaving_stats);
crc_type = CRC24_B; req=createRequest(DECODE,sizeof(turboDecode_t));
union turboReqUnion id= {.s={eNB->ulsch[UE_id]->rnti,frame,subframe,r,0}};
start_meas(&eNB->ulsch_turbo_decoding_stats); req->id= id.p;
turboDecode_t * rdata=(turboDecode_t *) req->data;
ret = tc(&ulsch_harq->d[r][96], sub_block_deinterleaving_turbo(4+Kr,
ulsch_harq->c[r], rdata->soft_bits+96,
Kr, ulsch_harq->w[r]);
f1f2mat_old[iind*2], stop_meas(&eNB->ulsch_deinterleaving_stats);
f1f2mat_old[(iind*2)+1], start_meas(&eNB->ulsch_turbo_decoding_stats);
ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, if (Kr_bytes<=64)
crc_type, rdata->iind = (Kr_bytes-5);
(r==0) ? ulsch_harq->F : 0, else if (Kr_bytes <=128)
&eNB->ulsch_tc_init_stats, rdata->iind = 59 + ((Kr_bytes-64)>>1);
&eNB->ulsch_tc_alpha_stats, else if (Kr_bytes <= 256)
&eNB->ulsch_tc_beta_stats, rdata->iind = 91 + ((Kr_bytes-128)>>2);
&eNB->ulsch_tc_gamma_stats, else if (Kr_bytes <= 768)
&eNB->ulsch_tc_ext_stats, rdata->iind = 123 + ((Kr_bytes-256)>>3);
&eNB->ulsch_tc_intl1_stats, else {
&eNB->ulsch_tc_intl2_stats); LOG_E(PHY,"ulsch_decoding: Illegal codeword size %d!!!\n",Kr_bytes);
return NULL;
stop_meas(&eNB->ulsch_turbo_decoding_stats); }
// Reassembly of Transport block here
if (ret != (1+ulsch->max_turbo_iterations)) { rdata->frame=frame;
if (r<ulsch_harq->Cminus) rdata->subframe=subframe;
Kr = ulsch_harq->Kminus; rdata->UEid=UE_id;
else rdata->harq_pid=harq_pid;
Kr = ulsch_harq->Kplus; rdata->Kr=Kr;
rdata->maxIterations=eNB->ulsch[UE_id]->max_turbo_iterations;
Kr_bytes = Kr>>3; rdata->ulsch_harq=ulsch_harq;
rdata->eNB=eNB;
if (r==0) { rdata->nbSegments=ulsch_harq->C;
memcpy(ulsch_harq->b, rdata->segment_r=r;
&ulsch_harq->c[0][(ulsch_harq->F>>3)], rdata->Fbits=(r==0) ? ulsch_harq->F : 0;
Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); rdata->offset=offset;
offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); rdata->function=td;
} else { int Fbytes=rdata->Fbits>>3;
memcpy(ulsch_harq->b+offset, int blockSize=Kr_bytes - Fbytes - (rdata->nbSegments>1?3:0);
ulsch_harq->c[r], if ( eNB->proc.threadPool.activated) {
Kr_bytes - ((ulsch_harq->C>1)?3:0)); add_request(req, &eNB->proc.threadPool);
offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); req=NULL;
} } else {
req->creationTime=req->startProcessingTime=rdtsc();
} else { rdata->decodeIterations = td( rdata->soft_bits+96,
break; rdata->decoded_bytes,
rdata->Kr,
f1f2mat_old[rdata->iind*2],
f1f2mat_old[(rdata->iind*2)+1],
rdata->maxIterations,
rdata->nbSegments == 1 ? CRC24_A: CRC24_B,
rdata->Fbits,
&eNB->ulsch_tc_init_stats,
&eNB->ulsch_tc_alpha_stats,
&eNB->ulsch_tc_beta_stats,
&eNB->ulsch_tc_gamma_stats,
&eNB->ulsch_tc_ext_stats,
&eNB->ulsch_tc_intl1_stats,
&eNB->ulsch_tc_intl2_stats);
stop_meas(&eNB->ulsch_turbo_decoding_stats);
req->returnTime=req->endProcessingTime=rdtsc();
req->decodeIterations=rdata->decodeIterations;
req->coreId=0;
req->processedBy[0]=0;
// Ignore write error (if no trace listner)
if (write(eNB->proc.threadPool.traceFd, req, sizeof(request_t)- 2*sizeof(void*))) {}; // Reassembly of Transport block here
if (rdata->decodeIterations <= eNB->ulsch[UE_id]->max_turbo_iterations ) {
// last block in a TDU is processed in caller
if ( rdata->segment_r < (rdata->nbSegments - 1) ) {
ulsch_harq->processedSegments++;
memcpy(ulsch_harq->b+rdata->offset,
rdata->decoded_bytes+Fbytes,
blockSize);
freeRequest(req);
}
}
else
// Entire TPU need retransmission
break;
}
offset += blockSize;
} }
return(req);
}
return(ret);
} }
static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset) __attribute__((always_inline)); static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset) __attribute__((always_inline));
...@@ -852,52 +752,52 @@ static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, ...@@ -852,52 +752,52 @@ static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2,
// printf("n=%d : c %x\n",n,x1^x2); // printf("n=%d : c %x\n",n,x1^x2);
} }
unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, request_t* ulsch_decoding(PHY_VARS_eNB *eNB,
uint8_t UE_id, eNB_rxtx_proc_t *proc,
uint8_t control_only_flag, uint8_t UE_id,
uint8_t Nbundled, uint8_t control_only_flag,
uint8_t llr8_flag) uint8_t Nbundled,
uint8_t llr8_flag,
int frame,
int subframe)
{ {
int16_t *ulsch_llr = eNB->pusch_vars[UE_id]->llr; int16_t *ulsch_llr = eNB->pusch_vars[UE_id]->llr;
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
uint8_t harq_pid; uint8_t harq_pid;
unsigned short nb_rb; unsigned short nb_rb;
unsigned int A; unsigned int A;
uint8_t Q_m; uint8_t Q_m;
unsigned int i,i2,q,j,j2; unsigned int i,i2,q,j,j2;
int iprime; int iprime;
unsigned int ret=0;
// uint8_t dummy_channel_output[(3*8*block_length)+12];
// uint8_t dummy_channel_output[(3*8*block_length)+12]; int r,Kr;
int r,Kr;
uint8_t *columnset;
uint8_t *columnset; unsigned int sumKr=0;
unsigned int sumKr=0; unsigned int Qprime,L,G,Q_CQI,Q_RI,H,Hprime,Hpp,Cmux,Rmux_prime,O_RCC;
unsigned int Qprime,L,G,Q_CQI,Q_RI,H,Hprime,Hpp,Cmux,Rmux_prime,O_RCC; unsigned int Qprime_ACK,Qprime_RI,len_ACK=0,len_RI=0;
unsigned int Qprime_ACK,Qprime_RI,len_ACK=0,len_RI=0; // uint8_t q_ACK[MAX_ACK_PAYLOAD],q_RI[MAX_RI_PAYLOAD];
// uint8_t q_ACK[MAX_ACK_PAYLOAD],q_RI[MAX_RI_PAYLOAD]; int metric,metric_new;
int metric,metric_new; uint32_t x1, x2, s=0;
uint32_t x1, x2, s=0; int16_t ys,c;
int16_t ys,c; uint32_t wACK_idx;
uint32_t wACK_idx; uint8_t dummy_w_cc[3*(MAX_CQI_BITS+8+32)];
uint8_t dummy_w_cc[3*(MAX_CQI_BITS+8+32)]; int16_t y[6*14*1200] __attribute__((aligned(32)));
int16_t y[6*14*1200] __attribute__((aligned(32))); uint8_t ytag[14*1200];
uint8_t ytag[14*1200]; // uint8_t ytag2[6*14*1200],*ytag2_ptr;
// uint8_t ytag2[6*14*1200],*ytag2_ptr; int16_t cseq[6*14*1200] __attribute__((aligned(32)));
int16_t cseq[6*14*1200] __attribute__((aligned(32))); int off;
int off;
LTE_UL_eNB_HARQ_t *ulsch_harq;
int frame = proc->frame_rx;
int subframe = proc->subframe_rx;
LTE_UL_eNB_HARQ_t *ulsch_harq;
harq_pid = subframe2harq_pid(frame_parms,frame,subframe); harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1);
...@@ -905,7 +805,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, ...@@ -905,7 +805,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
x2 = ((uint32_t)ulsch->rnti<<14) + ((uint32_t)subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1 x2 = ((uint32_t)ulsch->rnti<<14) + ((uint32_t)subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1
ulsch_harq = ulsch->harq_processes[harq_pid]; ulsch_harq = ulsch->harq_processes[harq_pid];
AssertFatal(harq_pid!=255, AssertFatal(harq_pid<8,
"FATAL ERROR: illegal harq_pid, returning\n"); "FATAL ERROR: illegal harq_pid, returning\n");
AssertFatal(ulsch_harq->Nsymb_pusch != 0, AssertFatal(ulsch_harq->Nsymb_pusch != 0,
...@@ -1200,9 +1100,11 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, ...@@ -1200,9 +1100,11 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
c = cseq[i]; c = cseq[i];
y[i2] = c*ulsch_llr[i++]; y[i2] = c*ulsch_llr[i++];
i2=(i2+(Cmux<<2)-3); i2=(i2+(Cmux<<2)-3);
*/ */
// slightly more optimized version (equivalent to above) for 16QAM to improve computational performance // slightly more optimized version (equivalent to above) for 16QAM to improve computational performance
*(__m64 *)&y[i2] = _mm_sign_pi16(*(__m64*)&ulsch_llr[i],*(__m64*)&cseq[i]);i+=4;i2+=(Cmux<<2); *(__m64 *)&y[i2] = _mm_sign_pi16(*(__m64*)&ulsch_llr[i],*(__m64*)&cseq[i]);
i+=4;
i2+=(Cmux<<2);
} }
...@@ -1281,51 +1183,51 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, ...@@ -1281,51 +1183,51 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
} }
} }
if (ulsch_harq->O_ACK > 2) { if (ulsch_harq->O_ACK > 2) {
LOG_E(PHY,"ulsch_decoding: FATAL, ACK cannot be more than 2 bits yet O_ACK:%d SFN/SF:%04d%d UE_id:%d rnti:%x\n",ulsch_harq->O_ACK,proc->frame_rx,proc->subframe_rx,UE_id,ulsch->rnti); LOG_E(PHY,"ulsch_decoding: FATAL, ACK cannot be more than 2 bits yet\n");
return(-1); return NULL;
} }
for (i=0; i<len_ACK; i++) for (i=0; i<len_ACK; i++)
ulsch_harq->q_ACK[i] = 0; ulsch_harq->q_ACK[i] = 0;
for (i=0; i<Qprime_ACK; i++) { for (i=0; i<Qprime_ACK; i++) {
r = Rmux_prime -1 - (i>>2); r = Rmux_prime -1 - (i>>2);
for (q=0; q<Q_m; q++) { for (q=0; q<Q_m; q++) {
if (y[q+(Q_m*((r*Cmux) + columnset[j]))]!=0) if (y[q+(Q_m*((r*Cmux) + columnset[j]))]!=0)
ulsch_harq->q_ACK[(q+(Q_m*i))%len_ACK] += y[q+(Q_m*((r*Cmux) + columnset[j]))]; ulsch_harq->q_ACK[(q+(Q_m*i))%len_ACK] += y[q+(Q_m*((r*Cmux) + columnset[j]))];
y[q+(Q_m*((r*Cmux) + columnset[j]))]=0; // NULL LLRs in ACK positions y[q+(Q_m*((r*Cmux) + columnset[j]))]=0; // NULL LLRs in ACK positions
} }
j=(j+3)&3; j=(j+3)&3;
} }
// printf("after ACKNAK c[%d] = %p\n",0,ulsch_harq->c[0]); // printf("after ACKNAK c[%d] = %p\n",0,ulsch_harq->c[0]);
// RI BITS // RI BITS
if (ulsch_harq->O_RI == 1) { if (ulsch_harq->O_RI == 1) {
switch (Q_m) { switch (Q_m) {
case 2: case 2:
len_RI=2; len_RI=2;
break; break;
case 4: case 4:
len_RI=4; len_RI=4;
break; break;
case 6: case 6:
len_RI=6; len_RI=6;
break; break;
}
} }
}
if (ulsch_harq->O_RI > 1) { if (ulsch_harq->O_RI > 1) {
LOG_E(PHY,"ulsch_decoding: FATAL, RI cannot be more than 1 bit yet\n"); LOG_E(PHY,"ulsch_decoding: FATAL, RI cannot be more than 1 bit yet\n");
return(-1); return NULL;
} }
for (i=0; i<len_RI; i++) for (i=0; i<len_RI; i++)
ulsch_harq->q_RI[i] = 0; ulsch_harq->q_RI[i] = 0;
...@@ -1598,7 +1500,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, ...@@ -1598,7 +1500,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
// Do ULSCH Decoding for data portion // Do ULSCH Decoding for data portion
ret = eNB->td(eNB,UE_id,harq_pid,llr8_flag); request_t * ret = eNB->td(eNB,UE_id,harq_pid,llr8_flag, frame, subframe);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0);
......
...@@ -1361,8 +1361,6 @@ void rx_ulsch_emul(PHY_VARS_eNB *eNB, ...@@ -1361,8 +1361,6 @@ void rx_ulsch_emul(PHY_VARS_eNB *eNB,
eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS,eNB->ulsch[UE_id]->harq_processes[harq_pid]->Qm, eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS,eNB->ulsch[UE_id]->harq_processes[harq_pid]->Qm,
eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_pusch); eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_pusch);
//#ifndef OAI_EMU //#ifndef OAI_EMU
write_output("/tmp/ulsch_d.m","ulsch_dseq",&eNB->ulsch[UE_id]->harq_processes[harq_pid]->d[0][96],
eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus*3,1,0);
if (eNB->common_vars.rxdata) write_output("/tmp/rxsig0.m","rxs0", &eNB->common_vars.rxdata[0][0],eNB->frame_parms.samples_per_tti*10,1,1); if (eNB->common_vars.rxdata) write_output("/tmp/rxsig0.m","rxs0", &eNB->common_vars.rxdata[0][0],eNB->frame_parms.samples_per_tti*10,1,1);
if (eNB->frame_parms.nb_antennas_rx>1) if (eNB->frame_parms.nb_antennas_rx>1)
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include <math.h> #include <math.h>
#include "common_lib.h" #include "common_lib.h"
#include "msc.h" #include "msc.h"
#include <thread-pool.h>
#include "openair2/PHY_INTERFACE/IF_Module.h" #include "openair2/PHY_INTERFACE/IF_Module.h"
...@@ -196,8 +197,9 @@ enum transmission_access_mode { ...@@ -196,8 +197,9 @@ enum transmission_access_mode {
POSTPONED_ACCESS, POSTPONED_ACCESS,
CANCELED_ACCESS, CANCELED_ACCESS,
UNKNOWN_ACCESS, UNKNOWN_ACCESS,
SCHEDULED_ACCESS, SCHEDULED_ACCESS,
CBA_ACCESS}; CBA_ACCESS
};
typedef enum { typedef enum {
eNodeB_3GPP=0, // classical eNodeB function eNodeB_3GPP=0, // classical eNodeB function
...@@ -430,6 +432,7 @@ typedef struct eNB_proc_t_s { ...@@ -430,6 +432,7 @@ typedef struct eNB_proc_t_s {
uint8_t CC_id; uint8_t CC_id;
/// thread index /// thread index
int thread_index; int thread_index;
tpool_t threadPool;
/// timestamp received from HW /// timestamp received from HW
openair0_timestamp timestamp_rx; openair0_timestamp timestamp_rx;
/// timestamp to send to "slave rru" /// timestamp to send to "slave rru"
...@@ -927,6 +930,20 @@ typedef struct { ...@@ -927,6 +930,20 @@ typedef struct {
int prach_I0; int prach_I0;
} PHY_MEASUREMENTS_eNB; } PHY_MEASUREMENTS_eNB;
typedef request_t *(ulsch_decoding_t)(struct PHY_VARS_eNB_s *phy_vars_eNB,
eNB_rxtx_proc_t *proc,
uint8_t UE_id,
uint8_t control_only_flag,
uint8_t Nbundled,
uint8_t llr8_flag,
int frame,
int subframe);
typedef request_t *(ulsch_decoding_data_t)(struct PHY_VARS_eNB_s *eNB,
int UE_id,
int harq_pid,
int llr8_flag,
int frame,
int subframe);
/// Top-level PHY Data Structure for eNB /// Top-level PHY Data Structure for eNB
typedef struct PHY_VARS_eNB_s { typedef struct PHY_VARS_eNB_s {
...@@ -944,7 +961,8 @@ typedef struct PHY_VARS_eNB_s { ...@@ -944,7 +961,8 @@ typedef struct PHY_VARS_eNB_s {
/// Ethernet parameters for fronthaul interface /// Ethernet parameters for fronthaul interface
eth_params_t eth_params; eth_params_t eth_params;
int rx_total_gain_dB; int rx_total_gain_dB;
int (*td)(struct PHY_VARS_eNB_s *eNB,int UE_id,int harq_pid,int llr8_flag); //int (*td)(struct PHY_VARS_eNB_s *eNB,int UE_id,int harq_pid,int llr8_flag);
ulsch_decoding_data_t *td;
int (*te)(struct PHY_VARS_eNB_s *,uint8_t *,uint8_t,LTE_eNB_DLSCH_t *,int,uint8_t,time_stats_t *,time_stats_t *,time_stats_t *); int (*te)(struct PHY_VARS_eNB_s *,uint8_t *,uint8_t,LTE_eNB_DLSCH_t *,int,uint8_t,time_stats_t *,time_stats_t *,time_stats_t *);
int (*start_if)(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB); int (*start_if)(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB);
uint8_t local_flag; uint8_t local_flag;
...@@ -1615,6 +1633,55 @@ static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char * ...@@ -1615,6 +1633,55 @@ static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *
return(0); return(0);
} }
// OpenAir .h files are very very badly intricated, so we redeclare a type
// A major issue to fix in whole OAI: total crap (reprototype in .c, loops of includes, ...)
typedef uint8_t (turboDecoder)(int16_t *y,
uint8_t *,
uint16_t,
uint16_t,
uint16_t,
uint8_t,
uint8_t,
uint8_t,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *,
time_stats_t *);
typedef struct TurboDecode_s {
turboDecoder *function;
int16_t soft_bits[3*8*6144+12+96] __attribute__((aligned(32)));
uint8_t decoded_bytes[3+768] __attribute__((aligned(32)));
int UEid;
int harq_pid;
int frame;
int subframe;
int iind;
int Fbits;
int Kr;
LTE_UL_eNB_HARQ_t *ulsch_harq;
PHY_VARS_eNB *eNB;
int nbSegments;
int segment_r;
int offset;
int maxIterations;
int decodeIterations;
} turboDecode_t;
#define TURBO_SIMD_SOFTBITS 96+12+3+3*6144
typedef struct turboEncode_s {
uint8_t * input;
uint8_t output[TURBO_SIMD_SOFTBITS];
int Kr_bytes;
int filler;
int iind;
int r;
int harq_pid;
LTE_eNB_DLSCH_t *dlsch;
} turboEncode_t;
#include "PHY/INIT/defs.h" #include "PHY/INIT/defs.h"
#include "PHY/LTE_REFSIG/defs.h" #include "PHY/LTE_REFSIG/defs.h"
......
...@@ -344,17 +344,43 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, ...@@ -344,17 +344,43 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,
} }
start_meas(&eNB->dlsch_encoding_stats); start_meas(&eNB->dlsch_encoding_stats);
AssertFatal(dlsch_harq->pdu!=NULL,"dlsch_harq->pdu == NULL (rnti %x)\n",dlsch->rnti);
if (dlsch->harq_processes[harq_pid]->round == 0) // this is a new packet
eNB->te(eNB,
dlsch_harq->pdu,
dlsch_harq->pdsch_start,
dlsch,
frame,subframe,
&eNB->dlsch_rate_matching_stats,
&eNB->dlsch_turbo_encoding_stats,
&eNB->dlsch_interleaving_stats);
stop_meas(&eNB->dlsch_encoding_stats);
}
}
eNB->te(eNB, void pdsch_procedures2(PHY_VARS_eNB *eNB,
dlsch_harq->pdu, eNB_rxtx_proc_t *proc,
dlsch_harq->pdsch_start, int harq_pid,
dlsch, LTE_eNB_DLSCH_t *dlsch,
frame,subframe, LTE_eNB_DLSCH_t *dlsch1,
&eNB->dlsch_rate_matching_stats, LTE_eNB_UE_stats *ue_stats,
&eNB->dlsch_turbo_encoding_stats, int ra_flag) {
&eNB->dlsch_interleaving_stats); // 36-211
stop_meas(&eNB->dlsch_encoding_stats); int frame=proc->frame_tx;
// 36-211 int subframe=proc->subframe_tx;
LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
if (nfapi_mode == 0 || nfapi_mode == 1) { // monolthic OR PNF - do not need turbo encoding on VNF
dlsch_encoding2(eNB,
dlsch_harq->pdu,
dlsch_harq->pdsch_start,
dlsch,
frame,subframe,
&eNB->dlsch_rate_matching_stats,
&eNB->dlsch_turbo_encoding_stats,
&eNB->dlsch_interleaving_stats);
start_meas(&eNB->dlsch_scrambling_stats); start_meas(&eNB->dlsch_scrambling_stats);
dlsch_scrambling(fp, dlsch_scrambling(fp,
0, 0,
...@@ -518,7 +544,9 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -518,7 +544,9 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
// Now scan UE specific DLSCH // Now scan UE specific DLSCH
LTE_eNB_DLSCH_t *dlsch0,*dlsch1; LTE_eNB_DLSCH_t *dlsch0,*dlsch1;
if (eNB->proc.threadPool.notFinishedJobs != 0 )
LOG_E(PHY,"no finished = %d\n",eNB->proc.threadPool.notFinishedJobs);
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
{ {
dlsch0 = eNB->dlsch[(uint8_t)UE_id][0]; dlsch0 = eNB->dlsch[(uint8_t)UE_id][0];
...@@ -547,12 +575,71 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -547,12 +575,71 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
&eNB->UE_stats[(uint32_t)UE_id], &eNB->UE_stats[(uint32_t)UE_id],
0); 0);
} }
}
}
if ( eNB->proc.threadPool.activated ) {
// Wait all other threads finish to process
int nbRequest=0;
//printf("%s:%d:%d\n", __FILE__,__LINE__,eNB->proc.threadPool.notFinishedJobs);
AssertFatal(pthread_mutex_lock(&eNB->proc.threadPool.lockReportDone)==0,"");
while ( eNB->proc.threadPool.notFinishedJobs > 0 ) {
// printf("%s:%d:%d\n", __FILE__,__LINE__,eNB->proc.threadPool.notFinishedJobs);
struct timespec t;
clock_gettime(CLOCK_REALTIME,&t);
t.tv_nsec+=100*1000*1000;
if ( t.tv_nsec >= 1000*1000*1000 ) {
t.tv_nsec -= 1000*1000*1000;
t.tv_sec++;
}
int rr;
if ((rr=pthread_cond_timedwait(&eNB->proc.threadPool.notifDone,&eNB->proc.threadPool.lockReportDone, &t))!=0)
LOG_E(PHY,"timedwait1:%s,%p,%p,%p,%d\n", rr==ETIMEDOUT?"ETIMEDOUT":"other",
eNB->proc.threadPool.oldestRequests,
eNB->proc.threadPool.newestRequests,
eNB->proc.threadPool.doneRequests,
eNB->proc.threadPool.notFinishedJobs);
}
AssertFatal(pthread_mutex_unlock(&eNB->proc.threadPool.lockReportDone)==0,"");
request_t* tmp;
while ((tmp=eNB->proc.threadPool.doneRequests)!=NULL) {
tmp->returnTime=rdtsc();
// Ignore write error (if no trace listner)
if (write(eNB->proc.threadPool.traceFd, tmp, sizeof(request_t)- 2*sizeof(void*))) {};
eNB->proc.threadPool.doneRequests=tmp->next;
start_meas(&eNB->dlsch_interleaving_stats);
turboEncode_t * rdata=(turboEncode_t *) tmp->data;
rdata->dlsch->harq_processes[rdata->harq_pid]->RTC[rdata->r] =
sub_block_interleaving_turbo(4+(rdata->Kr_bytes*8),
rdata->output+96, //&dlsch->harq_processes[harq_pid]->d[r][96],
rdata->dlsch->harq_processes[rdata->harq_pid]->w[rdata->r]);
freeRequest(tmp);
stop_meas(&eNB->dlsch_interleaving_stats);
nbRequest++;
}
//if ( nbRequest ) printf("Done %d code blocks in %ld µsec\n", nbRequest, (rdtsc()-now)/eNB->proc.threadPool.cpuCyclesMicroSec);
}
} for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
dlsch0 = eNB->dlsch[(uint8_t)UE_id][0];
dlsch1 = eNB->dlsch[(uint8_t)UE_id][1];
if ((dlsch0)&&
(dlsch0->rnti>0)&&
(dlsch0->active == 1)) {
// get harq_pid
harq_pid = dlsch0->harq_ids[subframe];
pdsch_procedures2(eNB,
proc,
harq_pid,
dlsch0,
dlsch1,
&eNB->UE_stats[(uint32_t)UE_id],
0);
}
else if ((dlsch0)&& else if ((dlsch0)&&
(dlsch0->rnti>0)&& (dlsch0->rnti>0)&&
(dlsch0->active == 0)) { (dlsch0->active == 0)) {
...@@ -817,7 +904,7 @@ void uci_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) ...@@ -817,7 +904,7 @@ void uci_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
{ {
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
uint8_t SR_payload = 0,pucch_b0b1[4][2]= {{0,0},{0,0},{0,0},{0,0}},harq_ack[4]={0,0,0,0}; uint8_t SR_payload = 0,pucch_b0b1[4][2]= {{0,0},{0,0},{0,0},{0,0}},harq_ack[4]={0,0,0,0};
int32_t metric[4]={0,0,0,0},metric_SR=0,max_metric; int32_t metric[4]= {0,0,0,0},metric_SR=0,max_metric=0;
const int subframe = proc->subframe_rx; const int subframe = proc->subframe_rx;
const int frame = proc->frame_rx; const int frame = proc->frame_rx;
int i; int i;
...@@ -1312,213 +1399,187 @@ void uci_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) ...@@ -1312,213 +1399,187 @@ void uci_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
} }
} }
void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) void post_decode(request_t* decodeResult) {
{ turboDecode_t * rdata=(turboDecode_t *) decodeResult->data;
uint32_t ret=0,i; LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid];
uint32_t harq_pid; LTE_UL_eNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
uint8_t nPRS; PHY_VARS_eNB *eNB=rdata->eNB;
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; bool decodeSucess=rdata->decodeIterations <= rdata->maxIterations;
LTE_eNB_ULSCH_t *ulsch; ulsch_harq->processedSegments++;
LTE_UL_eNB_HARQ_t *ulsch_harq; if (decodeSucess) {
int Fbytes=rdata->Fbits>>3;
int Kr=rdata->segment_r < ulsch_harq->Cminus?
ulsch_harq->Kminus:
ulsch_harq->Kplus;
int Kr_bytes = Kr>>3;
int blockSize=Kr_bytes - Fbytes - (rdata->nbSegments>1?3:0);
memcpy(ulsch_harq->b+rdata->offset,
rdata->decoded_bytes+Fbytes,
blockSize);
const int subframe = proc->subframe_rx; } else {
const int frame = proc->frame_rx; if (rdata->nbSegments > 1 ) {
// Purge pending decoding of the same TDU
if (fp->frame_type == FDD) harq_pid = ((10*frame) + subframe)&7; union turboReqUnion idInFailure= {.p=decodeResult->id};
else harq_pid = subframe%10; rnti_t rntiInFailure=idInFailure.s.rnti;
tpool_t * tp=&eNB->proc.threadPool;
for (i=0; i<NUMBER_OF_UE_MAX; i++) { AssertFatal(pthread_mutex_lock(&tp->lockRequests)==0,"");
ulsch = eNB->ulsch[i]; request_t* pending=NULL;
ulsch_harq = ulsch->harq_processes[harq_pid]; while ( (pending=searchRNTI(tp, rntiInFailure)) != NULL) {
if (ulsch->rnti>0) LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n", LOG_W(MAC,"removing a CB belonging to a bad TPU");
i, harq_pid, frame,subframe,i,ulsch->rnti, freeRequest(pending);
ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); }
AssertFatal(pthread_mutex_unlock(&tp->lockRequests)==0,"");
if ((ulsch) && }
(ulsch->rnti>0) && }
(ulsch_harq->status == ACTIVE) &&
(ulsch_harq->frame == frame) &&
(ulsch_harq->subframe == subframe) &&
(ulsch_harq->handled == 0)) {
// UE has ULSCH scheduling
for (int rb=0;
rb<=ulsch_harq->nb_rb;
rb++) {
int rb2 = rb+ulsch_harq->first_rb;
eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
}
LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d \n", eNB->Mod_id, frame, subframe, i);
nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
ulsch->cyclicShift = (ulsch_harq->n_DMRS2 +
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
nPRS)%12;
LOG_D(PHY,
"[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, Qm %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, ), O_ACK %d, beta_cqi %d \n",
eNB->Mod_id,harq_pid,frame,subframe,
ulsch_harq->dci_alloc,
ulsch_harq->rar_alloc,
ulsch_harq->round,
ulsch_harq->first_rb,
ulsch_harq->nb_rb,
ulsch_harq->Qm,
ulsch_harq->TBS,
ulsch_harq->rvidx,
ulsch->cyclicShift,
ulsch_harq->n_DMRS2,
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
ulsch_harq->O_ACK,
ulsch->beta_offset_cqi_times8);
start_meas(&eNB->ulsch_demodulation_stats);
rx_ulsch(eNB,proc, i);
stop_meas(&eNB->ulsch_demodulation_stats);
start_meas(&eNB->ulsch_decoding_stats);
ret = ulsch_decoding(eNB,proc,
i,
0, // control_only_flag
ulsch_harq->V_UL_DAI,
ulsch_harq->nb_rb>20 ? 1 : 0);
stop_meas(&eNB->ulsch_decoding_stats);
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d ulsch_harq->cqi_crc_status:%d ackBits:%d ulsch_decoding_stats[t:%lld max:%lld]\n",
eNB->Mod_id,harq_pid,
frame,subframe,
ulsch->rnti,
dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]),
dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]),
20,//eNB->measurements.n0_power_dB[0],
20,//eNB->measurements.n0_power_dB[1],
ulsch_harq->o_ACK[0],
ulsch_harq->o_ACK[1],
ret,
ulsch_harq->cqi_crc_status,
ulsch_harq->O_ACK,
eNB->ulsch_decoding_stats.diff_now, eNB->ulsch_decoding_stats.max);
// Check if TDU is complete: either we have all blocks in success
// either at least one block can't be decoded
// Maybe we receive decoded block alter a first failure,
// so we protect ourselves against multiple executions
if ( (rdata->nbSegments == ulsch_harq->processedSegments || decodeSucess==false) &&
ulsch_harq->processedBadSegment == 0 ) {
//compute the expected ULSCH RX power (for the stats) //compute the expected ULSCH RX power (for the stats)
ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,rdata->UEid,rdata->harq_pid, 0); // 0 means bw_factor is not considered
if (ulsch_harq->cqi_crc_status == 1) { if (ulsch_harq->cqi_crc_status == 1)
#ifdef DEBUG_PHY_PROC fill_ulsch_cqi_indication(eNB,rdata->frame,rdata->subframe,
//if (((frame%10) == 0) || (frame < 50)) ulsch_harq,
print_CQI(ulsch_harq->o,ulsch_harq->uci_format,0,fp->N_RB_DL); ulsch->rnti);
#endif
fill_crc_indication(eNB,rdata->UEid,rdata->frame,rdata->subframe,decodeSucess?0:1); // indicate result to MAC
fill_ulsch_cqi_indication(eNB,frame,subframe, fill_rx_indication(eNB,rdata->UEid,rdata->frame,rdata->subframe); // indicate SDU to MAC
ulsch_harq,
ulsch->rnti); if (!decodeSucess) {
} ulsch_harq->processedBadSegment =1;
if (ulsch_harq->round >= 3) {
if (ret == (1+MAX_TURBO_ITERATIONS)) { ulsch_harq->status = SCH_IDLE;
T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti), ulsch_harq->handled = 0;
T_INT(harq_pid)); ulsch->harq_mask &= ~(1 << rdata->harq_pid);
ulsch_harq->round = 0;
fill_crc_indication(eNB,i,frame,subframe,1); // indicate NAK to MAC }
fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n",
eNB->Mod_id,harq_pid,
frame,subframe, i,
ulsch_harq->round-1,
ulsch->Mlimit,
ulsch_harq->o_ACK[0],
ulsch_harq->o_ACK[1]);
if (ulsch_harq->round >= 3) {
ulsch_harq->status = SCH_IDLE;
ulsch_harq->handled = 0;
ulsch->harq_mask &= ~(1 << harq_pid);
ulsch_harq->round = 0;
}
#if defined(MESSAGE_CHART_GENERATOR_PHY)
MSC_LOG_RX_DISCARDED_MESSAGE(
MSC_PHY_ENB,MSC_PHY_UE,
NULL,0,
"%05u:%02u ULSCH received rnti %x harq id %u round %d",
frame,subframe,
ulsch->rnti,harq_pid,
ulsch_harq->round-1
);
#endif
/* Mark the HARQ process to release it later if max transmission reached
* (see below).
* MAC does not send the max transmission count, we have to deal with it
* locally in PHY.
*/
ulsch_harq->handled = 1;
} // ulsch in error
else {
fill_crc_indication(eNB,i,frame,subframe,0); // indicate ACK to MAC
fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC
ulsch_harq->status = SCH_IDLE; /* Mark the HARQ process to release it later if max transmission reached
ulsch->harq_mask &= ~(1 << harq_pid); * (see below).
* MAC does not send the max transmission count, we have to deal with it
* locally in PHY.
*/
ulsch_harq->handled = 1;
} else {
ulsch_harq->status = SCH_IDLE;
ulsch->harq_mask &= ~(1 << rdata->harq_pid);
} // ulsch not in error
T(T_ENB_PHY_ULSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti), if (ulsch_harq->O_ACK>0)
T_INT(harq_pid)); fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,rdata->frame,rdata->subframe,ulsch->bundling);
}
freeRequest(decodeResult);
}
#if defined(MESSAGE_CHART_GENERATOR_PHY) void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
MSC_LOG_RX_MESSAGE( {
MSC_PHY_ENB,MSC_PHY_UE, uint32_t harq_pid;
NULL,0, uint8_t nPRS;
"%05u:%02u ULSCH received rnti %x harq id %u", LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
frame,subframe,
ulsch->rnti,harq_pid
);
#endif
#ifdef DEBUG_PHY_PROC const int subframe = proc->subframe_rx;
#ifdef DEBUG_ULSCH const int frame = proc->frame_rx;
LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
harq_pid,ulsch_harq->TBS>>3);
for (j=0; j<ulsch_harq->TBS>>3; j++) if (fp->frame_type == FDD)
LOG_T(PHY,"%x.",ulsch->harq_processes[harq_pid]->b[j]); harq_pid = ((10*frame) + subframe)&7;
else
harq_pid = subframe%10;
if (eNB->proc.threadPool.notFinishedJobs != 0 )
LOG_E(PHY,"no finisehd = %d\n",eNB->proc.threadPool.notFinishedJobs);
for (int i=0; i<NUMBER_OF_UE_MAX; i++) {
LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i];
LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid];
if (ulsch && ulsch->rnti>0 &&
ulsch_harq->status == ACTIVE &&
ulsch_harq->frame == frame && ulsch_harq->subframe == subframe &&
ulsch_harq->handled == 0 ) {
// UE has ULSCH scheduling
for (int rb=0; rb<=ulsch_harq->nb_rb; rb++) {
int rb2 = rb+ulsch_harq->first_rb;
eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
}
LOG_T(PHY,"\n"); nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
#endif
#endif ulsch->cyclicShift = (ulsch_harq->n_DMRS2 +
} // ulsch not in error fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
nPRS)%12;
start_meas(&eNB->ulsch_demodulation_stats);
rx_ulsch(eNB,proc, i);
stop_meas(&eNB->ulsch_demodulation_stats);
ulsch_harq->processedSegments=0;
ulsch_harq->processedBadSegment=0;
request_t* ret;
start_meas(&eNB->ulsch_decoding_stats);
ret = ulsch_decoding(eNB,proc,
i,
0, // control_only_flag
ulsch_harq->V_UL_DAI,
ulsch_harq->nb_rb>20 ? 1 : 0,
frame,
subframe);
stop_meas(&eNB->ulsch_decoding_stats);
if ( ret != NULL )
post_decode(ret);
} else if (ulsch && ulsch->rnti>0 &&
(ulsch_harq->status == ACTIVE) &&
(ulsch_harq->frame == frame) &&
(ulsch_harq->subframe == subframe) &&
(ulsch_harq->handled == 1)) {
// this harq process is stale, kill it, this 1024 frames later (10s), consider reducing that
ulsch_harq->status = SCH_IDLE;
ulsch_harq->handled = 0;
ulsch->harq_mask &= ~(1 << harq_pid);
LOG_W(PHY,"Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n",
ulsch->rnti, harq_pid, ulsch->harq_mask);
}
} // for (i=0; i<NUMBER_OF_UE_MAX; i++) {
if ( eNB->proc.threadPool.activated ) {
// Wait all other threads finish to process
//printf("%s:%d:%d\n", __FILE__,__LINE__,eNB->proc.threadPool.notFinishedJobs);
AssertFatal(pthread_mutex_lock(&eNB->proc.threadPool.lockReportDone)==0,"");
while ( eNB->proc.threadPool.notFinishedJobs > 0 ) {
//printf("%s:%d:%d\n", __FILE__,__LINE__,eNB->proc.threadPool.notFinishedJobs);
struct timespec t;
clock_gettime(CLOCK_REALTIME,&t);
t.tv_nsec+=100*1000*1000;
if ( t.tv_nsec >= 1000*1000*1000 ) {
t.tv_nsec -= 1000*1000*1000;
t.tv_sec++;
}
int rr;
if ((rr=pthread_cond_timedwait(&eNB->proc.threadPool.notifDone,&eNB->proc.threadPool.lockReportDone, &t))!=0)
LOG_E(PHY,"timedwait1:%s,%p,%p,%p,%d\n", rr==ETIMEDOUT?"ETIMEDOUT":"other",
eNB->proc.threadPool.oldestRequests,
eNB->proc.threadPool.newestRequests,
eNB->proc.threadPool.doneRequests,
eNB->proc.threadPool.notFinishedJobs);
if (ulsch_harq->O_ACK>0) fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,frame,subframe,ulsch->bundling); }
AssertFatal(pthread_mutex_unlock(&eNB->proc.threadPool.lockReportDone)==0,"");
LOG_D(PHY,"[eNB %d] Frame %d subframe %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n",
eNB->Mod_id,frame,subframe, request_t* tmp;
harq_pid, while ((tmp=eNB->proc.threadPool.doneRequests)!=NULL) {
i, tmp->returnTime=rdtsc();
ret, turboDecode_t * rdata=(turboDecode_t *) tmp->data;
ulsch_harq->cqi_crc_status, tmp->decodeIterations=rdata->decodeIterations;
ulsch_harq->o_ACK[0], // Ignore write error (if no trace listner)
ulsch_harq->o_ACK[1], if (write(eNB->proc.threadPool.traceFd, tmp, sizeof(request_t)- 2*sizeof(void*))) {};
eNB->UE_stats[i].ulsch_errors[harq_pid], eNB->proc.threadPool.doneRequests=tmp->next;
eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]); post_decode(tmp);
} // if ((ulsch) && }
// (ulsch->rnti>0) &&
// (ulsch_harq->status == ACTIVE))
else if ((ulsch) &&
(ulsch->rnti>0) &&
(ulsch_harq->status == ACTIVE) &&
(ulsch_harq->frame == frame) &&
(ulsch_harq->subframe == subframe) &&
(ulsch_harq->handled == 1)) {
// this harq process is stale, kill it, this 1024 frames later (10s), consider reducing that
ulsch_harq->status = SCH_IDLE;
ulsch_harq->handled = 0;
ulsch->harq_mask &= ~(1 << harq_pid);
LOG_W(PHY,"Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n",
ulsch->rnti, harq_pid, ulsch->harq_mask);
} }
} // for (i=0; i<NUMBER_OF_UE_MAX; i++)
} }
extern int oai_exit; extern int oai_exit;
...@@ -1586,15 +1647,27 @@ void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe) ...@@ -1586,15 +1647,27 @@ void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe)
// if (timing_advance_update > 10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} // if (timing_advance_update > 10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);}
// if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} // if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);}
switch (eNB->frame_parms.N_RB_DL) { switch (eNB->frame_parms.N_RB_DL) {
case 6: /* nothing to do */ break; case 6: /* nothing to do */
case 15: timing_advance_update /= 2; break; break;
case 25: timing_advance_update /= 4; break; case 15:
case 50: timing_advance_update /= 8; break; timing_advance_update /= 2;
case 75: timing_advance_update /= 12; break; break;
case 100: timing_advance_update /= 16; break; case 25:
default: abort(); timing_advance_update /= 4;
} break;
case 50:
timing_advance_update /= 8;
break;
case 75:
timing_advance_update /= 12;
break;
case 100:
timing_advance_update /= 16;
break;
default:
abort();
}
// put timing advance command in 0..63 range // put timing advance command in 0..63 range
timing_advance_update += 31; timing_advance_update += 31;
if (timing_advance_update < 0) timing_advance_update = 0; if (timing_advance_update < 0) timing_advance_update = 0;
......
...@@ -101,6 +101,7 @@ unsigned short config_frames[4] = {2,9,11,13}; ...@@ -101,6 +101,7 @@ unsigned short config_frames[4] = {2,9,11,13};
#endif #endif
#include "lte-softmodem.h" #include "lte-softmodem.h"
#include <thread-pool.h>
#ifdef XFORMS #ifdef XFORMS
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
// at eNB 0, an UL scope for every UE // at eNB 0, an UL scope for every UE
...@@ -133,6 +134,7 @@ volatile int start_UE = 0; ...@@ -133,6 +134,7 @@ volatile int start_UE = 0;
volatile int oai_exit = 0; volatile int oai_exit = 0;
static clock_source_t clock_source = internal; static clock_source_t clock_source = internal;
static char threadpool[1024]="";
static int wait_for_sync = 0; static int wait_for_sync = 0;
static char UE_flag=0; static char UE_flag=0;
...@@ -1311,8 +1313,14 @@ int main( int argc, char **argv ) ...@@ -1311,8 +1313,14 @@ int main( int argc, char **argv )
number_of_cards = 1; number_of_cards = 1;
printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst); printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
if (RC.nb_L1_inst > 0) { if (RC.nb_L1_inst > 0) {
printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", single_thread_flag,wait_for_sync); LOG_W(PHY, "Initializing eNB threads, single thread flag= %d, clock_source=%d\n", single_thread_flag, clock_source);
init_eNB(single_thread_flag,wait_for_sync); init_eNB(single_thread_flag,wait_for_sync);
if ( strlen(threadpool) > 0 ) {
LOG_W(PHY, "Creating turbo codec thread pool on cores: %s\n",threadpool);
init_tpool(threadpool, &RC.eNB[0][0]->proc.threadPool);
}
else
init_tpool("n", &RC.eNB[0][0]->proc.threadPool);
// for (inst=0;inst<RC.nb_L1_inst;inst++) // for (inst=0;inst<RC.nb_L1_inst;inst++)
// for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) phy_init_lte_eNB(RC.eNB[inst][CC_id],0,0); // for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) phy_init_lte_eNB(RC.eNB[inst][CC_id],0,0);
} }
......
...@@ -138,6 +138,7 @@ extern int16_t dlsch_demod_shift; ...@@ -138,6 +138,7 @@ extern int16_t dlsch_demod_shift;
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define CMDLINE_PARAMS_DESC { \ #define CMDLINE_PARAMS_DESC { \
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)}, \ {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)}, \
{"turbo-thread-pool", NULL, 0, strptr:(char **)&threadpool, defstrval:NULL, TYPE_STRING, sizeof(threadpool)}, \
{"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \ {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \
{"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&phy_test, defintval:0, TYPE_INT, 0}, \ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&phy_test, defintval:0, TYPE_INT, 0}, \
{"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&usim_test, defintval:0, TYPE_UINT8, 0}, \ {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&usim_test, defintval:0, TYPE_UINT8, 0}, \
......
#define __USE_GNU
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
// OAI includes
uint64_t cpuCyclesMicroSec;
static __inline__ uint64_t rdtsc(void) {
uint64_t a, d;
__asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
return (d<<32) | a;
}
#include "thread-pool.h"
int main(int argc, char* argv[]) {
uint64_t deb=rdtsc();
usleep(100000);
cpuCyclesMicroSec=(rdtsc()-deb)/100000;
printf("Cycles per µs: %lu\n",cpuCyclesMicroSec);
#define SEP " "
printf("Frame" SEP "SubFrame" SEP "CodeBlock" SEP "RNTI" SEP "Iterations" SEP
"StartTime" SEP "RunTime" SEP "ReturnTime" SEP
"CPUcore" SEP "ThreadID" "\n");
mkfifo("/tmp/test-tcri",0666);
int fd=open("/tmp/test-tcri", O_RDONLY);
if ( fd == -1 ) {
perror("open read mode trace file:");
exit(1);
}
request_t doneRequest;
int s=sizeof(request_t) -2*sizeof(void*);
while ( 1 ) {
if ( read(fd,&doneRequest, s) == s ) {
union turboReqUnion id={.p=doneRequest.id};
doneRequest.processedBy[15]='\0';
printf("%u" SEP "%u" SEP "%u" SEP "%u" SEP "%lu" SEP
"%lu" SEP "%lu" SEP "%lu" SEP
"%u" SEP "%s" "\n",
id.s.frame,
id.s.subframe,
id.s.codeblock,
id.s.rnti,
doneRequest.decodeIterations,
(doneRequest.startProcessingTime-doneRequest.creationTime)/cpuCyclesMicroSec,
(doneRequest.endProcessingTime-doneRequest.startProcessingTime)/cpuCyclesMicroSec,
(doneRequest.returnTime-doneRequest.endProcessingTime)/cpuCyclesMicroSec,
doneRequest.coreId,
doneRequest.processedBy
);
} else {
printf("no measurements\n");
sleep(1);
}
}
}
#define __USE_GNU
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <stdbool.h>
// OAI includes
#include <assertions.h>
#include <log.h>
#include "PHY/TOOLS/time_meas.h"
#include "PHY/CODING/defs.h"
#include "PHY/CODING/extern.h"
#include <thread-pool.h>
#ifdef DEBUG
#define THREADINIT PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
#else
#define THREADINIT PTHREAD_MUTEX_INITIALIZER
#endif
request_t * createRequest(enum request_t type,int size) {
request_t* request;
AssertFatal( (request = (request_t*)aligned_alloc(32,sizeof(request_t)+size)) != NULL,"");
request->id = 0;
request->type=type;
request->next = NULL;
request->creationTime=rdtsc();
request->data=(void*)(request+1);
return request;
}
void freeRequest(request_t* request) {
free(request);
}
int add_request(request_t* request, tpool_t * tp) {
AssertFatal(pthread_mutex_lock(&tp->lockRequests)==0,"");
if (tp->oldestRequests == NULL)
tp->oldestRequests = request;
else {
AssertFatal(tp->newestRequests != NULL, "");
tp->newestRequests->next = request;
}
tp->newestRequests = request;
AssertFatal(pthread_mutex_lock(&tp->lockReportDone)==0,"");
tp->notFinishedJobs++;
//printf("added:%d\n", tp->notFinishedJobs);
AssertFatal(pthread_mutex_unlock(&tp->lockReportDone)==0,"");
AssertFatal(pthread_cond_broadcast(&tp->notifRequest)==0,"");
AssertFatal(pthread_mutex_unlock(&tp->lockRequests)==0,"");
return 0;
}
int add_requests(uint64_t request_num, tpool_t * tp) {
request_t* request;
int nbToAdd=((uint32_t)lrand48())%20+1;
for (int i=0; i<nbToAdd; i++) {
// simulate request
request=createRequest(DECODE,sizeof(turboDecode_t));
union turboReqUnion id= {.s={request_num*100+i,1000,i*10,111,222}};
request->id= id.p;
turboDecode_t * rdata=(turboDecode_t *) request->data;
rdata->function=phy_threegpplte_turbo_decoder8;
rdata->Kr=6144;
rdata->iind=0; // not used, OAI code need cleanup!!!
rdata->Fbits=0;
rdata->maxIterations=6;
if (tp->oldestRequests == NULL)
tp->oldestRequests = request;
else
tp->newestRequests->next = request;
tp->newestRequests = request;
}
return nbToAdd;
}
request_t * get_request(tpool_t * tp, uint16_t threadID ) {
int nb=0;
request_t* r=tp->oldestRequests;
while (r!=NULL) {
nb++;
r=r->next;
}
request_t* request=tp->oldestRequests;
if (request == NULL)
return NULL;
if ( tp->restrictRNTI ) {
request_t** start=&tp->oldestRequests;
request = NULL;
while(*start!=NULL && request==NULL) {
union turboReqUnion id= {.p=(*start)->id};
if ( id.s.rnti % tp->nbThreads == threadID ) {
request=*start;
*start=(*start)->next;
} else
start=&((*start)->next);
}
} else
tp->oldestRequests = request->next;
if ( tp->oldestRequests == NULL)
tp->newestRequests=NULL;
int nnb=0;
r=tp->oldestRequests;
while (r!=NULL) {
nnb++;
r=r->next;
}
//if ( ! ( nb == nnb && request == NULL))
//printf("getr:was=%d,is=%d,gotit=%p\n",nb,nnb,request);
return request;
}
request_t * searchRNTI(tpool_t * tp, rnti_t rnti) {
request_t * result=NULL;
request_t ** start=&tp->oldestRequests;
while(*start!=NULL && result==NULL) {
union turboReqUnion id= {.p=(*start)->id};
if ( id.s.rnti == rnti ) {
result=*start;
*start=(*start)->next;
if ( tp->oldestRequests == NULL)
tp->newestRequests=NULL;
} else
start=&((*start)->next);
}
return result;
}
void process_request(request_t* request) {
//printf("S:%s...",request->type==DECODE?"D":"E");
switch(request->type) {
case DECODE : {
time_stats_t oaitimes[7];
turboDecode_t * rdata=(turboDecode_t*) request->data;
rdata->decodeIterations=rdata->function(rdata->soft_bits+96,
rdata->decoded_bytes,
rdata->Kr,
f1f2mat_old[rdata->iind*2],
f1f2mat_old[(rdata->iind*2)+1],
rdata->maxIterations,
rdata->nbSegments == 1 ? CRC24_A: CRC24_B,
rdata->Fbits,
oaitimes+0,
oaitimes+1,
oaitimes+2,
oaitimes+3,
oaitimes+4,
oaitimes+5,
oaitimes+6);
};
break;
case ENCODE : {
turboEncode_t * rdata=(turboEncode_t*) request->data;
memset(rdata->output,LTE_NULL,TURBO_SIMD_SOFTBITS);
threegpplte_turbo_encoder(rdata->input,
rdata->Kr_bytes,
rdata->output+96,//&dlsch->harq_processes[harq_pid]->d[r][96],
rdata->filler,
f1f2mat_old[rdata->iind*2], // f1 (see 36121-820, page 14)
f1f2mat_old[(rdata->iind*2)+1] // f2 (see 36121-820, page 14)
);
};
break;
default:
AssertFatal(false,"");
}
//printf("..End\n");
}
void handle_request(tpool_t * tp, request_t* request) {
request->startProcessingTime=rdtsc();
process_request(request);
request->endProcessingTime=rdtsc();
AssertFatal(pthread_mutex_lock(&tp->lockReportDone)==0,"");
tp->notFinishedJobs--;
//printf("Removed:%d\n",tp->notFinishedJobs);
request->next=tp->doneRequests;
tp->doneRequests=request;
//printf("signaling ...");
AssertFatal(pthread_cond_signal(&tp->notifDone)==0,"");
//printf("...done\n");
AssertFatal(pthread_mutex_unlock(&tp->lockReportDone)==0,"");
/*
printf("Thread '%ld' handled request '%d' delay in µs:%ld\n",
syscall( SYS_gettid ),
request->id,
(rdtsc() - request->creationTime)/tp->cpuCyclesMicroSec);
*/
}
void* one_thread(void* data) {
struct one_thread * myThread=(struct one_thread *) data;
struct thread_pool* tp=myThread->pool;
// configure the thread core assignment
// TBD: reserve the core for us exclusively
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(myThread->coreID, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
//Configure the thread scheduler policy for Linux
struct sched_param sparam= {0};
sparam.sched_priority = sched_get_priority_max(SCHED_RR);
pthread_setschedparam(pthread_self(), SCHED_RR, &sparam);
// set the thread name for debugging
sprintf(myThread->name,"Tcodec_%d",myThread->coreID);
pthread_setname_np(pthread_self(), myThread->name );
// Infinite loop to process requests
do {
AssertFatal(pthread_mutex_lock(&tp->lockRequests)==0,"");
request_t* request = get_request(tp, myThread->id);
if (request == NULL) {
AssertFatal(pthread_cond_wait(&tp->notifRequest,&tp->lockRequests)==0,"");
request = get_request(tp, myThread->id);
}
AssertFatal(pthread_mutex_unlock(&tp->lockRequests)==0,"");
if (request!=NULL) {
strncpy(request->processedBy,myThread->name, 15);
request->coreId=myThread->coreID;
handle_request(tp, request);
}
} while (true);
}
void init_tpool(char * params,tpool_t * pool) {
mkfifo("/tmp/test-tcri",0666);
pool->dummyTraceFd=open("/tmp/test-tcri", O_RDONLY| O_NONBLOCK);
if ( pool->dummyTraceFd == -1 ) {
perror("open read mode trace file:");
exit(1);
}
pool->traceFd=open("/tmp/test-tcri", O_WRONLY|O_APPEND|O_NOATIME|O_NONBLOCK);
if ( pool->traceFd == -1 ) {
perror("open trace file:");
exit(1);
}
//Configure the thread scheduler policy for Linux
struct sched_param sparam= {0};
sparam.sched_priority = sched_get_priority_max(SCHED_RR)-1;
pthread_setschedparam(pthread_self(), SCHED_RR, &sparam);
pool->activated=true;
pthread_mutex_init(&pool->lockRequests,NULL);
pthread_cond_init (&pool->notifRequest,NULL);
pthread_mutex_init(&pool->lockReportDone,NULL);
pthread_cond_init (&pool->notifDone,NULL);
pool->oldestRequests=NULL;
pool->newestRequests=NULL;
pool->doneRequests=NULL;
pool->notFinishedJobs=0;
pool->allthreads=NULL;
char * saveptr, * curptr;
pool->nbThreads=0;
pool->restrictRNTI=false;
curptr=strtok_r(params,",",&saveptr);
while ( curptr!=NULL ) {
if (curptr[0] == 'u' || curptr[0] == 'U') {
pool->restrictRNTI=true;
} else if ( curptr[0]>='0' && curptr[0]<='9' ) {
struct one_thread *tmp=pool->allthreads;
pool->allthreads=(struct one_thread *)malloc(sizeof(struct one_thread));
pool->allthreads->next=tmp;
printf("create a thread for core %d\n", atoi(curptr));
pool->allthreads->coreID=atoi(curptr);
pool->allthreads->id=pool->nbThreads;
pool->allthreads->pool=pool;
pthread_create(&pool->allthreads->threadID, NULL, one_thread, (void*)pool->allthreads);
pool->nbThreads++;
} else if (curptr[0] == 'n' || curptr[0] == 'N') {
pool->activated=false;
} else
printf("Error in options for thread pool: %s\n",curptr);
curptr=strtok_r(NULL,",",&saveptr);
}
if (pool->activated && pool->nbThreads==0) {
printf("No servers created in the thread pool, exit\n");
exit(1);
}
uint64_t deb=rdtsc();
usleep(100000);
pool->cpuCyclesMicroSec=(rdtsc()-deb)/100000;
printf("Cycles per µs: %lu\n",pool->cpuCyclesMicroSec);
}
void displayList(request_t*start, request_t*end) {
int n=0;
while(start!=NULL) {
n++;
union turboReqUnion id= {.p=start->id};
printf("rnti:%u frame:%u-%u codeblock:%u\n",
id.s.rnti,
id.s.frame,
id.s.subframe,
id.s.codeblock);
if ( start->next==NULL && start!=end)
printf("Error of end pointer");
start=start->next;
}
printf("End of list: %d elements\n",n);
}
#ifdef TESTMAIN
#include "PHY/CODING/lte_interleaver.h"
#include "PHY/CODING/lte_interleaver2.h"
int main(int argc, char* argv[]) {
if (argc<2) {
printf("Usage: %s core,core,...\n",argv[0]);
exit(1);
}
// configure the thread core assignment: client thread on core 0
// TBD: reserve the core for us exclusively
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
tpool_t pool;
init_tpool(argv[1], &pool);
//initialize turbo decoder tables
init_td8();
uint64_t i=1;
// Test the lists
srand48(time(NULL));
AssertFatal(pthread_mutex_lock(&pool.lockRequests)==0,"");
int nbRequest=add_requests(i, &pool);
printf("These should be: %d elements in the list\n",nbRequest);
displayList(pool.oldestRequests, pool.newestRequests);
// remove in middle
request_t *req106=searchRNTI(&pool.oldestRequests, &pool.newestRequests, 106);
if (req106) {
union turboReqUnion id= {.p=req106->id};
printf("Removed: rnti:%u frame:%u-%u codeblock:%u, check it\n",
id.s.rnti,
id.s.frame,
id.s.subframe,
id.s.codeblock);
freeRequest(req106);
} else
printf("no rnti 106\n");
displayList(pool.oldestRequests, pool.newestRequests);
request_t *reqlast=searchRNTI(&pool.oldestRequests, &pool.newestRequests,
100+nbRequest-1);
if (reqlast) {
printf("Removed last item, check it\n");
freeRequest(reqlast);
} else
printf("tried to removed from empty list\n");
displayList(pool.oldestRequests, pool.newestRequests);
printf("Remove all jobs\n");
while(pool.oldestRequests!=NULL)
get_request(&pool);
printf("List should be empty now\n");
displayList(pool.oldestRequests, pool.newestRequests);
AssertFatal(pthread_mutex_unlock(&pool.lockRequests)==0,"");
while (1) {
uint64_t now=rdtsc();
/* run a loop that generates a lot of requests */
AssertFatal(pthread_mutex_lock(&pool.lockRequests)==0,"");
int nbRequest=add_requests(i, &pool);
AssertFatal(pthread_mutex_lock(&pool.lockReportDone)==0,"");
pool.notFinishedJobs+=nbRequest;
AssertFatal(pthread_mutex_unlock(&pool.lockReportDone)==0,"");
AssertFatal(pthread_cond_broadcast(&pool.notifRequest)==0,"");
AssertFatal(pthread_mutex_unlock(&pool.lockRequests)==0,"");
/*
// The main thread also process the queue
AssertFatal(pthread_mutex_lock(&pool.lockRequests)==0,"");
request_t* request= NULL;
while ( (request=get_request(&pool)) != NULL ) {
AssertFatal(pthread_mutex_unlock(&pool.lockRequests)==0,"");
strcpy(request->processedBy,"MainThread");
handle_request(&pool, request);
AssertFatal(pthread_mutex_lock(&pool.lockRequests)==0,"");
}
AssertFatal(pthread_mutex_unlock(&pool.lockRequests)==0,"");
*/
// Wait all other threads finish to process
AssertFatal(pthread_mutex_lock(&pool.lockReportDone)==0,"");
while ( pool.notFinishedJobs > 0 ) {
AssertFatal(pthread_cond_wait(&pool.notifDone,&pool.lockReportDone)==0,"");
}
AssertFatal(pthread_mutex_unlock(&pool.lockReportDone)==0,"");
while (pool.doneRequests!=NULL) {
pool.doneRequests->returnTime=rdtsc();
if(write(pool.traceFd,pool.doneRequests,sizeof(request_t))) {};
request_t* tmp=pool.doneRequests;
pool.doneRequests=pool.doneRequests->next;
free(tmp);
}
printf("Requests %lu Done %d requests in %ld µsec\n",i, nbRequest, (rdtsc()-now)/pool.cpuCyclesMicroSec);
i++;
};
return 0;
}
#endif
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#include <stdbool.h>
#include <openair2/COMMON/platform_types.h>
enum request_t {
DECODE,
ENCODE
};
struct turboReqId {
uint16_t rnti;
uint16_t frame;
uint8_t subframe;
uint8_t codeblock;
uint16_t spare;
} __attribute__((packed));
union turboReqUnion {
struct turboReqId s;
uint64_t p;
};
typedef struct request {
uint64_t id;
enum request_t type;
uint64_t creationTime;
uint64_t startProcessingTime;
uint64_t endProcessingTime;
uint64_t returnTime;
uint64_t decodeIterations;
int coreId;
char processedBy[16];
struct request* next;
void * data __attribute__((aligned(32)));
} request_t;
struct one_thread {
pthread_t threadID;
int id;
int coreID;
char name[256];
struct thread_pool * pool;
struct one_thread* next;
};
typedef struct thread_pool {
int activated;
pthread_mutex_t lockRequests;
pthread_cond_t notifRequest;
pthread_mutex_t lockReportDone;
pthread_cond_t notifDone;
request_t* oldestRequests;
request_t* newestRequests;
request_t* doneRequests;
int notFinishedJobs;
int traceFd;
int dummyTraceFd;
uint64_t cpuCyclesMicroSec;
int nbThreads;
bool restrictRNTI;
struct one_thread * allthreads;
} tpool_t;
void init_tpool(char*,tpool_t* );
request_t * createRequest(enum request_t type,int size);
void freeRequest(request_t* request);
int add_request(request_t* request, tpool_t * tp);
request_t * searchRNTI(tpool_t*, rnti_t rnti);
#endif
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