Commit aea3aa29 authored by Pietro Fezzardi's avatar Pietro Fezzardi Committed by Alessandro Rubini

time-sim: added time operations

They're designed to be used for both the instances, master and slave.
This is possible because the new data structure pp_sim_time_instance
holding all the information about the time of a single instance is
placed inside the ppi arch_data
parent 44e73697
......@@ -4,6 +4,22 @@
* Released to the public domain
*/
/*
* This structure represents a clock abstraction. You can use it to
* have different pp_instances with different notions of time.
* When you try to get the time the sim_get_time function is performing the
* calculations needed to convert the raw data from the "real" clock to the
* timescale of the simulated one.
* When you set the time you're not actually setting it in the hardware but
* only in the parameters in this structure.
*/
struct pp_sim_time_instance {
int64_t current_ns; // with nsecs it's enough for ~300 years
int64_t freq_ppm_real; // drift of the simulated hw clock
int64_t freq_ppm_servo; // drift applied from servo to correct the hw
// Future parameters can be added
};
/*
* This structure holds the lowest timeout of all the state machines in the
* ppg, namely the master and slave state machines in the simulator. All the
......@@ -19,4 +35,20 @@ static inline struct sim_ppg_arch_data *SIM_PPG_ARCH(struct pp_globals *ppg)
return (struct sim_ppg_arch_data *)(ppg->arch_data);
}
/*
* Structure holding parameters and informations restricted to just a single
* instance, like timing informations. Infact in the simulator, even if both
* master and slave are ppi inside the same ppg, they act like every one of
* them had its own clock.
* More stuff can be added here in the future if necessary
*/
struct sim_ppi_arch_data {
struct pp_sim_time_instance time;
};
static inline struct sim_ppi_arch_data *SIM_PPI_ARCH(struct pp_instance *ppi)
{
return (struct sim_ppi_arch_data *)(ppi->arch_data);
}
extern void sim_main_loop(struct pp_globals *ppg);
/*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Pietro Fezzardi (pietrofezzardi@gmail.com)
*
* Released to the public domain
*/
/*
* Time operations for the simulator, design to be used both for
* master and the slave instance.
*/
#include <time.h>
#include <errno.h>
#include <ppsi/ppsi.h>
#include "../arch-sim/ppsi-sim.h"
static int sim_time_get(struct pp_instance *ppi, TimeInternal *t)
{
struct timespec ts;
ts.tv_nsec = SIM_PPI_ARCH(ppi)->time.current_ns %
(long long)PP_NSEC_PER_SEC;
ts.tv_sec = (SIM_PPI_ARCH(ppi)->time.current_ns - ts.tv_nsec) /
(long long)PP_NSEC_PER_SEC;
t->nanoseconds = ts.tv_nsec;
t->seconds = ts.tv_sec;
t->correct = 1;
if (!(pp_global_flags & PP_FLAG_NOTIMELOG))
pp_diag(ppi, time, 2, "%s: %9li.%09li\n", __func__,
(long)t->seconds, (long)t->nanoseconds);
return 0;
}
static int sim_time_set(struct pp_instance *ppi, TimeInternal *t)
{
if (!t) {
/* Change the network notion of utc/tai offset */
return 0;
}
SIM_PPI_ARCH(ppi)->time.current_ns = t->nanoseconds
+ t->seconds * (long long)PP_NSEC_PER_SEC;
pp_diag(ppi, time, 1, "%s: %9i.%09i\n", __func__,
t->seconds, t->nanoseconds);
return 0;
}
static int sim_time_adjust(struct pp_instance *ppi, long offset_ns,
long freq_ppm)
{
if (freq_ppm) {
if (freq_ppm > PP_ADJ_FREQ_MAX)
freq_ppm = PP_ADJ_FREQ_MAX;
if (freq_ppm < -PP_ADJ_FREQ_MAX)
freq_ppm = -PP_ADJ_FREQ_MAX;
SIM_PPI_ARCH(ppi)->time.freq_ppm_servo = freq_ppm;
}
if (offset_ns)
SIM_PPI_ARCH(ppi)->time.current_ns += offset_ns;
pp_diag(ppi, time, 1, "%s: %li %li\n", __func__, offset_ns, freq_ppm);
return 0;
}
static int sim_adjust_freq(struct pp_instance *ppi, long freq_ppm)
{
return sim_time_adjust(ppi, 0, freq_ppm);
}
static int sim_adjust_offset(struct pp_instance *ppi, long offset_ns)
{
return sim_time_adjust(ppi, offset_ns, 0);
}
static inline int sim_init_servo(struct pp_instance *ppi)
{
return SIM_PPI_ARCH(ppi)->time.freq_ppm_servo;
}
static unsigned long sim_calc_timeout(struct pp_instance *ppi, int millisec)
{
unsigned long res;
res = millisec + SIM_PPI_ARCH(ppi)->time.current_ns / 1000LL / 1000LL;
return res ? res : 1;
}
struct pp_time_operations sim_time_ops = {
.get = sim_time_get,
.set = sim_time_set,
.adjust = sim_time_adjust,
.adjust_offset = sim_adjust_offset,
.adjust_freq = sim_adjust_freq,
.init_servo = sim_init_servo,
.calc_timeout = sim_calc_timeout,
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment