X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=blobdiff_plain;f=fhi_lib%2Flib%2Fsrc%2Fxran_timer.c;h=2bee2c3fa81ce04a66da2bf39d6bf890c6577313;hp=2390b7e3af3e728c2a5bede5c89ccb2fa198f64a;hb=2fbf70096f64af622da983e88c5a64e90ad9bdbd;hpb=9e108bb6d4caf2f6d4e920c640882fa49c15684c diff --git a/fhi_lib/lib/src/xran_timer.c b/fhi_lib/lib/src/xran_timer.c index 2390b7e..2bee2c3 100644 --- a/fhi_lib/lib/src/xran_timer.c +++ b/fhi_lib/lib/src/xran_timer.c @@ -1,276 +1,276 @@ -/****************************************************************************** -* -* Copyright (c) 2019 Intel. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -*******************************************************************************/ - -/** - * @brief This file provides implementation to Timing for XRAN. - * - * @file xran_timer.c - * @ingroup group_lte_source_xran - * @author Intel Corporation - * - **/ - -#include -#include -#include -#include - -#include "xran_timer.h" -#include "xran_printf.h" -#include "xran_mlog_lnx.h" -#include "xran_lib_mlog_tasks_id.h" -#include "ethdi.h" -#include "xran_fh_o_du.h" -#include "xran_common.h" - -#define NSEC_PER_SEC 1000000000L -#define NSEC_PER_USEC 1000L -#define THRESHOLD 35 /**< the avg cost of clock_gettime() in ns */ -#define TIMECOMPENSATION 2 /**< time compensation in us, avg latency of clock_nanosleep */ - -#define SEC_MOD_STOP (60) - -static struct timespec started_time; -static struct timespec last_time; -static struct timespec cur_time; - -static uint64_t curr_tick; -static uint64_t last_tick; - -static struct timespec* p_cur_time = &cur_time; -static struct timespec* p_last_time = &last_time; - - -static struct timespec* p_temp_time; - -static unsigned long current_second = 0; -static unsigned long started_second = 0; -static uint8_t numerlogy = 0; -extern uint32_t xran_lib_ota_sym; -extern uint32_t xran_lib_ota_tti; -extern uint32_t xran_lib_ota_sym_idx; - -static int debugStop = 0; -static int debugStopCount = 0; - -static long fine_tuning[5][2] = -{ - {71428L, 71429L}, /* mu = 0 */ - {35714L, 35715L}, /* mu = 1 */ - {0, 0}, /* mu = 2 not supported */ - {8928L, 8929L}, /* mu = 3 */ - {0,0 } /* mu = 4 not supported */ -}; - -static uint8_t slots_per_subframe[4] = -{ - 1, /* mu = 0 */ - 2, /* mu = 1 */ - 4, /* mu = 2 */ - 8, /* mu = 3 */ -}; - -uint64_t timing_get_current_second(void) -{ - return current_second; -} - -int timing_set_numerology(uint8_t value) -{ - numerlogy = value; - return numerlogy; -} - -int timing_set_debug_stop(int value, int count) -{ - debugStop = value; - debugStopCount = count; - - if(debugStop){ - clock_gettime(CLOCK_REALTIME, &started_time); - started_second =started_time.tv_sec; - } - return debugStop; -} - -int timing_get_debug_stop(void) -{ - return debugStop; -} - -void timing_adjust_gps_second(struct timespec* p_time) -{ - struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx(); - - long nsec = p_time->tv_nsec + p_xran_dev_ctx->offset_nsec; - p_time->tv_sec += p_xran_dev_ctx->offset_sec; - if (nsec >= 1e9) - { - nsec -=1e9; - p_time->tv_sec += 1; - } - p_time->tv_nsec = nsec; - - return; -} -uint64_t xran_tick(void) -{ - uint32_t hi, lo; - __asm volatile ("rdtsc" : "=a"(lo), "=d"(hi)); - return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 ); -} - -unsigned long get_ticks_diff(unsigned long curr_tick, unsigned long last_tick) -{ - if (curr_tick >= last_tick) - return (unsigned long)(curr_tick - last_tick); - else - return (unsigned long)(0xFFFFFFFFFFFFFFFF - last_tick + curr_tick); -} - -long poll_next_tick(long interval_ns, unsigned long *used_tick) -{ - struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx(); - long target_time; - long delta; - static int counter = 0; - static long sym_acc = 0; - static long sym_cnt = 0; - - if(counter == 0) { - clock_gettime(CLOCK_REALTIME, p_last_time); - last_tick = MLogTick(); - if(unlikely(p_xran_dev_ctx->offset_sec || p_xran_dev_ctx->offset_nsec)) - timing_adjust_gps_second(p_last_time); - current_second = p_last_time->tv_sec; - counter = 1; - } - - target_time = (p_last_time->tv_sec * NSEC_PER_SEC + p_last_time->tv_nsec + interval_ns); - - while(1) { - clock_gettime(CLOCK_REALTIME, p_cur_time); - curr_tick = MLogTick(); - if(unlikely(p_xran_dev_ctx->offset_sec || p_xran_dev_ctx->offset_nsec)) - timing_adjust_gps_second(p_cur_time); - delta = (p_cur_time->tv_sec * NSEC_PER_SEC + p_cur_time->tv_nsec) - target_time; - if(delta > 0 || (delta < 0 && abs(delta) < THRESHOLD)) { - if (debugStop &&(debugStopCount > 0) && (tx_counter >= debugStopCount)){ - uint64_t t1; - printf("STOP:[%ld.%09ld], debugStopCount %d, tx_counter %ld\n", p_cur_time->tv_sec, p_cur_time->tv_nsec, debugStopCount, tx_counter); - t1 = MLogTick(); - rte_pause(); - MLogTask(PID_TIME_SYSTIME_STOP, t1, MLogTick()); - xran_if_current_state = XRAN_STOPPED; - } - if(current_second != p_cur_time->tv_sec){ - current_second = p_cur_time->tv_sec; - xran_updateSfnSecStart(); - xran_lib_ota_sym_idx = 0; - xran_lib_ota_tti = 0; - xran_lib_ota_sym = 0; - sym_cnt = 0; - sym_acc = 0; - print_dbg("ToS:C Sync timestamp: [%ld.%09ld]\n", p_cur_time->tv_sec, p_cur_time->tv_nsec); - if(debugStop){ - if(p_cur_time->tv_sec > started_second && ((p_cur_time->tv_sec % SEC_MOD_STOP) == 0)){ - uint64_t t1; - printf("STOP:[%ld.%09ld]\n", p_cur_time->tv_sec, p_cur_time->tv_nsec); - t1 = MLogTick(); - rte_pause(); - MLogTask(PID_TIME_SYSTIME_STOP, t1, MLogTick()); - xran_if_current_state = XRAN_STOPPED; - } - } - p_cur_time->tv_nsec = 0; // adjust to 1pps - } else { - xran_lib_ota_sym_idx = XranIncrementSymIdx(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT*slots_per_subframe[numerlogy]); - /* adjust to sym boundary */ - if(sym_cnt & 1) - sym_acc += fine_tuning[numerlogy][0]; - else - sym_acc += fine_tuning[numerlogy][1]; - /* fine tune to second boundary */ - if(sym_cnt % 13 == 0) - sym_acc += 1; - - p_cur_time->tv_nsec = sym_acc; - sym_cnt++; - } - -#ifdef USE_PTP_TIME - if(debugStop && delta < interval_ns*10) - MLogTask(PID_TIME_SYSTIME_POLL, (p_last_time->tv_sec * NSEC_PER_SEC + p_last_time->tv_nsec), (p_cur_time->tv_sec * NSEC_PER_SEC + p_cur_time->tv_nsec)); -#else - MLogTask(PID_TIME_SYSTIME_POLL, last_tick, curr_tick); - last_tick = curr_tick; -#endif - - - p_temp_time = p_last_time; - p_last_time = p_cur_time; - p_cur_time = p_temp_time; - break; - } else { - if( likely(xran_if_current_state == XRAN_RUNNING)){ - uint64_t t1, t2; - t1 = xran_tick(); - - ring_processing_func(); - process_dpdk_io(); - - t2 = xran_tick(); - *used_tick += get_ticks_diff(t2, t1); - } - } - } - - return delta; -} - -long sleep_next_tick(long interval) -{ - struct timespec start_time; - struct timespec cur_time; - //struct timespec target_time_convert; - struct timespec sleep_target_time_convert; - long target_time; - long sleep_target_time; - long delta; - - clock_gettime(CLOCK_REALTIME, &start_time); - target_time = (start_time.tv_sec * NSEC_PER_SEC + start_time.tv_nsec + interval * NSEC_PER_USEC) / (interval * NSEC_PER_USEC) * interval; - //printf("target: %ld, current: %ld, %ld\n", target_time, start_time.tv_sec, start_time.tv_nsec); - sleep_target_time = target_time - TIMECOMPENSATION; - sleep_target_time_convert.tv_sec = sleep_target_time * NSEC_PER_USEC / NSEC_PER_SEC; - sleep_target_time_convert.tv_nsec = (sleep_target_time * NSEC_PER_USEC) % NSEC_PER_SEC; - - //target_time_convert.tv_sec = target_time * NSEC_PER_USEC / NSEC_PER_SEC; - //target_time_convert.tv_nsec = (target_time * NSEC_PER_USEC) % NSEC_PER_SEC; - - clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &sleep_target_time_convert, NULL); - - clock_gettime(CLOCK_REALTIME, &cur_time); - - delta = (cur_time.tv_sec * NSEC_PER_SEC + cur_time.tv_nsec) - target_time * NSEC_PER_USEC; - - return delta; -} - - - +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +/** + * @brief This file provides implementation to Timing for XRAN. + * + * @file xran_timer.c + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#include +#include +#include +#include + +#include "xran_timer.h" +#include "xran_printf.h" +#include "xran_mlog_lnx.h" +#include "xran_lib_mlog_tasks_id.h" +#include "ethdi.h" +#include "xran_fh_o_du.h" +#include "xran_common.h" + +#define NSEC_PER_SEC 1000000000L +#define NSEC_PER_USEC 1000L +#define THRESHOLD 35 /**< the avg cost of clock_gettime() in ns */ +#define TIMECOMPENSATION 2 /**< time compensation in us, avg latency of clock_nanosleep */ + +#define SEC_MOD_STOP (60) + +static struct timespec started_time; +static struct timespec last_time; +static struct timespec cur_time; + +static uint64_t curr_tick; +static uint64_t last_tick; + +static struct timespec* p_cur_time = &cur_time; +static struct timespec* p_last_time = &last_time; + + +static struct timespec* p_temp_time; + +static unsigned long current_second = 0; +static unsigned long started_second = 0; +static uint8_t numerlogy = 0; +extern uint32_t xran_lib_ota_sym; +extern uint32_t xran_lib_ota_tti; +extern uint32_t xran_lib_ota_sym_idx; + +static int debugStop = 0; +static int debugStopCount = 0; + +static long fine_tuning[5][2] = +{ + {71428L, 71429L}, /* mu = 0 */ + {35714L, 35715L}, /* mu = 1 */ + {0, 0}, /* mu = 2 not supported */ + {8928L, 8929L}, /* mu = 3 */ + {0,0 } /* mu = 4 not supported */ +}; + +static uint8_t slots_per_subframe[4] = +{ + 1, /* mu = 0 */ + 2, /* mu = 1 */ + 4, /* mu = 2 */ + 8, /* mu = 3 */ +}; + +uint64_t timing_get_current_second(void) +{ + return current_second; +} + +int timing_set_numerology(uint8_t value) +{ + numerlogy = value; + return numerlogy; +} + +int timing_set_debug_stop(int value, int count) +{ + debugStop = value; + debugStopCount = count; + + if(debugStop){ + clock_gettime(CLOCK_REALTIME, &started_time); + started_second =started_time.tv_sec; + } + return debugStop; +} + +int timing_get_debug_stop(void) +{ + return debugStop; +} + +void timing_adjust_gps_second(struct timespec* p_time) +{ + struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx(); + + long nsec = p_time->tv_nsec + p_xran_dev_ctx->offset_nsec; + p_time->tv_sec += p_xran_dev_ctx->offset_sec; + if (nsec >= 1e9) + { + nsec -=1e9; + p_time->tv_sec += 1; + } + p_time->tv_nsec = nsec; + + return; +} +uint64_t xran_tick(void) +{ + uint32_t hi, lo; + __asm volatile ("rdtsc" : "=a"(lo), "=d"(hi)); + return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 ); +} + +unsigned long get_ticks_diff(unsigned long curr_tick, unsigned long last_tick) +{ + if (curr_tick >= last_tick) + return (unsigned long)(curr_tick - last_tick); + else + return (unsigned long)(0xFFFFFFFFFFFFFFFF - last_tick + curr_tick); +} + +long poll_next_tick(long interval_ns, unsigned long *used_tick) +{ + struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx(); + long target_time; + long delta; + static int counter = 0; + static long sym_acc = 0; + static long sym_cnt = 0; + + if(counter == 0) { + clock_gettime(CLOCK_REALTIME, p_last_time); + last_tick = MLogTick(); + if(unlikely(p_xran_dev_ctx->offset_sec || p_xran_dev_ctx->offset_nsec)) + timing_adjust_gps_second(p_last_time); + current_second = p_last_time->tv_sec; + counter = 1; + } + + target_time = (p_last_time->tv_sec * NSEC_PER_SEC + p_last_time->tv_nsec + interval_ns); + + while(1) { + clock_gettime(CLOCK_REALTIME, p_cur_time); + curr_tick = MLogTick(); + if(unlikely(p_xran_dev_ctx->offset_sec || p_xran_dev_ctx->offset_nsec)) + timing_adjust_gps_second(p_cur_time); + delta = (p_cur_time->tv_sec * NSEC_PER_SEC + p_cur_time->tv_nsec) - target_time; + if(delta > 0 || (delta < 0 && abs(delta) < THRESHOLD)) { + if (debugStop &&(debugStopCount > 0) && (tx_counter >= debugStopCount)){ + uint64_t t1; + printf("STOP:[%ld.%09ld], debugStopCount %d, tx_counter %ld\n", p_cur_time->tv_sec, p_cur_time->tv_nsec, debugStopCount, tx_counter); + t1 = MLogTick(); + rte_pause(); + MLogTask(PID_TIME_SYSTIME_STOP, t1, MLogTick()); + xran_if_current_state = XRAN_STOPPED; + } + if(current_second != p_cur_time->tv_sec){ + current_second = p_cur_time->tv_sec; + xran_updateSfnSecStart(); + xran_lib_ota_sym_idx = 0; + xran_lib_ota_tti = 0; + xran_lib_ota_sym = 0; + sym_cnt = 0; + sym_acc = 0; + print_dbg("ToS:C Sync timestamp: [%ld.%09ld]\n", p_cur_time->tv_sec, p_cur_time->tv_nsec); + if(debugStop){ + if(p_cur_time->tv_sec > started_second && ((p_cur_time->tv_sec % SEC_MOD_STOP) == 0)){ + uint64_t t1; + printf("STOP:[%ld.%09ld]\n", p_cur_time->tv_sec, p_cur_time->tv_nsec); + t1 = MLogTick(); + rte_pause(); + MLogTask(PID_TIME_SYSTIME_STOP, t1, MLogTick()); + xran_if_current_state = XRAN_STOPPED; + } + } + p_cur_time->tv_nsec = 0; // adjust to 1pps + } else { + xran_lib_ota_sym_idx = XranIncrementSymIdx(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT*slots_per_subframe[numerlogy]); + /* adjust to sym boundary */ + if(sym_cnt & 1) + sym_acc += fine_tuning[numerlogy][0]; + else + sym_acc += fine_tuning[numerlogy][1]; + /* fine tune to second boundary */ + if(sym_cnt % 13 == 0) + sym_acc += 1; + + p_cur_time->tv_nsec = sym_acc; + sym_cnt++; + } + +#ifdef USE_PTP_TIME + if(debugStop && delta < interval_ns*10) + MLogTask(PID_TIME_SYSTIME_POLL, (p_last_time->tv_sec * NSEC_PER_SEC + p_last_time->tv_nsec), (p_cur_time->tv_sec * NSEC_PER_SEC + p_cur_time->tv_nsec)); +#else + MLogTask(PID_TIME_SYSTIME_POLL, last_tick, curr_tick); + last_tick = curr_tick; +#endif + + + p_temp_time = p_last_time; + p_last_time = p_cur_time; + p_cur_time = p_temp_time; + break; + } else { + if( likely(xran_if_current_state == XRAN_RUNNING)){ + uint64_t t1, t2; + t1 = xran_tick(); + + ring_processing_func(); + process_dpdk_io(); + + t2 = xran_tick(); + *used_tick += get_ticks_diff(t2, t1); + } + } + } + + return delta; +} + +long sleep_next_tick(long interval) +{ + struct timespec start_time; + struct timespec cur_time; + //struct timespec target_time_convert; + struct timespec sleep_target_time_convert; + long target_time; + long sleep_target_time; + long delta; + + clock_gettime(CLOCK_REALTIME, &start_time); + target_time = (start_time.tv_sec * NSEC_PER_SEC + start_time.tv_nsec + interval * NSEC_PER_USEC) / (interval * NSEC_PER_USEC) * interval; + //printf("target: %ld, current: %ld, %ld\n", target_time, start_time.tv_sec, start_time.tv_nsec); + sleep_target_time = target_time - TIMECOMPENSATION; + sleep_target_time_convert.tv_sec = sleep_target_time * NSEC_PER_USEC / NSEC_PER_SEC; + sleep_target_time_convert.tv_nsec = (sleep_target_time * NSEC_PER_USEC) % NSEC_PER_SEC; + + //target_time_convert.tv_sec = target_time * NSEC_PER_USEC / NSEC_PER_SEC; + //target_time_convert.tv_nsec = (target_time * NSEC_PER_USEC) % NSEC_PER_SEC; + + clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &sleep_target_time_convert, NULL); + + clock_gettime(CLOCK_REALTIME, &cur_time); + + delta = (cur_time.tv_sec * NSEC_PER_SEC + cur_time.tv_nsec) - target_time * NSEC_PER_USEC; + + return delta; +} + + +