Merge branch 'next' into enbmimo

master
Xavier Arteaga 7 years ago
commit 96a6d6ae9f

@ -61,7 +61,7 @@ set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "")
option(ENABLE_SRSUE "Build srsUE application" ON) option(ENABLE_SRSUE "Build srsUE application" ON)
option(ENABLE_SRSENB "Build srsENB application" ON) option(ENABLE_SRSENB "Build srsENB application" ON)
option(ENABLE_VOLK "Enable use of VOLK SIMD library" ON) option(ENABLE_VOLK "Enable use of VOLK SIMD library" OFF)
option(ENABLE_GUI "Enable GUI (using srsGUI)" ON) option(ENABLE_GUI "Enable GUI (using srsGUI)" ON)
option(ENABLE_BLADERF "Enable BladeRF" ON) option(ENABLE_BLADERF "Enable BladeRF" ON)
@ -282,6 +282,11 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
endif(HAVE_AVX) endif(HAVE_AVX)
endif (HAVE_AVX2) endif (HAVE_AVX2)
if (HAVE_AVX512)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx512f -mavx512cd -DLV_HAVE_AVX512")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -mavx512cd -DLV_HAVE_AVX512")
endif(HAVE_AVX512)
if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
if(HAVE_SSE) if(HAVE_SSE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Ofast -funroll-loops") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Ofast -funroll-loops")

@ -4,10 +4,11 @@
include(CheckCSourceRuns) include(CheckCSourceRuns)
option(ENABLE_SSE "Enable compile-time SSE4.1 support." ON) option(ENABLE_SSE "Enable compile-time SSE4.1 support." ON)
option(ENABLE_AVX "Enable compile-time AVX support." ON) option(ENABLE_AVX "Enable compile-time AVX support." ON)
option(ENABLE_AVX2 "Enable compile-time AVX2 support." ON) option(ENABLE_AVX2 "Enable compile-time AVX2 support." ON)
option(ENABLE_FMA "Enable compile-time FMA support." ON) option(ENABLE_FMA "Enable compile-time FMA support." ON)
option(ENABLE_AVX512 "Enable compile-time AVX512 support." ON)
if (ENABLE_SSE) if (ENABLE_SSE)
# #
@ -135,6 +136,41 @@ if (ENABLE_SSE)
endif() endif()
endif() endif()
if (ENABLE_AVX512)
#
# Check compiler for AVX intrinsics
#
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG )
set(CMAKE_REQUIRED_FLAGS "-mavx512f")
check_c_source_runs("
#include <immintrin.h>
int main()
{
__m512i a, b, c;
const int src[16] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 , 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
int dst[16];
a = _mm512_loadu_si512( (__m512i*)src );
b = _mm512_loadu_si512( (__m512i*)src );
c = _mm512_add_epi32( a, b );
_mm512_storeu_si512( (__m512i*)dst, c );
int i = 0;
for( i = 0; i < 16; i++ ){
if( ( src[i] + src[i] ) != dst[i] ){
return -1;
}
}
return 0;
}"
HAVE_AVX512)
endif()
if (HAVE_AVX512)
message(STATUS "AVX512 is enabled - target CPU must support it")
endif()
endif()
endif() endif()
mark_as_advanced(HAVE_SSE, HAVE_AVX, HAVE_AVX2, HAVE_FMA) mark_as_advanced(HAVE_SSE, HAVE_AVX, HAVE_AVX2, HAVE_FMA, HAVE_AVX512)

@ -1,161 +0,0 @@
INCLUDE(FindPkgConfig)
PKG_CHECK_MODULES(PC_VOLK volk QUIET)
FIND_PATH(
VOLK_INCLUDE_DIRS
NAMES volk/volk.h
HINTS $ENV{VOLK_DIR}/include
${CMAKE_INSTALL_PREFIX}/include
${PC_VOLK_INCLUDE_DIR}
PATHS /usr/local/include
/usr/include
)
FIND_LIBRARY(
VOLK_LIBRARIES
NAMES volk
HINTS $ENV{VOLK_DIR}/lib
${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
${PC_VOLK_LIBDIR}
PATHS /usr/local/lib
/usr/local/lib64
/usr/lib
/usr/lib64
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(VOLK DEFAULT_MSG VOLK_LIBRARIES VOLK_INCLUDE_DIRS)
MARK_AS_ADVANCED(VOLK_LIBRARIES VOLK_INCLUDE_DIRS VOLK_DEFINITIONS)
IF(VOLK_FOUND)
SET(CMAKE_REQUIRED_LIBRARIES ${VOLK_LIBRARIES} m)
CHECK_FUNCTION_EXISTS_MATH(volk_16i_s32f_convert_32f HAVE_VOLK_CONVERT_IF_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_index_max_16u HAVE_VOLK_MAX_FUNCTION_16)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_index_max_32u HAVE_VOLK_MAX_FUNCTION_32)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_max_32f HAVE_VOLK_MAX_VEC_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_accumulator_s32f HAVE_VOLK_ACC_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_s32fc_multiply_32fc HAVE_VOLK_MULT_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_conjugate_32fc HAVE_VOLK_CONJ_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_multiply_32fc HAVE_VOLK_MULT2_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_multiply_conjugate_32fc HAVE_VOLK_MULT2_CONJ_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_32f_multiply_32fc HAVE_VOLK_MULT_REAL_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_s32f_multiply_32f HAVE_VOLK_MULT_FLOAT_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_magnitude_32f HAVE_VOLK_MAG_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_magnitude_squared_32f HAVE_VOLK_MAG_SQUARE_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_divide_32f HAVE_VOLK_DIVIDE_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_dot_prod_32fc HAVE_VOLK_DOTPROD_FC_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_32f_dot_prod_32fc HAVE_VOLK_DOTPROD_CFC_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_conjugate_dot_prod_32fc HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_dot_prod_32f HAVE_VOLK_DOTPROD_F_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_s32f_atan2_32f HAVE_VOLK_ATAN_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_s32f_convert_16i HAVE_VOLK_CONVERT_FI_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_deinterleave_32f_x2 HAVE_VOLK_DEINTERLEAVE_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_interleave_32fc HAVE_VOLK_INTERLEAVE_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_subtract_32f HAVE_VOLK_SUB_FLOAT_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_add_32f HAVE_VOLK_ADD_FLOAT_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_square_dist_32f HAVE_VOLK_SQUARE_DIST_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_deinterleave_real_32f HAVE_VOLK_DEINTERLEAVE_REAL_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_index_max_16u HAVE_VOLK_MAX_ABS_FUNCTION_16)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_index_max_32u HAVE_VOLK_MAX_ABS_FUNCTION_32)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_multiply_32f HAVE_VOLK_MULT_REAL2_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_16i_max_star_16i HAVE_VOLK_MAX_STAR_S_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_8i_convert_16i HAVE_VOLK_CONVERT_CI_FUNCTION)
SET(VOLK_DEFINITIONS "HAVE_VOLK")
IF(${HAVE_VOLK_CONVERT_IF_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_CONVERT_IF_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MULT_REAL2_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT_REAL2_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_CONVERT_CI_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_CONVERT_CI_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MAX_STAR_S_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_STAR_S_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MAX_ABS_FUNCTION_16})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_ABS_FUNCTION_16")
ENDIF()
IF(${HAVE_VOLK_MAX_ABS_FUNCTION_32})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_ABS_FUNCTION_32")
ENDIF()
IF(${HAVE_VOLK_MAX_VEC_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_VEC_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MAG_SQUARE_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAG_SQUARE_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_SQUARE_DIST_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_SQUARE_DIST_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_DEINTERLEAVE_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DEINTERLEAVE_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_INTERLEAVE_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_INTERLEAVE_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_SUB_FLOAT_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_SUB_FLOAT_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_ADD_FLOAT_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_ADD_FLOAT_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MULT2_CONJ_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT2_CONJ_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_DEINTERLEAVE_REAL_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DEINTERLEAVE_REAL_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_CONVERT_FI_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_CONVERT_FI_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MAX_FUNCTION_16})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_FUNCTION_16")
ENDIF()
IF(${HAVE_VOLK_MAX_FUNCTION_32})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_FUNCTION_32")
ENDIF()
IF(${HAVE_VOLK_ACC_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_ACC_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MULT_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_CONJ_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_CONJ_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MULT2_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT2_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MULT_FLOAT_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT_FLOAT_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MULT_REAL_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT_REAL_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MAG_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAG_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_DIVIDE_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DIVIDE_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_DOTPROD_FC_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_FC_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_DOTPROD_CFC_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_CFC_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_DOTPROD_F_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_F_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_ATAN_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_ATAN_FUNCTION")
ENDIF()
ENDIF(VOLK_FOUND)

@ -249,7 +249,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
return -1; return -1;
} }
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) { if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, 1)) {
fprintf(stderr, "Error initiating UE downlink processing module\n"); fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1; return -1;
} }
@ -257,7 +257,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating UE downlink processing module\n"); fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1; return -1;
} }
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) { if (srslte_ue_mib_init(&ue_mib, sf_buffer, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n"); fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1; return -1;
} }
@ -272,7 +272,15 @@ int main(int argc, char **argv) {
/* Initialize subframe counter */ /* Initialize subframe counter */
sf_cnt = 0; sf_cnt = 0;
if (srslte_ofdm_rx_init(&fft, cell.cp, cell.nof_prb)) { int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re);
}
if (srslte_ofdm_rx_init(&fft, cell.cp, sf_buffer[0], sf_symbols, cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n"); fprintf(stderr, "Error initiating FFT\n");
return -1; return -1;
} }
@ -285,14 +293,6 @@ int main(int argc, char **argv) {
return -1; return -1;
} }
int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re);
}
srslte_rf_start_rx_stream(&rf); srslte_rf_start_rx_stream(&rf);
float rx_gain_offset = 0; float rx_gain_offset = 0;
@ -315,7 +315,7 @@ int main(int argc, char **argv) {
case DECODE_MIB: case DECODE_MIB:
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) { if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
srslte_pbch_decode_reset(&ue_mib.pbch); srslte_pbch_decode_reset(&ue_mib.pbch);
n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset); n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n"); fprintf(stderr, "Error decoding UE MIB\n");
return -1; return -1;
@ -351,7 +351,7 @@ int main(int argc, char **argv) {
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) { if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
/* Run FFT for all subframe data */ /* Run FFT for all subframe data */
srslte_ofdm_rx_sf(&fft, sf_buffer[0], sf_symbols); srslte_ofdm_rx_sf(&fft);
srslte_chest_dl_estimate(&chest, sf_symbols, ce, srslte_ue_sync_get_sfidx(&ue_sync)); srslte_chest_dl_estimate(&chest, sf_symbols, ce, srslte_ue_sync_get_sfidx(&ue_sync));

@ -86,7 +86,7 @@ float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000;
bool null_file_sink=false; bool null_file_sink=false;
srslte_filesink_t fsink; srslte_filesink_t fsink;
srslte_ofdm_t ifft; srslte_ofdm_t ifft[SRSLTE_MAX_PORTS];
srslte_ofdm_t ifft_mbsfn; srslte_ofdm_t ifft_mbsfn;
srslte_pbch_t pbch; srslte_pbch_t pbch;
srslte_pcfich_t pcfich; srslte_pcfich_t pcfich;
@ -311,18 +311,21 @@ void base_init() {
} }
/* create ifft object */ /* create ifft object */
if (srslte_ofdm_tx_init(&ifft, SRSLTE_CP_NORM, cell.nof_prb)) { for (i = 0; i < cell.nof_ports; i++) {
fprintf(stderr, "Error creating iFFT object\n"); if (srslte_ofdm_tx_init(&ifft[i], SRSLTE_CP_NORM, sf_buffer[i], output_buffer[i], cell.nof_prb)) {
exit(-1); fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_normalize(&ifft[i], true);
} }
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) {
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, sf_buffer[0], output_buffer[0], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n"); fprintf(stderr, "Error creating iFFT object\n");
exit(-1); exit(-1);
} }
srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, 2); srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, 2);
srslte_ofdm_set_normalize(&ifft_mbsfn, true); srslte_ofdm_set_normalize(&ifft_mbsfn, true);
srslte_ofdm_set_normalize(&ifft, true);
if (srslte_pbch_init(&pbch)) { if (srslte_pbch_init(&pbch)) {
fprintf(stderr, "Error creating PBCH object\n"); fprintf(stderr, "Error creating PBCH object\n");
@ -413,8 +416,9 @@ void base_free() {
srslte_pmch_free(&pmch); srslte_pmch_free(&pmch);
} }
srslte_ofdm_tx_free(&ifft_mbsfn); srslte_ofdm_tx_free(&ifft_mbsfn);
srslte_ofdm_tx_free(&ifft); for (i = 0; i < cell.nof_ports; i++) {
srslte_ofdm_tx_free(&ifft[i]);
}
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (data[i]) { if (data[i]) {
@ -977,10 +981,10 @@ int main(int argc, char **argv) {
/* Transform to OFDM symbols */ /* Transform to OFDM symbols */
if(sf_idx != 1 || mbsfn_area_id < 0){ if(sf_idx != 1 || mbsfn_area_id < 0){
for (i = 0; i < cell.nof_ports; i++) { for (i = 0; i < cell.nof_ports; i++) {
srslte_ofdm_tx_sf(&ifft, sf_buffer[i], output_buffer[i]); srslte_ofdm_tx_sf(&ifft[i]);
} }
}else{ }else{
srslte_ofdm_tx_sf(&ifft_mbsfn, sf_buffer[0], output_buffer[0]); srslte_ofdm_tx_sf(&ifft_mbsfn);
} }
/* send to file or usrp */ /* send to file or usrp */

@ -510,7 +510,10 @@ int main(int argc, char **argv) {
#endif #endif
} }
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) { for (int i=0;i<prog_args.rf_nof_rx_ant;i++) {
sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
if (srslte_ue_mib_init(&ue_mib, sf_buffer, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n"); fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1); exit(-1);
} }
@ -519,7 +522,7 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, prog_args.rf_nof_rx_ant)) { if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
fprintf(stderr, "Error initiating UE downlink processing module\n"); fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1); exit(-1);
} }
@ -528,10 +531,6 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
for (int i=0;i<prog_args.rf_nof_rx_ant;i++) {
sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */ /* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti); srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti);
@ -632,7 +631,7 @@ int main(int argc, char **argv) {
switch (state) { switch (state) {
case DECODE_MIB: case DECODE_MIB:
if (sfidx == 0) { if (sfidx == 0) {
n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset); n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n"); fprintf(stderr, "Error decoding UE MIB\n");
exit(-1); exit(-1);

@ -6435,11 +6435,102 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mobility_from_eutra_command_msg(LIBLTE_BIT_M
Document Reference: 36.331 v10.0.0 Section 6.2.2 Document Reference: 36.331 v10.0.0 Section 6.2.2
*********************************************************************/ *********************************************************************/
// Defines typedef struct{
// Enums LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT cell_global_id;
uint16 tracking_area_code;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_identity_list[5];
uint32 n_plmn_identity_list;
bool have_plmn_identity_list;
}LIBLTE_RRC_CGI_INFO_STRUCT;
LIBLTE_ERROR_ENUM liblte_rrc_pack_cgi_info_ie(LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info,
uint8 **ie_ptr);
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cgi_info_ie(uint8 **ie_ptr,
LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info);
typedef struct{
uint8 rsrp_result;
bool have_rsrp;
uint8 rsrq_result;
bool have_rsrq;
}LIBLTE_RRC_MEAS_RESULT_STRUCT;
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_ie(LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result,
uint8 **ie_ptr);
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_ie(uint8 **ie_ptr,
LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result);
typedef struct{
uint16 phys_cell_id;
LIBLTE_RRC_CGI_INFO_STRUCT cgi_info;
bool have_cgi_info;
LIBLTE_RRC_MEAS_RESULT_STRUCT meas_result;
}LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT;
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_eutra_ie(LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra,
uint8 **ie_ptr);
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_eutra_ie(uint8 **ie_ptr,
LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra);
typedef struct{
//FIXME
}LIBLTE_RRC_MEAS_RESULT_UTRA_STRUCT;
typedef struct{
//FIXME
}LIBLTE_RRC_MEAS_RESULT_GERAN_STRUCT;
typedef struct{
//FIXME
}LIBLTE_RRC_MEAS_RESULT_CDMA2000_STRUCT;
typedef struct{
LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT result_eutra_list[8];
uint8 n_result;
}LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT;
typedef struct{
LIBLTE_RRC_MEAS_RESULT_UTRA_STRUCT result_utra_list[8];
uint8 n_result;
}LIBLTE_RRC_MEAS_RESULT_LIST_UTRA_STRUCT;
typedef struct{
LIBLTE_RRC_MEAS_RESULT_GERAN_STRUCT result_geran_list[8];
uint8 n_result;
}LIBLTE_RRC_MEAS_RESULT_LIST_GERAN_STRUCT;
typedef struct{
bool pre_registration_status_HRPD;
LIBLTE_RRC_MEAS_RESULT_CDMA2000_STRUCT cdma2000[8];
}LIBLTE_RRC_MEAS_RESULTS_CDMA2000_STRUCT;
typedef enum{
LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA = 0,
LIBLTE_RRC_MEAS_RESULT_LIST_UTRA,
LIBLTE_RRC_MEAS_RESULT_LIST_GERAN,
LIBLTE_RRC_MEAS_RESULTS_CDMA2000,
LIBLTE_RRC_MEAS_RESULT_N_ITEMS,
}LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM;
static const char liblte_rrc_meas_reult_neigh_cells_text[LIBLTE_RRC_MEAS_RESULT_N_ITEMS][32] = { "measResultListEUTRA", "measResultListUTRA", "measResultListGERAN", "measResultsCDMA2000"};
typedef union{
LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT eutra;
LIBLTE_RRC_MEAS_RESULT_LIST_UTRA_STRUCT utra;
LIBLTE_RRC_MEAS_RESULT_LIST_GERAN_STRUCT geran;
LIBLTE_RRC_MEAS_RESULTS_CDMA2000_STRUCT cdma2000;
}LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_UNION;
//TODO: pack/unpack for the result lists
// Structs // Structs
typedef struct{ typedef struct{
// FIXME uint8 meas_id;
uint8 pcell_rsrp_result;
uint8 pcell_rsrq_result;
LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_UNION meas_result_neigh_cells;
LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM meas_result_neigh_cells_choice;
bool have_meas_result_neigh_cells;
}LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT; }LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT;
// Functions // Functions
LIBLTE_ERROR_ENUM liblte_rrc_pack_measurement_report_msg(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report, LIBLTE_ERROR_ENUM liblte_rrc_pack_measurement_report_msg(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report,

@ -93,7 +93,7 @@ public:
available.pop(); available.pop();
if (available.size() < capacity/20) { if (available.size() < capacity/20) {
printf("Warning buffer pool capacity is %f %%\n", (float) available.size()/capacity); printf("Warning buffer pool capacity is %f %%\n", (float) 100*available.size()/capacity);
} }
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
if (debug_name) { if (debug_name) {

@ -44,6 +44,16 @@
#define SRSLTE_N_DRB 8 #define SRSLTE_N_DRB 8
#define SRSLTE_N_RADIO_BEARERS 11 #define SRSLTE_N_RADIO_BEARERS 11
#define HARQ_DELAY_MS 4
#define MSG3_DELAY_MS 2 // Delay added to HARQ_DELAY_MS
#define TTI_TX(tti) ((tti+HARQ_DELAY_MS)%10240)
#define TTI_RX_ACK(tti) ((tti+(2*HARQ_DELAY_MS))%10240)
#define TTIMOD_SZ (((2*HARQ_DELAY_MS) < 10)?10:20)
#define TTIMOD(tti) (tti%TTIMOD_SZ)
#define ASYNC_DL_SCHED (HARQ_DELAY_MS <= 4)
// Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI // Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI
// 3GPP 36.306 Table 4.1.1 // 3GPP 36.306 Table 4.1.1
#define SRSLTE_MAX_BUFFER_SIZE_BITS 102048 #define SRSLTE_MAX_BUFFER_SIZE_BITS 102048

@ -31,8 +31,13 @@ template<typename metrics_t>
class metrics_hub : public periodic_thread class metrics_hub : public periodic_thread
{ {
public: public:
bool init(metrics_interface<metrics_t> *m_, float report_period_secs=1.0) { metrics_hub()
:m(NULL)
,report_period_secs(1)
{}
bool init(metrics_interface<metrics_t> *m_, float report_period_secs_=1.0) {
m = m_; m = m_;
report_period_secs = report_period_secs_;
start_periodic(report_period_secs*1e6); start_periodic(report_period_secs*1e6);
return true; return true;
} }
@ -47,16 +52,18 @@ public:
private: private:
void run_period() { void run_period() {
metrics_t metric; if (m) {
bzero(&metric, sizeof(metrics_t)); metrics_t metric;
m->get_metrics(metric); bzero(&metric, sizeof(metrics_t));
for (uint32_t i=0;i<listeners.size();i++) { m->get_metrics(metric);
listeners[i]->set_metrics(metric); for (uint32_t i=0;i<listeners.size();i++) {
listeners[i]->set_metrics(metric, report_period_secs);
}
} }
} }
metrics_interface<metrics_t> *m; metrics_interface<metrics_t> *m;
std::vector<metrics_listener<metrics_t>*> listeners; std::vector<metrics_listener<metrics_t>*> listeners;
float report_period_secs;
}; };
} // namespace srslte } // namespace srslte

@ -59,5 +59,6 @@
// cf_t definition // cf_t definition
typedef _Complex float cf_t; typedef _Complex float cf_t;
typedef _Complex short int c16_t;
#endif // CONFIG_H #endif // CONFIG_H

@ -446,6 +446,7 @@ typedef struct {
std::string snr_estim_alg; std::string snr_estim_alg;
bool cfo_integer_enabled; bool cfo_integer_enabled;
float cfo_correct_tol_hz; float cfo_correct_tol_hz;
float cfo_ema;
int time_correct_period; int time_correct_period;
bool sfo_correct_disable; bool sfo_correct_disable;
std::string sss_algorithm; std::string sss_algorithm;

@ -101,8 +101,8 @@ typedef enum {SRSLTE_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t;
#define SRSLTE_CP_ISEXT(cp) (cp==SRSLTE_CP_EXT) #define SRSLTE_CP_ISEXT(cp) (cp==SRSLTE_CP_EXT)
#define SRSLTE_CP_NSYMB(cp) (SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB) #define SRSLTE_CP_NSYMB(cp) (SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB)
#define SRSLTE_CP_LEN(symbol_sz, c) ((int) ceil((((float) (c)*(symbol_sz))/2048))) #define SRSLTE_CP_LEN(symbol_sz, c) ((int) ceilf((((float) (c)*(symbol_sz))/2048.0f)))
#define SRSLTE_CP_LEN_NORM(symbol, symbol_sz) ((symbol==0)?SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_LEN)) #define SRSLTE_CP_LEN_NORM(symbol, symbol_sz) (((symbol)==0)?SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_LEN))
#define SRSLTE_CP_LEN_EXT(symbol_sz) (SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_EXT_LEN)) #define SRSLTE_CP_LEN_EXT(symbol_sz) (SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_EXT_LEN))
#define SRSLTE_SLOT_LEN(symbol_sz) (symbol_sz*15/2) #define SRSLTE_SLOT_LEN(symbol_sz) (symbol_sz*15/2)
@ -197,7 +197,8 @@ typedef enum SRSLTE_API {
SRSLTE_MOD_BPSK = 0, SRSLTE_MOD_BPSK = 0,
SRSLTE_MOD_QPSK, SRSLTE_MOD_QPSK,
SRSLTE_MOD_16QAM, SRSLTE_MOD_16QAM,
SRSLTE_MOD_64QAM SRSLTE_MOD_64QAM,
SRSLTE_MOD_LAST
} srslte_mod_t; } srslte_mod_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {

@ -63,6 +63,7 @@ typedef struct SRSLTE_API {
void *in; // Input buffer void *in; // Input buffer
void *out; // Output buffer void *out; // Output buffer
void *p; // DFT plan void *p; // DFT plan
bool is_guru;
bool forward; // Forward transform? bool forward; // Forward transform?
bool mirror; // Shift negative and positive frequencies? bool mirror; // Shift negative and positive frequencies?
bool db; // Provide output in dB? bool db; // Provide output in dB?
@ -85,6 +86,17 @@ SRSLTE_API int srslte_dft_plan_c(srslte_dft_plan_t *plan,
int dft_points, int dft_points,
srslte_dft_dir_t dir); srslte_dft_dir_t dir);
SRSLTE_API int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan,
int dft_points,
srslte_dft_dir_t dir,
cf_t *in_buffer,
cf_t *out_buffer,
int istride,
int ostride,
int how_many,
int idist,
int odist);
SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan, SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan,
int dft_points, int dft_points,
srslte_dft_dir_t dir); srslte_dft_dir_t dir);
@ -92,6 +104,16 @@ SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan,
SRSLTE_API int srslte_dft_replan(srslte_dft_plan_t *plan, SRSLTE_API int srslte_dft_replan(srslte_dft_plan_t *plan,
const int new_dft_points); const int new_dft_points);
SRSLTE_API int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan,
const int new_dft_points,
cf_t *in_buffer,
cf_t *out_buffer,
int istride,
int ostride,
int how_many,
int idist,
int odist);
SRSLTE_API int srslte_dft_replan_c(srslte_dft_plan_t *plan, SRSLTE_API int srslte_dft_replan_c(srslte_dft_plan_t *plan,
int new_dft_points); int new_dft_points);
@ -129,6 +151,8 @@ SRSLTE_API void srslte_dft_run_c(srslte_dft_plan_t *plan,
cf_t *in, cf_t *in,
cf_t *out); cf_t *out);
SRSLTE_API void srslte_dft_run_guru_c(srslte_dft_plan_t *plan);
SRSLTE_API void srslte_dft_run_r(srslte_dft_plan_t *plan, SRSLTE_API void srslte_dft_run_r(srslte_dft_plan_t *plan,
float *in, float *in,
float *out); float *out);

@ -47,14 +47,18 @@
/* This is common for both directions */ /* This is common for both directions */
typedef struct SRSLTE_API{ typedef struct SRSLTE_API{
srslte_dft_plan_t fft_plan; srslte_dft_plan_t fft_plan;
srslte_dft_plan_t fft_plan_sf[2];
uint32_t max_prb; uint32_t max_prb;
uint32_t nof_symbols; uint32_t nof_symbols;
uint32_t symbol_sz; uint32_t symbol_sz;
uint32_t nof_guards; uint32_t nof_guards;
uint32_t nof_re; uint32_t nof_re;
uint32_t slot_sz; uint32_t slot_sz;
uint32_t sf_sz;
srslte_cp_t cp; srslte_cp_t cp;
cf_t *tmp; // for removing zero padding cf_t *tmp; // for removing zero padding
cf_t *in_buffer;
cf_t *out_buffer;
bool mbsfn_subframe; bool mbsfn_subframe;
uint32_t mbsfn_guard_len; uint32_t mbsfn_guard_len;
@ -69,12 +73,16 @@ typedef struct SRSLTE_API{
SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q,
srslte_cp_t cp, srslte_cp_t cp,
cf_t *in_buffer,
cf_t *out_buffer,
int symbol_sz, int symbol_sz,
int nof_prb, int nof_prb,
srslte_dft_dir_t dir); srslte_dft_dir_t dir);
SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q,
srslte_cp_t cp, srslte_cp_t cp,
cf_t *in_buffer,
cf_t *out_buffer,
int symbol_sz, int symbol_sz,
int nof_prb, int nof_prb,
srslte_dft_dir_t dir, srslte_dft_dir_t dir,
@ -82,12 +90,14 @@ SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q,
SRSLTE_API int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q,
srslte_cp_t cp_type, srslte_cp_t cp_type,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t nof_prb); uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type, srslte_cp_t cp_type,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t max_prb); uint32_t max_prb);
SRSLTE_API int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q,
@ -101,38 +111,34 @@ SRSLTE_API int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q,
SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q); SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q);
SRSLTE_API void srslte_ofdm_rx_slot(srslte_ofdm_t *q, SRSLTE_API void srslte_ofdm_rx_slot(srslte_ofdm_t *q,
cf_t *input, int slot_in_sf);
cf_t *output);
SRSLTE_API void srslte_ofdm_rx_sf(srslte_ofdm_t *q,
cf_t *input,
cf_t *output);
SRSLTE_API void srslte_ofdm_rx_sf(srslte_ofdm_t *q);
SRSLTE_API int srslte_ofdm_tx_init(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_tx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type, srslte_cp_t cp_type,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t nof_prb); uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q,
srslte_cp_t cp, srslte_cp_t cp,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t nof_prb); uint32_t nof_prb);
SRSLTE_API void srslte_ofdm_tx_free(srslte_ofdm_t *q); SRSLTE_API void srslte_ofdm_tx_free(srslte_ofdm_t *q);
SRSLTE_API void srslte_ofdm_tx_slot(srslte_ofdm_t *q, SRSLTE_API void srslte_ofdm_tx_slot(srslte_ofdm_t *q,
cf_t *input, int slot_in_sf);
cf_t *output);
SRSLTE_API void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q, SRSLTE_API void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q,
cf_t *input, cf_t *input,
cf_t *output); cf_t *output);
SRSLTE_API void srslte_ofdm_tx_sf(srslte_ofdm_t *q, SRSLTE_API void srslte_ofdm_tx_sf(srslte_ofdm_t *q);
cf_t *input,
cf_t *output);
SRSLTE_API int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q,
float freq_shift); float freq_shift);

@ -68,7 +68,7 @@ typedef struct SRSLTE_API {
cf_t *sf_symbols[SRSLTE_MAX_PORTS]; cf_t *sf_symbols[SRSLTE_MAX_PORTS];
cf_t *slot1_symbols[SRSLTE_MAX_PORTS]; cf_t *slot1_symbols[SRSLTE_MAX_PORTS];
srslte_ofdm_t ifft; srslte_ofdm_t ifft[SRSLTE_MAX_PORTS];
srslte_pbch_t pbch; srslte_pbch_t pbch;
srslte_pcfich_t pcfich; srslte_pcfich_t pcfich;
srslte_regs_t regs; srslte_regs_t regs;
@ -111,6 +111,7 @@ typedef struct {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q, SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q,
cf_t *out_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb); uint32_t max_prb);
SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q); SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q);
@ -147,8 +148,7 @@ SRSLTE_API void srslte_enb_dl_put_phich(srslte_enb_dl_t *q,
SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t *q, SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t *q,
uint32_t tti); uint32_t tti);
SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q);
cf_t *signal_buffer[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q,
uint16_t rnti); uint16_t rnti);

@ -101,6 +101,7 @@ typedef struct {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q, SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q,
cf_t *in_buffer,
uint32_t max_prb); uint32_t max_prb);
SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q); SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q);
@ -124,8 +125,7 @@ SRSLTE_API int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti,
srslte_refsignal_srs_cfg_t *srs_cfg); srslte_refsignal_srs_cfg_t *srs_cfg);
SRSLTE_API void srslte_enb_ul_fft(srslte_enb_ul_t *q, SRSLTE_API void srslte_enb_ul_fft(srslte_enb_ul_t *q);
cf_t *signal_buffer);
SRSLTE_API int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, SRSLTE_API int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q,
uint16_t rnti, uint16_t rnti,

@ -103,9 +103,7 @@ typedef struct SRSLTE_API {
bool prb_idx[2][SRSLTE_MAX_PRB]; bool prb_idx[2][SRSLTE_MAX_PRB];
uint32_t nof_prb; uint32_t nof_prb;
uint32_t Qm[SRSLTE_MAX_CODEWORDS]; uint32_t Qm[SRSLTE_MAX_CODEWORDS];
uint32_t Qm2[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS]; srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs2[SRSLTE_MAX_CODEWORDS];
uint32_t nof_tb; uint32_t nof_tb;
srslte_sf_t sf_type; srslte_sf_t sf_type;
bool tb_en[SRSLTE_MAX_CODEWORDS]; bool tb_en[SRSLTE_MAX_CODEWORDS];
@ -226,8 +224,7 @@ SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant,
SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci,
uint32_t nof_prb, uint32_t nof_prb,
uint32_t n_rb_ho, uint32_t n_rb_ho,
srslte_ra_ul_grant_t *grant, srslte_ra_ul_grant_t *grant);
uint32_t harq_pid);
SRSLTE_API void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, SRSLTE_API void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant,
srslte_cp_t cp, srslte_cp_t cp,

@ -80,7 +80,7 @@ typedef struct SRSLTE_API {
srslte_pmch_t pmch; srslte_pmch_t pmch;
srslte_phich_t phich; srslte_phich_t phich;
srslte_regs_t regs; srslte_regs_t regs;
srslte_ofdm_t fft; srslte_ofdm_t fft[SRSLTE_MAX_PORTS];
srslte_ofdm_t fft_mbsfn; srslte_ofdm_t fft_mbsfn;
srslte_chest_dl_t chest; srslte_chest_dl_t chest;
@ -128,6 +128,7 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
cf_t *in_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb, uint32_t max_prb,
uint32_t nof_rx_antennas); uint32_t nof_rx_antennas);

@ -79,6 +79,7 @@ typedef struct SRSLTE_API {
} srslte_ue_mib_t; } srslte_ue_mib_t;
SRSLTE_API int srslte_ue_mib_init(srslte_ue_mib_t *q, SRSLTE_API int srslte_ue_mib_init(srslte_ue_mib_t *q,
cf_t *in_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb); uint32_t max_prb);
SRSLTE_API void srslte_ue_mib_free(srslte_ue_mib_t *q); SRSLTE_API void srslte_ue_mib_free(srslte_ue_mib_t *q);
@ -89,7 +90,6 @@ SRSLTE_API int srslte_ue_mib_set_cell(srslte_ue_mib_t * q,
SRSLTE_API void srslte_ue_mib_reset(srslte_ue_mib_t * q); SRSLTE_API void srslte_ue_mib_reset(srslte_ue_mib_t * q);
SRSLTE_API int srslte_ue_mib_decode(srslte_ue_mib_t * q, SRSLTE_API int srslte_ue_mib_decode(srslte_ue_mib_t * q,
cf_t *input,
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN], uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN],
uint32_t *nof_tx_ports, uint32_t *nof_tx_ports,
int *sfn_offset); int *sfn_offset);

@ -187,6 +187,9 @@ SRSLTE_API void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q,
SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q,
float cfo); float cfo);
SRSLTE_API void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q,
float ema);
SRSLTE_API void srslte_ue_sync_cfo_i_detec_en(srslte_ue_sync_t *q, SRSLTE_API void srslte_ue_sync_cfo_i_detec_en(srslte_ue_sync_t *q,
bool enable); bool enable);

@ -108,6 +108,7 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q, SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q,
cf_t *out_buffer,
uint32_t max_prb); uint32_t max_prb);
SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q); SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q);

@ -27,14 +27,8 @@
#ifndef SRSLTE_MAT_H #ifndef SRSLTE_MAT_H
#define SRSLTE_MAT_H #define SRSLTE_MAT_H
#include "srslte/phy/utils/simd.h"
#include "srslte/config.h" #include "srslte/config.h"
#include "srslte/phy/utils/simd.h"
/*
* Generic Macros
*/
#define RANDOM_CF() (((float)rand())/((float)RAND_MAX) + _Complex_I*((float)rand())/((float)RAND_MAX))
/* Generic implementation for complex reciprocal */ /* Generic implementation for complex reciprocal */
SRSLTE_API cf_t srslte_mat_cf_recip_gen(cf_t a); SRSLTE_API cf_t srslte_mat_cf_recip_gen(cf_t a);
@ -66,7 +60,6 @@ SRSLTE_API float srslte_mat_2x2_cn(cf_t h00,
#ifdef LV_HAVE_SSE #ifdef LV_HAVE_SSE
#include <smmintrin.h>
/* SSE implementation for complex reciprocal */ /* SSE implementation for complex reciprocal */
SRSLTE_API __m128 srslte_mat_cf_recip_sse(__m128 a); SRSLTE_API __m128 srslte_mat_cf_recip_sse(__m128 a);
@ -90,8 +83,6 @@ SRSLTE_API void srslte_mat_2x2_mmse_sse(__m128 y0, __m128 y1,
#ifdef LV_HAVE_AVX #ifdef LV_HAVE_AVX
#include <immintrin.h>
/* AVX implementation for complex reciprocal */ /* AVX implementation for complex reciprocal */
SRSLTE_API __m256 srslte_mat_cf_recip_avx(__m256 a); SRSLTE_API __m256 srslte_mat_cf_recip_avx(__m256 a);

File diff suppressed because it is too large Load Diff

@ -54,7 +54,6 @@ extern "C" {
#define SRSLTE_VEC_EMA(data, average, alpha) ((alpha)*(data)+(1-alpha)*(average)) #define SRSLTE_VEC_EMA(data, average, alpha) ((alpha)*(data)+(1-alpha)*(average))
/** Return the sum of all the elements */ /** Return the sum of all the elements */
SRSLTE_API int srslte_vec_acc_ii(int *x, uint32_t len);
SRSLTE_API float srslte_vec_acc_ff(float *x, uint32_t len); SRSLTE_API float srslte_vec_acc_ff(float *x, uint32_t len);
SRSLTE_API cf_t srslte_vec_acc_cc(cf_t *x, uint32_t len); SRSLTE_API cf_t srslte_vec_acc_cc(cf_t *x, uint32_t len);
@ -77,52 +76,29 @@ SRSLTE_API void srslte_vec_save_file(char *filename, void *buffer, uint32_t len)
SRSLTE_API void srslte_vec_load_file(char *filename, void *buffer, uint32_t len); SRSLTE_API void srslte_vec_load_file(char *filename, void *buffer, uint32_t len);
/* sum two vectors */ /* sum two vectors */
SRSLTE_API void srslte_vec_sum_ch(uint8_t *x, uint8_t *y, char *z, uint32_t len);
SRSLTE_API void srslte_vec_sum_fff(float *x, float *y, float *z, uint32_t len); SRSLTE_API void srslte_vec_sum_fff(float *x, float *y, float *z, uint32_t len);
SRSLTE_API void srslte_vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len);
SRSLTE_API void srslte_vec_sub_sss(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_sub_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len);
SRSLTE_API void srslte_vec_sum_sss(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_sum_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len);
/* substract two vectors z=x-y */ /* substract two vectors z=x-y */
SRSLTE_API void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len); SRSLTE_API void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len);
SRSLTE_API void srslte_vec_sub_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_sub_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len);
/* EMA filter: output=coeff*new_data + (1-coeff)*average */
SRSLTE_API void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float coeff, uint32_t len);
/* Square distance */
SRSLTE_API void srslte_vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoints);
/* scalar addition */
SRSLTE_API void srslte_vec_sc_add_fff(float *x, float h, float *z, uint32_t len);
SRSLTE_API void srslte_vec_sc_add_cfc(cf_t *x, float h, cf_t *z, uint32_t len);
SRSLTE_API void srslte_vec_sc_add_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len);
SRSLTE_API void srslte_vec_sc_add_sss(int16_t *x, int16_t h, int16_t *z, uint32_t len);
/* scalar product */ /* scalar product */
SRSLTE_API void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len);
SRSLTE_API void srslte_vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len);
SRSLTE_API void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len); SRSLTE_API void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len);
SRSLTE_API void srslte_vec_sc_prod_sfs(short *x, float h, short *z, uint32_t len);
SRSLTE_API void srslte_vec_sc_div2_sss(short *x, int pow2_div, short *z, uint32_t len);
/* Normalization */
SRSLTE_API void srslte_vec_norm_cfc(cf_t *x, float amplitude, cf_t *y, uint32_t len);
SRSLTE_API void srslte_vec_convert_fi(float *x, int16_t *z, float scale, uint32_t len); SRSLTE_API void srslte_vec_convert_fi(float *x, int16_t *z, float scale, uint32_t len);
SRSLTE_API void srslte_vec_convert_if(int16_t *x, float *z, float scale, uint32_t len); SRSLTE_API void srslte_vec_convert_if(int16_t *x, float *z, float scale, uint32_t len);
SRSLTE_API void srslte_vec_convert_ci(int8_t *x, int16_t *z, uint32_t len);
SRSLTE_API void srslte_vec_lut_fuf(float *x, uint32_t *lut, float *y, uint32_t len);
SRSLTE_API void srslte_vec_lut_sss(short *x, unsigned short *lut, short *y, uint32_t len); SRSLTE_API void srslte_vec_lut_sss(short *x, unsigned short *lut, short *y, uint32_t len);
SRSLTE_API void srslte_vec_deinterleave_cf(cf_t *x, float *real, float *imag, uint32_t len);
SRSLTE_API void srslte_vec_deinterleave_real_cf(cf_t *x, float *real, uint32_t len);
SRSLTE_API void srslte_vec_interleave_cf(float *real, float *imag, cf_t *x, uint32_t len);
/* vector product (element-wise) */ /* vector product (element-wise) */
SRSLTE_API void srslte_vec_prod_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_prod_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len);
SRSLTE_API void srslte_vec_prod_ccc_split(float *x_re, float *x_im, float *y_re, float *y_im, float *z_re, float *z_im, uint32_t len);
/* vector product (element-wise) */ /* vector product (element-wise) */
SRSLTE_API void srslte_vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len);
@ -132,7 +108,7 @@ SRSLTE_API void srslte_vec_prod_conj_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len
/* real vector product (element-wise) */ /* real vector product (element-wise) */
SRSLTE_API void srslte_vec_prod_fff(float *x, float *y, float *z, uint32_t len); SRSLTE_API void srslte_vec_prod_fff(float *x, float *y, float *z, uint32_t len);
SRSLTE_API void srslte_vec_prod_sss(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_prod_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len);
/* Dot-product */ /* Dot-product */
SRSLTE_API cf_t srslte_vec_dot_prod_cfc(cf_t *x, float *y, uint32_t len); SRSLTE_API cf_t srslte_vec_dot_prod_cfc(cf_t *x, float *y, uint32_t len);
@ -142,8 +118,8 @@ SRSLTE_API float srslte_vec_dot_prod_fff(float *x, float *y, uint32_t len);
SRSLTE_API int32_t srslte_vec_dot_prod_sss(int16_t *x, int16_t *y, uint32_t len); SRSLTE_API int32_t srslte_vec_dot_prod_sss(int16_t *x, int16_t *y, uint32_t len);
/* z=x/y vector division (element-wise) */ /* z=x/y vector division (element-wise) */
SRSLTE_API void srslte_vec_div_ccc(cf_t *x, cf_t *y, float *y_mod, cf_t *z, float *z_real, float *z_imag, uint32_t len); SRSLTE_API void srslte_vec_div_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len);
void srslte_vec_div_cfc(cf_t *x, float *y, cf_t *z, float *z_real, float *z_imag, uint32_t len); SRSLTE_API void srslte_vec_div_cfc(cf_t *x, float *y, cf_t *z, uint32_t len);
SRSLTE_API void srslte_vec_div_fff(float *x, float *y, float *z, uint32_t len); SRSLTE_API void srslte_vec_div_fff(float *x, float *y, float *z, uint32_t len);
/* conjugate */ /* conjugate */
@ -158,11 +134,6 @@ SRSLTE_API float srslte_vec_corr_ccc(cf_t *x, cf_t *y, uint32_t len);
/* return the index of the maximum value in the vector */ /* return the index of the maximum value in the vector */
SRSLTE_API uint32_t srslte_vec_max_fi(float *x, uint32_t len); SRSLTE_API uint32_t srslte_vec_max_fi(float *x, uint32_t len);
SRSLTE_API uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len); SRSLTE_API uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len);
SRSLTE_API int16_t srslte_vec_max_star_si(int16_t *x, uint32_t len);
SRSLTE_API int16_t srslte_vec_max_abs_star_si(int16_t *x, uint32_t len);
/* maximum between two vectors */
SRSLTE_API void srslte_vec_max_fff(float *x, float *y, float *z, uint32_t len);
/* quantify vector of floats or int16 and convert to uint8_t */ /* quantify vector of floats or int16 and convert to uint8_t */
SRSLTE_API void srslte_vec_quant_fuc(float *in, uint8_t *out, float gain, float offset, float clip, uint32_t len); SRSLTE_API void srslte_vec_quant_fuc(float *in, uint8_t *out, float gain, float offset, float clip, uint32_t len);
@ -172,9 +143,6 @@ SRSLTE_API void srslte_vec_quant_suc(int16_t *in, uint8_t *out, float gain, int1
SRSLTE_API void srslte_vec_abs_cf(cf_t *x, float *abs, uint32_t len); SRSLTE_API void srslte_vec_abs_cf(cf_t *x, float *abs, uint32_t len);
SRSLTE_API void srslte_vec_abs_square_cf(cf_t *x, float *abs_square, uint32_t len); SRSLTE_API void srslte_vec_abs_square_cf(cf_t *x, float *abs_square, uint32_t len);
/* argument of each vector element */
SRSLTE_API void srslte_vec_arg_cf(cf_t *x, float *arg, uint32_t len);
/* Copy 256 bit aligned vector */ /* Copy 256 bit aligned vector */
SRSLTE_API void srs_vec_cf_cpy(cf_t *src, cf_t *dst, int len); SRSLTE_API void srs_vec_cf_cpy(cf_t *src, cf_t *dst, int len);

@ -35,32 +35,94 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#include "srslte/config.h" #include "srslte/config.h"
SRSLTE_API int srslte_vec_dot_prod_sss_sse(short *x, short *y, uint32_t len); #ifdef LV_HAVE_AVX512
#define SRSLTE_SIMD_BIT_ALIGN 512
#define SRSLTE_IS_ALIGNED(PTR) (((size_t)(PTR) & 0x3F) == 0)
#else /* LV_HAVE_AVX512 */
#ifdef LV_HAVE_AVX
#define SRSLTE_SIMD_BIT_ALIGN 256
#define SRSLTE_IS_ALIGNED(PTR) (((size_t)(PTR) & 0x1F) == 0)
#else /* LV_HAVE_AVX */
#ifdef LV_HAVE_SSE
#define SRSLTE_SIMD_BIT_ALIGN 128
#define SRSLTE_IS_ALIGNED(PTR) (((size_t)(PTR) & 0x0F) == 0)
#else /* LV_HAVE_SSE */
#define SRSLTE_SIMD_BIT_ALIGN 64
#define SRSLTE_IS_ALIGNED(PTR) (1)
#endif /* LV_HAVE_SSE */
#endif /* LV_HAVE_AVX */
#endif /* LV_HAVE_AVX512 */
SRSLTE_API int srslte_vec_dot_prod_sss_avx2(short *x, short *y, uint32_t len); /* SIMD Basic vector math */
SRSLTE_API void srslte_vec_sum_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len);
SRSLTE_API void srslte_vec_sum_sss_sse(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_sub_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len);
SRSLTE_API void srslte_vec_sum_sss_avx2(short *x, short *y, short *z, uint32_t len); SRSLTE_API float srslte_vec_acc_ff_simd(float *x, int len);
SRSLTE_API void srslte_vec_sub_sss_sse(short *x, short *y, short *z, uint32_t len); SRSLTE_API cf_t srslte_vec_acc_cc_simd(cf_t *x, int len);
SRSLTE_API void srslte_vec_sub_sss_avx2(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_add_fff_simd(float *x, float *y, float *z, int len);
SRSLTE_API void srslte_vec_prod_sss_sse(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_sub_fff_simd(float *x, float *y, float *z, int len);
SRSLTE_API void srslte_vec_prod_sss_avx2(short *x, short *y, short *z, uint32_t len); /* SIMD Vector Scalar Product */
SRSLTE_API void srslte_vec_sc_prod_cfc_simd(const cf_t *x,const float h,cf_t *y,const int len);
SRSLTE_API void srslte_vec_sc_prod_fff_simd(float *x, float h, float *z, int len);
SRSLTE_API void srslte_vec_sc_div2_sss_sse(short *x, int n_rightshift, short *z, uint32_t len); SRSLTE_API void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len);
SRSLTE_API void srslte_vec_sc_div2_sss_avx2(short *x, int k, short *z, uint32_t len); /* SIMD Vector Product */
SRSLTE_API void srslte_vec_prod_ccc_split_simd(float *a_re, float *a_im, float *b_re, float *b_im, float *r_re, float *r_im, int len);
SRSLTE_API void srslte_vec_lut_sss_sse(short *x, unsigned short *lut, short *y, uint32_t len); SRSLTE_API void srslte_vec_prod_ccc_c16_simd(int16_t *a_re, int16_t *a_im, int16_t *b_re, int16_t *b_im, int16_t *r_re,
int16_t *r_im, int len);
SRSLTE_API void srslte_vec_convert_fi_sse(float *x, int16_t *z, float scale, uint32_t len); SRSLTE_API void srslte_vec_prod_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len);
SRSLTE_API void srslte_vec_prod_cfc_simd(cf_t *x, float *y, cf_t *z, int len);
SRSLTE_API void srslte_vec_prod_fff_simd(float *x, float *y, float *z, int len);
SRSLTE_API void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len);
SRSLTE_API void srslte_vec_prod_conj_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len);
/* SIMD Division */
SRSLTE_API void srslte_vec_div_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len);
SRSLTE_API void srslte_vec_div_cfc_simd(cf_t *x, float *y, cf_t *z, int len);
SRSLTE_API void srslte_vec_div_fff_simd(float *x, float *y, float *z, int len);
/* SIMD Dot product */
SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_simd(cf_t *x, cf_t *y, int len);
SRSLTE_API cf_t srslte_vec_dot_prod_ccc_simd(cf_t *x, cf_t *y, int len);
SRSLTE_API c16_t srslte_vec_dot_prod_ccc_c16i_simd(c16_t *x, c16_t *y, int len);
SRSLTE_API int srslte_vec_dot_prod_sss_simd(int16_t *x, int16_t *y, int len);
/* SIMD Modulus functions */
SRSLTE_API void srslte_vec_abs_cf_simd(cf_t *x, float *z, int len);
SRSLTE_API void srslte_vec_abs_square_cf_simd(cf_t *x, float *z, int len);
/* Other Functions */
SRSLTE_API void srslte_vec_lut_sss_simd(short *x, unsigned short *lut, short *y, int len);
SRSLTE_API void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, int len);
SRSLTE_API void srslte_vec_cp_simd(cf_t *src, cf_t *dst, int len);
/* SIMD Find Max functions */
SRSLTE_API uint32_t srslte_vec_max_fi_simd(float *x, int len);
SRSLTE_API uint32_t srslte_vec_max_ci_simd(cf_t *x, int len);
SRSLTE_API void srslte_vec_sc_prod_cfc_avx(const cf_t *x,const float h,cf_t *y,const uint32_t len);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -4764,6 +4764,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_plmn_identity_ie(LIBLTE_RRC_PLMN_IDENTITY_STRU
if(plmn_id != NULL && if(plmn_id != NULL &&
ie_ptr != NULL) ie_ptr != NULL)
{ {
if(0xFFFF == plmn_id->mcc) {
mcc_opt = false;
}
liblte_value_2_bits(mcc_opt, ie_ptr, 1); liblte_value_2_bits(mcc_opt, ie_ptr, 1);
if(true == mcc_opt) if(true == mcc_opt)
@ -12754,7 +12757,241 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_paging_msg(LIBLTE_BIT_MSG_STRUCT *msg,
Document Reference: 36.331 v10.0.0 Section 6.2.2 Document Reference: 36.331 v10.0.0 Section 6.2.2
*********************************************************************/ *********************************************************************/
// FIXME LIBLTE_ERROR_ENUM liblte_rrc_pack_cgi_info_ie(LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info,
uint8 **ie_ptr)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(cgi_info != NULL &&
ie_ptr != NULL)
{
liblte_value_2_bits(cgi_info->have_plmn_identity_list, ie_ptr, 1);
liblte_rrc_pack_cell_global_id_eutra_ie(&cgi_info->cell_global_id, ie_ptr);
liblte_rrc_pack_tracking_area_code_ie(cgi_info->tracking_area_code, ie_ptr);
if(cgi_info->have_plmn_identity_list) {
liblte_value_2_bits(cgi_info->n_plmn_identity_list-1, ie_ptr, 3);
for(uint32 i=0; i<cgi_info->n_plmn_identity_list; i++) {
liblte_rrc_pack_plmn_identity_ie(&cgi_info->plmn_identity_list[i], ie_ptr);
}
}
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cgi_info_ie(uint8 **ie_ptr,
LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(ie_ptr != NULL &&
cgi_info != NULL)
{
cgi_info->have_plmn_identity_list = (bool)liblte_bits_2_value(ie_ptr, 1);
liblte_rrc_unpack_cell_global_id_eutra_ie(ie_ptr, &cgi_info->cell_global_id);
liblte_rrc_unpack_tracking_area_code_ie(ie_ptr, &cgi_info->tracking_area_code);
if(cgi_info->have_plmn_identity_list) {
cgi_info->n_plmn_identity_list = liblte_bits_2_value(ie_ptr, 3) + 1;
for(uint32 i=0; i<cgi_info->n_plmn_identity_list; i++) {
liblte_rrc_unpack_plmn_identity_ie(ie_ptr, &cgi_info->plmn_identity_list[i]);
}
}
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_ie(LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result,
uint8 **ie_ptr)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(meas_result != NULL &&
ie_ptr != NULL)
{
//ext
liblte_value_2_bits(0, ie_ptr, 1);
//options
liblte_value_2_bits(meas_result->have_rsrp, ie_ptr, 1);
liblte_value_2_bits(meas_result->have_rsrq, ie_ptr, 1);
if(meas_result->have_rsrp) {
liblte_rrc_pack_rsrp_range_ie(meas_result->rsrp_result, ie_ptr);
}
if(meas_result->have_rsrq) {
liblte_rrc_pack_rsrq_range_ie(meas_result->rsrq_result, ie_ptr);
}
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_ie(uint8 **ie_ptr,
LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(ie_ptr != NULL &&
meas_result != NULL)
{
//ext
bool ext = liblte_bits_2_value(ie_ptr, 1);
//options
meas_result->have_rsrp = liblte_bits_2_value(ie_ptr, 1);
meas_result->have_rsrq = liblte_bits_2_value(ie_ptr, 1);
if(meas_result->have_rsrp) {
liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &meas_result->rsrp_result);
}
if(meas_result->have_rsrq) {
liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &meas_result->rsrq_result);
}
//skip extensions
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_eutra_ie(LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra,
uint8 **ie_ptr)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(meas_result_eutra != NULL &&
ie_ptr != NULL)
{
liblte_value_2_bits(meas_result_eutra->have_cgi_info, ie_ptr, 1);
liblte_rrc_pack_phys_cell_id_ie(meas_result_eutra->phys_cell_id, ie_ptr);
if(meas_result_eutra->have_cgi_info) {
liblte_rrc_pack_cgi_info_ie(&meas_result_eutra->cgi_info, ie_ptr);
}
liblte_rrc_pack_meas_result_ie(&meas_result_eutra->meas_result, ie_ptr);
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_eutra_ie(uint8 **ie_ptr,
LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if(ie_ptr != NULL &&
meas_result_eutra != NULL)
{
meas_result_eutra->have_cgi_info = liblte_bits_2_value(ie_ptr, 1);
liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &meas_result_eutra->phys_cell_id);
if(meas_result_eutra->have_cgi_info) {
liblte_rrc_unpack_cgi_info_ie(ie_ptr, &meas_result_eutra->cgi_info);
}
liblte_rrc_unpack_meas_result_ie(ie_ptr, &meas_result_eutra->meas_result);
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_pack_measurement_report_msg(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report,
LIBLTE_BIT_MSG_STRUCT *msg)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 *msg_ptr = msg->msg;
if(meas_report != NULL &&
msg != NULL)
{
//MeasurementReport
liblte_value_2_bits(0, &msg_ptr, 1); //critical extensions
liblte_value_2_bits(0, &msg_ptr, 3); //c1
//MeasurementReport-r8-IEs
liblte_value_2_bits(0, &msg_ptr, 1); //non-critical extensions
//MeasResults
liblte_value_2_bits(0, &msg_ptr, 1); //ext
liblte_value_2_bits(meas_report->have_meas_result_neigh_cells, &msg_ptr, 1);
liblte_rrc_pack_meas_id_ie(meas_report->meas_id, &msg_ptr);
liblte_rrc_pack_rsrp_range_ie(meas_report->pcell_rsrp_result, &msg_ptr);
liblte_rrc_pack_rsrq_range_ie(meas_report->pcell_rsrq_result, &msg_ptr);
if(meas_report->have_meas_result_neigh_cells) {
liblte_value_2_bits(0, &msg_ptr, 1); //choice from before extension marker
liblte_value_2_bits(meas_report->meas_result_neigh_cells_choice, &msg_ptr, 2);
if(meas_report->meas_result_neigh_cells_choice != LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA) {
printf("NOT HANDLING %s\n", liblte_rrc_meas_reult_neigh_cells_text[meas_report->meas_result_neigh_cells_choice]);
} else {
//MeasResultListEUTRA
liblte_value_2_bits(meas_report->meas_result_neigh_cells.eutra.n_result-1, &msg_ptr, 3);
for(uint32 i=0; i<meas_report->meas_result_neigh_cells.eutra.n_result; i++) {
liblte_rrc_pack_meas_result_eutra_ie(&meas_report->meas_result_neigh_cells.eutra.result_eutra_list[i], &msg_ptr);
}
}
}
// Fill in the number of bits used
msg->N_bits = msg_ptr - msg->msg;
err = LIBLTE_SUCCESS;
}
return(err);
}
LIBLTE_ERROR_ENUM liblte_rrc_unpack_measurement_report_msg(LIBLTE_BIT_MSG_STRUCT *msg,
LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 *msg_ptr = msg->msg;
if(msg != NULL &&
meas_report != NULL)
{
//MeasurementReport
bool crit_ext = liblte_bits_2_value(&msg_ptr, 1); //critical extensions
liblte_bits_2_value(&msg_ptr, 3); //c1
//MeasurementReport-r8-IEs
bool non_crit_ext = liblte_bits_2_value(&msg_ptr, 1); //non-critical extensions
//MeasResults
bool ext = liblte_bits_2_value(&msg_ptr, 1);
meas_report->have_meas_result_neigh_cells = liblte_bits_2_value(&msg_ptr, 1);
liblte_rrc_unpack_meas_id_ie(&msg_ptr, &meas_report->meas_id);
liblte_rrc_unpack_rsrp_range_ie(&msg_ptr, &meas_report->pcell_rsrp_result);
liblte_rrc_unpack_rsrq_range_ie(&msg_ptr, &meas_report->pcell_rsrq_result);
if(meas_report->have_meas_result_neigh_cells) {
liblte_bits_2_value(&msg_ptr, 1); //choice from before extension marker
meas_report->meas_result_neigh_cells_choice = (LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM) liblte_bits_2_value(&msg_ptr, 2);
if(meas_report->meas_result_neigh_cells_choice != LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA) {
printf("NOT HANDLING %s\n", liblte_rrc_meas_reult_neigh_cells_text[meas_report->meas_result_neigh_cells_choice]);
} else {
//MeasResultListEUTRA
meas_report->meas_result_neigh_cells.eutra.n_result = liblte_bits_2_value(&msg_ptr, 3) + 1;
for(uint32 i=0; i<meas_report->meas_result_neigh_cells.eutra.n_result; i++) {
liblte_rrc_unpack_meas_result_eutra_ie(&msg_ptr, &meas_report->meas_result_neigh_cells.eutra.result_eutra_list[i]);
}
}
}
//skip extensions
liblte_rrc_consume_noncrit_extension(crit_ext, __func__, &msg_ptr);
liblte_rrc_consume_noncrit_extension(non_crit_ext, __func__, &msg_ptr);
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
err = LIBLTE_SUCCESS;
}
return(err);
}
/********************************************************************* /*********************************************************************
Message Name: MBSFN Area Configuration Message Name: MBSFN Area Configuration
@ -13550,9 +13787,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_dcch_msg(LIBLTE_RRC_UL_DCCH_MSG_STRUCT *ul_
err = liblte_rrc_pack_csfb_parameters_request_cdma2000_msg((LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg, err = liblte_rrc_pack_csfb_parameters_request_cdma2000_msg((LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg,
&global_msg); &global_msg);
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){ }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){
printf("NOT HANDLING MEASUREMENT REPORT\n"); err = liblte_rrc_pack_measurement_report_msg((LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg,
// err = liblte_rrc_pack_measurement_report_msg((LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg, &global_msg);
// &global_msg);
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){ }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){
err = liblte_rrc_pack_rrc_connection_reconfiguration_complete_msg((LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg, err = liblte_rrc_pack_rrc_connection_reconfiguration_complete_msg((LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg,
&global_msg); &global_msg);
@ -13630,9 +13866,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_dcch_msg(LIBLTE_BIT_MSG_STRUCT *m
err = liblte_rrc_unpack_csfb_parameters_request_cdma2000_msg(&global_msg, err = liblte_rrc_unpack_csfb_parameters_request_cdma2000_msg(&global_msg,
(LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg); (LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg);
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){ }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){
printf("NOT HANDLING MEASUREMENT REPORT\n"); err = liblte_rrc_unpack_measurement_report_msg(&global_msg,
// err = liblte_rrc_unpack_measurement_report_msg(&global_msg, (LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg);
// (LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg);
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){ }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){
err = liblte_rrc_unpack_rrc_connection_reconfiguration_complete_msg(&global_msg, err = liblte_rrc_unpack_rrc_connection_reconfiguration_complete_msg(&global_msg,
(LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg); (LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg);

@ -55,7 +55,7 @@ void logger_file::init(std::string file) {
filename = file; filename = file;
logfile = fopen(filename.c_str(), "w"); logfile = fopen(filename.c_str(), "w");
if(logfile==NULL) { if(logfile==NULL) {
printf("Error: could not create log file, no messages will be logged"); printf("Error: could not create log file, no messages will be logged!\n");
} }
start(); start();
inited = true; inited = true;

@ -86,11 +86,7 @@ uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id)
uint32_t srslte_refsignal_mbsfn_nof_symbols() uint32_t srslte_refsignal_mbsfn_nof_symbols()
{ {
if(false){ return 3;
return 3;
}else{
return 3;
}
} }

@ -605,7 +605,7 @@ int srslte_band_get_fd_region(enum band_geographical_area region, srslte_earfcn_
/* Returns the interval tti1-tti2 mod 10240 */ /* Returns the interval tti1-tti2 mod 10240 */
uint32_t srslte_tti_interval(uint32_t tti1, uint32_t tti2) { uint32_t srslte_tti_interval(uint32_t tti1, uint32_t tti2) {
if (tti1 > tti2) { if (tti1 >= tti2) {
return tti1-tti2; return tti1-tti2;
} else { } else {
return 10240-tti2+tti1; return 10240-tti2+tti1;

@ -56,9 +56,7 @@ void srslte_dft_load() {
void srslte_dft_exit() { void srslte_dft_exit() {
#ifdef FFTW_WISDOM_FILE #ifdef FFTW_WISDOM_FILE
if (!fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE)) { fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE);
fprintf(stderr, "Error saving FFTW wisdom to file %s\n", FFTW_WISDOM_FILE);
}
#endif #endif
} }
@ -93,6 +91,27 @@ static void allocate(srslte_dft_plan_t *plan, int size_in, int size_out, int len
plan->out = fftwf_malloc(size_out*len); plan->out = fftwf_malloc(size_out*len);
} }
int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan, const int new_dft_points, cf_t *in_buffer,
cf_t *out_buffer, int istride, int ostride, int how_many,
int idist, int odist) {
int sign = (plan->forward) ? FFTW_FORWARD : FFTW_BACKWARD;
const fftwf_iodim iodim = {new_dft_points, istride, ostride};
const fftwf_iodim howmany_dims = {how_many, idist, odist};
/* Destroy current plan */
fftwf_destroy_plan(plan->p);
plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE);
if (!plan->p) {
return -1;
}
plan->size = new_dft_points;
plan->init_size = plan->size;
return 0;
}
int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) { int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) {
int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
if (plan->p) { if (plan->p) {
@ -107,6 +126,32 @@ int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) {
return 0; return 0;
} }
int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir, cf_t *in_buffer,
cf_t *out_buffer, int istride, int ostride, int how_many,
int idist, int odist) {
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
const fftwf_iodim iodim = {dft_points, istride, ostride};
const fftwf_iodim howmany_dims = {how_many, idist, odist};
plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE);
if (!plan->p) {
return -1;
}
plan->size = dft_points;
plan->init_size = plan->size;
plan->mode = SRSLTE_DFT_COMPLEX;
plan->dir = dir;
plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false;
plan->mirror = false;
plan->db = false;
plan->norm = false;
plan->dc = false;
plan->is_guru = true;
return 0;
}
int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) { int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) {
allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points); allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points);
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
@ -123,6 +168,7 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_
plan->db = false; plan->db = false;
plan->norm = false; plan->norm = false;
plan->dc = false; plan->dc = false;
plan->is_guru = false;
return 0; return 0;
} }
@ -232,6 +278,14 @@ void srslte_dft_run_c(srslte_dft_plan_t *plan, cf_t *in, cf_t *out) {
plan->forward, plan->mirror, plan->dc); plan->forward, plan->mirror, plan->dc);
} }
void srslte_dft_run_guru_c(srslte_dft_plan_t *plan) {
if (plan->is_guru == true) {
fftwf_execute(plan->p);
} else {
fprintf(stderr, "srslte_dft_run_guru_c: the selected plan is not guru!\n");
}
}
void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out) { void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out) {
float norm; float norm;
int i; int i;
@ -255,8 +309,10 @@ void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out) {
void srslte_dft_plan_free(srslte_dft_plan_t *plan) { void srslte_dft_plan_free(srslte_dft_plan_t *plan) {
if (!plan) return; if (!plan) return;
if (!plan->size) return; if (!plan->size) return;
if (plan->in) fftwf_free(plan->in); if (!plan->is_guru) {
if (plan->out) fftwf_free(plan->out); if (plan->in) fftwf_free(plan->in);
if (plan->out) fftwf_free(plan->out);
}
if (plan->p) fftwf_destroy_plan(plan->p); if (plan->p) fftwf_destroy_plan(plan->p);
bzero(plan, sizeof(srslte_dft_plan_t)); bzero(plan, sizeof(srslte_dft_plan_t));
} }

@ -37,23 +37,79 @@
#include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h" #include "srslte/phy/utils/vector.h"
/* Uncomment next line for avoiding Guru DFT call */
//#define AVOID_GURU
int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir) { int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, int symbol_sz, int nof_prb, srslte_dft_dir_t dir) {
return srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, dir, SRSLTE_SF_NORM); return srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, dir, SRSLTE_SF_NORM);
} }
int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, int symbol_sz, int nof_prb, srslte_dft_dir_t dir, srslte_sf_t sf_type) {
int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir, srslte_sf_t sf_type) { /* Set OFDM object attributes */
q->symbol_sz = (uint32_t) symbol_sz;
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->nof_symbols_mbsfn = SRSLTE_CP_NSYMB(SRSLTE_CP_EXT);
q->cp = cp;
q->freq_shift = false;
q->nof_re = (uint32_t) nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = (uint32_t) SRSLTE_SLOT_LEN(symbol_sz);
q->sf_sz = (uint32_t) SRSLTE_SF_LEN(symbol_sz);
q->in_buffer = in_buffer;
q->out_buffer= out_buffer;
if (srslte_dft_plan_c(&q->fft_plan, symbol_sz, dir)) { if (srslte_dft_plan_c(&q->fft_plan, symbol_sz, dir)) {
fprintf(stderr, "Error: Creating DFT plan\n"); fprintf(stderr, "Error: Creating DFT plan\n");
return -1; return -1;
} }
#ifdef AVOID_GURU
q->tmp = srslte_vec_malloc((uint32_t) symbol_sz * sizeof(cf_t)); q->tmp = srslte_vec_malloc((uint32_t) symbol_sz * sizeof(cf_t));
if (!q->tmp) { if (!q->tmp) {
perror("malloc"); perror("malloc");
return -1; return -1;
} }
bzero(q->tmp, sizeof(cf_t) * symbol_sz);
#else
int cp1 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(0, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz);
int cp2 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(1, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz);
q->tmp = srslte_vec_malloc(sizeof(cf_t) * q->sf_sz);
if (!q->tmp) {
perror("malloc");
return -1;
}
bzero(q->tmp, sizeof(cf_t) * q->sf_sz);
if (dir == SRSLTE_DFT_BACKWARD) {
bzero(in_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_RE(nof_prb, cp));
}else {
bzero(in_buffer, sizeof(cf_t) * q->sf_sz);
}
for (int slot = 0; slot < 2; slot++) {
//bzero(&q->fft_plan_sf[slot], sizeof(srslte_dft_plan_t));
//bzero(q->tmp + SRSLTE_CP_NSYMB(cp)*symbol_sz*slot, sizeof(cf_t) * (cp1 + (SRSLTE_CP_NSYMB(cp) - 1)*cp2 + SRSLTE_CP_NSYMB(cp)*symbol_sz));
if (dir == SRSLTE_DFT_FORWARD) {
if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir,
in_buffer + cp1 + q->slot_sz * slot,
q->tmp + q->nof_symbols * q->symbol_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz + cp2, symbol_sz)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
return -1;
}
} else {
if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir,
q->tmp + q->nof_symbols * q->symbol_sz * slot,
out_buffer + cp1 + q->slot_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz, symbol_sz + cp2)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
return -1;
}
}
}
#endif
q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(symbol_sz)); q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(symbol_sz));
if (!q->shift_buffer) { if (!q->shift_buffer) {
@ -64,15 +120,6 @@ int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int
srslte_dft_plan_set_mirror(&q->fft_plan, true); srslte_dft_plan_set_mirror(&q->fft_plan, true);
srslte_dft_plan_set_dc(&q->fft_plan, true); srslte_dft_plan_set_dc(&q->fft_plan, true);
q->symbol_sz = (uint32_t) symbol_sz;
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->nof_symbols_mbsfn = SRSLTE_CP_NSYMB(SRSLTE_CP_EXT);
q->cp = cp;
q->freq_shift = false;
q->nof_re = nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz);
DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n", DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n",
dir==SRSLTE_DFT_FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols, dir==SRSLTE_DFT_FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols,
q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards); q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards);
@ -101,9 +148,60 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof
q->symbol_sz = (uint32_t) symbol_sz; q->symbol_sz = (uint32_t) symbol_sz;
q->nof_symbols = SRSLTE_CP_NSYMB(cp); q->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->cp = cp; q->cp = cp;
q->nof_re = nof_prb * SRSLTE_NRE; q->nof_re = (uint32_t) nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2); q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz); q->slot_sz = (uint32_t) SRSLTE_SLOT_LEN(symbol_sz);
q->sf_sz = (uint32_t) SRSLTE_SF_LEN(symbol_sz);
#ifndef AVOID_GURU
cf_t *in_buffer = q->in_buffer;
cf_t *out_buffer = q->out_buffer;
int cp1 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(0, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz);
int cp2 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(1, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz);
srslte_dft_dir_t dir = q->fft_plan_sf[0].dir;
if (q->tmp) {
free(q->tmp);
}
q->tmp = srslte_vec_malloc(sizeof(cf_t) * q->sf_sz);
if (!q->tmp) {
perror("malloc");
return -1;
}
bzero(q->tmp, sizeof(cf_t) * q->sf_sz);
if (dir == SRSLTE_DFT_BACKWARD) {
bzero(in_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_RE(nof_prb, cp));
}else {
bzero(in_buffer, sizeof(cf_t) * q->sf_sz);
}
for (int slot = 0; slot < 2; slot++) {
srslte_dft_plan_free(&q->fft_plan_sf[slot]);
if (dir == SRSLTE_DFT_FORWARD) {
if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir,
in_buffer + cp1 + q->slot_sz * slot,
q->tmp + q->nof_symbols * q->symbol_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz + cp2, symbol_sz)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
return -1;
}
} else {
if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir,
q->tmp + q->nof_symbols * q->symbol_sz * slot,
out_buffer + cp1 + q->slot_sz * slot,
1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz, symbol_sz + cp2)) {
fprintf(stderr, "Error: Creating DFT plan (1)\n");
return -1;
}
}
}
#endif /* AVOID_GURU */
if (q->freq_shift) { if (q->freq_shift) {
srslte_ofdm_set_freq_shift(q, q->freq_shift_f); srslte_ofdm_set_freq_shift(q, q->freq_shift_f);
@ -118,6 +216,15 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof
void srslte_ofdm_free_(srslte_ofdm_t *q) { void srslte_ofdm_free_(srslte_ofdm_t *q) {
srslte_dft_plan_free(&q->fft_plan); srslte_dft_plan_free(&q->fft_plan);
#ifndef AVOID_GURU
for (int slot = 0; slot < 2; slot++) {
if (q->fft_plan_sf[slot].init_size) {
srslte_dft_plan_free(&q->fft_plan_sf[slot]);
}
}
#endif
if (q->tmp) { if (q->tmp) {
free(q->tmp); free(q->tmp);
} }
@ -127,28 +234,28 @@ void srslte_ofdm_free_(srslte_ofdm_t *q) {
bzero(q, sizeof(srslte_ofdm_t)); bzero(q, sizeof(srslte_ofdm_t));
} }
int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t max_prb) {
int symbol_sz = srslte_symbol_sz(max_prb); int symbol_sz = srslte_symbol_sz(max_prb);
if (symbol_sz < 0) { if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb); fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb);
return -1; return -1;
} }
q->max_prb = max_prb; q->max_prb = max_prb;
return srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_FORWARD); return srslte_ofdm_init_(q, cp, in_buffer, out_buffer, symbol_sz, max_prb, SRSLTE_DFT_FORWARD);
} }
int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t nof_prb)
{ {
int symbol_sz = srslte_symbol_sz(nof_prb); int symbol_sz = srslte_symbol_sz(nof_prb);
if (symbol_sz < 0) { if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
return -1; return -1;
} }
return srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN); return srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN);
} }
int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t max_prb) {
uint32_t i; uint32_t i;
int ret; int ret;
@ -158,7 +265,7 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
return -1; return -1;
} }
q->max_prb = max_prb; q->max_prb = max_prb;
ret = srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD); ret = srslte_ofdm_init_(q, cp, in_buffer, out_buffer, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD);
if (ret == SRSLTE_SUCCESS) { if (ret == SRSLTE_SUCCESS) {
@ -173,7 +280,7 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
return ret; return ret;
} }
int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t nof_prb)
{ {
uint32_t i; uint32_t i;
int ret; int ret;
@ -184,7 +291,7 @@ int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb
return -1; return -1;
} }
ret = srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD, SRSLTE_SF_MBSFN); ret = srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD, SRSLTE_SF_MBSFN);
if (ret == SRSLTE_SUCCESS) { if (ret == SRSLTE_SUCCESS) {
srslte_dft_plan_set_norm(&q->fft_plan, false); srslte_dft_plan_set_norm(&q->fft_plan, false);
@ -207,7 +314,8 @@ int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
} }
return srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb); return srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb);
} else { } else {
fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n"); fprintf(stderr, "OFDM (Rx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n",
nof_prb, q->max_prb);
return -1; return -1;
} }
} }
@ -234,7 +342,8 @@ int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
} }
return ret; return ret;
} else { } else {
fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n"); fprintf(stderr, "OFDM (Tx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n",
nof_prb, q->max_prb);
return -1; return -1;
} }
} }
@ -274,8 +383,12 @@ void srslte_ofdm_tx_free(srslte_ofdm_t *q) {
/* Transforms input samples into output OFDM symbols. /* Transforms input samples into output OFDM symbols.
* Performs FFT on a each symbol and removes CP. * Performs FFT on a each symbol and removes CP.
*/ */
void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { void srslte_ofdm_rx_slot(srslte_ofdm_t *q, int slot_in_sf) {
cf_t *output = q->out_buffer + slot_in_sf * q->nof_re * q->nof_symbols;
#ifdef AVOID_GURU
uint32_t i; uint32_t i;
cf_t *input = q->in_buffer + slot_in_sf * q->slot_sz;
for (i=0;i<q->nof_symbols;i++) { for (i=0;i<q->nof_symbols;i++) {
input += SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz); input += SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
srslte_dft_run_c(&q->fft_plan, input, q->tmp); srslte_dft_run_c(&q->fft_plan, input, q->tmp);
@ -283,6 +396,25 @@ void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
input += q->symbol_sz; input += q->symbol_sz;
output += q->nof_re; output += q->nof_re;
} }
#else
float norm = 1.0f/sqrtf(q->fft_plan.size);
cf_t *tmp = q->tmp + slot_in_sf * q->symbol_sz * q->nof_symbols;
uint32_t dc = (q->fft_plan.dc) ? 1:0;
srslte_dft_run_guru_c(&q->fft_plan_sf[slot_in_sf]);
for (int i = 0; i < q->nof_symbols; i++) {
memcpy(output, tmp + q->symbol_sz - q->nof_re / 2, sizeof(cf_t) * q->nof_re / 2);
memcpy(output + q->nof_re / 2, &tmp[dc], sizeof(cf_t) * q->nof_re / 2);
if (q->fft_plan.norm) {
srslte_vec_sc_prod_cfc(output, norm, output, q->nof_re);
}
tmp += q->symbol_sz;
output += q->nof_re;
}
#endif
} }
void srslte_ofdm_rx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output) void srslte_ofdm_rx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output)
@ -314,29 +446,32 @@ void srslte_ofdm_rx_slot_zerocopy(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
} }
} }
void srslte_ofdm_rx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output) { void srslte_ofdm_rx_sf(srslte_ofdm_t *q) {
uint32_t n; uint32_t n;
if (q->freq_shift) { if (q->freq_shift) {
srslte_vec_prod_ccc(input, q->shift_buffer, input, 2*q->slot_sz); srslte_vec_prod_ccc(q->in_buffer, q->shift_buffer, q->in_buffer, 2*q->slot_sz);
} }
if(!q->mbsfn_subframe){ if(!q->mbsfn_subframe){
for (n=0;n<2;n++) { for (n=0;n<2;n++) {
srslte_ofdm_rx_slot(q, &input[n*q->slot_sz], &output[n*q->nof_re*q->nof_symbols]); srslte_ofdm_rx_slot(q, n);
} }
} }
else{ else{
srslte_ofdm_rx_slot_mbsfn(q, &input[0*q->slot_sz], &output[0*q->nof_re*q->nof_symbols]); srslte_ofdm_rx_slot_mbsfn(q, &q->in_buffer[0*q->slot_sz], &q->out_buffer[0*q->nof_re*q->nof_symbols]);
srslte_ofdm_rx_slot(q, &input[1*q->slot_sz], &output[1*q->nof_re*q->nof_symbols]); srslte_ofdm_rx_slot(q, 1);
} }
} }
/* Transforms input OFDM symbols into output samples. /* Transforms input OFDM symbols into output samples.
* Performs FFT on a each symbol and adds CP. * Performs FFT on a each symbol and adds CP.
*/ */
void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { void srslte_ofdm_tx_slot(srslte_ofdm_t *q, int slot_in_sf) {
uint32_t i, cp_len; cf_t *input = q->in_buffer + slot_in_sf * q->nof_re * q->nof_symbols;
for (i=0;i<q->nof_symbols;i++) { cf_t *output = q->out_buffer + slot_in_sf * q->slot_sz;
cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
#ifdef AVOID_GURU
for (int i=0;i<q->nof_symbols;i++) {
int cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t));
srslte_dft_run_c(&q->fft_plan, q->tmp, &output[cp_len]); srslte_dft_run_c(&q->fft_plan, q->tmp, &output[cp_len]);
input += q->nof_re; input += q->nof_re;
@ -344,6 +479,60 @@ void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) {
memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t)); memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t));
output += q->symbol_sz + cp_len; output += q->symbol_sz + cp_len;
} }
#else
float norm = 1.0f/sqrtf(q->symbol_sz);
cf_t *tmp = q->tmp + slot_in_sf * q->symbol_sz * q->nof_symbols;
bzero(tmp, q->slot_sz);
uint32_t dc = (q->fft_plan.dc) ? 1:0;
for (int i = 0; i < q->nof_symbols; i++) {
memcpy(&tmp[dc], &input[q->nof_re / 2], q->nof_re / 2 * sizeof(cf_t));
memcpy(&tmp[q->symbol_sz - q->nof_re / 2], &input[0], q->nof_re / 2 * sizeof(cf_t));
input += q->nof_re;
tmp += q->symbol_sz;
}
srslte_dft_run_guru_c(&q->fft_plan_sf[slot_in_sf]);
for (int i=0;i<q->nof_symbols;i++) {
int cp_len = SRSLTE_CP_ISNORM(q->cp) ? SRSLTE_CP_LEN_NORM(i, q->symbol_sz) : SRSLTE_CP_LEN_EXT(q->symbol_sz);
if (q->fft_plan.norm) {
srslte_vec_sc_prod_cfc(&output[cp_len], norm, &output[cp_len], q->symbol_sz);
}
/* add CP */
memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t));
output += q->symbol_sz + cp_len;
}
#endif
/*input = q->in_buffer + slot_in_sf * q->nof_re * q->nof_symbols;
cf_t *output2 = srslte_vec_malloc(sizeof(cf_t) * q->slot_sz);
cf_t *o2 = output2;
bzero(q->tmp, sizeof(cf_t)*q->symbol_sz);
//bzero(output2, sizeof(cf_t)*q->slot_sz);
for (int i=0;i<q->nof_symbols;i++) {
int cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz);
memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t));
srslte_dft_run_c(&q->fft_plan, q->tmp, &o2[cp_len]);
input += q->nof_re;
memcpy(o2, &o2[q->symbol_sz], cp_len * sizeof(cf_t));
o2 += q->symbol_sz + cp_len;
}
cf_t *output1 = q->out_buffer + slot_in_sf * q->slot_sz;//srslte_vec_malloc(sizeof(cf_t) * q->slot_sz);
for (int i = 0; i < q->slot_sz; i++) {
float error = cabsf(output1[i] - output2[i])/cabsf(output2[i]);
cf_t k = output1[i]/output2[i];
if (error > 0.1) printf("%d/%05d error=%f output=%+f%+fi gold=%+f%+fi k=%+f%+fi\n", slot_in_sf, i, error,
__real__ output1[i], __imag__ output1[i],
__real__ output2[i], __imag__ output2[i],
__real__ k, __imag__ k);
}
free(output2);/**/
} }
void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output) void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output)
@ -369,20 +558,20 @@ void srslte_ofdm_set_normalize(srslte_ofdm_t *q, bool normalize_enable) {
srslte_dft_plan_set_norm(&q->fft_plan, normalize_enable); srslte_dft_plan_set_norm(&q->fft_plan, normalize_enable);
} }
void srslte_ofdm_tx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output) void srslte_ofdm_tx_sf(srslte_ofdm_t *q)
{ {
uint32_t n; uint32_t n;
if(!q->mbsfn_subframe){ if(!q->mbsfn_subframe){
for (n=0;n<2;n++) { for (n=0;n<2;n++) {
srslte_ofdm_tx_slot(q, &input[n*q->nof_re*q->nof_symbols], &output[n*q->slot_sz]); srslte_ofdm_tx_slot(q, n);
} }
} }
else{ else{
srslte_ofdm_tx_slot_mbsfn(q, &input[0*q->nof_re*q->nof_symbols], &output[0*q->slot_sz]); srslte_ofdm_tx_slot_mbsfn(q, &q->in_buffer[0*q->nof_re*q->nof_symbols], &q->out_buffer[0*q->slot_sz]);
srslte_ofdm_tx_slot(q, &input[1*q->nof_re*q->nof_symbols], &output[1*q->slot_sz]); srslte_ofdm_tx_slot(q, 1);
} }
if (q->freq_shift) { if (q->freq_shift) {
srslte_vec_prod_ccc(output, q->shift_buffer, output, 2*q->slot_sz); srslte_vec_prod_ccc(q->out_buffer, q->shift_buffer, q->out_buffer, 2*q->slot_sz);
} }
} }

@ -35,16 +35,28 @@
int nof_prb = -1; int nof_prb = -1;
srslte_cp_t cp = SRSLTE_CP_NORM; srslte_cp_t cp = SRSLTE_CP_NORM;
int nof_repetitions = 128;
static double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) {
if (ts_end->tv_usec > ts_start->tv_usec) {
return ((double) ts_end->tv_sec - (double) ts_start->tv_sec) * 1000000 +
(double) ts_end->tv_usec - (double) ts_start->tv_usec;
} else {
return ((double) ts_end->tv_sec - (double) ts_start->tv_sec - 1) * 1000000 +
((double) ts_end->tv_usec + 1000000) - (double) ts_start->tv_usec;
}
}
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s\n", prog); printf("Usage: %s\n", prog);
printf("\t-n nof_prb [Default All]\n"); printf("\t-n nof_prb [Default All]\n");
printf("\t-e extended cyclic prefix [Default Normal]\n"); printf("\t-e extended cyclic prefix [Default Normal]\n");
printf("\t-r nof_repetitions [Default %d]\n", nof_repetitions);
} }
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "ne")) != -1) { while ((opt = getopt(argc, argv, "ner")) != -1) {
switch (opt) { switch (opt) {
case 'n': case 'n':
nof_prb = atoi(argv[optind]); nof_prb = atoi(argv[optind]);
@ -52,6 +64,9 @@ void parse_args(int argc, char **argv) {
case 'e': case 'e':
cp = SRSLTE_CP_EXT; cp = SRSLTE_CP_EXT;
break; break;
case 'r':
nof_repetitions = atoi(argv[optind]);
break;
default: default:
usage(argv[0]); usage(argv[0]);
exit(-1); exit(-1);
@ -61,6 +76,7 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
struct timeval start, end;
srslte_ofdm_t fft, ifft; srslte_ofdm_t fft, ifft;
cf_t *input, *outfft, *outifft; cf_t *input, *outfft, *outifft;
float mse; float mse;
@ -81,48 +97,65 @@ int main(int argc, char **argv) {
printf("Running test for %d PRB, %d RE... ", n_prb, n_re);fflush(stdout); printf("Running test for %d PRB, %d RE... ", n_prb, n_re);fflush(stdout);
input = malloc(sizeof(cf_t) * n_re); input = srslte_vec_malloc(sizeof(cf_t) * n_re * 2);
if (!input) { if (!input) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
outfft = malloc(sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb))); outfft = srslte_vec_malloc(sizeof(cf_t) * n_re * 2);
if (!outfft) { if (!outfft) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
outifft = malloc(sizeof(cf_t) * n_re); outifft = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb)) * 2);
if (!outifft) { if (!outifft) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
bzero(outifft, sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb)) * 2);
if (srslte_ofdm_rx_init(&fft, cp, n_prb)) { if (srslte_ofdm_rx_init(&fft, cp, outifft, outfft, n_prb)) {
fprintf(stderr, "Error initializing FFT\n"); fprintf(stderr, "Error initializing FFT\n");
exit(-1); exit(-1);
} }
srslte_dft_plan_set_norm(&fft.fft_plan, true); srslte_ofdm_set_normalize(&fft, true);
if (srslte_ofdm_tx_init(&ifft, cp, n_prb)) { if (srslte_ofdm_tx_init(&ifft, cp, input, outifft, n_prb)) {
fprintf(stderr, "Error initializing iFFT\n"); fprintf(stderr, "Error initializing iFFT\n");
exit(-1); exit(-1);
} }
srslte_dft_plan_set_norm(&ifft.fft_plan, true); srslte_ofdm_set_normalize(&ifft, true);
for (i=0;i<n_re;i++) { for (i=0;i<n_re;i++) {
input[i] = 100 * ((float) rand()/RAND_MAX + (float) I*rand()/RAND_MAX); input[i] = 100 * ((float) rand() / (float) RAND_MAX + I * ((float) rand() / (float) RAND_MAX));
//input[i] = 100;
} }
srslte_ofdm_tx_slot(&ifft, input, outfft); gettimeofday(&start, NULL);
srslte_ofdm_rx_slot(&fft, outfft, outifft); for (int i = 0; i < nof_repetitions; i++) {
srslte_ofdm_tx_slot(&ifft, 0);
}
gettimeofday(&end, NULL);\
printf(" Tx@%.1fMsps", (float)(SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb))*nof_repetitions)/elapsed_us(&start, &end));
/* compute MSE */ gettimeofday(&start, NULL);
for (int i = 0; i < nof_repetitions; i++) {
srslte_ofdm_rx_slot(&fft, 0);
}
gettimeofday(&end, NULL);\
printf(" Rx@%.1fMsps", (float)(SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb))*nof_repetitions)/elapsed_us(&start, &end));
mse = 0; /* compute MSE */
mse = 0.0f;
for (i=0;i<n_re;i++) { for (i=0;i<n_re;i++) {
mse += cabsf(input[i] - outifft[i]); cf_t error = input[i] - outfft[i];
mse += (__real__ error * __real__ error + __imag__ error * __imag__ error)/cabsf(input[i]);
if (mse > 1.0f) printf("%04d. %+.1f%+.1fi Vs. %+.1f%+.1f %+.1f%+.1f (mse=%f)\n", i, __real__ input[i], __imag__ input[i], __real__ outifft[i], __imag__ outifft[i], __real__ outfft[i], __imag__ outfft[i], mse);
} }
printf("MSE=%f\n", mse); /*for (i=0;i<n_re;i++) {
mse += cabsf(input[i] - outfft[i]);
}*/
printf(" MSE=%.6f\n", mse);
if (mse >= 0.07) { if (mse >= 0.07) {
printf("MSE too large\n"); printf("MSE too large\n");

@ -41,7 +41,7 @@
#define SRSLTE_ENB_RF_AMP 0.1 #define SRSLTE_ENB_RF_AMP 0.1
int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb) int srslte_enb_dl_init(srslte_enb_dl_t *q, cf_t *out_buffer[SRSLTE_MAX_PORTS], uint32_t max_prb)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -54,12 +54,25 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb)
q->cfi = 3; q->cfi = 3;
q->tx_amp = SRSLTE_ENB_RF_AMP; q->tx_amp = SRSLTE_ENB_RF_AMP;
if (srslte_ofdm_tx_init(&q->ifft, SRSLTE_CP_NORM, max_prb)) { for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
fprintf(stderr, "Error initiating FFT\n"); q->sf_symbols[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
goto clean_exit; if (!q->sf_symbols[i]) {
perror("malloc");
goto clean_exit;
}
q->slot1_symbols[i] = &q->sf_symbols[i][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)];
}
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (srslte_ofdm_tx_init(&q->ifft[i], SRSLTE_CP_NORM, q->sf_symbols[i], out_buffer[i], max_prb)) {
fprintf(stderr, "Error initiating FFT (%d)\n", i);
goto clean_exit;
}
} }
srslte_ofdm_set_normalize(&q->ifft, true); for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
srslte_ofdm_set_normalize(&q->ifft[i], true);
}
if (srslte_pbch_init(&q->pbch)) { if (srslte_pbch_init(&q->pbch)) {
fprintf(stderr, "Error creating PBCH object\n"); fprintf(stderr, "Error creating PBCH object\n");
@ -89,15 +102,6 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb)
goto clean_exit; goto clean_exit;
} }
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->sf_symbols[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols[i]) {
perror("malloc");
goto clean_exit;
}
q->slot1_symbols[i] = &q->sf_symbols[i][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)];
}
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} else { } else {
@ -114,7 +118,9 @@ clean_exit:
void srslte_enb_dl_free(srslte_enb_dl_t *q) void srslte_enb_dl_free(srslte_enb_dl_t *q)
{ {
if (q) { if (q) {
srslte_ofdm_tx_free(&q->ifft); for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
srslte_ofdm_tx_free(&q->ifft[i]);
}
srslte_regs_free(&q->regs); srslte_regs_free(&q->regs);
srslte_pbch_free(&q->pbch); srslte_pbch_free(&q->pbch);
srslte_pcfich_free(&q->pcfich); srslte_pcfich_free(&q->pcfich);
@ -152,9 +158,11 @@ int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell)
fprintf(stderr, "Error resizing REGs\n"); fprintf(stderr, "Error resizing REGs\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (srslte_ofdm_rx_set_prb(&q->ifft, q->cell.cp, q->cell.nof_prb)) { for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
fprintf(stderr, "Error initiating FFT\n"); if (srslte_ofdm_tx_set_prb(&q->ifft[i], q->cell.cp, q->cell.nof_prb)) {
return SRSLTE_ERROR; fprintf(stderr, "Error re-planning iFFT (%d)\n", i);
return SRSLTE_ERROR;
}
} }
if (srslte_pbch_set_cell(&q->pbch, q->cell)) { if (srslte_pbch_set_cell(&q->pbch, q->cell)) {
fprintf(stderr, "Error creating PBCH object\n"); fprintf(stderr, "Error creating PBCH object\n");
@ -268,14 +276,14 @@ void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti)
} }
void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, cf_t *signal_buffer[SRSLTE_MAX_PORTS]) void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q)
{ {
// TODO: PAPR control // TODO: PAPR control
float norm_factor = (float) sqrt(q->cell.nof_prb)/15; float norm_factor = (float) sqrt(q->cell.nof_prb)/15;
for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { for (int i = 0; i < q->cell.nof_ports; i++) {
srslte_ofdm_tx_sf(&q->ifft, q->sf_symbols[p], signal_buffer[p]); srslte_ofdm_tx_sf(&q->ifft[i]);
srslte_vec_sc_prod_cfc(signal_buffer[p], q->tx_amp*norm_factor, signal_buffer[p], (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); srslte_vec_sc_prod_cfc(q->ifft[i].out_buffer, q->tx_amp*norm_factor, q->ifft[i].out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
} }
} }

@ -40,6 +40,7 @@
#define MAX_CANDIDATES 16 #define MAX_CANDIDATES 16
int srslte_enb_ul_init(srslte_enb_ul_t *q, int srslte_enb_ul_init(srslte_enb_ul_t *q,
cf_t *in_buffer,
uint32_t max_prb) uint32_t max_prb)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -56,7 +57,19 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q,
goto clean_exit; goto clean_exit;
} }
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->ce = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->ce) {
perror("malloc");
goto clean_exit;
}
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, in_buffer, q->sf_symbols, max_prb)) {
fprintf(stderr, "Error initiating FFT\n"); fprintf(stderr, "Error initiating FFT\n");
goto clean_exit; goto clean_exit;
} }
@ -80,18 +93,6 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q,
goto clean_exit; goto clean_exit;
} }
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->ce = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->ce) {
perror("malloc");
goto clean_exit;
}
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} else { } else {
@ -252,9 +253,9 @@ int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti,
} }
} }
void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer) void srslte_enb_ul_fft(srslte_enb_ul_t *q)
{ {
srslte_ofdm_rx_sf(&q->fft, signal_buffer, q->sf_symbols); srslte_ofdm_rx_sf(&q->fft);
} }
int get_pucch(srslte_enb_ul_t *q, uint16_t rnti, int get_pucch(srslte_enb_ul_t *q, uint16_t rnti,

@ -741,4 +741,3 @@ int srslte_rm_turbo_rx(float *w_buff, uint32_t w_buff_len, float *input, uint32_
return 0; return 0;
} }

@ -33,6 +33,7 @@
#include "srslte/phy/mimo/precoding.h" #include "srslte/phy/mimo/precoding.h"
#include "srslte/phy/utils/vector.h" #include "srslte/phy/utils/vector.h"
#include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/mat.h"
#ifdef LV_HAVE_SSE #ifdef LV_HAVE_SSE
#include <immintrin.h> #include <immintrin.h>
@ -46,7 +47,6 @@ int srslte_predecoding_single_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_
#endif #endif
#include "srslte/phy/utils/mat.h" #include "srslte/phy/utils/mat.h"
static srslte_mimo_decoder_t mimo_decoder = SRSLTE_MIMO_DECODER_MMSE; static srslte_mimo_decoder_t mimo_decoder = SRSLTE_MIMO_DECODER_MMSE;
/************************************************ /************************************************

@ -44,6 +44,7 @@ int srslte_demod_hard_demodulate(srslte_demod_hard_t* q, cf_t* symbols, uint8_t
int nbits=-1; int nbits=-1;
switch(q->mod) { switch(q->mod) {
case SRSLTE_MOD_LAST:
case SRSLTE_MOD_BPSK: case SRSLTE_MOD_BPSK:
hard_bpsk_demod(symbols,bits,nsymbols); hard_bpsk_demod(symbols,bits,nsymbols);
nbits=nsymbols; nbits=nsymbols;

@ -82,6 +82,7 @@ int srslte_modem_table_set(srslte_modem_table_t* q, cf_t* table, uint32_t nsymbo
int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation) { int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation) {
srslte_modem_table_init(q); srslte_modem_table_init(q);
switch(modulation) { switch(modulation) {
case SRSLTE_MOD_LAST:
case SRSLTE_MOD_BPSK: case SRSLTE_MOD_BPSK:
q->nbits_x_symbol = 1; q->nbits_x_symbol = 1;
q->nsymbols = 2; q->nsymbols = 2;

@ -111,7 +111,7 @@ int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar, uint32_t nof_prb,
srslte_ra_type2_from_riv(riv, &ul_dci->type2_alloc.L_crb, &ul_dci->type2_alloc.RB_start, srslte_ra_type2_from_riv(riv, &ul_dci->type2_alloc.L_crb, &ul_dci->type2_alloc.RB_start,
nof_prb, nof_prb); nof_prb, nof_prb);
if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant, 0)) { if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -177,7 +177,7 @@ int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, uint32_t nof_prb,
return ret; return ret;
} }
if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant, harq_pid)) { if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant)) {
return ret; return ret;
} }

@ -381,11 +381,11 @@ int srslte_pmch_decode_multi(srslte_pmch_t *q,
srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits[0].nof_re, noise_estimate); srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits[0].nof_re, noise_estimate);
if (SRSLTE_VERBOSE_ISDEBUG()) { if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("SAVED FILE subframe.dat: received subframe symbols\n",0); DEBUG("SAVED FILE subframe.dat: received subframe symbols\n");
srslte_vec_save_file("subframe.dat", sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); srslte_vec_save_file("subframe.dat", sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
DEBUG("SAVED FILE hest0.dat: channel estimates for port 4\n",0); DEBUG("SAVED FILE hest0.dat: channel estimates for port 4\n");
srslte_vec_save_file("hest0.dat", ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); srslte_vec_save_file("hest0.dat", ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
DEBUG("SAVED FILE pmch_symbols.dat: symbols after equalization\n",0); DEBUG("SAVED FILE pmch_symbols.dat: symbols after equalization\n");
srslte_vec_save_file("pmch_symbols.bin", q->d, cfg->nbits[0].nof_re*sizeof(cf_t)); srslte_vec_save_file("pmch_symbols.bin", q->d, cfg->nbits[0].nof_re*sizeof(cf_t));
} }
@ -393,16 +393,13 @@ int srslte_pmch_decode_multi(srslte_pmch_t *q,
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in thde LLRs normalization * thus we don't need tot set it in thde LLRs normalization
*/ */
srslte_demod_soft_demodulate_s(cfg->grant.mcs[0].mod, q->d, q->e, cfg->nbits[0].nof_re); srslte_demod_soft_demodulate_s(cfg->grant.mcs[0].mod, q->d, q->e, cfg->nbits[0].nof_re);
/* descramble */ /* descramble */
srslte_scrambling_s_offset(&q->seqs[area_id]->seq[cfg->sf_idx], q->e, 0, cfg->nbits[0].nof_bits); srslte_scrambling_s_offset(&q->seqs[area_id]->seq[cfg->sf_idx], q->e, 0, cfg->nbits[0].nof_bits);
if (SRSLTE_VERBOSE_ISDEBUG()) { if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0); DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n");
srslte_vec_save_file("llr.dat", q->e, cfg->nbits[0].nof_bits*sizeof(int16_t)); srslte_vec_save_file("llr.dat", q->e, cfg->nbits[0].nof_bits*sizeof(int16_t));
} }
return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data); return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data);

@ -323,7 +323,7 @@ int srslte_pusch_set_cell(srslte_pusch_t *q, srslte_cell_t cell) {
q->max_re = cell.nof_prb * MAX_PUSCH_RE(q->cell.cp); q->max_re = cell.nof_prb * MAX_PUSCH_RE(q->cell.cp);
INFO("PUSCH: Cell config PCI=5d, %d ports %d PRBs, max_symbols: %d\n", INFO("PUSCH: Cell config PCI=%d, %d ports %d PRBs, max_symbols: %d\n",
q->cell.id, q->cell.nof_ports, q->cell.nof_prb, q->max_re); q->cell.id, q->cell.nof_ports, q->cell.nof_prb, q->max_re);
if (q->cell.id != cell.id || q->cell.nof_prb == 0) { if (q->cell.id != cell.id || q->cell.nof_prb == 0) {

@ -185,51 +185,34 @@ int srslte_ra_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_
} }
} }
srslte_mod_t last_mod[8]; static void ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant) {
uint32_t last_ul_tbs_idx[8];
uint32_t last_dl_tbs[8];
uint32_t last_dl_tbs2[8];
static int ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, uint32_t harq_pid) {
int tbs = -1;
// 8.6.2 First paragraph // 8.6.2 First paragraph
if (dci->mcs_idx <= 28) { if (dci->mcs_idx <= 28) {
/* Table 8.6.1-1 on 36.213 */ /* Table 8.6.1-1 on 36.213 */
if (dci->mcs_idx < 11) { if (dci->mcs_idx < 11) {
grant->mcs.mod = SRSLTE_MOD_QPSK; grant->mcs.mod = SRSLTE_MOD_QPSK;
tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb); grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb);
last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx;
} else if (dci->mcs_idx < 21) { } else if (dci->mcs_idx < 21) {
grant->mcs.mod = SRSLTE_MOD_16QAM; grant->mcs.mod = SRSLTE_MOD_16QAM;
tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-1, grant->L_prb); grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-1, grant->L_prb);
last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx-1;
} else if (dci->mcs_idx < 29) { } else if (dci->mcs_idx < 29) {
grant->mcs.mod = SRSLTE_MOD_64QAM; grant->mcs.mod = SRSLTE_MOD_64QAM;
tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-2, grant->L_prb); grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-2, grant->L_prb);
last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx-2;
} else { } else {
fprintf(stderr, "Invalid MCS index %d\n", dci->mcs_idx); fprintf(stderr, "Invalid MCS index %d\n", dci->mcs_idx);
} }
last_mod[harq_pid%8] = grant->mcs.mod;
} else if (dci->mcs_idx == 29 && dci->cqi_request && grant->L_prb <= 4) { } else if (dci->mcs_idx == 29 && dci->cqi_request && grant->L_prb <= 4) {
// 8.6.1 and 8.6.2 36.213 second paragraph // 8.6.1 and 8.6.2 36.213 second paragraph
grant->mcs.mod = SRSLTE_MOD_QPSK; grant->mcs.mod = SRSLTE_MOD_QPSK;
tbs = srslte_ra_tbs_from_idx(last_ul_tbs_idx[harq_pid%8], grant->L_prb); grant->mcs.tbs = 0;
dci->rv_idx = 1; dci->rv_idx = 1;
} else if (dci->mcs_idx >= 29) { } else if (dci->mcs_idx >= 29) {
// Else use last TBS/Modulation and use mcs to obtain rv_idx // Else use last TBS/Modulation and use mcs to obtain rv_idx
tbs = srslte_ra_tbs_from_idx(last_ul_tbs_idx[harq_pid%8], grant->L_prb); grant->mcs.tbs = -1;
grant->mcs.mod = last_mod[harq_pid%8]; grant->mcs.mod = SRSLTE_MOD_LAST;
dci->rv_idx = dci->mcs_idx - 28; dci->rv_idx = dci->mcs_idx - 28;
DEBUG("TTI=%d, harq_pid=%d, mcs_idx=%d, tbs=%d, mod=%d, rv=%d\n", DEBUG("mcs_idx=%d, tbs=%d, mod=%d, rv=%d\n",
harq_pid, harq_pid%8, dci->mcs_idx, tbs/8, grant->mcs.mod, dci->rv_idx); dci->mcs_idx, grant->mcs.tbs/8, grant->mcs.mod, dci->rv_idx);
}
if (tbs < 0) {
fprintf(stderr, "Error computing TBS\n");
return SRSLTE_ERROR;
} else {
grant->mcs.tbs = (uint32_t) tbs;
return SRSLTE_SUCCESS;
} }
} }
@ -241,25 +224,21 @@ void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, srslte_cp_t cp, ui
} }
/** Compute PRB allocation for Uplink as defined in 8.1 and 8.4 of 36.213 */ /** Compute PRB allocation for Uplink as defined in 8.1 and 8.4 of 36.213 */
int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_t n_rb_ho, srslte_ra_ul_grant_t *grant, int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_t n_rb_ho, srslte_ra_ul_grant_t *grant)
uint32_t harq_pid)
{ {
// Compute PRB allocation // Compute PRB allocation
if (!srslte_ra_ul_dci_to_grant_prb_allocation(dci, grant, n_rb_ho, nof_prb)) { if (!srslte_ra_ul_dci_to_grant_prb_allocation(dci, grant, n_rb_ho, nof_prb)) {
// Compute MCS // Compute MCS
if (!ul_dci_to_grant_mcs(dci, grant, harq_pid)) { ul_dci_to_grant_mcs(dci, grant);
// Fill rest of grant structure
grant->mcs.idx = dci->mcs_idx;
grant->M_sc = grant->L_prb*SRSLTE_NRE;
grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be?
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
// Fill rest of grant structure
grant->mcs.idx = dci->mcs_idx;
grant->M_sc = grant->L_prb*SRSLTE_NRE;
grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be?
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
} else {
fprintf(stderr, "Error computing MCS\n");
return SRSLTE_ERROR;
}
} else { } else {
printf("Error computing UL PRB allocation\n"); printf("Error computing UL PRB allocation\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -442,8 +421,7 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_
} }
int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) { int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) {
uint32_t i_tbs = 0; int i_tbs = 0;
int tbs = -1;
if (mcs->idx < 10) { if (mcs->idx < 10) {
mcs->mod = SRSLTE_MOD_QPSK; mcs->mod = SRSLTE_MOD_QPSK;
i_tbs = mcs->idx; i_tbs = mcs->idx;
@ -455,23 +433,19 @@ int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) {
i_tbs = mcs->idx-2; i_tbs = mcs->idx-2;
} else if (mcs->idx == 29) { } else if (mcs->idx == 29) {
mcs->mod = SRSLTE_MOD_QPSK; mcs->mod = SRSLTE_MOD_QPSK;
tbs = 0; i_tbs = -1;
i_tbs = 0;
} else if (mcs->idx == 30) { } else if (mcs->idx == 30) {
mcs->mod = SRSLTE_MOD_16QAM; mcs->mod = SRSLTE_MOD_16QAM;
tbs = 0; i_tbs = -1;
i_tbs = 0;
} else if (mcs->idx == 31) { } else if (mcs->idx == 31) {
mcs->mod = SRSLTE_MOD_64QAM; mcs->mod = SRSLTE_MOD_64QAM;
tbs = 0; i_tbs = -1;
i_tbs = 0;
} }
if (tbs == -1) { int tbs = -1;
if (i_tbs >= 0) {
tbs = srslte_ra_tbs_from_idx(i_tbs, nprb); tbs = srslte_ra_tbs_from_idx(i_tbs, nprb);
if (tbs >= 0) { mcs->tbs = tbs;
mcs->tbs = tbs;
}
} }
return tbs; return tbs;
} }
@ -555,26 +529,14 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
grant->nof_tb = 0; grant->nof_tb = 0;
if (dci->tb_en[0]) { if (dci->tb_en[0]) {
grant->mcs[0].idx = dci->mcs_idx; grant->mcs[0].idx = dci->mcs_idx;
tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb); grant->mcs[0].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb);
if (tbs) {
last_dl_tbs[dci->harq_process%8] = tbs;
} else {
// For mcs>=29, set last TBS received for this PID
grant->mcs[0].tbs = last_dl_tbs[dci->harq_process%8];
}
grant->nof_tb++; grant->nof_tb++;
} else { } else {
grant->mcs[0].tbs = 0; grant->mcs[0].tbs = 0;
} }
if (dci->tb_en[1]) { if (dci->tb_en[1]) {
grant->mcs[1].idx = dci->mcs_idx_1; grant->mcs[1].idx = dci->mcs_idx_1;
tbs = srslte_dl_fill_ra_mcs(&grant->mcs[1], n_prb); grant->mcs[1].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[1], n_prb);
if (tbs) {
last_dl_tbs2[dci->harq_process%8] = tbs;
} else {
// For mcs>=29, set last TBS received for this PID
grant->mcs[1].tbs = last_dl_tbs2[dci->harq_process%8];
}
} else { } else {
grant->mcs[1].tbs = 0; grant->mcs[1].tbs = 0;
} }
@ -587,7 +549,7 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
} }
grant->pinfo = dci->pinfo; grant->pinfo = dci->pinfo;
if (tbs < 0) { if (grant->mcs[0].tbs < 0 || grant->mcs[1].tbs < 0) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} else { } else {
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
@ -623,9 +585,11 @@ int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
crc_is_crnti = true; crc_is_crnti = true;
} }
// Compute PRB allocation // Compute PRB allocation
if (!srslte_ra_dl_dci_to_grant_prb_allocation(dci, grant, nof_prb)) { int ret =srslte_ra_dl_dci_to_grant_prb_allocation(dci, grant, nof_prb);
if (!ret) {
// Compute MCS // Compute MCS
if (!dl_dci_to_grant_mcs(dci, grant, crc_is_crnti)) { ret = dl_dci_to_grant_mcs(dci, grant, crc_is_crnti);
if (ret == SRSLTE_SUCCESS) {
// Apply Section 7.1.7.3. If RA-RNTI and Format1C rv_idx=0 // Apply Section 7.1.7.3. If RA-RNTI and Format1C rv_idx=0
if (msg_rnti >= SRSLTE_RARNTI_START && msg_rnti <= SRSLTE_RARNTI_END && if (msg_rnti >= SRSLTE_RARNTI_START && msg_rnti <= SRSLTE_RARNTI_END &&
dci->dci_is_1c) dci->dci_is_1c)

@ -140,7 +140,7 @@ int base_init() {
return -1; return -1;
} }
if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
fprintf(stderr, "Error initializing FFT\n"); fprintf(stderr, "Error initializing FFT\n");
return -1; return -1;
} }
@ -203,7 +203,7 @@ int main(int argc, char **argv) {
if (nread > 0) { if (nread > 0) {
// process 1st subframe only // process 1st subframe only
srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); srslte_ofdm_rx_sf(&fft);
/* Get channel estimates for each port */ /* Get channel estimates for each port */
srslte_chest_dl_estimate(&chest, fft_buffer, ce, 0); srslte_chest_dl_estimate(&chest, fft_buffer, ce, 0);

@ -120,15 +120,15 @@ int base_init() {
fmatlab = NULL; fmatlab = NULL;
} }
flen = SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb)); flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb));
input_buffer = malloc(flen * sizeof(cf_t)); input_buffer = srslte_vec_malloc(flen * sizeof(cf_t));
if (!input_buffer) { if (!input_buffer) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
fft_buffer = malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); fft_buffer = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
if (!fft_buffer) { if (!fft_buffer) {
perror("malloc"); perror("malloc");
return -1; return -1;
@ -151,7 +151,7 @@ int base_init() {
return -1; return -1;
} }
if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
fprintf(stderr, "Error initializing FFT\n"); fprintf(stderr, "Error initializing FFT\n");
return -1; return -1;
} }
@ -215,7 +215,7 @@ int main(int argc, char **argv) {
n = srslte_filesource_read(&fsrc, input_buffer, flen); n = srslte_filesource_read(&fsrc, input_buffer, flen);
srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); srslte_ofdm_rx_sf(&fft);
if (fmatlab) { if (fmatlab) {
fprintf(fmatlab, "infft="); fprintf(fmatlab, "infft=");

@ -126,7 +126,7 @@ int base_init() {
exit(-1); exit(-1);
} }
flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz(cell.nof_prb))); flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz_power2(cell.nof_prb)));
input_buffer = malloc(flen * sizeof(cf_t)); input_buffer = malloc(flen * sizeof(cf_t));
if (!input_buffer) { if (!input_buffer) {
@ -157,7 +157,7 @@ int base_init() {
return -1; return -1;
} }
if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
fprintf(stderr, "Error initializing FFT\n"); fprintf(stderr, "Error initializing FFT\n");
return -1; return -1;
} }
@ -231,7 +231,7 @@ int main(int argc, char **argv) {
INFO("Reading %d samples sub-frame %d\n", flen, frame_cnt); INFO("Reading %d samples sub-frame %d\n", flen, frame_cnt);
srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); srslte_ofdm_rx_sf(&fft);
/* Get channel estimates for each port */ /* Get channel estimates for each port */
srslte_chest_dl_estimate(&chest, fft_buffer, ce, frame_cnt %10); srslte_chest_dl_estimate(&chest, fft_buffer, ce, frame_cnt %10);

@ -129,7 +129,7 @@ int base_init() {
exit(-1); exit(-1);
} }
flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz(cell.nof_prb))); flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb));
input_buffer[0] = malloc(flen * sizeof(cf_t)); input_buffer[0] = malloc(flen * sizeof(cf_t));
if (!input_buffer[0]) { if (!input_buffer[0]) {
@ -137,7 +137,7 @@ int base_init() {
exit(-1); exit(-1);
} }
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) { if (srslte_ue_dl_init(&ue_dl, input_buffer, cell.nof_prb, 1)) {
fprintf(stderr, "Error initializing UE DL\n"); fprintf(stderr, "Error initializing UE DL\n");
return -1; return -1;
} }

@ -144,7 +144,7 @@ int base_init() {
fmatlab = NULL; fmatlab = NULL;
} }
flen = SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb)); flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb));
input_buffer = malloc(flen * sizeof(cf_t)); input_buffer = malloc(flen * sizeof(cf_t));
if (!input_buffer) { if (!input_buffer) {
@ -175,7 +175,7 @@ int base_init() {
return -1; return -1;
} }
if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) {
fprintf(stderr, "Error initializing FFT\n"); fprintf(stderr, "Error initializing FFT\n");
return -1; return -1;
} }
@ -242,7 +242,7 @@ int main(int argc, char **argv) {
n = srslte_filesource_read(&fsrc, input_buffer, flen); n = srslte_filesource_read(&fsrc, input_buffer, flen);
srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); srslte_ofdm_rx_sf(&fft);
if (fmatlab) { if (fmatlab) {
fprintf(fmatlab, "infft="); fprintf(fmatlab, "infft=");
@ -263,7 +263,11 @@ int main(int argc, char **argv) {
for (ngroup=0;ngroup<srslte_phich_ngroups(&phich);ngroup++) { for (ngroup=0;ngroup<srslte_phich_ngroups(&phich);ngroup++) {
for (nseq=0;nseq<max_nseq;nseq++) { for (nseq=0;nseq<max_nseq;nseq++) {
if (srslte_phich_decode(&phich, &fft_buffer, &ce, srslte_chest_dl_get_noise_estimate(&chest), ngroup, nseq, numsubframe, &ack_rx, &distance)<0) { cf_t *input[SRSLTE_MAX_PORTS] = {fft_buffer, NULL};
cf_t *cebuf[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS] = {{ce[0], ce[1]},{ce[0], ce[1]}};
if (srslte_phich_decode(&phich, input, cebuf, srslte_chest_dl_get_noise_estimate(&chest),
ngroup, nseq, numsubframe, &ack_rx, &distance)<0)
{
printf("Error decoding ACK\n"); printf("Error decoding ACK\n");
exit(-1); exit(-1);
} }

@ -140,7 +140,7 @@ int base_init() {
exit(-1); exit(-1);
} }
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) { if (srslte_ue_dl_init(&ue_dl, input_buffer, cell.nof_prb, 1)) {
fprintf(stderr, "Error initializing UE DL\n"); fprintf(stderr, "Error initializing UE DL\n");
return -1; return -1;
} }
@ -157,7 +157,7 @@ int base_init() {
srslte_ue_dl_set_non_mbsfn_region(&ue_dl, non_mbsfn_region); srslte_ue_dl_set_non_mbsfn_region(&ue_dl, non_mbsfn_region);
DEBUG("Memory init OK\n",0); DEBUG("Memory init OK\n");
return 0; return 0;
} }

@ -139,7 +139,7 @@ cf_t *tx_slot_symbols[SRSLTE_MAX_PORTS];
cf_t *rx_slot_symbols[SRSLTE_MAX_PORTS]; cf_t *rx_slot_symbols[SRSLTE_MAX_PORTS];
srslte_pmch_t pmch_tx, pmch_rx; srslte_pmch_t pmch_tx, pmch_rx;
srslte_pdsch_cfg_t pmch_cfg; srslte_pdsch_cfg_t pmch_cfg;
srslte_ofdm_t ifft_mbsfn, fft_mbsfn; srslte_ofdm_t ifft_mbsfn[SRSLTE_MAX_PORTS], fft_mbsfn[SRSLTE_MAX_PORTS];
int main(int argc, char **argv) { int main(int argc, char **argv) {
uint32_t i, j, k; uint32_t i, j, k;
@ -181,46 +181,11 @@ int main(int argc, char **argv) {
} }
} }
#ifdef DO_OFDM
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
if (srslte_ofdm_rx_init_mbsfn(&fft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, non_mbsfn_region);
srslte_ofdm_set_non_mbsfn_region(&fft_mbsfn, non_mbsfn_region);
srslte_ofdm_set_normalize(&ifft_mbsfn, true);
srslte_ofdm_set_normalize(&fft_mbsfn, true);
for (i = 0; i < cell.nof_ports; i++) {
tx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
for (i = 0; i < nof_rx_antennas; i++) {
rx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
#endif /* DO_OFDM */
/* Configure PDSCH */
if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) {
fprintf(stderr, "Error configuring PMCH\n");
exit(-1);
}
/* init memory */ /* init memory */
for (i=0;i<SRSLTE_MAX_PORTS;i++) { for (i=0;i<SRSLTE_MAX_PORTS;i++) {
for (j = 0; j < SRSLTE_MAX_PORTS; j++) { for (j = 0; j < SRSLTE_MAX_PORTS; j++) {
ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * NOF_CE_SYMBOLS); ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * NOF_CE_SYMBOLS);
if (!ce[i]) { if (!ce[i][j]) {
perror("srslte_vec_malloc"); perror("srslte_vec_malloc");
goto quit; goto quit;
} }
@ -235,6 +200,25 @@ int main(int argc, char **argv) {
} }
} }
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
softbuffers_tx[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1);
if (!softbuffers_tx[i]) {
fprintf(stderr, "Error allocating TX soft buffer\n");
}
if (srslte_softbuffer_tx_init(softbuffers_tx[i], cell.nof_prb)) {
fprintf(stderr, "Error initiating TX soft buffer\n");
goto quit;
}
}
for (i = 0; i < cell.nof_ports; i++) {
tx_slot_symbols[i] = calloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), sizeof(cf_t));
if (!tx_slot_symbols[i]) {
perror("srslte_vec_malloc");
goto quit;
}
}
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant.tb_en[i]) { if (grant.tb_en[i]) {
@ -270,6 +254,44 @@ int main(int argc, char **argv) {
} }
} }
#ifdef DO_OFDM
for (i = 0; i < cell.nof_ports; i++) {
tx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn[i], SRSLTE_CP_EXT, tx_slot_symbols[i], tx_sf_symbols[i], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn[i], non_mbsfn_region);
srslte_ofdm_set_normalize(&ifft_mbsfn[i], true);
}
for (i = 0; i < nof_rx_antennas; i++) {
rx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (srslte_ofdm_rx_init_mbsfn(&fft_mbsfn[i], SRSLTE_CP_EXT, rx_sf_symbols[i], rx_slot_symbols[i], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_non_mbsfn_region(&fft_mbsfn[i], non_mbsfn_region);
srslte_ofdm_set_normalize(&fft_mbsfn[i], true);
}
#endif /* DO_OFDM */
/* Configure PDSCH */
if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) {
fprintf(stderr, "Error configuring PMCH\n");
exit(-1);
}
if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) { if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) {
fprintf(stderr, "Error configuring PMCH\n"); fprintf(stderr, "Error configuring PMCH\n");
exit(-1); exit(-1);
@ -312,25 +334,7 @@ int main(int argc, char **argv) {
srslte_pmch_set_area_id(&pmch_rx, mbsfn_area_id); srslte_pmch_set_area_id(&pmch_rx, mbsfn_area_id);
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
softbuffers_tx[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1);
if (!softbuffers_tx[i]) {
fprintf(stderr, "Error allocating TX soft buffer\n");
}
if (srslte_softbuffer_tx_init(softbuffers_tx[i], cell.nof_prb)) {
fprintf(stderr, "Error initiating TX soft buffer\n");
goto quit;
}
}
for (i = 0; i < cell.nof_ports; i++) {
tx_slot_symbols[i] = calloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), sizeof(cf_t));
if (!tx_slot_symbols[i]) {
perror("srslte_vec_malloc");
goto quit;
}
}
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (grant.tb_en[tb]) { if (grant.tb_en[tb]) {
@ -353,7 +357,7 @@ int main(int argc, char **argv) {
#ifdef DO_OFDM #ifdef DO_OFDM
for (i = 0; i < cell.nof_ports; i++) { for (i = 0; i < cell.nof_ports; i++) {
/* For each Tx antenna modulate OFDM */ /* For each Tx antenna modulate OFDM */
srslte_ofdm_tx_sf(&ifft_mbsfn, tx_slot_symbols[i], tx_sf_symbols[i]); srslte_ofdm_tx_sf(&ifft_mbsfn[i]);
} }
@ -387,7 +391,7 @@ int main(int argc, char **argv) {
#ifdef DO_OFDM #ifdef DO_OFDM
/* For each Rx antenna demodulate OFDM */ /* For each Rx antenna demodulate OFDM */
for (i = 0; i < nof_rx_antennas; i++) { for (i = 0; i < nof_rx_antennas; i++) {
srslte_ofdm_rx_sf(&fft_mbsfn, tx_sf_symbols[i], rx_slot_symbols[i]); srslte_ofdm_rx_sf(&fft_mbsfn[i]);
} }
#endif #endif
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {

@ -136,7 +136,7 @@ int main(int argc, char **argv) {
dci.mcs_idx = mcs_idx; dci.mcs_idx = mcs_idx;
srslte_ra_ul_grant_t grant; srslte_ra_ul_grant_t grant;
if (srslte_ra_ul_dci_to_grant(&dci, cell.nof_prb, 0, &grant, 0)) { if (srslte_ra_ul_dci_to_grant(&dci, cell.nof_prb, 0, &grant)) {
fprintf(stderr, "Error computing resource allocation\n"); fprintf(stderr, "Error computing resource allocation\n");
return ret; return ret;
} }

@ -649,12 +649,14 @@ int rf_uhd_recv_with_time_multi(void *h,
fprintf(stderr, "Error receiving from UHD: %d\n", error); fprintf(stderr, "Error receiving from UHD: %d\n", error);
return -1; return -1;
} }
uhd_rx_metadata_error_code_t error_code = 0;
uhd_rx_metadata_error_code(*md, &error_code);
md = &handler->rx_md; md = &handler->rx_md;
n += rxd_samples; n += rxd_samples;
trials++; trials++;
uhd_rx_metadata_error_code_t error_code;
uhd_rx_metadata_error_code(*md, &error_code);
if (error_code == UHD_RX_METADATA_ERROR_CODE_OVERFLOW) { if (error_code == UHD_RX_METADATA_ERROR_CODE_OVERFLOW) {
log_overflow(handler); log_overflow(handler);
} else if (error_code == UHD_RX_METADATA_ERROR_CODE_LATE_COMMAND) { } else if (error_code == UHD_RX_METADATA_ERROR_CODE_LATE_COMMAND) {

@ -70,14 +70,12 @@ static void corr_all_sz_partial(cf_t z[SRSLTE_SSS_N], float s[SRSLTE_SSS_N][SRSL
static void extract_pair_sss(srslte_sss_synch_t *q, cf_t *input, cf_t *ce, cf_t y[2][SRSLTE_SSS_N]) { static void extract_pair_sss(srslte_sss_synch_t *q, cf_t *input, cf_t *ce, cf_t y[2][SRSLTE_SSS_N]) {
cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX];
float ce_mod[2*SRSLTE_SSS_N], z_real[2*SRSLTE_SSS_N], z_imag[2*SRSLTE_SSS_N];
srslte_dft_run_c(&q->dftp_input, input, input_fft); srslte_dft_run_c(&q->dftp_input, input, input_fft);
if (ce) { if (ce) {
srslte_vec_div_ccc(&input_fft[q->fft_size/2-SRSLTE_SSS_N], ce, ce_mod, srslte_vec_div_ccc(&input_fft[q->fft_size/2-SRSLTE_SSS_N], ce,
&input_fft[q->fft_size/2-SRSLTE_SSS_N], z_real, z_imag, &input_fft[q->fft_size/2-SRSLTE_SSS_N], 2*SRSLTE_SSS_N);
2*SRSLTE_SSS_N);
} }
for (int i = 0; i < SRSLTE_SSS_N; i++) { for (int i = 0; i < SRSLTE_SSS_N; i++) {

@ -109,7 +109,7 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
if (srslte_ofdm_tx_init(&ifft, cp, nof_prb)) { if (srslte_ofdm_tx_init(&ifft, cp, buffer, fft_buffer, nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n"); fprintf(stderr, "Error creating iFFT object\n");
exit(-1); exit(-1);
} }
@ -150,7 +150,13 @@ int main(int argc, char **argv) {
/* Transform to OFDM symbols */ /* Transform to OFDM symbols */
memset(fft_buffer, 0, sizeof(cf_t) * FLEN); memset(fft_buffer, 0, sizeof(cf_t) * FLEN);
srslte_ofdm_tx_sf(&ifft, buffer, &fft_buffer[offset]); srslte_ofdm_tx_sf(&ifft);
/* Apply sample offset */
for (int i = 0; i < FLEN; i++) {
fft_buffer[FLEN - i - 1 + offset] = fft_buffer[FLEN - i - 1];
}
bzero(fft_buffer, sizeof(cf_t) * offset);
if (srslte_sync_find(&syncobj, fft_buffer, 0, &find_idx) < 0) { if (srslte_sync_find(&syncobj, fft_buffer, 0, &find_idx) < 0) {
fprintf(stderr, "Error running srslte_sync_find\n"); fprintf(stderr, "Error running srslte_sync_find\n");

@ -53,6 +53,7 @@ static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FO
const uint32_t nof_common_formats = 2; const uint32_t nof_common_formats = 2;
int srslte_ue_dl_init(srslte_ue_dl_t *q, int srslte_ue_dl_init(srslte_ue_dl_t *q,
cf_t *in_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb, uint32_t max_prb,
uint32_t nof_rx_antennas) uint32_t nof_rx_antennas)
{ {
@ -73,12 +74,35 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
q->sample_offset = 0; q->sample_offset = 0;
q->nof_rx_antennas = nof_rx_antennas; q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { for (int j = 0; j < SRSLTE_MAX_PORTS; j++) {
fprintf(stderr, "Error initiating FFT\n"); q->sf_symbols_m[j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
goto clean_exit; if (!q->sf_symbols_m[j]) {
perror("malloc");
goto clean_exit;
}
for (uint32_t i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->ce_m[i][j]) {
perror("malloc");
goto clean_exit;
}
bzero(q->ce_m[i][j], MAX_SFLEN_RE * sizeof(cf_t));
}
}
q->sf_symbols = q->sf_symbols_m[0];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce[i] = q->ce_m[i][0];
}
for (int i = 0; i < nof_rx_antennas; i++) {
if (srslte_ofdm_rx_init(&q->fft[i], SRSLTE_CP_NORM, in_buffer[i], q->sf_symbols_m[i], max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
} }
if (srslte_ofdm_rx_init_mbsfn(&q->fft_mbsfn, SRSLTE_CP_EXT, max_prb)) { if (srslte_ofdm_rx_init_mbsfn(&q->fft_mbsfn, SRSLTE_CP_EXT, in_buffer[0], q->sf_symbols_m[0], max_prb)) {
fprintf(stderr, "Error initiating FFT for MBSFN subframes \n"); fprintf(stderr, "Error initiating FFT for MBSFN subframes \n");
goto clean_exit; goto clean_exit;
} }
@ -127,28 +151,7 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
fprintf(stderr, "Error initiating SFO correct\n"); fprintf(stderr, "Error initiating SFO correct\n");
goto clean_exit; goto clean_exit;
} }
srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft.symbol_sz); srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft[0].symbol_sz);
for (int j = 0; j < SRSLTE_MAX_PORTS; j++) {
q->sf_symbols_m[j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols_m[j]) {
perror("malloc");
goto clean_exit;
}
for (uint32_t i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->ce_m[i][j]) {
perror("malloc");
goto clean_exit;
}
bzero(q->ce_m[i][j], MAX_SFLEN_RE * sizeof(cf_t));
}
}
q->sf_symbols = q->sf_symbols_m[0];
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce[i] = q->ce_m[i][0];
}
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} else { } else {
@ -164,7 +167,9 @@ clean_exit:
void srslte_ue_dl_free(srslte_ue_dl_t *q) { void srslte_ue_dl_free(srslte_ue_dl_t *q) {
if (q) { if (q) {
srslte_ofdm_rx_free(&q->fft); for (int port = 0; port < SRSLTE_MAX_PORTS; port++) {
srslte_ofdm_rx_free(&q->fft[port]);
}
srslte_ofdm_rx_free(&q->fft_mbsfn); srslte_ofdm_rx_free(&q->fft_mbsfn);
srslte_chest_dl_free(&q->chest); srslte_chest_dl_free(&q->chest);
srslte_regs_free(&q->regs); srslte_regs_free(&q->regs);
@ -219,10 +224,12 @@ int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell)
fprintf(stderr, "Error resizing SFO correct\n"); fprintf(stderr, "Error resizing SFO correct\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz); srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft[0].symbol_sz);
if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) { for (int port = 0; port < q->nof_rx_antennas; port++) {
fprintf(stderr, "Error resizing FFT\n"); if (srslte_ofdm_rx_set_prb(&q->fft[port], q->cell.cp, q->cell.nof_prb)) {
return SRSLTE_ERROR; fprintf(stderr, "Error resizing FFT\n");
return SRSLTE_ERROR;
}
} }
if (srslte_chest_dl_set_cell(&q->chest, q->cell)) { if (srslte_chest_dl_set_cell(&q->chest, q->cell)) {
fprintf(stderr, "Error resizing channel estimator\n"); fprintf(stderr, "Error resizing channel estimator\n");
@ -339,9 +346,9 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, cf_t *input[SRSLTE
/* Run FFT for all subframe data */ /* Run FFT for all subframe data */
for (int j=0;j<q->nof_rx_antennas;j++) { for (int j=0;j<q->nof_rx_antennas;j++) {
if(sf_type == SRSLTE_SF_MBSFN ) { if(sf_type == SRSLTE_SF_MBSFN ) {
srslte_ofdm_rx_sf(&q->fft_mbsfn, input[j], q->sf_symbols_m[j]); srslte_ofdm_rx_sf(&q->fft_mbsfn);
}else{ }else{
srslte_ofdm_rx_sf(&q->fft, input[j], q->sf_symbols_m[j]); srslte_ofdm_rx_sf(&q->fft[j]);
} }
/* Correct SFO multiplying by complex exponential in the time domain */ /* Correct SFO multiplying by complex exponential in the time domain */
@ -351,7 +358,7 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, cf_t *input[SRSLTE
srslte_cfo_correct(&q->sfo_correct, srslte_cfo_correct(&q->sfo_correct,
&q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE], &q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE],
&q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE], &q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE],
q->sample_offset / q->fft.symbol_sz); q->sample_offset / q->fft[j].symbol_sz);
} }
} }
} }
@ -603,7 +610,8 @@ int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q,
grant.sf_type = SRSLTE_SF_MBSFN; grant.sf_type = SRSLTE_SF_MBSFN;
grant.nof_tb = 1; grant.nof_tb = 1;
grant.mcs[0].idx = 2; grant.mcs[0].idx = 2;
grant.tb_en[0] = true;
grant.tb_en[1] = false;
grant.nof_prb = q->pmch.cell.nof_prb; grant.nof_prb = q->pmch.cell.nof_prb;
srslte_dl_fill_ra_mcs(&grant.mcs[0], grant.nof_prb); srslte_dl_fill_ra_mcs(&grant.mcs[0], grant.nof_prb);
srslte_softbuffer_rx_reset_tbs(q->softbuffers[0], (uint32_t) grant.mcs[0].tbs); srslte_softbuffer_rx_reset_tbs(q->softbuffers[0], (uint32_t) grant.mcs[0].tbs);

@ -36,6 +36,7 @@
#include "srslte/phy/utils/vector.h" #include "srslte/phy/utils/vector.h"
int srslte_ue_mib_init(srslte_ue_mib_t * q, int srslte_ue_mib_init(srslte_ue_mib_t * q,
cf_t *in_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb) uint32_t max_prb)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -65,7 +66,7 @@ int srslte_ue_mib_init(srslte_ue_mib_t * q,
} }
} }
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, in_buffer[0], q->sf_symbols, max_prb)) {
fprintf(stderr, "Error initializing FFT\n"); fprintf(stderr, "Error initializing FFT\n");
goto clean_exit; goto clean_exit;
} }
@ -143,14 +144,14 @@ void srslte_ue_mib_reset(srslte_ue_mib_t * q)
srslte_pbch_decode_reset(&q->pbch); srslte_pbch_decode_reset(&q->pbch);
} }
int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input, int srslte_ue_mib_decode(srslte_ue_mib_t * q,
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, int *sfn_offset) uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, int *sfn_offset)
{ {
int ret = SRSLTE_SUCCESS; int ret = SRSLTE_SUCCESS;
cf_t *ce_slot1[SRSLTE_MAX_PORTS]; cf_t *ce_slot1[SRSLTE_MAX_PORTS];
/* Run FFT for the slot symbols */ /* Run FFT for the slot symbols */
srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols); srslte_ofdm_rx_sf(&q->fft);
/* Get channel estimates of sf idx #0 for each port */ /* Get channel estimates of sf idx #0 for each port */
ret = srslte_chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, 0); ret = srslte_chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, 0);
@ -198,7 +199,7 @@ int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q,
} }
q->nof_rx_antennas = nof_rx_antennas; q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ue_mib_init(&q->ue_mib, SRSLTE_UE_MIB_NOF_PRB)) { if (srslte_ue_mib_init(&q->ue_mib, q->sf_buffer, SRSLTE_UE_MIB_NOF_PRB)) {
fprintf(stderr, "Error initiating ue_mib\n"); fprintf(stderr, "Error initiating ue_mib\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -261,10 +262,10 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q,
uint32_t nof_frames = 0; uint32_t nof_frames = 0;
int mib_ret = SRSLTE_UE_MIB_NOTFOUND; int mib_ret = SRSLTE_UE_MIB_NOTFOUND;
srslte_ue_mib_sync_reset(q);
if (q != NULL) if (q != NULL)
{ {
srslte_ue_mib_sync_reset(q);
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
do { do {
mib_ret = SRSLTE_UE_MIB_NOTFOUND; mib_ret = SRSLTE_UE_MIB_NOTFOUND;
@ -274,7 +275,7 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q,
return -1; return -1;
} else if (srslte_ue_sync_get_sfidx(&q->ue_sync) == 0) { } else if (srslte_ue_sync_get_sfidx(&q->ue_sync) == 0) {
if (ret == 1) { if (ret == 1) {
mib_ret = srslte_ue_mib_decode(&q->ue_mib, q->sf_buffer[0], bch_payload, nof_tx_ports, sfn_offset); mib_ret = srslte_ue_mib_decode(&q->ue_mib, bch_payload, nof_tx_ports, sfn_offset);
} else { } else {
DEBUG("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt); DEBUG("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt);
srslte_ue_mib_reset(&q->ue_mib); srslte_ue_mib_reset(&q->ue_mib);

@ -359,6 +359,11 @@ uint32_t srslte_ue_sync_peak_idx(srslte_ue_sync_t *q) {
return q->peak_idx; return q->peak_idx;
} }
void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q, float ema) {
srslte_sync_set_cfo_ema_alpha(&q->sfind, ema);
srslte_sync_set_cfo_ema_alpha(&q->strack, ema);
}
srslte_ue_sync_state_t srslte_ue_sync_get_state(srslte_ue_sync_t *q) { srslte_ue_sync_state_t srslte_ue_sync_get_state(srslte_ue_sync_t *q) {
return q->state; return q->state;
} }

@ -41,6 +41,7 @@
#define DEFAULT_CFO_TOL 50.0 // Hz #define DEFAULT_CFO_TOL 50.0 // Hz
int srslte_ue_ul_init(srslte_ue_ul_t *q, int srslte_ue_ul_init(srslte_ue_ul_t *q,
cf_t *out_buffer,
uint32_t max_prb) uint32_t max_prb)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -51,7 +52,13 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
bzero(q, sizeof(srslte_ue_ul_t)); bzero(q, sizeof(srslte_ue_ul_t));
if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_PRB(max_prb) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, q->sf_symbols, out_buffer, max_prb)) {
fprintf(stderr, "Error initiating FFT\n"); fprintf(stderr, "Error initiating FFT\n");
goto clean_exit; goto clean_exit;
} }
@ -83,11 +90,6 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
fprintf(stderr, "Error initiating srslte_refsignal_ul\n"); fprintf(stderr, "Error initiating srslte_refsignal_ul\n");
goto clean_exit; goto clean_exit;
} }
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_PRB(max_prb) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * max_prb * sizeof(cf_t)); q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * max_prb * sizeof(cf_t));
if (!q->refsignal) { if (!q->refsignal) {
perror("malloc"); perror("malloc");
@ -360,7 +362,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
q->last_pucch_format = format; q->last_pucch_format = format;
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); srslte_ofdm_tx_sf(&q->fft);
if (q->cfo_en) { if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
@ -430,7 +432,7 @@ int srslte_ue_ul_srs_encode(srslte_ue_ul_t *q, uint32_t tti, cf_t *output_signal
} }
} }
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); srslte_ofdm_tx_sf(&q->fft);
if (q->cfo_en) { if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
@ -499,7 +501,7 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q,
} }
} }
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); srslte_ofdm_tx_sf(&q->fft);
if (q->cfo_en) { if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));

@ -31,6 +31,12 @@
#include <string.h> #include <string.h>
#include <stddef.h> #include <stddef.h>
#ifdef LV_HAVE_SSE
#include <immintrin.h>
#endif /* LV_HAVE_SSE */
#include "srslte/phy/utils/bit.h" #include "srslte/phy/utils/bit.h"
void srslte_bit_interleave(uint8_t *input, uint8_t *output, uint16_t *interleaver, uint32_t nof_bits) { void srslte_bit_interleave(uint8_t *input, uint8_t *output, uint16_t *interleaver, uint32_t nof_bits) {
@ -53,6 +59,125 @@ void srslte_bit_interleave_w_offset(uint8_t *input, uint8_t *output, uint16_t *i
} }
w_offset_p=8-w_offset; w_offset_p=8-w_offset;
} }
#ifdef LV_HAVE_SSE
__m64 m64mask = _mm_setr_pi8((uint8_t) 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1);
__m128i m128mask = _mm_set1_epi64(m64mask);
union {
uint8_t v[8];
__m64 m64;
} a, b, c;
union {
__m128i m128;
uint16_t u16[8];
uint8_t u8[16];
struct {
__m64 reg_a;
__m64 reg_b;
} m64;
struct {
uint16_t i0, i1, i2, i3, i4, i5, i6, i7;
} v;
} ipx, epx, ipx2, epx2, b128, a128, c128;
uint32_t i = st;
for (; i < (nof_bits / 8 - 1); i += 2) {
ipx.m128 = _mm_loadu_si128((__m128i *) (interleaver + (i * 8) - w_offset_p));
epx.m128 = _mm_shuffle_epi8(ipx.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E));
ipx2.m128 = _mm_loadu_si128((__m128i *) (interleaver + ((i + 1) * 8) - w_offset_p));
epx2.m128 = _mm_shuffle_epi8(ipx2.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E));
epx.m64.reg_b = epx2.m64.reg_a;
b128.m128 = _mm_and_si128(epx.m128, _mm_set1_epi8(0x7));
b128.m128 = _mm_shuffle_epi8(m128mask, b128.m128);
ipx.m128 = _mm_srli_epi16(ipx.m128, 3);
ipx2.m128 = _mm_srli_epi16(ipx2.m128, 3);
a128.m128 = _mm_set_epi8(input[ipx2.v.i0],
input[ipx2.v.i1],
input[ipx2.v.i2],
input[ipx2.v.i3],
input[ipx2.v.i4],
input[ipx2.v.i5],
input[ipx2.v.i6],
input[ipx2.v.i7],
input[ipx.v.i0],
input[ipx.v.i1],
input[ipx.v.i2],
input[ipx.v.i3],
input[ipx.v.i4],
input[ipx.v.i5],
input[ipx.v.i6],
input[ipx.v.i7]);
c128.m128 = _mm_cmpeq_epi8(_mm_and_si128(a128.m128, b128.m128), b128.m128);
uint16_t o = (uint16_t) _mm_movemask_epi8(c128.m128);
*((uint16_t *) (output + i)) = o;
}
for (; i < nof_bits / 8; i++) {
ipx.m128 = _mm_loadu_si128((__m128i *) (interleaver + i * 8 - w_offset_p));
epx.m128 = _mm_shuffle_epi8(ipx.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E));
b.m64 = _mm_and_si64(epx.m64.reg_a, _mm_set1_pi8(0x7));
b.m64 = _mm_shuffle_pi8(m64mask, b.m64);
ipx.m128 = _mm_srli_epi16(ipx.m128, 3);
a.m64 = _mm_set_pi8(input[ipx.v.i0],
input[ipx.v.i1],
input[ipx.v.i2],
input[ipx.v.i3],
input[ipx.v.i4],
input[ipx.v.i5],
input[ipx.v.i6],
input[ipx.v.i7]);
c.m64 = _mm_cmpeq_pi8(_mm_and_si64(a.m64, b.m64), b.m64);
output[i] = (uint8_t) _mm_movemask_pi8(c.m64);
}
#if 0
/* THIS PIECE OF CODE IS FOR CHECKING SIMD BEHAVIOUR. DO NOT ENABLE. */
uint8_t *output2 = malloc(nof_bits/8);
for (i=st;i<nof_bits/8;i++) {
uint16_t i_p0 = interleaver[i*8+0-w_offset_p];
uint16_t i_p1 = interleaver[i*8+1-w_offset_p];
uint16_t i_p2 = interleaver[i*8+2-w_offset_p];
uint16_t i_p3 = interleaver[i*8+3-w_offset_p];
uint16_t i_p4 = interleaver[i*8+4-w_offset_p];
uint16_t i_p5 = interleaver[i*8+5-w_offset_p];
uint16_t i_p6 = interleaver[i*8+6-w_offset_p];
uint16_t i_p7 = interleaver[i*8+7-w_offset_p];
uint8_t out0 = (input[i_p0/8] & mask[i_p0%8])?mask[0]:(uint8_t)0;
uint8_t out1 = (input[i_p1/8] & mask[i_p1%8])?mask[1]:(uint8_t)0;
uint8_t out2 = (input[i_p2/8] & mask[i_p2%8])?mask[2]:(uint8_t)0;
uint8_t out3 = (input[i_p3/8] & mask[i_p3%8])?mask[3]:(uint8_t)0;
uint8_t out4 = (input[i_p4/8] & mask[i_p4%8])?mask[4]:(uint8_t)0;
uint8_t out5 = (input[i_p5/8] & mask[i_p5%8])?mask[5]:(uint8_t)0;
uint8_t out6 = (input[i_p6/8] & mask[i_p6%8])?mask[6]:(uint8_t)0;
uint8_t out7 = (input[i_p7/8] & mask[i_p7%8])?mask[7]:(uint8_t)0;
output2[i] = out0 | out1 | out2 | out3 | out4 | out5 | out6 | out7;
}
for(i = st; i < nof_bits/8; i++) {
if (output[i] != output2[i]) {
printf("%05d/%05d %02X %02X\n", i, nof_bits/8, output[i], output2[i]);
}
//output[i] = output2[i];
}
free(output2);
#endif
#else /* LV_HAVE_SSE */
for (uint32_t i=st;i<nof_bits/8;i++) { for (uint32_t i=st;i<nof_bits/8;i++) {
uint16_t i_p0 = interleaver[i*8+0-w_offset_p]; uint16_t i_p0 = interleaver[i*8+0-w_offset_p];
@ -75,6 +200,7 @@ void srslte_bit_interleave_w_offset(uint8_t *input, uint8_t *output, uint16_t *i
output[i] = out0 | out1 | out2 | out3 | out4 | out5 | out6 | out7; output[i] = out0 | out1 | out2 | out3 | out4 | out5 | out6 | out7;
} }
#endif /* LV_HAVE_SSE */
for (uint32_t j=0;j<nof_bits%8;j++) { for (uint32_t j=0;j<nof_bits%8;j++) {
uint16_t i_p = interleaver[(nof_bits/8)*8+j-w_offset]; uint16_t i_p = interleaver[(nof_bits/8)*8+j-w_offset];
if (input[i_p/8] & mask[i_p%8]) { if (input[i_p/8] & mask[i_p%8]) {

@ -27,6 +27,7 @@
#include <complex.h> #include <complex.h>
#include <math.h> #include <math.h>
#include <srslte/config.h>
#include "srslte/phy/utils/mat.h" #include "srslte/phy/utils/mat.h"

@ -42,3 +42,7 @@ target_link_libraries(algebra_test srslte_phy)
add_test(algebra_2x2_zf_solver_test algebra_test -z) add_test(algebra_2x2_zf_solver_test algebra_test -z)
add_test(algebra_2x2_mmse_solver_test algebra_test -m) add_test(algebra_2x2_mmse_solver_test algebra_test -m)
add_executable(vector_test vector_test.c)
target_link_libraries(vector_test srslte_phy)
add_test(vector_test vector_test)

@ -29,16 +29,21 @@
#include <unistd.h> #include <unistd.h>
#include <complex.h> #include <complex.h>
#include <stdbool.h> #include <stdbool.h>
#include <immintrin.h>
#include <sys/time.h> #include <sys/time.h>
#include "srslte/phy/utils/mat.h" #include "srslte/phy/utils/mat.h"
#include "srslte/phy/utils/simd.h"
#include "srslte/phy/utils/vector.h"
bool zf_solver = false; bool zf_solver = false;
bool mmse_solver = false; bool mmse_solver = false;
bool verbose = false; bool verbose = false;
#define RANDOM_F() ((float)rand())/((float)RAND_MAX)
#define RANDOM_S() ((int16_t)(rand() && 0x800F))
#define RANDOM_CF() (RANDOM_F() + _Complex_I*RANDOM_F())
double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) { double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) {
if (ts_end->tv_usec > ts_start->tv_usec) { if (ts_end->tv_usec > ts_start->tv_usec) {
return ((double) ts_end->tv_sec - (double) ts_start->tv_sec) * 1000000 + return ((double) ts_end->tv_sec - (double) ts_start->tv_sec) * 1000000 +
@ -49,16 +54,16 @@ double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) {
} }
} }
#define NOF_REPETITIONS 1000 #define BLOCK_SIZE 1000
#define RUN_TEST(FUNCTION) /*TYPE NAME (void)*/ { \ #define RUN_TEST(FUNCTION) /*TYPE NAME (void)*/ { \
int i;\ int i;\
struct timeval start, end;\ struct timeval start, end;\
gettimeofday(&start, NULL); \ gettimeofday(&start, NULL); \
bool ret = true; \ bool ret = true; \
for (i = 0; i < NOF_REPETITIONS; i++) {ret &= FUNCTION ();}\ for (i = 0; i < BLOCK_SIZE; i++) {ret &= FUNCTION ();}\
gettimeofday(&end, NULL);\ gettimeofday(&end, NULL);\
if (verbose) printf("%32s: %s ... %6.2f us/call\n", #FUNCTION, (ret)?"Pass":"Fail", \ if (verbose) printf("%32s: %s ... %6.2f us/call\n", #FUNCTION, (ret)?"Pass":"Fail", \
elapsed_us(&start, &end)/NOF_REPETITIONS);\ elapsed_us(&start, &end)/BLOCK_SIZE);\
passed &= ret;\ passed &= ret;\
} }
@ -373,6 +378,24 @@ bool test_mmse_solver_avx(void) {
#endif /* LV_HAVE_AVX */ #endif /* LV_HAVE_AVX */
bool test_vec_dot_prod_ccc(void) {
__attribute__((aligned(256))) cf_t a[14];
__attribute__((aligned(256))) cf_t b[14];
cf_t res = 0, gold = 0;
for (int i = 0; i < 14; i++) {
a[i] = RANDOM_CF();
b[i] = RANDOM_CF();
}
res = srslte_vec_dot_prod_ccc(a, b, 14);
for (int i=0;i<14;i++) {
gold += a[i]*b[i];
}
return (cabsf(res - gold) < 1e-3);
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
bool passed = true; bool passed = true;
@ -405,6 +428,8 @@ int main(int argc, char **argv) {
#endif /* LV_HAVE_AVX */ #endif /* LV_HAVE_AVX */
} }
RUN_TEST(test_vec_dot_prod_ccc);
printf("%s!\n", (passed) ? "Ok" : "Failed"); printf("%s!\n", (passed) ? "Ok" : "Failed");
if (!passed) { if (!passed) {

@ -0,0 +1,822 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <complex.h>
#include <stdbool.h>
#include <sys/time.h>
#include <memory.h>
#include <math.h>
#include "srslte/phy/utils/mat.h"
#include "srslte/phy/utils/simd.h"
#include "srslte/phy/utils/vector.h"
bool zf_solver = false;
bool mmse_solver = false;
bool verbose = false;
#define MAX_MSE (1e-3)
#define NOF_REPETITIONS (1024)
#define MAX_FUNCTIONS (64)
#define MAX_BLOCKS (16)
#define RANDOM_F() ((float)rand())/((float)RAND_MAX)
#define RANDOM_S() ((int16_t)(rand() && 0x800F))
#define RANDOM_CF() (RANDOM_F() + _Complex_I*RANDOM_F())
#define TEST_CALL(TEST_CODE) gettimeofday(&start, NULL);\
for (int i = 0; i < NOF_REPETITIONS; i++){TEST_CODE;}\
gettimeofday(&end, NULL); \
*timing = elapsed_us(&start, &end);
#define TEST(X, CODE) static bool test_##X (char *func_name, double *timing, uint32_t block_size) {\
struct timeval start, end;\
float mse = 0.0f;\
bool passed;\
strncpy(func_name, #X, 32);\
CODE;\
passed = (mse < MAX_MSE);\
printf("%32s (%5d) ... %7.1f MSamp/s ... %3s Passed (%.6f)\n", func_name, block_size, \
(double) block_size*NOF_REPETITIONS/ *timing, passed?"":"Not", mse);\
return passed;\
}
#define MALLOC(TYPE, NAME) TYPE *NAME = srslte_vec_malloc(sizeof(TYPE)*block_size)
static double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) {
if (ts_end->tv_usec > ts_start->tv_usec) {
return ((double) ts_end->tv_sec - (double) ts_start->tv_sec) * 1000000 +
(double) ts_end->tv_usec - (double) ts_start->tv_usec;
} else {
return ((double) ts_end->tv_sec - (double) ts_start->tv_sec - 1) * 1000000 +
((double) ts_end->tv_usec + 1000000) - (double) ts_start->tv_usec;
}
}
float squared_error (cf_t a, cf_t b) {
float diff_re = __real__ a - __real__ b;
float diff_im = __imag__ a - __imag__ b;
return diff_re*diff_re + diff_im*diff_im;
}
TEST(srslte_vec_acc_ff,
MALLOC(float, x);
float z;
cf_t gold = 0.0f;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_F();
}
TEST_CALL(z = srslte_vec_acc_ff(x, block_size))
for (int i = 0; i < block_size; i++) {
gold += x[i];
}
mse += fabs(gold - z) / gold;
free(x);
)
TEST(srslte_vec_dot_prod_sss,
MALLOC(int16_t, x);
MALLOC(int16_t, y);
int16_t z;
cf_t gold = 0.0f;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_S();
y[i] = RANDOM_S();
}
TEST_CALL(z = srslte_vec_dot_prod_sss(x, y, block_size))
for (int i = 0; i < block_size; i++) {
gold += x[i] * y[i];
}
mse += cabsf(gold - z) / cabsf(gold);
free(x);
free(y);
)
TEST(srslte_vec_sum_sss,
MALLOC(int16_t, x);
MALLOC(int16_t, y);
MALLOC(int16_t, z);
cf_t gold = 0.0f;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_S();
y[i] = RANDOM_S();
}
TEST_CALL(srslte_vec_sum_sss(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] + y[i];
mse += cabsf(gold - z[i]);
}
free(x);
free(y);
free(z);
)
TEST(srslte_vec_sub_sss,
MALLOC(int16_t, x);
MALLOC(int16_t, y);
MALLOC(int16_t, z);
cf_t gold = 0.0f;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_S();
y[i] = RANDOM_S();
}
TEST_CALL(srslte_vec_sub_sss(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] - y[i];
mse += cabsf(gold - z[i]);
}
free(x);
free(y);
free(z);
)
TEST(srslte_vec_prod_sss,
MALLOC(int16_t, x);
MALLOC(int16_t, y);
MALLOC(int16_t, z);
cf_t gold = 0.0f;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_S();
y[i] = RANDOM_S();
}
TEST_CALL(srslte_vec_prod_sss(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] * y[i];
mse += cabsf(gold - z[i]);
}
free(x);
free(y);
free(z);
)
TEST(srslte_vec_acc_cc,
MALLOC(cf_t, x);
cf_t z;
cf_t gold = 0.0f;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_F();
}
TEST_CALL(z = srslte_vec_acc_cc(x, block_size))
for (int i = 0; i < block_size; i++) {
gold += x[i];
}
mse += cabsf(gold - z)/cabsf(gold);
free(x);
)
TEST(srslte_vec_sum_fff,
MALLOC(float, x);
MALLOC(float, y);
MALLOC(float, z);
cf_t gold = 0.0f;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_F();
y[i] = RANDOM_F();
}
TEST_CALL(srslte_vec_sum_fff(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] + y[i];
mse += cabsf(gold - z[i]);
}
free(x);
free(y);
)
TEST(srslte_vec_sub_fff,
MALLOC(float, x);
MALLOC(float, y);
MALLOC(float, z);
cf_t gold = 0.0f;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_F();
y[i] = RANDOM_F();
}
TEST_CALL(srslte_vec_sub_fff(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] - y[i];
mse += cabsf(gold - z[i]);
}
free(x);
free(y);
)
TEST(srslte_vec_dot_prod_ccc,
MALLOC(cf_t, x);
MALLOC(cf_t, y);
cf_t z;
cf_t gold = 0.0f;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
y[i] = RANDOM_CF();
}
TEST_CALL(z = srslte_vec_dot_prod_ccc(x, y, block_size))
for (int i = 0; i < block_size; i++) {
gold += x[i] * y[i];
}
mse = cabsf(gold - z) / cabsf(gold);
free(x);
free(y);
)
TEST(srslte_vec_dot_prod_conj_ccc,
MALLOC(cf_t, x);
MALLOC(cf_t, y);
cf_t z;
cf_t gold = 0.0f;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
y[i] = RANDOM_CF();
}
TEST_CALL(z = srslte_vec_dot_prod_conj_ccc(x, y, block_size))
for (int i = 0; i < block_size; i++) {
gold += x[i] * conjf(y[i]);
}
mse = cabsf(gold - z) / cabsf(gold);
free(x);
free(y);
)
TEST(srslte_vec_prod_ccc,
MALLOC(cf_t, x);
MALLOC(cf_t, y);
MALLOC(cf_t, z);
cf_t gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
y[i] = RANDOM_CF();
}
TEST_CALL(srslte_vec_prod_ccc(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] * y[i];
mse += cabsf(gold - z[i]);
}
free(x);
free(z);
)
TEST(srslte_vec_prod_ccc_split,
MALLOC(float, x_re);
MALLOC(float, x_im);
MALLOC(float, y_re);
MALLOC(float, y_im);
MALLOC(float, z_re);
MALLOC(float, z_im);
cf_t gold;
for (int i = 0; i < block_size; i++) {
x_re[i] = RANDOM_F();
x_im[i] = RANDOM_F();
y_re[i] = RANDOM_F();
y_im[i] = RANDOM_F();
}
TEST_CALL(srslte_vec_prod_ccc_split(x_re, x_im, y_re, y_im, z_re, z_im, block_size))
for (int i = 0; i < block_size; i++) {
gold = (x_re[i] + I * x_im[i]) * (y_re[i] + I * y_im[i]);
mse += cabsf(gold - (z_re[i] + I*z_im[i]));
}
free(x_re);
free(x_im);
free(y_re);
free(y_im);
free(z_re);
free(z_im);
)
TEST(srslte_vec_prod_conj_ccc,
MALLOC(cf_t, x);
MALLOC(cf_t, y);
MALLOC(cf_t, z);
cf_t gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
y[i] = RANDOM_CF();
}
TEST_CALL(srslte_vec_prod_conj_ccc(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] * conjf(y[i]);
mse += cabsf(gold - z[i]);
}
free(x);
free(z);
)
TEST(srslte_vec_sc_prod_ccc,
MALLOC(cf_t, x);
MALLOC(cf_t, z);
cf_t y = RANDOM_CF();
cf_t gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
}
TEST_CALL(srslte_vec_sc_prod_ccc(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] * y;
mse += cabsf(gold - z[i]);
}
free(x);
free(z);
)
TEST(srslte_vec_convert_fi,
MALLOC(float, x);
MALLOC(short, z);
float scale = 1000.0f;
short gold;
for (int i = 0; i < block_size; i++) {
x[i] = (float) RANDOM_F();
}
TEST_CALL(srslte_vec_convert_fi(x, z, scale, block_size))
for (int i = 0; i < block_size; i++) {
gold = (short) ((x[i] * scale));
mse += cabsf((float)gold - (float) z[i]);
}
free(x);
free(z);
)
TEST(srslte_vec_prod_fff,
MALLOC(float, x);
MALLOC(float, y);
MALLOC(float, z);
cf_t gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
y[i] = RANDOM_CF();
}
TEST_CALL(srslte_vec_prod_fff(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] * y[i];
mse += cabsf(gold - z[i]);
}
free(x);
free(y);
free(z);
)
TEST(srslte_vec_prod_cfc,
MALLOC(cf_t, x);
MALLOC(float, y);
MALLOC(cf_t, z);
cf_t gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
y[i] = RANDOM_F();
}
TEST_CALL(srslte_vec_prod_cfc(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] * y[i];
mse += cabsf(gold - z[i]);
}
free(x);
free(y);
free(z);
)
TEST(srslte_vec_sc_prod_fff,
MALLOC(float, x);
MALLOC(float, z);
float y = RANDOM_F();
float gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
}
TEST_CALL(srslte_vec_sc_prod_fff(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] * y;
mse += cabsf(gold - z[i]);
}
free(x);
free(z);
)
TEST(srslte_vec_abs_cf,
MALLOC(cf_t, x);
MALLOC(float, z);
float gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
}
TEST_CALL(srslte_vec_abs_cf(x, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = sqrtf(crealf(x[i]) * crealf(x[i]) + cimagf(x[i])*cimagf(x[i]));
mse += cabsf(gold - z[i])/block_size;
}
free(x);
free(z);
)
TEST(srslte_vec_abs_square_cf,
MALLOC(cf_t, x);
MALLOC(float, z);
float gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
}
TEST_CALL(srslte_vec_abs_square_cf(x, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = crealf(x[i]) * crealf(x[i]) + cimagf(x[i])*cimagf(x[i]);
mse += cabsf(gold - z[i]);
}
free(x);
free(z);
)
TEST(srslte_vec_sc_prod_cfc,
MALLOC(cf_t, x);
MALLOC(cf_t, z);
cf_t gold;
float h = RANDOM_F();
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
}
TEST_CALL(srslte_vec_sc_prod_cfc(x, h, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] * h;
mse += cabsf(gold - z[i]);
}
free(x);
free(z);
)
TEST(srslte_vec_div_ccc,
MALLOC(cf_t, x);
MALLOC(cf_t, y);
MALLOC(cf_t, z);
cf_t gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
y[i] = RANDOM_CF();
}
TEST_CALL(srslte_vec_div_ccc(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] / y[i];
mse += cabsf(gold - z[i]);
}
mse /= block_size;
free(x);
free(y);
free(z);
)
TEST(srslte_vec_div_cfc,
MALLOC(cf_t, x);
MALLOC(float, y);
MALLOC(cf_t, z);
cf_t gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
y[i] = RANDOM_F();
}
TEST_CALL(srslte_vec_div_cfc(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] / y[i];
mse += cabsf(gold - z[i])/cabsf(gold);
}
mse /= block_size;
free(x);
free(y);
free(z);
)
TEST(srslte_vec_div_fff,
MALLOC(float, x);
MALLOC(float, y);
MALLOC(float, z);
cf_t gold;
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_F();
y[i] = RANDOM_F();
}
TEST_CALL(srslte_vec_div_fff(x, y, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = x[i] / y[i];
mse += cabsf(gold - z[i]);
}
mse /= block_size;
free(x);
free(y);
free(z);
)
TEST(srslte_vec_max_fi,
MALLOC(float, x);
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_F();
}
uint32_t max_index = 0;
TEST_CALL(max_index = srslte_vec_max_fi(x, block_size);)
float gold_value = -INFINITY;
uint32_t gold_index = 0;
for (int i = 0; i < block_size; i++) {
if (gold_value < x[i]) {
gold_value = x[i];
gold_index = i;
}
}
mse = (gold_index != max_index) ? 1:0;
free(x);
)
TEST(srslte_vec_max_abs_ci,
MALLOC(cf_t, x);
for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF();
}
uint32_t max_index = 0;
TEST_CALL(max_index = srslte_vec_max_abs_ci(x, block_size);)
float gold_value = -INFINITY;
uint32_t gold_index = 0;
for (int i = 0; i < block_size; i++) {
cf_t a = x[i];
float abs2 = __real__ a * __real__ a + __imag__ a * __imag__ a;
if (abs2 > gold_value) {
gold_value = abs2;
gold_index = (uint32_t)i;
}
}
mse = (gold_index != max_index) ? 1:0;
free(x);
)
int main(int argc, char **argv) {
char func_names[MAX_FUNCTIONS][32];
double timmings[MAX_FUNCTIONS][MAX_BLOCKS];
uint32_t sizes[32];
uint32_t size_count = 0;
uint32_t func_count = 0;
bool passed[MAX_FUNCTIONS][MAX_BLOCKS];
bool all_passed = true;
for (uint32_t block_size = 1; block_size <= 1024*8; block_size *= 2) {
func_count = 0;
passed[func_count][size_count] = test_srslte_vec_acc_ff(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_dot_prod_sss(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_sum_sss(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_sub_sss(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_prod_sss(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_acc_cc(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_sum_fff(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_sub_fff(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_dot_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_dot_prod_conj_ccc(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_convert_fi(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_prod_fff(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_prod_cfc(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_prod_ccc_split(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_prod_conj_ccc(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_sc_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_sc_prod_fff(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_abs_cf(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_abs_square_cf(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_sc_prod_cfc(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_div_ccc(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_div_cfc(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_div_fff(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_max_fi(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_max_abs_ci(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
sizes[size_count] = block_size;
size_count++;
}
char fname[68];
FILE *f = NULL;
void * p = popen("(date +%g%m%d && hostname) | tr '\\r\\n' '__'", "r");
if (p) {
fgets(fname, 64, p);
strncpy(fname + strnlen(fname, 64) - 1, ".tsv", 4);
f = fopen(fname, "w");
if (f) printf("Saving benchmark results in '%s'\n", fname);
}
pclose(p);
printf("\n");
printf("%32s |", "Subroutine/MSps");
if (f) fprintf(f, "Subroutine/MSps Vs Vector size\t");
for (int i = 0; i < size_count; i++) {
printf(" %7d", sizes[i]);
if (f) fprintf(f, "%d\t", sizes[i]);
}
printf(" |\n");
if (f) fprintf(f, "\n");
for (int j = 0; j < 32; j++) {
printf("-");
}
printf("-+-");
for (int j = 0; j < size_count; j++) {
printf("--------");
}
printf("-|\n");
for (int i = 0; i < func_count; i++) {
printf("%32s | ", func_names[i]);
if (f) fprintf(f, "%s\t", func_names[i]);
for (int j = 0; j < size_count; j++) {
printf(" %s%7.1f\x1b[0m", (passed[i][j])?"":"\x1B[31m", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]);
if (f) fprintf(f, "%.1f\t", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]);
all_passed &= passed[i][j];
}
printf(" |\n");
if (f) fprintf(f, "\n");
}
if (f) fclose(f);
return (all_passed)?SRSLTE_SUCCESS:SRSLTE_ERROR;
}

@ -36,48 +36,10 @@
#include "srslte/phy/utils/bit.h" #include "srslte/phy/utils/bit.h"
#ifdef LV_HAVE_SSE
#include <smmintrin.h>
#endif
#ifdef LV_HAVE_AVX
#include <immintrin.h>
#endif
#ifdef HAVE_VOLK
#include "volk/volk.h"
#endif
#ifdef DEBUG_MODE
#warning FIXME: Disabling SSE/AVX vector code
#undef LV_HAVE_SSE
#undef LV_HAVE_AVX
#endif
int srslte_vec_acc_ii(int *x, uint32_t len) {
int i;
int z=0;
for (i=0;i<len;i++) {
z+=x[i];
}
return z;
}
// Used in PRACH detector, AGC and chest_dl for noise averaging
float srslte_vec_acc_ff(float *x, uint32_t len) { float srslte_vec_acc_ff(float *x, uint32_t len) {
#ifdef HAVE_VOLK_ACC_FUNCTION return srslte_vec_acc_ff_simd(x, len);
float result;
volk_32f_accumulator_s32f(&result,x,len);
return result;
#else
int i;
float z=0;
for (i=0;i<len;i++) {
z+=x[i];
}
return z;
#endif
} }
void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float coeff, uint32_t len) { void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float coeff, uint32_t len) {
@ -87,282 +49,69 @@ void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float co
} }
cf_t srslte_vec_acc_cc(cf_t *x, uint32_t len) { cf_t srslte_vec_acc_cc(cf_t *x, uint32_t len) {
int i; return srslte_vec_acc_cc_simd(x, len);
cf_t z=0;
for (i=0;i<len;i++) {
z+=x[i];
}
return z;
}
void srslte_vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoints) {
#ifndef HAVE_VOLK_SQUARE_DIST_FUNCTION
uint32_t i;
cf_t diff;
for (i=0;i<npoints;i++) {
diff = symbol - points[i];
distance[i] = crealf(diff) * crealf(diff) + cimagf(diff) * cimagf(diff);
}
#else
volk_32fc_x2_square_dist_32f(distance,&symbol,points,npoints);
#endif
} }
void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len) { void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len) {
#ifndef HAVE_VOLK_SUB_FLOAT_FUNCTION srslte_vec_sub_fff_simd(x, y, z, len);
int i;
for (i=0;i<len;i++) {
z[i] = x[i]-y[i];
}
#else
volk_32f_x2_subtract_32f(z,x,y,len);
#endif
} }
void srslte_vec_sub_sss(short *x, short *y, short *z, uint32_t len) { void srslte_vec_sub_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len) {
#ifdef LV_HAVE_AVX2 srslte_vec_sub_sss_simd(x, y, z, len);
srslte_vec_sub_sss_avx2(x, y, z, len);
#else
#ifdef LV_HAVE_SSE
srslte_vec_sub_sss_sse(x, y, z, len);
#else
int i;
for (i=0;i<len;i++) {
z[i] = x[i]-y[i];
}
#endif
#endif
} }
// Noise estimation in chest_dl, interpolation
void srslte_vec_sub_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) { void srslte_vec_sub_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) {
return srslte_vec_sub_fff((float*) x,(float*) y,(float*) z, 2*len); return srslte_vec_sub_fff((float*) x,(float*) y,(float*) z, 2*len);
} }
// Used in PSS/SSS and sum_ccc
void srslte_vec_sum_fff(float *x, float *y, float *z, uint32_t len) { void srslte_vec_sum_fff(float *x, float *y, float *z, uint32_t len) {
#ifndef HAVE_VOLK_ADD_FLOAT_FUNCTION srslte_vec_add_fff_simd(x, y, z, len);
int i;
for (i=0;i<len;i++) {
z[i] = x[i]+y[i];
}
#else
volk_32f_x2_add_32f(z,x,y,len);
#endif
} }
void srslte_vec_sum_sss(short *x, short *y, short *z, uint32_t len) { void srslte_vec_sum_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len) {
#ifdef LV_HAVE_AVX2 srslte_vec_sum_sss_simd(x, y, z, len);
srslte_vec_sum_sss_avx2(x, y, z, len);
#else
#ifdef LV_HAVE_SSE
srslte_vec_sum_sss_sse(x, y, z, len);
#else
int i;
for (i=0;i<len;i++) {
z[i] = x[i]+y[i];
}
#endif
#endif
} }
void srslte_vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) { void srslte_vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) {
srslte_vec_sum_fff((float*) x,(float*) y,(float*) z,2*len); srslte_vec_sum_fff((float*) x,(float*) y,(float*) z,2*len);
} }
void srslte_vec_sum_bbb(uint8_t *x, uint8_t *y, uint8_t *z, uint32_t len) { // PSS, PBCH, DEMOD, FFTW, etc.
int i;
for (i=0;i<len;i++) {
z[i] = x[i]+y[i];
}
}
void srslte_vec_sc_add_fff(float *x, float h, float *z, uint32_t len) {
int i;
for (i=0;i<len;i++) {
z[i] = x[i]+h;
}
}
void srslte_vec_sc_add_cfc(cf_t *x, float h, cf_t *z, uint32_t len) {
int i;
for (i=0;i<len;i++) {
z[i] = x[i]+ h;
}
}
void srslte_vec_sc_add_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len) {
int i;
for (i=0;i<len;i++) {
z[i] = x[i]+ h;
}
}
void srslte_vec_sc_add_sss(int16_t *x, int16_t h, int16_t *z, uint32_t len) {
int i;
for (i=0;i<len;i++) {
z[i] = x[i]+ h;
}
}
void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len) { void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_FLOAT_FUNCTION srslte_vec_sc_prod_fff_simd(x, h, z, len);
int i;
for (i=0;i<len;i++) {
z[i] = x[i]*h;
}
#else
volk_32f_s32f_multiply_32f(z,x,h,len);
#endif
}
void srslte_vec_sc_prod_sfs(short *x, float h, short *z, uint32_t len) {
int i;
for (i=0;i<len;i++) {
z[i] = x[i]*h;
}
}
void srslte_vec_sc_div2_sss(short *x, int n_rightshift, short *z, uint32_t len) {
#ifdef LV_HAVE_AVX2
srslte_vec_sc_div2_sss_avx2(x, n_rightshift, z, len);
#else
#ifdef LV_HAVE_SSE
srslte_vec_sc_div2_sss_sse(x, n_rightshift, z, len);
#else
int i;
int pow2_div = 1<<n_rightshift;
for (i=0;i<len;i++) {
z[i] = x[i]/pow2_div;
}
#endif
#endif
}
// TODO: Improve this implementation
void srslte_vec_norm_cfc(cf_t *x, float amplitude, cf_t *y, uint32_t len) {
// We should use fabs() here but is statistically should be similar
float *xp = (float*) x;
uint32_t idx = srslte_vec_max_fi(xp, 2*len);
float max = xp[idx];
// Normalize before TX
srslte_vec_sc_prod_cfc(x, amplitude/max, y, len);
} }
// Used throughout
void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) { void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) {
#ifdef LV_HAVE_AVX srslte_vec_sc_prod_cfc_simd(x,h,z,len);
srslte_vec_sc_prod_cfc_avx(x,h,z,len);
#else
int i;
for (i=0;i<len;i++) {
z[i] = x[i]*h;
}
#endif
} }
// Chest UL
void srslte_vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len) { void srslte_vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_FUNCTION srslte_vec_sc_prod_ccc_simd(x,h,z,len);
int i;
for (i=0;i<len;i++) {
z[i] = x[i]*h;
}
#else
volk_32fc_s32fc_multiply_32fc(z,x,h,len);
#endif
} }
// Used in turbo decoder
void srslte_vec_convert_if(int16_t *x, float *z, float scale, uint32_t len) { void srslte_vec_convert_if(int16_t *x, float *z, float scale, uint32_t len) {
#ifndef HAVE_VOLK_CONVERT_IF_FUNCTION
int i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
z[i] = ((float) x[i])/scale; z[i] = ((float) x[i])/scale;
} }
#else
volk_16i_s32f_convert_32f(z,x,scale,len);
#endif
}
void srslte_vec_convert_ci(int8_t *x, int16_t *z, uint32_t len) {
#ifndef HAVE_VOLK_CONVERT_CI_FUNCTION
int i;
for (i=0;i<len;i++) {
z[i] = ((int16_t) x[i]);
}
#else
volk_8i_convert_16i(z,x,len);
#endif
} }
void srslte_vec_convert_fi(float *x, int16_t *z, float scale, uint32_t len) { void srslte_vec_convert_fi(float *x, int16_t *z, float scale, uint32_t len) {
#ifndef LV_HAVE_SSE srslte_vec_convert_fi_simd(x, z, scale, len);
int i;
for (i=0;i<len;i++) {
z[i] = (int16_t) (x[i]*scale);
}
#else
srslte_vec_convert_fi_sse(x, z, scale, len);
#endif
}
void srslte_vec_lut_fuf(float *x, uint32_t *lut, float *y, uint32_t len) {
for (int i=0;i<len;i++) {
y[lut[i]] = x[i];
}
} }
void srslte_vec_lut_sss(short *x, unsigned short *lut, short *y, uint32_t len) { void srslte_vec_lut_sss(short *x, unsigned short *lut, short *y, uint32_t len) {
#ifndef LV_HAVE_SSE srslte_vec_lut_sss_simd(x, lut, y, len);
for (int i=0;i<len;i++) {
y[lut[i]] = x[i];
}
#else
srslte_vec_lut_sss_sse(x, lut, y, len);
#endif
}
void srslte_vec_interleave_cf(float *real, float *imag, cf_t *x, uint32_t len) {
#ifdef HAVE_VOLK_INTERLEAVE_FUNCTION
volk_32f_x2_interleave_32fc(x, real, imag, len);
#else
int i;
for (i=0;i<len;i++) {
x[i] = real[i] + _Complex_I*imag[i];
}
#endif
}
void srslte_vec_deinterleave_cf(cf_t *x, float *real, float *imag, uint32_t len) {
#ifdef HAVE_VOLK_DEINTERLEAVE_FUNCTION
volk_32fc_deinterleave_32f_x2(real, imag, x, len);
#else
int i;
for (i=0;i<len;i++) {
real[i] = __real__ x[i];
imag[i] = __imag__ x[i];
}
#endif
}
void srslte_vec_deinterleave_real_cf(cf_t *x, float *real, uint32_t len) {
#ifdef HAVE_VOLK_DEINTERLEAVE_REAL_FUNCTION
volk_32fc_deinterleave_real_32f(real, x, len);
#else
int i;
for (i=0;i<len;i++) {
real[i] = __real__ x[i];
}
#endif
} }
/* Note: We align memory to 32 bytes (for AVX2 compatibility)
* because in some cases volk can incorrectly detect the architecture.
* This could be inefficient for SSE or non-SIMD platforms but shouldn't
* be a huge problem.
*/
void *srslte_vec_malloc(uint32_t size) { void *srslte_vec_malloc(uint32_t size) {
void *ptr; void *ptr;
if (posix_memalign(&ptr,256,size)) { if (posix_memalign(&ptr, SRSLTE_SIMD_BIT_ALIGN, size)) {
return NULL; return NULL;
} else { } else {
return ptr; return ptr;
@ -370,11 +119,11 @@ void *srslte_vec_malloc(uint32_t size) {
} }
void *srslte_vec_realloc(void *ptr, uint32_t old_size, uint32_t new_size) { void *srslte_vec_realloc(void *ptr, uint32_t old_size, uint32_t new_size) {
#ifndef HAVE_VOLK #ifndef LV_HAVE_SSE
return realloc(ptr, new_size); return realloc(ptr, new_size);
#else #else
void *new_ptr; void *new_ptr;
if (posix_memalign(&new_ptr,256,new_size)) { if (posix_memalign(&new_ptr, SRSLTE_SIMD_BIT_ALIGN, new_size)) {
return NULL; return NULL;
} else { } else {
memcpy(new_ptr, ptr, old_size); memcpy(new_ptr, ptr, old_size);
@ -495,196 +244,92 @@ void srslte_vec_load_file(char *filename, void *buffer, uint32_t len) {
} }
} }
// Used in PSS
void srslte_vec_conj_cc(cf_t *x, cf_t *y, uint32_t len) { void srslte_vec_conj_cc(cf_t *x, cf_t *y, uint32_t len) {
#ifndef HAVE_VOLK_CONJ_FUNCTION /* This function is used in initialisation only, then no optimisation is required */
int i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
y[i] = conjf(x[i]); y[i] = conjf(x[i]);
} }
#else
volk_32fc_conjugate_32fc(y,x,len);
#endif
} }
// Used in scrambling complex
void srslte_vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len) { void srslte_vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_REAL_FUNCTION srslte_vec_prod_cfc_simd(x, y, z, len);
int i;
for (i=0;i<len;i++) {
z[i] = x[i]*y[i];
}
#else
volk_32fc_32f_multiply_32fc(z,x,y,len);
#endif
} }
// Used in scrambling float
void srslte_vec_prod_fff(float *x, float *y, float *z, uint32_t len) { void srslte_vec_prod_fff(float *x, float *y, float *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_REAL2_FUNCTION srslte_vec_prod_fff_simd(x, y, z, len);
int i;
for (i=0;i<len;i++) {
z[i] = x[i]*y[i];
}
#else
volk_32f_x2_multiply_32f(z,x,y,len);
#endif
} }
void srslte_vec_prod_sss(short *x, short *y, short *z, uint32_t len) { // Scrambling Short
#ifdef LV_HAVE_AVX2 void srslte_vec_prod_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len) {
srslte_vec_prod_sss_avx2(x,y,z,len); srslte_vec_prod_sss_simd(x,y,z,len);
#else
#ifdef LV_HAVE_SSE
srslte_vec_prod_sss_sse(x,y,z,len);
#else
int i;
for (i=0;i<len;i++) {
z[i] = x[i]*y[i];
}
#endif
#endif
} }
// CFO and OFDM processing
void srslte_vec_prod_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) { void srslte_vec_prod_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT2_FUNCTION srslte_vec_prod_ccc_simd(x,y,z,len);
int i;
for (i=0;i<len;i++) {
z[i] = x[i]*y[i];
}
#else
volk_32fc_x2_multiply_32fc(z,x,y,len);
#endif
} }
void srslte_vec_prod_ccc_split(float *x_re, float *x_im, float *y_re, float *y_im, float *z_re, float *z_im, uint32_t len) {
srslte_vec_prod_ccc_split_simd(x_re, x_im, y_re , y_im, z_re,z_im, len);
}
// PRACH, CHEST UL, etc.
void srslte_vec_prod_conj_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) { void srslte_vec_prod_conj_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT2_CONJ_FUNCTION srslte_vec_prod_conj_ccc_simd(x,y,z,len);
int i;
for (i=0;i<len;i++) {
z[i] = x[i]*conjf(y[i]);
}
#else
volk_32fc_x2_multiply_conjugate_32fc(z,x,y,len);
#endif
} }
#define DIV_USE_VEC //#define DIV_USE_VEC
/* Complex division is conjugate multiplication + real division */ // Used in SSS
void srslte_vec_div_ccc(cf_t *x, cf_t *y, float *y_mod, cf_t *z, float *z_real, float *z_imag, uint32_t len) { void srslte_vec_div_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) {
#ifdef DIV_USE_VEC srslte_vec_div_ccc_simd(x, y, z, len);
srslte_vec_prod_conj_ccc(x,y,z,len);
srslte_vec_abs_square_cf(y,y_mod,len);
srslte_vec_div_cfc(z,y_mod,z,z_real,z_imag,len);
#else
int i;
for (i=0;i<len;i++) {
z[i] = x[i] / y[i];
}
#endif
} }
/* Complex division by float z=x/y */ /* Complex division by float z=x/y */
void srslte_vec_div_cfc(cf_t *x, float *y, cf_t *z, float *z_real, float *z_imag, uint32_t len) { void srslte_vec_div_cfc(cf_t *x, float *y, cf_t *z, uint32_t len) {
#ifdef DIV_USE_VEC srslte_vec_div_cfc_simd(x, y, z, len);
srslte_vec_deinterleave_cf(x, z_real, z_imag, len);
srslte_vec_div_fff(z_real, y, z_real, len);
srslte_vec_div_fff(z_imag, y, z_imag, len);
srslte_vec_interleave_cf(z_real, z_imag, z, len);
#else
int i;
for (i=0;i<len;i++) {
z[i] = x[i] / y[i];
}
#endif
} }
void srslte_vec_div_fff(float *x, float *y, float *z, uint32_t len) { void srslte_vec_div_fff(float *x, float *y, float *z, uint32_t len) {
#ifdef HAVE_VOLK_DIVIDE_FUNCTION srslte_vec_div_fff_simd(x, y, z, len);
volk_32f_x2_divide_32f(z, x, y, len);
#else
int i;
for (i=0;i<len;i++) {
z[i] = x[i] / y[i];
}
#endif
} }
// PSS. convolution
cf_t srslte_vec_dot_prod_ccc(cf_t *x, cf_t *y, uint32_t len) { cf_t srslte_vec_dot_prod_ccc(cf_t *x, cf_t *y, uint32_t len) {
#ifdef HAVE_VOLK_DOTPROD_FC_FUNCTION return srslte_vec_dot_prod_ccc_simd(x, y, len);
cf_t res;
volk_32fc_x2_dot_prod_32fc(&res, x, y, len);
return res;
#else
uint32_t i;
cf_t res = 0;
for (i=0;i<len;i++) {
res += x[i]*y[i];
}
return res;
#endif
} }
// Convolution filter and in SSS search
cf_t srslte_vec_dot_prod_cfc(cf_t *x, float *y, uint32_t len) { cf_t srslte_vec_dot_prod_cfc(cf_t *x, float *y, uint32_t len) {
#ifdef HAVE_VOLK_DOTPROD_CFC_FUNCTION
cf_t res;
volk_32fc_32f_dot_prod_32fc(&res, x, y, len);
return res;
#else
uint32_t i; uint32_t i;
cf_t res = 0; cf_t res = 0;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
res += x[i]*y[i]; res += x[i]*y[i];
} }
return res; return res;
#endif
} }
// SYNC
cf_t srslte_vec_dot_prod_conj_ccc(cf_t *x, cf_t *y, uint32_t len) { cf_t srslte_vec_dot_prod_conj_ccc(cf_t *x, cf_t *y, uint32_t len) {
#ifdef HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION return srslte_vec_dot_prod_conj_ccc_simd(x, y, len);
cf_t res;
volk_32fc_x2_conjugate_dot_prod_32fc(&res, x, y, len);
return res;
#else
uint32_t i;
cf_t res = 0;
for (i=0;i<len;i++) {
res += x[i]*conjf(y[i]);
}
return res;
#endif
} }
// PHICH
float srslte_vec_dot_prod_fff(float *x, float *y, uint32_t len) { float srslte_vec_dot_prod_fff(float *x, float *y, uint32_t len) {
#ifdef HAVE_VOLK_DOTPROD_F_FUNCTION
float res;
volk_32f_x2_dot_prod_32f(&res, x, y, len);
return res;
#else
uint32_t i; uint32_t i;
float res = 0; float res = 0;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
res += x[i]*y[i]; res += x[i]*y[i];
} }
return res; return res;
#endif
} }
int32_t srslte_vec_dot_prod_sss(int16_t *x, int16_t *y, uint32_t len) { int32_t srslte_vec_dot_prod_sss(int16_t *x, int16_t *y, uint32_t len) {
#ifdef LV_HAVE_AVX2 return srslte_vec_dot_prod_sss_simd(x, y, len);
return srslte_vec_dot_prod_sss_avx2(x, y, len);
#else
#ifdef LV_HAVE_SSE
return srslte_vec_dot_prod_sss_sse(x, y, len);
#else
uint32_t i;
int32_t res = 0;
for (i=0;i<len;i++) {
res += x[i]*y[i];
}
return res;
#endif
#endif
} }
float srslte_vec_avg_power_cf(cf_t *x, uint32_t len) { float srslte_vec_avg_power_cf(cf_t *x, uint32_t len) {
@ -697,141 +342,26 @@ float srslte_vec_corr_ccc(cf_t *x, cf_t *y, uint32_t len) {
float s_x = crealf(srslte_vec_dot_prod_conj_ccc(x, x, len))/len; float s_x = crealf(srslte_vec_dot_prod_conj_ccc(x, x, len))/len;
float s_y = crealf(srslte_vec_dot_prod_conj_ccc(y, y, len))/len; float s_y = crealf(srslte_vec_dot_prod_conj_ccc(y, y, len))/len;
float cov = crealf(srslte_vec_dot_prod_conj_ccc(x, y, len))/len; float cov = crealf(srslte_vec_dot_prod_conj_ccc(x, y, len))/len;
return cov/(sqrt(s_x*s_y)); return cov/(sqrtf(s_x*s_y));
} }
// PSS (disabled and using abs_square )
void srslte_vec_abs_cf(cf_t *x, float *abs, uint32_t len) { void srslte_vec_abs_cf(cf_t *x, float *abs, uint32_t len) {
#ifndef HAVE_VOLK_MAG_FUNCTION srslte_vec_abs_cf_simd(x, abs, len);
int i;
for (i=0;i<len;i++) {
abs[i] = cabsf(x[i]);
}
#else
volk_32fc_magnitude_32f(abs,x,len);
#endif
} }
void srslte_vec_abs_square_cf(cf_t *x, float *abs_square, uint32_t len) {
#ifndef HAVE_VOLK_MAG_SQUARE_FUNCTION
int i;
for (i=0;i<len;i++) {
abs_square[i] = crealf(x[i])*crealf(x[i])+cimagf(x[i])*cimagf(x[i]);
}
#else
volk_32fc_magnitude_squared_32f(abs_square,x,len);
#endif
}
void srslte_vec_arg_cf(cf_t *x, float *arg, uint32_t len) {
#ifndef HAVE_VOLK_ATAN_FUNCTION
int i;
for (i=0;i<len;i++) {
arg[i] = cargf(x[i]);
}
#else
volk_32fc_s32f_atan2_32f(arg,x,1,len);
#endif
// PRACH
void srslte_vec_abs_square_cf(cf_t *x, float *abs_square, uint32_t len) {
srslte_vec_abs_square_cf_simd(x,abs_square,len);
} }
uint32_t srslte_vec_max_fi(float *x, uint32_t len) { uint32_t srslte_vec_max_fi(float *x, uint32_t len) {
return srslte_vec_max_fi_simd(x, len);
// This is to solve an issue with incorrect type of 1st parameter in version 1.2 of volk
#ifdef HAVE_VOLK_MAX_FUNCTION_32
uint32_t target=0;
volk_32f_index_max_32u(&target,x,len);
return target;
#else
#ifdef HAVE_VOLK_MAX_FUNCTION_16
uint32_t target=0;
volk_32f_index_max_16u(&target,x,len);
return target;
#else
uint32_t i;
float m=-FLT_MAX;
uint32_t p=0;
for (i=0;i<len;i++) {
if (x[i]>m) {
m=x[i];
p=i;
}
}
return p;
#endif
#endif
}
int16_t srslte_vec_max_star_si(int16_t *x, uint32_t len) {
#ifdef HAVE_VOLK_MAX_STAR_S_FUNCTION
int16_t target=0;
volk_16i_max_star_16i(&target,x,len);
return target;
#else
uint32_t i;
int16_t m=-INT16_MIN;
for (i=0;i<len;i++) {
if (x[i]>m) {
m=x[i];
}
}
return m;
#endif
}
int16_t srslte_vec_max_abs_star_si(int16_t *x, uint32_t len) {
uint32_t i;
int16_t m=-INT16_MIN;
for (i=0;i<len;i++) {
if (abs(x[i])>m) {
m=abs(x[i]);
}
}
return m;
} }
void srslte_vec_max_fff(float *x, float *y, float *z, uint32_t len) { // CP autocorr
#ifdef HAVE_VOLK_MAX_VEC_FUNCTION
volk_32f_x2_max_32f(z,x,y,len);
#else
uint32_t i;
for (i=0;i<len;i++) {
if (x[i] > y[i]) {
z[i] = x[i];
} else {
z[i] = y[i];
}
}
#endif
}
uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len) { uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len) {
#ifdef HAVE_VOLK_MAX_ABS_FUNCTION_32 return srslte_vec_max_ci_simd(x, len);
uint32_t target=0;
volk_32fc_index_max_32u(&target,x,len);
return target;
#else
#ifdef HAVE_VOLK_MAX_ABS_FUNCTION_16
uint32_t target=0;
volk_32fc_index_max_16u(&target,x,len);
return target;
#else
uint32_t i;
float m=-FLT_MAX;
uint32_t p=0;
float tmp;
for (i=0;i<len;i++) {
tmp = crealf(x[i])*crealf(x[i]) + cimagf(x[i])*cimagf(x[i]);
if (tmp>m) {
m=tmp;
p=i;
}
}
return p;
#endif
#endif
} }
void srslte_vec_quant_fuc(float *in, uint8_t *out, float gain, float offset, float clip, uint32_t len) { void srslte_vec_quant_fuc(float *in, uint8_t *out, float gain, float offset, float clip, uint32_t len) {
@ -863,23 +393,5 @@ void srslte_vec_quant_suc(int16_t *in, uint8_t *out, float gain, int16_t offset,
} }
void srs_vec_cf_cpy(cf_t *dst, cf_t *src, int len) { void srs_vec_cf_cpy(cf_t *dst, cf_t *src, int len) {
int i = 0; srslte_vec_cp_simd(dst, src, len);
#ifdef LV_HAVE_AVX
for (; i < len - 3; i += 4) {
_mm256_store_ps((float *) &dst[i], _mm256_load_ps((float *) &src[i]));
}
#endif /* LV_HAVE_AVX */
#ifdef LV_HAVE_SSE
for (; i < len - 1; i += 2) {
_mm_store_ps((float *) &dst[i], _mm_load_ps((float *) &src[i]));
}
for (; i < len; i++) {
((__m64*) dst)[i] = ((__m64*) src)[i];
}
#else
for (; i < len; i++) {
dst[i] = src[i];
}
#endif /* LV_HAVE_SSE */
} }

File diff suppressed because it is too large Load Diff

@ -63,10 +63,10 @@ bool radio::init(char *args, char *devname, uint32_t nof_channels)
} }
if (args) { if (args) {
strncpy(saved_args, args, 128); strncpy(saved_args, args, 127);
} }
if (devname) { if (devname) {
strncpy(saved_devname, devname, 128); strncpy(saved_devname, devname, 127);
} }
saved_nof_channels = nof_channels; saved_nof_channels = nof_channels;

@ -31,10 +31,10 @@ bool radio_multi::init_multi(uint32_t nof_rx_antennas, char* args, char* devname
} }
if (args) { if (args) {
strncpy(saved_args, args, 128); strncpy(saved_args, args, 127);
} }
if (devname) { if (devname) {
strncpy(saved_devname, devname, 128); strncpy(saved_devname, devname, 127);
} }
return true; return true;

@ -613,7 +613,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
uint32_t pdu_space = nof_bytes; uint32_t pdu_space = nof_bytes;
uint8_t *pdu_ptr = pdu->msg; uint8_t *pdu_ptr = pdu->msg;
if(pdu_space <= head_len) if(pdu_space <= head_len + 1)
{ {
log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n",
rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len);
@ -652,7 +652,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
} }
// Pull SDUs from queue // Pull SDUs from queue
while(pdu_space > head_len && tx_sdu_queue.size() > 0) while(pdu_space > head_len + 1 && tx_sdu_queue.size() > 0)
{ {
if(last_li > 0) if(last_li > 0)
header.li[header.N_li++] = last_li; header.li[header.N_li++] = last_li;

@ -277,7 +277,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
int head_len = rlc_um_packed_length(&header); int head_len = rlc_um_packed_length(&header);
int pdu_space = nof_bytes; int pdu_space = nof_bytes;
if(pdu_space <= head_len) if(pdu_space <= head_len + 1)
{ {
log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n",
rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len);
@ -309,7 +309,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
} }
// Pull SDUs from queue // Pull SDUs from queue
while(pdu_space > head_len && tx_sdu_queue.size() > 0) while(pdu_space > head_len + 1 && tx_sdu_queue.size() > 0)
{ {
log->debug("pdu_space=%d, head_len=%d\n", pdu_space, head_len); log->debug("pdu_space=%d, head_len=%d\n", pdu_space, head_len);
if(last_li > 0) if(last_li > 0)

@ -18,5 +18,6 @@
# and at http://www.gnu.org/licenses/. # and at http://www.gnu.org/licenses/.
# #
add_subdirectory(asn1)
add_subdirectory(common) add_subdirectory(common)
add_subdirectory(upper) add_subdirectory(upper)

@ -0,0 +1,23 @@
#
# Copyright 2013-2017 Software Radio Systems Limited
#
# This file is part of srsLTE
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# srsLTE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
add_executable(rrc_meas_test rrc_meas_test.cc)
target_link_libraries(rrc_meas_test srslte_common srslte_phy srslte_asn1)
add_test(rrc_meas_test rrc_meas_test)

@ -0,0 +1,91 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsUE library.
*
* srsUE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsUE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <assert.h>
#include <iostream>
#include <srslte/srslte.h>
#include "srslte/common/log_filter.h"
#include "srslte/asn1/liblte_rrc.h"
void basic_test() {
srslte::log_filter log1("RRC");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(128);
LIBLTE_BIT_MSG_STRUCT bit_buf;
LIBLTE_BIT_MSG_STRUCT bit_buf2;
LIBLTE_BYTE_MSG_STRUCT byte_buf;
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
uint32_t rrc_message_len = 18;
uint8_t rrc_message[] = {0x08, 0x10, 0x49, 0x3C, 0x0D, 0x97, 0x89, 0x83,
0xC0, 0x84, 0x20, 0x82, 0x08, 0x21, 0x00, 0x01,
0xBC, 0x48};
srslte_bit_unpack_vector(rrc_message, bit_buf.msg, rrc_message_len*8);
bit_buf.N_bits = rrc_message_len*8;
liblte_rrc_unpack_ul_dcch_msg((LIBLTE_BIT_MSG_STRUCT*)&bit_buf, &ul_dcch_msg);
assert(ul_dcch_msg.msg_type == LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT);
LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *rep = &ul_dcch_msg.msg.measurement_report;
assert(rep->meas_id == 1);
assert(rep->pcell_rsrp_result == 73);
assert(rep->pcell_rsrq_result == 15);
assert(rep->have_meas_result_neigh_cells);
assert(rep->meas_result_neigh_cells_choice == LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA);
LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT *eutra = &rep->meas_result_neigh_cells.eutra;
assert(eutra->n_result == 1);
assert(eutra->result_eutra_list[0].phys_cell_id == 357);
assert(eutra->result_eutra_list[0].have_cgi_info);
assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mcc == 0xF898);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mnc == 0xFF78);
assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.cell_id == 0x1084104);
assert(eutra->result_eutra_list[0].cgi_info.tracking_area_code == 0x1042);
assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list);
assert(eutra->result_eutra_list[0].cgi_info.n_plmn_identity_list == 1);
assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mcc == 0xFFFF);
assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mnc == 0xFF00);
assert(eutra->result_eutra_list[0].meas_result.have_rsrp);
assert(eutra->result_eutra_list[0].meas_result.rsrp_result == 60);
assert(eutra->result_eutra_list[0].meas_result.have_rsrp);
assert(eutra->result_eutra_list[0].meas_result.rsrq_result == 18);
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT*)&bit_buf2);
srslte_bit_pack_vector(bit_buf2.msg, byte_buf.msg, bit_buf2.N_bits);
byte_buf.N_bytes = (bit_buf2.N_bits+7)/8;
log1.info_hex(byte_buf.msg, byte_buf.N_bytes, "UL_DCCH Packed message\n");
for(uint32_t i=0; i<rrc_message_len; i++) {
assert(byte_buf.msg[i] == rrc_message[i]);
}
}
int main(int argc, char **argv) {
basic_test();
}

@ -123,7 +123,7 @@ void basic_test()
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
for(int i=0;i<NBUFS;i++) for(int i=0;i<NBUFS;i++)
{ {
len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 3 bytes for header + payload len = rlc1.read_pdu(pdu_bufs[i].msg, 4); // 3 bytes for header + payload
pdu_bufs[i].N_bytes = len; pdu_bufs[i].N_bytes = len;
} }
@ -351,7 +351,7 @@ void retx_test()
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
for(int i=0;i<NBUFS;i++) for(int i=0;i<NBUFS;i++)
{ {
len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 2 byte header + 1 byte payload len = rlc1.read_pdu(pdu_bufs[i].msg, 4); // 2 byte header + 1 byte payload
pdu_bufs[i].N_bytes = len; pdu_bufs[i].N_bytes = len;
} }

@ -123,7 +123,7 @@ void basic_test()
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
for(int i=0;i<NBUFS;i++) for(int i=0;i<NBUFS;i++)
{ {
len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 3 bytes for header + payload len = rlc1.read_pdu(pdu_bufs[i].msg, 4); // 3 bytes for header + payload
pdu_bufs[i].N_bytes = len; pdu_bufs[i].N_bytes = len;
} }
@ -191,7 +191,7 @@ void loss_test()
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
for(int i=0;i<NBUFS;i++) for(int i=0;i<NBUFS;i++)
{ {
len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 3 bytes for header + payload len = rlc1.read_pdu(pdu_bufs[i].msg, 4); // 3 bytes for header + payload
pdu_bufs[i].N_bytes = len; pdu_bufs[i].N_bytes = len;
} }

@ -46,6 +46,8 @@ drb_config = drb.conf
# rx_gain: Optional receive gain (dB). If disabled, AGC if enabled # rx_gain: Optional receive gain (dB). If disabled, AGC if enabled
# #
# Optional parameters: # Optional parameters:
# dl_freq: Override DL frequency corresponding to dl_earfcn
# ul_freq: Override UL frequency corresponding to dl_earfcn (must be set if dl_freq is set)
# device_name: Device driver family. Supported options: "auto" (uses first found), "UHD" or "bladeRF" # device_name: Device driver family. Supported options: "auto" (uses first found), "UHD" or "bladeRF"
# device_args: Arguments for the device driver. Options are "auto" or any string. # device_args: Arguments for the device driver. Options are "auto" or any string.
# Default for UHD: "recv_frame_size=9232,send_frame_size=9232" # Default for UHD: "recv_frame_size=9232,send_frame_size=9232"

@ -182,7 +182,7 @@ private:
// Allowed DCI locations per CFI and per subframe // Allowed DCI locations per CFI and per subframe
sched_dci_cce_t dci_locations[3][10]; sched_dci_cce_t dci_locations[3][10];
const static int SCHED_MAX_HARQ_PROC = 8; const static int SCHED_MAX_HARQ_PROC = 2*HARQ_DELAY_MS;
dl_harq_proc dl_harq[SCHED_MAX_HARQ_PROC]; dl_harq_proc dl_harq[SCHED_MAX_HARQ_PROC];
ul_harq_proc ul_harq[SCHED_MAX_HARQ_PROC]; ul_harq_proc ul_harq[SCHED_MAX_HARQ_PROC];

@ -124,7 +124,7 @@ private:
uint32_t nof_failures; uint32_t nof_failures;
const static int NOF_HARQ_PROCESSES = 8; const static int NOF_HARQ_PROCESSES = 2*HARQ_DELAY_MS;
srslte_softbuffer_tx_t softbuffer_tx[NOF_HARQ_PROCESSES]; srslte_softbuffer_tx_t softbuffer_tx[NOF_HARQ_PROCESSES];
srslte_softbuffer_rx_t softbuffer_rx[NOF_HARQ_PROCESSES]; srslte_softbuffer_rx_t softbuffer_rx[NOF_HARQ_PROCESSES];

@ -78,13 +78,13 @@ public:
mac_interface_phy *mac; mac_interface_phy *mac;
// Common objects for schedulign grants // Common objects for schedulign grants
mac_interface_phy::ul_sched_t ul_grants[10]; mac_interface_phy::ul_sched_t ul_grants[TTIMOD_SZ];
mac_interface_phy::dl_sched_t dl_grants[10]; mac_interface_phy::dl_sched_t dl_grants[TTIMOD_SZ];
// Map of pending ACKs for each user // Map of pending ACKs for each user
typedef struct { typedef struct {
bool is_pending[10]; bool is_pending[TTIMOD_SZ];
uint16_t n_pdcch[10]; uint16_t n_pdcch[TTIMOD_SZ];
} pending_ack_t; } pending_ack_t;
std::map<uint16_t,pending_ack_t> pending_ack; std::map<uint16_t,pending_ack_t> pending_ack;

@ -75,12 +75,12 @@ private:
void work_imp(); void work_imp();
int encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants, uint32_t sf_idx); int encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants);
int decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch, uint32_t tti_rx); int decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch);
int encode_phich(srslte_enb_dl_phich_t *acks, uint32_t nof_acks, uint32_t sf_idx); int encode_phich(srslte_enb_dl_phich_t *acks, uint32_t nof_acks);
int encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants, uint32_t sf_idx); int encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants);
int encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_grants, uint32_t sf_idx); int encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_grants);
int decode_pucch(uint32_t tti_rx); int decode_pucch();
/* Common objects */ /* Common objects */
@ -91,8 +91,9 @@ private:
cf_t *signal_buffer_rx[SRSLTE_MAX_PORTS]; cf_t *signal_buffer_rx[SRSLTE_MAX_PORTS];
cf_t *signal_buffer_tx[SRSLTE_MAX_PORTS]; cf_t *signal_buffer_tx[SRSLTE_MAX_PORTS];
uint32_t tti_rx, tti_tx, tti_sched_ul, sf_rx, sf_tx, sf_sched_ul, tx_mutex_cnt; uint32_t tti_rx, tti_tx_dl, tti_tx_ul;
uint32_t sf_rx, sf_tx, tx_mutex_cnt;
uint32_t t_rx, t_tx_dl, t_tx_ul;
srslte_enb_dl_t enb_dl; srslte_enb_dl_t enb_dl;
srslte_enb_ul_t enb_ul; srslte_enb_ul_t enb_ul;

@ -582,7 +582,7 @@ int sched::dl_sched_rar(dl_sched_rar_t rar[MAX_RAR_LIST])
pending_rar[j].rar_tti = 0; pending_rar[j].rar_tti = 0;
// Save UL resources // Save UL resources
uint32_t pending_tti=(current_tti+6)%10; uint32_t pending_tti=(current_tti+MSG3_DELAY_MS+HARQ_DELAY_MS)%10;
pending_msg3[pending_tti].enabled = true; pending_msg3[pending_tti].enabled = true;
pending_msg3[pending_tti].rnti = pending_rar[j].rnti; pending_msg3[pending_tti].rnti = pending_rar[j].rnti;
pending_msg3[pending_tti].L = L_prb; pending_msg3[pending_tti].L = L_prb;
@ -734,17 +734,17 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
/* If dl_sched() not yet called this tti (this tti is +4ms advanced), reset CCE state */ /* If dl_sched() not yet called this tti (this tti is +4ms advanced), reset CCE state */
if ((current_tti+4)%10240 != tti) { if (TTI_TX(current_tti) != tti) {
bzero(used_cce, MAX_CCE*sizeof(bool)); bzero(used_cce, MAX_CCE*sizeof(bool));
} }
/* Initialize variables */ /* Initialize variables */
current_tti = tti; current_tti = tti;
sfn = tti/10; sfn = tti/10;
if (tti > 4) { if (tti > HARQ_DELAY_MS) {
sf_idx = (tti-4)%10; sf_idx = (tti-HARQ_DELAY_MS)%10;
} else { } else {
sf_idx = (tti+10240-4)%10; sf_idx = (tti+10240-HARQ_DELAY_MS)%10;
} }
int nof_dci_elems = 0; int nof_dci_elems = 0;
int nof_phich_elems = 0; int nof_phich_elems = 0;

@ -179,7 +179,7 @@ void dl_harq_proc::set_rbgmask(uint32_t new_mask)
bool dl_harq_proc::has_pending_retx(uint32_t tb_idx, uint32_t current_tti) bool dl_harq_proc::has_pending_retx(uint32_t tb_idx, uint32_t current_tti)
{ {
return srslte_tti_interval(current_tti, tti) >= 8 && has_pending_retx_common(tb_idx); return srslte_tti_interval(current_tti, tti) >= (2*HARQ_DELAY_MS) && has_pending_retx_common(tb_idx);
} }
int dl_harq_proc::get_tbs(uint32_t tb_idx) int dl_harq_proc::get_tbs(uint32_t tb_idx)

@ -142,7 +142,11 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user)
dl_harq_proc *h = user->get_pending_dl_harq(current_tti); dl_harq_proc *h = user->get_pending_dl_harq(current_tti);
// Time-domain RR scheduling // Time-domain RR scheduling
#if ASYNC_DL_SCHED
if (pending_data || h) { if (pending_data || h) {
#else
if (pending_data || (h && !h->is_empty())) {
#endif
if (nof_users_with_data) { if (nof_users_with_data) {
if (nof_users_with_data == 2) { if (nof_users_with_data == 2) {
} }
@ -153,7 +157,11 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user)
} }
// Schedule retx if we have space // Schedule retx if we have space
#if ASYNC_DL_SCHED
if (h) { if (h) {
#else
if (h && !h->is_empty()) {
#endif
uint32_t retx_mask = h->get_rbgmask(); uint32_t retx_mask = h->get_rbgmask();
// If can schedule the same mask, do it // If can schedule the same mask, do it
if (!allocation_is_valid(retx_mask)) { if (!allocation_is_valid(retx_mask)) {
@ -171,8 +179,12 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user)
} }
} }
// If could not schedule the reTx, or there wasn't any pending retx, find an empty PID // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID
#if ASYNC_DL_SCHED
h = user->get_empty_dl_harq(); h = user->get_empty_dl_harq();
if (h) { if (h) {
#else
if (h && h->is_empty()) {
#endif
// Allocate resources based on pending data // Allocate resources based on pending data
if (pending_data) { if (pending_data) {
uint32_t pending_rb = user->get_required_prb_dl(pending_data, nof_ctrl_symbols); uint32_t pending_rb = user->get_required_prb_dl(pending_data, nof_ctrl_symbols);

@ -249,15 +249,15 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2])
// First check if it has pending ACKs // First check if it has pending ACKs
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) { for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
if (((dl_harq[i].get_tti()+4)%10240) == current_tti) { if (TTI_TX(dl_harq[i].get_tti()) == current_tti) {
uint32_t n_pucch = srslte_pucch_get_npucch(dl_harq[i].get_n_cce(), SRSLTE_PUCCH_FORMAT_1A, has_sr, &pucch_sched); uint32_t n_pucch = srslte_pucch_get_npucch(dl_harq[i].get_n_cce(), SRSLTE_PUCCH_FORMAT_1A, has_sr, &pucch_sched);
if (prb_idx) { if (prb_idx) {
for (int i=0;i<2;i++) { for (int j=0;j<2;j++) {
prb_idx[i] = srslte_pucch_n_prb(&cfg.pucch_cfg, SRSLTE_PUCCH_FORMAT_1A, n_pucch, cell.nof_prb, cell.cp, i); prb_idx[j] = srslte_pucch_n_prb(&cfg.pucch_cfg, SRSLTE_PUCCH_FORMAT_1A, n_pucch, cell.nof_prb, cell.cp, j);
} }
Debug("SCHED: Reserved Format1A PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d, ncce=%d, has_sr=%d, n_pucch_1=%d\n",
rnti, prb_idx[0], prb_idx[1], n_pucch, dl_harq[i].get_n_cce(), has_sr, pucch_sched.N_pucch_1);
} }
Debug("SCHED: Reserved Format1A PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d, ncce=%d, has_sr=%d, n_pucch_1=%d\n",
rnti, prb_idx[0], prb_idx[1], n_pucch, dl_harq[i].get_n_cce(), has_sr, pucch_sched.N_pucch_1);
return true; return true;
} }
} }
@ -277,9 +277,9 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2])
for (int i=0;i<2;i++) { for (int i=0;i<2;i++) {
prb_idx[i] = srslte_pucch_n_prb(&cfg.pucch_cfg, SRSLTE_PUCCH_FORMAT_2, cfg.cqi_pucch, cell.nof_prb, cell.cp, i); prb_idx[i] = srslte_pucch_n_prb(&cfg.pucch_cfg, SRSLTE_PUCCH_FORMAT_2, cfg.cqi_pucch, cell.nof_prb, cell.cp, i);
} }
Debug("SCHED: Reserved Format2 PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d, pmi_idx=%d\n",
rnti, prb_idx[0], prb_idx[1], cfg.cqi_pucch, cfg.cqi_idx);
} }
Debug("SCHED: Reserved Format2 PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d, pmi_idx=%d\n",
rnti, prb_idx[0], prb_idx[1], cfg.cqi_pucch, cfg.cqi_idx);
return true; return true;
} }
@ -289,7 +289,7 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2])
int sched_ue::set_ack_info(uint32_t tti, bool ack) int sched_ue::set_ack_info(uint32_t tti, bool ack)
{ {
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) { for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
if (((dl_harq[i].get_tti()+4)%10240) == tti) { if (TTI_TX(dl_harq[i].get_tti()) == tti) {
Debug("SCHED: Set ACK=%d for rnti=0x%x, pid=%d, tti=%d\n", ack, rnti, i, tti); Debug("SCHED: Set ACK=%d for rnti=0x%x, pid=%d, tti=%d\n", ack, rnti, i, tti);
dl_harq[i].set_ack(0, ack); dl_harq[i].set_ack(0, ack);
return dl_harq[i].get_tbs(0); return dl_harq[i].get_tbs(0);
@ -814,6 +814,7 @@ bool sched_ue::is_sr_triggered()
/* Gets HARQ process with oldest pending retx */ /* Gets HARQ process with oldest pending retx */
dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti) dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti)
{ {
#if ASYNC_DL_SCHED
int oldest_idx=-1; int oldest_idx=-1;
uint32_t oldest_tti = 0; uint32_t oldest_tti = 0;
for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) { for (int i=0;i<SCHED_MAX_HARQ_PROC;i++) {
@ -830,6 +831,9 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti)
} else { } else {
return NULL; return NULL;
} }
#else
return &dl_harq[tti%SCHED_MAX_HARQ_PROC];
#endif
} }
dl_harq_proc* sched_ue::get_empty_dl_harq() dl_harq_proc* sched_ue::get_empty_dl_harq()

@ -48,8 +48,8 @@ void phch_common::set_nof_mutex(uint32_t nof_mutex_) {
} }
void phch_common::reset() { void phch_common::reset() {
bzero(ul_grants, sizeof(mac_interface_phy::ul_sched_t)*10); bzero(ul_grants, sizeof(mac_interface_phy::ul_sched_t)*TTIMOD_SZ);
bzero(dl_grants, sizeof(mac_interface_phy::dl_sched_t)*10); bzero(dl_grants, sizeof(mac_interface_phy::dl_sched_t)*TTIMOD_SZ);
} }
bool phch_common::init(srslte_cell_t *cell_, srslte::radio* radio_h_, mac_interface_phy *mac_) bool phch_common::init(srslte_cell_t *cell_, srslte::radio* radio_h_, mac_interface_phy *mac_)
@ -104,7 +104,7 @@ void phch_common::ack_clear(uint32_t sf_idx)
void phch_common::ack_add_rnti(uint16_t rnti) void phch_common::ack_add_rnti(uint16_t rnti)
{ {
for (int sf_idx=0;sf_idx<10;sf_idx++) { for (int sf_idx=0;sf_idx<TTIMOD_SZ;sf_idx++) {
pending_ack[rnti].is_pending[sf_idx] = false; pending_ack[rnti].is_pending[sf_idx] = false;
} }
} }

@ -94,6 +94,7 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
fprintf(stderr, "Error allocating memory\n"); fprintf(stderr, "Error allocating memory\n");
return; return;
} }
bzero(signal_buffer_rx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t));
signal_buffer_tx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); signal_buffer_tx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t));
if (!signal_buffer_tx[p]) { if (!signal_buffer_tx[p]) {
fprintf(stderr, "Error allocating memory\n"); fprintf(stderr, "Error allocating memory\n");
@ -101,7 +102,7 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
} }
bzero(signal_buffer_tx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); bzero(signal_buffer_tx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t));
} }
if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) { if (srslte_enb_dl_init(&enb_dl, signal_buffer_tx, phy->cell.nof_prb)) {
fprintf(stderr, "Error initiating ENB DL\n"); fprintf(stderr, "Error initiating ENB DL\n");
return; return;
} }
@ -109,7 +110,7 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
fprintf(stderr, "Error initiating ENB DL\n"); fprintf(stderr, "Error initiating ENB DL\n");
return; return;
} }
if (srslte_enb_ul_init(&enb_ul, phy->cell.nof_prb)) { if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx[0], phy->cell.nof_prb)) {
fprintf(stderr, "Error initiating ENB UL\n"); fprintf(stderr, "Error initiating ENB UL\n");
return; return;
} }
@ -181,11 +182,16 @@ cf_t* phch_worker::get_buffer_rx(uint32_t antenna_idx)
void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_) void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_)
{ {
tti_rx = tti_; tti_rx = tti_;
tti_tx = (tti_ + 4)%10240; tti_tx_dl = TTI_TX(tti_rx);
tti_sched_ul = (tti_ + 8)%10240; tti_tx_ul = TTI_RX_ACK(tti_rx);
sf_rx = tti_rx%10; sf_rx = tti_rx%10;
sf_tx = tti_tx%10; sf_tx = tti_tx_dl%10;
sf_sched_ul = tti_sched_ul%10;
t_tx_dl = TTIMOD(tti_tx_dl);
t_rx = TTIMOD(tti_rx);
t_tx_ul = TTIMOD(tti_tx_ul);
tx_mutex_cnt = tx_mutex_cnt_; tx_mutex_cnt = tx_mutex_cnt_;
memcpy(&tx_time, &tx_time_, sizeof(srslte_timestamp_t)); memcpy(&tx_time, &tx_time_, sizeof(srslte_timestamp_t));
} }
@ -267,7 +273,7 @@ void phch_worker::rem_rnti(uint16_t rnti)
srslte_enb_ul_rem_rnti(&enb_ul, rnti); srslte_enb_ul_rem_rnti(&enb_ul, rnti);
// remove any pending grant for each subframe // remove any pending grant for each subframe
for (uint32_t i=0;i<10;i++) { for (uint32_t i=0;i<TTIMOD_SZ;i++) {
for (uint32_t j=0;j<phy->ul_grants[i].nof_grants;j++) { for (uint32_t j=0;j<phy->ul_grants[i].nof_grants;j++) {
if (phy->ul_grants[i].sched_grants[j].rnti == rnti) { if (phy->ul_grants[i].sched_grants[j].rnti == rnti) {
phy->ul_grants[i].sched_grants[j].rnti = 0; phy->ul_grants[i].sched_grants[j].rnti = 0;
@ -287,8 +293,6 @@ void phch_worker::rem_rnti(uint16_t rnti)
void phch_worker::work_imp() void phch_worker::work_imp()
{ {
uint32_t sf_ack;
if (!running) { if (!running) {
return; return;
} }
@ -309,56 +313,55 @@ void phch_worker::work_imp()
} }
// Process UL signal // Process UL signal
srslte_enb_ul_fft(&enb_ul, signal_buffer_rx[0]); srslte_enb_ul_fft(&enb_ul);
// Decode pending UL grants for the tti they were scheduled // Decode pending UL grants for the tti they were scheduled
decode_pusch(ul_grants[sf_rx].sched_grants, ul_grants[sf_rx].nof_grants, sf_rx); decode_pusch(ul_grants[t_rx].sched_grants, ul_grants[t_rx].nof_grants);
// Decode remaining PUCCH ACKs not associated with PUSCH transmission and SR signals // Decode remaining PUCCH ACKs not associated with PUSCH transmission and SR signals
decode_pucch(tti_rx); decode_pucch();
// Get DL scheduling for the TX TTI from MAC // Get DL scheduling for the TX TTI from MAC
if (mac->get_dl_sched(tti_tx, &dl_grants[sf_tx]) < 0) { if (mac->get_dl_sched(tti_tx_dl, &dl_grants[t_tx_dl]) < 0) {
Error("Getting DL scheduling from MAC\n"); Error("Getting DL scheduling from MAC\n");
goto unlock; goto unlock;
} }
if (dl_grants[sf_tx].cfi < 1 || dl_grants[sf_tx].cfi > 3) { if (dl_grants[t_tx_dl].cfi < 1 || dl_grants[t_tx_dl].cfi > 3) {
Error("Invalid CFI=%d\n", dl_grants[sf_tx].cfi); Error("Invalid CFI=%d\n", dl_grants[t_tx_dl].cfi);
goto unlock; goto unlock;
} }
// Get UL scheduling for the TX TTI from MAC // Get UL scheduling for the TX TTI from MAC
if (mac->get_ul_sched(tti_sched_ul, &ul_grants[sf_sched_ul]) < 0) { if (mac->get_ul_sched(tti_tx_ul, &ul_grants[t_tx_ul]) < 0) {
Error("Getting UL scheduling from MAC\n"); Error("Getting UL scheduling from MAC\n");
goto unlock; goto unlock;
} }
// Put base signals (references, PBCH, PCFICH and PSS/SSS) into the resource grid // Put base signals (references, PBCH, PCFICH and PSS/SSS) into the resource grid
srslte_enb_dl_clear_sf(&enb_dl); srslte_enb_dl_clear_sf(&enb_dl);
srslte_enb_dl_set_cfi(&enb_dl, dl_grants[sf_tx].cfi); srslte_enb_dl_set_cfi(&enb_dl, dl_grants[t_tx_dl].cfi);
srslte_enb_dl_put_base(&enb_dl, tti_tx); srslte_enb_dl_put_base(&enb_dl, tti_tx_dl);
// Put UL/DL grants to resource grid. PDSCH data will be encoded as well. // Put UL/DL grants to resource grid. PDSCH data will be encoded as well.
encode_pdcch_dl(dl_grants[sf_tx].sched_grants, dl_grants[sf_tx].nof_grants, sf_tx); encode_pdcch_dl(dl_grants[t_tx_dl].sched_grants, dl_grants[t_tx_dl].nof_grants);
encode_pdcch_ul(ul_grants[sf_sched_ul].sched_grants, ul_grants[sf_sched_ul].nof_grants, sf_tx); encode_pdcch_ul(ul_grants[t_tx_ul].sched_grants, ul_grants[t_tx_ul].nof_grants);
encode_pdsch(dl_grants[sf_tx].sched_grants, dl_grants[sf_tx].nof_grants, sf_tx); encode_pdsch(dl_grants[t_tx_dl].sched_grants, dl_grants[t_tx_dl].nof_grants);
// Put pending PHICH HARQ ACK/NACK indications into subframe // Put pending PHICH HARQ ACK/NACK indications into subframe
encode_phich(ul_grants[sf_sched_ul].phich, ul_grants[sf_sched_ul].nof_phich, sf_tx); encode_phich(ul_grants[t_tx_ul].phich, ul_grants[t_tx_ul].nof_phich);
// Prepare for receive ACK for DL grants in sf_tx+4 // Prepare for receive ACK for DL grants in t_tx_dl+4
sf_ack = (sf_tx+4)%10; phy->ack_clear(TTIMOD(TTI_TX(t_tx_dl)));
phy->ack_clear(sf_ack); for (uint32_t i=0;i<dl_grants[t_tx_dl].nof_grants;i++) {
for (uint32_t i=0;i<dl_grants[sf_tx].nof_grants;i++) {
// SI-RNTI and RAR-RNTI do not have ACK // SI-RNTI and RAR-RNTI do not have ACK
if (dl_grants[sf_tx].sched_grants[i].rnti >= SRSLTE_CRNTI_START && dl_grants[sf_tx].sched_grants[i].rnti <= SRSLTE_CRNTI_END) { if (dl_grants[t_tx_dl].sched_grants[i].rnti >= SRSLTE_CRNTI_START && dl_grants[t_tx_dl].sched_grants[i].rnti <= SRSLTE_CRNTI_END) {
phy->ack_set_pending(sf_ack, dl_grants[sf_tx].sched_grants[i].rnti, dl_grants[sf_tx].sched_grants[i].location.ncce); phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), dl_grants[t_tx_dl].sched_grants[i].rnti, dl_grants[t_tx_dl].sched_grants[i].location.ncce);
} }
} }
// Generate signal and transmit // Generate signal and transmit
srslte_enb_dl_gen_signal(&enb_dl, signal_buffer_tx); srslte_enb_dl_gen_signal(&enb_dl);
Debug("Sending to radio\n"); Debug("Sending to radio\n");
phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time); phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time);
@ -367,7 +370,7 @@ void phch_worker::work_imp()
#endif #endif
#ifdef DEBUG_WRITE_FILE #ifdef DEBUG_WRITE_FILE
if (tti_tx == 10) { if (tti_tx_dl == 10) {
fclose(f); fclose(f);
exit(-1); exit(-1);
} }
@ -386,7 +389,7 @@ unlock:
} }
int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch, uint32_t tti) int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
{ {
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
@ -405,7 +408,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch,
#endif #endif
// Get pending ACKs with an associated PUSCH transmission // Get pending ACKs with an associated PUSCH transmission
if (phy->ack_is_pending(sf_rx, rnti)) { if (phy->ack_is_pending(t_rx, rnti)) {
uci_data.uci_ack_len = 1; uci_data.uci_ack_len = 1;
} }
// Configure PUSCH CQI channel // Configure PUSCH CQI channel
@ -428,7 +431,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch,
srslte_ra_ul_grant_t phy_grant; srslte_ra_ul_grant_t phy_grant;
int res = -1; int res = -1;
if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant, tti%8)) { if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant)) {
if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) { if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) {
phy_grant.mcs.mod = SRSLTE_MOD_16QAM; phy_grant.mcs.mod = SRSLTE_MOD_16QAM;
} }
@ -438,7 +441,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch,
grants[i].current_tx_nb, grants[i].current_tx_nb,
grants[i].data, grants[i].data,
&uci_data, &uci_data,
tti); sf_rx);
} else { } else {
Error("Computing PUSCH grant\n"); Error("Computing PUSCH grant\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -524,9 +527,8 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch,
} }
int phch_worker::decode_pucch(uint32_t tti_rx) int phch_worker::decode_pucch()
{ {
uint32_t sf_rx = tti_rx%10;
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
for(std::map<uint16_t, ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { for(std::map<uint16_t, ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) {
@ -545,7 +547,8 @@ int phch_worker::decode_pucch(uint32_t tti_rx)
uci_data.scheduling_request = true; uci_data.scheduling_request = true;
} }
} }
if (phy->ack_is_pending(sf_rx, rnti, &last_n_pdcch)) {
if (phy->ack_is_pending(t_rx, rnti, &last_n_pdcch)) {
needs_pucch = true; needs_pucch = true;
needs_ack = true; needs_ack = true;
uci_data.uci_ack_len = 1; uci_data.uci_ack_len = 1;
@ -631,7 +634,7 @@ int phch_worker::decode_pucch(uint32_t tti_rx)
} }
int phch_worker::encode_phich(srslte_enb_dl_phich_t *acks, uint32_t nof_acks, uint32_t sf_idx) int phch_worker::encode_phich(srslte_enb_dl_phich_t *acks, uint32_t nof_acks)
{ {
for (uint32_t i=0;i<nof_acks;i++) { for (uint32_t i=0;i<nof_acks;i++) {
uint16_t rnti = acks[i].rnti; uint16_t rnti = acks[i].rnti;
@ -639,61 +642,60 @@ int phch_worker::encode_phich(srslte_enb_dl_phich_t *acks, uint32_t nof_acks, ui
srslte_enb_dl_put_phich(&enb_dl, acks[i].ack, srslte_enb_dl_put_phich(&enb_dl, acks[i].ack,
ue_db[rnti].phich_info.n_prb_lowest, ue_db[rnti].phich_info.n_prb_lowest,
ue_db[rnti].phich_info.n_dmrs, ue_db[rnti].phich_info.n_dmrs,
sf_idx); sf_tx);
Info("PHICH: rnti=0x%x, hi=%d, I_lowest=%d, n_dmrs=%d, tti_tx=%d\n", Info("PHICH: rnti=0x%x, hi=%d, I_lowest=%d, n_dmrs=%d, tti_tx_dl=%d\n",
rnti, acks[i].ack, rnti, acks[i].ack,
ue_db[rnti].phich_info.n_prb_lowest, ue_db[rnti].phich_info.n_prb_lowest,
ue_db[rnti].phich_info.n_dmrs, tti_tx); ue_db[rnti].phich_info.n_dmrs, tti_tx_dl);
} }
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
int phch_worker::encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_grants, uint32_t sf_idx) int phch_worker::encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_grants)
{ {
for (uint32_t i=0;i<nof_grants;i++) { for (uint32_t i=0;i<nof_grants;i++) {
uint16_t rnti = grants[i].rnti; uint16_t rnti = grants[i].rnti;
if (grants[i].needs_pdcch && rnti) { if (grants[i].needs_pdcch && rnti) {
if (srslte_enb_dl_put_pdcch_ul(&enb_dl, &grants[i].grant, grants[i].location, rnti, sf_idx)) { if (srslte_enb_dl_put_pdcch_ul(&enb_dl, &grants[i].grant, grants[i].location, rnti, sf_tx)) {
fprintf(stderr, "Error putting PUSCH %d\n",i); fprintf(stderr, "Error putting PUSCH %d\n",i);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
Info("PDCCH: UL DCI Format0 rnti=0x%x, cce_index=%d, L=%d, tti_tx=%d\n", Info("PDCCH: UL DCI Format0 rnti=0x%x, cce_index=%d, L=%d, tpc=%d, tti_tx_dl=%d\n",
rnti, grants[i].location.ncce, (1<<grants[i].location.L), tti_tx); rnti, grants[i].location.ncce, (1<<grants[i].location.L), grants[i].grant.tpc_pusch, tti_tx_dl);
} }
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants, uint32_t sf_idx) int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants)
{ {
/* For each grant... */
for (uint32_t i=0;i<nof_grants;i++) { for (uint32_t i=0;i<nof_grants;i++) {
srslte_enb_dl_pdsch_t *grant = &grants[i]; srslte_enb_dl_pdsch_t *grant = &grants[i];
uint16_t rnti = grant->rnti; uint16_t rnti = grant->rnti;
if (rnti) { if (rnti) {
if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, grant->dci_format, grants[i].location, rnti, sf_idx)) { if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, grant->dci_format, grants[i].location, rnti, sf_tx)) {
fprintf(stderr, "Error putting PDCCH %d\n",i); fprintf(stderr, "Error putting PDCCH %d\n",i);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (LOG_THIS(rnti)) { if (LOG_THIS(rnti)) {
Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx=%d\n", srslte_dci_format_string(grant->dci_format), Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx_dl=%d\n", srslte_dci_format_string(grant->dci_format),
rnti, grants[i].location.ncce, (1<<grants[i].location.L), tti_tx); rnti, grants[i].location.ncce, (1<<grants[i].location.L), tti_tx_dl);
} }
} }
} }
return 0; return 0;
} }
int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants, uint32_t sf_idx) int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants) {
{ for (uint32_t i = 0; i < nof_grants; i++) {
for (uint32_t i=0;i<nof_grants;i++) {
uint16_t rnti = grants[i].rnti; uint16_t rnti = grants[i].rnti;
if (rnti) { if (rnti) {
bool rnti_is_user = true; bool rnti_is_user = true;
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || rnti == SRSLTE_MRNTI) { if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || rnti == SRSLTE_MRNTI) {
rnti_is_user = false; rnti_is_user = false;
@ -705,17 +707,16 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
srslte_ra_dl_dci_to_grant(&grants[i].grant, enb_dl.cell.nof_prb, rnti, &phy_grant); srslte_ra_dl_dci_to_grant(&grants[i].grant, enb_dl.cell.nof_prb, rnti, &phy_grant);
char grant_str[64]; char grant_str[64];
switch(grants[i].grant.alloc_type) { switch (grants[i].grant.alloc_type) {
case SRSLTE_RA_ALLOC_TYPE0: case SRSLTE_RA_ALLOC_TYPE0:
sprintf(grant_str, "mask=0x%x",grants[i].grant.type0_alloc.rbg_bitmask); sprintf(grant_str, "mask=0x%x", grants[i].grant.type0_alloc.rbg_bitmask);
break; break;
case SRSLTE_RA_ALLOC_TYPE1: case SRSLTE_RA_ALLOC_TYPE1:
sprintf(grant_str, "mask=0x%x",grants[i].grant.type1_alloc.vrb_bitmask); sprintf(grant_str, "mask=0x%x", grants[i].grant.type1_alloc.vrb_bitmask);
break; break;
case SRSLTE_RA_ALLOC_TYPE2:
default: default:
sprintf(grant_str, "rb_start=%d",grants[i].grant.type2_alloc.RB_start); sprintf(grant_str, "rb_start=%d", grants[i].grant.type2_alloc.RB_start);
break; break;
} }
@ -726,6 +727,11 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
/* Do nothing, it keeps default */ /* Do nothing, it keeps default */
break; break;
case SRSLTE_DCI_FORMAT2A: case SRSLTE_DCI_FORMAT2A:
if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 2) {
mimo_type = SRSLTE_MIMO_TYPE_CDD;
}
break; break;
case SRSLTE_DCI_FORMAT2: case SRSLTE_DCI_FORMAT2:
if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1) { if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1) {
@ -734,7 +740,7 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
} else { } else {
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX; mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
} }
} else if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1 && phy_grant.pinfo == 0) { } else if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 2) {
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX; mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
} }
break; break;
@ -760,15 +766,26 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
snprintf(pinfo_str, 15, ", pinfo=%x", phy_grant.pinfo); snprintf(pinfo_str, 15, ", pinfo=%x", phy_grant.pinfo);
} }
log_h->info_hex(ptr, len, log_h->info_hex(ptr, len,
"PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d, tx_scheme=%s%s\n", "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx_dl=%d, tx_scheme=%s%s\n",
rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process,
phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx, srslte_mimotype2str(mimo_type), pinfo_str); phy_grant.mcs[0].tbs / 8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx_dl,
srslte_mimotype2str(mimo_type), pinfo_str);
}
srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS];
uint8_t *d[SRSLTE_MAX_CODEWORDS];
int rv[SRSLTE_MAX_CODEWORDS];
for (int tb = 0; tb < 2; tb++) {
sb[tb] = grants[tb].softbuffers[tb];
d[tb] = grants[tb].data[tb];
} }
rv[0] = grants[i].grant.rv_idx;
rv[1] = grants[i].grant.rv_idx_1;
int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1};
if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_idx, grants[i].data, mimo_type)) { if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, sb, rnti, rv, sf_tx, d, mimo_type)) {
fprintf(stderr, "Error putting PDSCH %d\n",i); fprintf(stderr, "Error putting PDSCH %d\n", i);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }

@ -117,7 +117,7 @@ void txrx::run_thread()
/* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */
srslte_timestamp_copy(&tx_time, &rx_time); srslte_timestamp_copy(&tx_time, &rx_time);
srslte_timestamp_add(&tx_time, 0, 4e-3); srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3);
Debug("Settting TTI=%d, tx_mutex=%d, tx_time=%d:%f to worker %d\n", Debug("Settting TTI=%d, tx_mutex=%d, tx_time=%d:%f to worker %d\n",
tti, tx_mutex_cnt, tti, tx_mutex_cnt,

@ -82,6 +82,7 @@ bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_
#endif #endif
struct sockaddr_in bindaddr; struct sockaddr_in bindaddr;
bzero(&bindaddr, sizeof(struct sockaddr_in));
bindaddr.sin_family = AF_INET; bindaddr.sin_family = AF_INET;
bindaddr.sin_addr.s_addr = inet_addr(gtp_bind_addr.c_str()); bindaddr.sin_addr.s_addr = inet_addr(gtp_bind_addr.c_str());
bindaddr.sin_port = htons(GTPU_PORT); bindaddr.sin_port = htons(GTPU_PORT);
@ -137,7 +138,10 @@ void gtpu::write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* pdu)
servaddr.sin_port = htons(GTPU_PORT); servaddr.sin_port = htons(GTPU_PORT);
gtpu_write_header(&header, pdu); gtpu_write_header(&header, pdu);
sendto(snk_fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in)); if (sendto(snk_fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in))<0) {
perror("sendto");
}
pool->deallocate(pdu); pool->deallocate(pdu);
} }

@ -223,9 +223,13 @@ void rrc::rem_user(uint16_t rnti)
if (users.count(rnti) == 1) { if (users.count(rnti) == 1) {
rrc_log->console("Disconnecting rnti=0x%x.\n", rnti); rrc_log->console("Disconnecting rnti=0x%x.\n", rnti);
rrc_log->info("Disconnecting rnti=0x%x.\n", rnti); rrc_log->info("Disconnecting rnti=0x%x.\n", rnti);
/* **Caution** order of removal here is imporant: from bottom to top */ /* **Caution** order of removal here is important: from bottom to top */
mac->ue_rem(rnti); // MAC handles PHY mac->ue_rem(rnti); // MAC handles PHY
pthread_mutex_unlock(&user_mutex);
usleep(50000); usleep(50000);
pthread_mutex_lock(&user_mutex);
rlc->rem_user(rnti); rlc->rem_user(rnti);
pdcp->rem_user(rnti); pdcp->rem_user(rnti);
gtpu->rem_user(rnti); gtpu->rem_user(rnti);

@ -41,14 +41,16 @@ namespace srsue {
class demux : public srslte::pdu_queue::process_callback class demux : public srslte::pdu_queue::process_callback
{ {
public: public:
demux(uint8_t nof_harq_proc_); demux();
void init(phy_interface_mac_common* phy_h_, rlc_interface_mac *rlc, srslte::log* log_h_, srslte::timers::timer* time_alignment_timer); void init(phy_interface_mac_common* phy_h_, rlc_interface_mac *rlc, srslte::log* log_h_, srslte::timers::timer* time_alignment_timer);
bool process_pdus(); bool process_pdus();
uint8_t* request_buffer(uint32_t pid, uint32_t len); uint8_t* request_buffer(uint32_t len);
uint8_t* request_buffer_bcch(uint32_t len);
void deallocate(uint8_t* payload_buffer_ptr); void deallocate(uint8_t* payload_buffer_ptr);
void push_pdu(uint32_t pid, uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp); void push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp);
void push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp);
void push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes); void push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes);
void set_uecrid_callback(bool (*callback)(void*, uint64_t), void *arg); void set_uecrid_callback(bool (*callback)(void*, uint64_t), void *arg);
@ -59,7 +61,8 @@ public:
private: private:
const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps
const static int NOF_BUFFER_PDUS = 64; // Number of PDU buffers per HARQ pid const static int NOF_BUFFER_PDUS = 64; // Number of PDU buffers per HARQ pid
uint8_t bcch_buffer[1024]; // BCCH PID has a dedicated buffer const static int MAX_BCCH_PDU_LEN = 1024;
uint8_t bcch_buffer[MAX_BCCH_PDU_LEN]; // BCCH PID has a dedicated buffer
bool (*uecrid_callback) (void*, uint64_t); bool (*uecrid_callback) (void*, uint64_t);
void *uecrid_callback_arg; void *uecrid_callback_arg;
@ -76,7 +79,6 @@ private:
srslte::log *log_h; srslte::log *log_h;
srslte::timers::timer *time_alignment_timer; srslte::timers::timer *time_alignment_timer;
rlc_interface_mac *rlc; rlc_interface_mac *rlc;
uint8_t nof_harq_proc;
// Buffer of PDUs // Buffer of PDUs
srslte::pdu_queue pdus; srslte::pdu_queue pdus;

@ -259,13 +259,16 @@ private:
memcpy(&cur_grant, &grant, sizeof(Tgrant)); memcpy(&cur_grant, &grant, sizeof(Tgrant));
// If data has not yet been successfully decoded // If data has not yet been successfully decoded
if (!ack) { if (!ack || (grant.rv[tid]==0 && grant.phy_grant.dl.mcs[tid].idx < 29)) {
// Instruct the PHY To combine the received data and attempt to decode it // Instruct the PHY To combine the received data and attempt to decode it
payload_buffer_ptr = harq_entity->demux_unit->request_buffer(pid * SRSLTE_MAX_TB + tid, if (pid == HARQ_BCCH_PID) {
cur_grant.n_bytes[tid]); payload_buffer_ptr = harq_entity->demux_unit->request_buffer_bcch(cur_grant.n_bytes[tid]);
} else {
payload_buffer_ptr = harq_entity->demux_unit->request_buffer(cur_grant.n_bytes[tid]);
}
action->payload_ptr[tid] = payload_buffer_ptr; action->payload_ptr[tid] = payload_buffer_ptr;
if (!action->payload_ptr) { if (!action->payload_ptr[tid]) {
action->decode_enabled[tid] = false; action->decode_enabled[tid] = false;
Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes[tid]); Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes[tid]);
return; return;
@ -305,8 +308,7 @@ private:
harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes[tid], ack, cur_grant.tti); harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes[tid], ack, cur_grant.tti);
} }
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes[tid]); Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes[tid]);
harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid], harq_entity->demux_unit->push_pdu_bcch(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.tti);
cur_grant.tti);
} else { } else {
if (harq_entity->pcap) { if (harq_entity->pcap) {
harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.rnti, ack, harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.rnti, ack,
@ -318,8 +320,7 @@ private:
harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid]); harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid]);
} else { } else {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes[tid]); Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes[tid]);
harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid], harq_entity->demux_unit->push_pdu(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.tti);
cur_grant.tti);
// Compute average number of retransmissions per packet // Compute average number of retransmissions per packet
harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx, harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx,
@ -346,9 +347,10 @@ private:
// Determine if it's a new transmission 5.3.2.2 // Determine if it's a new transmission 5.3.2.2
bool calc_is_new_transmission(Tgrant grant) { bool calc_is_new_transmission(Tgrant grant) {
if ((grant.ndi[tid] != cur_grant.ndi[tid]) || // 1st condition (NDI has changed) if (grant.phy_grant.dl.mcs[tid].idx <= 28 && // mcs 29,30,31 always retx regardless of rest
(pid == HARQ_BCCH_PID && grant.rv[tid] == 0) || // 2nd condition (Broadcast and 1st transmission) ((grant.ndi[tid] != cur_grant.ndi[tid]) || // 1st condition (NDI has changed)
is_first_tb) // 3rd condition (first TB) (pid == HARQ_BCCH_PID && grant.rv[tid] == 0) || // 2nd condition (Broadcast and 1st transmission)
is_first_tb))
{ {
is_first_tb = false; is_first_tb = false;
is_new_transmission = true; is_new_transmission = true;

@ -109,7 +109,7 @@ private:
static const int MAC_MAIN_THREAD_PRIO = 5; static const int MAC_MAIN_THREAD_PRIO = 5;
static const int MAC_PDU_THREAD_PRIO = 6; static const int MAC_PDU_THREAD_PRIO = 6;
static const int MAC_NOF_HARQ_PROC = 8; static const int MAC_NOF_HARQ_PROC = 2*HARQ_DELAY_MS;
// Interaction with PHY // Interaction with PHY
srslte::tti_sync_cv ttisync; srslte::tti_sync_cv ttisync;

@ -82,7 +82,6 @@ private:
const static int MIN_RLC_SDU_LEN = 0; const static int MIN_RLC_SDU_LEN = 0;
const static int MAX_NOF_SUBHEADERS = 20; const static int MAX_NOF_SUBHEADERS = 20;
const static int MAX_HARQ_PROC = 8;
std::vector<lchid_t> lch; std::vector<lchid_t> lch;
@ -100,7 +99,7 @@ private:
uint8_t nof_harq_proc; uint8_t nof_harq_proc;
/* Msg3 Buffer */ /* Msg3 Buffer */
static const uint32_t MSG3_BUFF_SZ = 128; static const uint32_t MSG3_BUFF_SZ = 1024;
uint8_t msg3_buff[MSG3_BUFF_SZ]; uint8_t msg3_buff[MSG3_BUFF_SZ];
/* PDU Buffer */ /* PDU Buffer */

@ -138,7 +138,7 @@ namespace srsue {
uint32_t I_lowest; uint32_t I_lowest;
uint32_t n_dmrs; uint32_t n_dmrs;
} pending_ack_t; } pending_ack_t;
pending_ack_t pending_ack[10]; pending_ack_t pending_ack[TTIMOD_SZ];
bool is_first_tx; bool is_first_tx;

@ -53,6 +53,7 @@ public:
void set_agc_enable(bool enable); void set_agc_enable(bool enable);
void set_earfcn(std::vector<uint32_t> earfcn); void set_earfcn(std::vector<uint32_t> earfcn);
void force_freq(float dl_freq, float ul_freq);
void reset_sync(); void reset_sync();
void cell_search_start(); void cell_search_start();
@ -157,7 +158,7 @@ private:
uint32_t current_earfcn; uint32_t current_earfcn;
uint32_t sync_sfn_cnt; uint32_t sync_sfn_cnt;
const static uint32_t SYNC_SFN_TIMEOUT = 200; const static uint32_t SYNC_SFN_TIMEOUT = 1000;
float ul_dl_factor; float ul_dl_factor;
int cur_earfcn_index; int cur_earfcn_index;
bool cell_search_in_progress; bool cell_search_in_progress;
@ -165,12 +166,16 @@ private:
float measure_rsrp; float measure_rsrp;
srslte_ue_dl_t ue_dl_measure; srslte_ue_dl_t ue_dl_measure;
const static int RSRP_MEASURE_NOF_FRAMES = 5; const static int RSRP_MEASURE_NOF_FRAMES = 10;
int cell_sync_sfn(); int cell_sync_sfn();
int cell_meas_rsrp(); int cell_meas_rsrp();
int cell_search(int force_N_id_2 = -1); int cell_search(int force_N_id_2 = -1);
bool set_cell(); bool set_cell();
float dl_freq;
float ul_freq;
}; };
} // namespace srsue } // namespace srsue

@ -151,6 +151,11 @@ private:
float cfo; float cfo;
bool rar_cqi_request; bool rar_cqi_request;
// Save last TBS for mcs>28 cases
int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS];
int last_ul_tbs[2*HARQ_DELAY_MS];
srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS];
// Metrics // Metrics
dl_metrics_t dl_metrics; dl_metrics_t dl_metrics;
ul_metrics_t ul_metrics; ul_metrics_t ul_metrics;

@ -76,6 +76,7 @@ public:
void write_trace(std::string filename); void write_trace(std::string filename);
void set_earfcn(std::vector<uint32_t> earfcns); void set_earfcn(std::vector<uint32_t> earfcns);
void force_freq(float dl_freq, float ul_freq);
/********** RRC INTERFACE ********************/ /********** RRC INTERFACE ********************/
void reset(); void reset();

@ -103,6 +103,7 @@ typedef struct {
}gui_args_t; }gui_args_t;
typedef struct { typedef struct {
std::string ip_netmask;
phy_args_t phy; phy_args_t phy;
float metrics_period_secs; float metrics_period_secs;
bool pregenerate_signals; bool pregenerate_signals;

@ -57,8 +57,13 @@ public:
// NAS interface // NAS interface
srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str); srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str);
void set_netmask(std::string netmask);
private: private:
bool default_netmask;
std::string netmask;
static const int GW_THREAD_PRIO = 7; static const int GW_THREAD_PRIO = 7;
pdcp_interface_gw *pdcp; pdcp_interface_gw *pdcp;

@ -98,6 +98,8 @@ private:
uint8_t transaction_id; uint8_t transaction_id;
bool drb_up; bool drb_up;
bool reestablishment_in_progress;
// timeouts in ms // timeouts in ms
uint32_t connecting_timeout; uint32_t connecting_timeout;
@ -244,6 +246,7 @@ private:
// Helpers // Helpers
void rrc_connection_release(); void rrc_connection_release();
void con_restablish_cell_reselected();
void radio_link_failure(); void radio_link_failure();
static void* start_sib_thread(void *rrc_); static void* start_sib_thread(void *rrc_);
void sib_search(); void sib_search();

@ -36,7 +36,7 @@
namespace srsue { namespace srsue {
demux::demux(uint8_t nof_harq_proc_) : mac_msg(20), pending_mac_msg(20), nof_harq_proc(nof_harq_proc_) demux::demux() : mac_msg(20), pending_mac_msg(20), rlc(NULL)
{ {
} }
@ -64,18 +64,18 @@ void demux::deallocate(uint8_t* payload_buffer_ptr)
pdus.deallocate(payload_buffer_ptr); pdus.deallocate(payload_buffer_ptr);
} }
} }
uint8_t* demux::request_buffer_bcch(uint32_t len)
uint8_t* demux::request_buffer(uint32_t pid, uint32_t len)
{ {
uint8_t *buff = NULL; if (len < MAX_BCCH_PDU_LEN) {
if (pid < nof_harq_proc) { return bcch_buffer;
return pdus.request(len);
} else if (pid == nof_harq_proc) {
buff = bcch_buffer;
} else { } else {
Error("Requested buffer for invalid PID=%d\n", pid); return NULL;
} }
return buff; }
uint8_t* demux::request_buffer(uint32_t len)
{
return pdus.request(len);
} }
/* Demultiplexing of MAC PDU associated with a Temporal C-RNTI. The PDU will /* Demultiplexing of MAC PDU associated with a Temporal C-RNTI. The PDU will
@ -117,21 +117,17 @@ void demux::push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes)
* This function enqueues the packet and returns quicly because ACK * This function enqueues the packet and returns quicly because ACK
* deadline is important here. * deadline is important here.
*/ */
void demux::push_pdu(uint32_t pid, uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) void demux::push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) {
{ return pdus.push(buff, nof_bytes, tstamp);
if (pid < nof_harq_proc) { }
return pdus.push(buff, nof_bytes, tstamp);
} else if (pid == nof_harq_proc) { /* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through
/* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through * the MAC in transparent mode.
* the MAC in transparent mode. * Warning: In this case function sends the message to RLC now, since SI blocks do not
* Warning: In this case function sends the message to RLC now, since SI blocks do not * require ACK feedback to be transmitted quickly.
* require ACK feedback to be transmitted quickly. */
*/ void demux::push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) {
Debug("Pushed BCCH MAC PDU in transparent mode\n"); rlc->write_pdu_bcch_dlsch(buff, nof_bytes);
rlc->write_pdu_bcch_dlsch(buff, nof_bytes);
} else {
Error("Pushed buffer for invalid PID=%d\n", pid);
}
} }
bool demux::process_pdus() bool demux::process_pdus()

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save