mirror of
https://github.com/nasa/trick.git
synced 2024-12-18 20:57:55 +00:00
Remove deprecated Clocks and unit tests, and update Trick::Clock documentation. #87
This commit is contained in:
parent
0e0f4f4365
commit
6df675c7ee
@ -1,170 +1,199 @@
|
||||
# Realtime-Clock
|
||||
|
||||
A realtime clock is an optional feature for Trick simulations.
|
||||
**Contents**
|
||||
|
||||
The Trick::Clock base class provides Trick with a consistent interface to different
|
||||
realtime clocks. The base class provides a common set of routines called by
|
||||
Trick::RealtimeSync to get and reset the realtime clock.
|
||||
* [Creating a Real-Time Clock Interface with Trick::Clock](#creating-a-clock)<br>
|
||||
* [Installing a Trick::Clock In Your Simulation](#installing-a-clock)<br>
|
||||
* [Example Implementation of a Trick::Clock](#example-implemntation)<br>
|
||||
|
||||
Trick provides built in support for using the system clock (Trick::GetTimeOfDayClock).
|
||||
***
|
||||
|
||||
Trick also provides built in support for using Spectracom's TPRO IRIG-B clock board,
|
||||
also referred as a Central Timing Equipment (CTE) board. TPRO CTE support is off
|
||||
by default. To enable TPRO CTE support Trick must be built with TPRO driver support.
|
||||
Go to http://www.spectracomcorp.com for driver support for your particular board.
|
||||
To enable TPRO CTE support, run ${TRICK_HOME/configure --tprocte=/paht/to/tpropci.
|
||||
Recompile Trick after the configure script.
|
||||
* [**Looking For The Current Simulation Time?**](#looking-for-sim-time)<br>
|
||||
|
||||
### Creating a User Defined Real-Time Clock
|
||||
***
|
||||
|
||||
Clocks may be created by users. To create a new clock, the class must inherit from
|
||||
the Trick::Clock. Trick::Clock is an abstract class with several methods for the user
|
||||
to implement. These methods provide the hardware specific code to initalize, access, and
|
||||
shutdown clock hardware. See [${TRICK_HOME}/trick_source/sim_services/Clock](../blob/master/trick_source/sim_services/Clock) for examples
|
||||
to how we implemented the GettimeofDay and the TPRO_CTE clock. This is the list of
|
||||
routines that must be implemented by the user:
|
||||
Every real-time simulation requires a clock to which its tasks can be synchronized. By default, a Trick simulation uses the local system clock, by calling *gettimeofday()*. When simulations running on different computers need to cooperate they need to be synchronized to the same clock. So, sometimes we want our simulation to synchronize a to an **external** clock rather than the local one. The ```Trick::Clock``` base class provides a way to create an interface between an external time source, and a real-time Trick simulation.
|
||||
|
||||
##### Trick::Clock::clock_init()
|
||||
<a id=creating-a-clock></a>
|
||||
## Creating a Real-Time Clock Interface with Trick::Clock
|
||||
|
||||
Opens the clock hardware, initializes the clock, etc.
|
||||
The Trick::Clock class is declared in ```trick/Clock.hh```. Deriving a new clock interface class from it requires the following three member functions to be implemented.
|
||||
|
||||
##### Trick::Clock::wall_clock_time()
|
||||
|
||||
Gets the wall clock time. Returns the time in integer number of tics of 1us.
|
||||
|
||||
##### Trick::Clock::clock_spin(long long req_time)
|
||||
|
||||
Waits for real-time to catch up to the requested simulation time. Polling or waiting
|
||||
for an interrupt are typical methods for spinning.
|
||||
|
||||
##### Trick::Clock::clock_stop()
|
||||
|
||||
Shuts down clock hardware, closes devices, etc.
|
||||
|
||||
### Specifying the Real-Time Clock
|
||||
|
||||
Trick instantiates an instance of the Trick::GetTimeOfDayClock by default.
|
||||
Trick includes a realtime clock based on a TPRO timing card. TPRO support must be enabled when compiling Trick core. A Trick::TPROCTEClock class may be included in an S_define file with <code>##include "sim_objects/TPROClock.sm"</code>.
|
||||
|
||||
Trick defaults to the Trick::GetTimeOfDay clock. To switch to the TPRO CTE clock
|
||||
or a user defined clock use the following line in the Python input file.
|
||||
***
|
||||
|
||||
```c
|
||||
int Trick::Clock::clock_init();
|
||||
```
|
||||
# Changes to the TPRO CTE clock
|
||||
trick.real_time_change_clock(trick_tpro.tpro_cte)
|
||||
# Changes to a user defined clock
|
||||
trick.real_time_change_clock(<user defined clock>)
|
||||
#### 1. clock\_init's Responsibilities
|
||||
1. If necessary, initialize the time source. This may involve opening and initializing a hardware device, or a network socket connection.
|
||||
2. If an error occurs, return a non-zero error code, otherwise call ```set_global_clock()``` and return 0.
|
||||
|
||||
***
|
||||
|
||||
```c
|
||||
long long Trick::Clock::wall_clock_time()
|
||||
```
|
||||
#### 2. wall\_clock\_time's Responsibilities
|
||||
1. Get the time from the time source.
|
||||
2. Return the time in microseconds, or 0 if there **is** an error.
|
||||
|
||||
***
|
||||
|
||||
```c
|
||||
int Trick::Clock::clock_stop()
|
||||
```
|
||||
#### 3. clock_stop's Responsibilities
|
||||
1. If necessary, disconnect from the time source.
|
||||
2. If an error occurs, return a non-zero error code, otherwise return 0.
|
||||
|
||||
***
|
||||
|
||||
<a id=installing-a-clock></a>
|
||||
|
||||
## Installing a Trick::Clock In Your Simulation
|
||||
|
||||
By default, Trick uses a derivative of ```Trick::Clock``` called ```Trick::GetTimeOfDayClock```.
|
||||
|
||||
Suppose we've derived a new class ```CuckooClock``` from ```Trick::Clock```, and have created an instance of it:
|
||||
|
||||
```c
|
||||
chalet.my_clock = new CuckooClock();
|
||||
```
|
||||
|
||||
### Accessing the Real-Time Clock
|
||||
|
||||
Typically, users will not have to access the real-time clock directly, the
|
||||
Trick::RealtimeSync uses the real time clock to synchronize to real time. However
|
||||
there are several user accessible routines to control the clock and get the status.
|
||||
In our simulation's S_define file, we could change the real-time scheduler's clock from the default ```Trick::GetTimeOfDayClock``` to our new ```CuckooClock``` using ```real_time_change_clock()```, declared in ```trick/realtimesync_proto.h```.
|
||||
|
||||
```c
|
||||
void create_connections() {
|
||||
chalet.my_clock = new CuckooClock();
|
||||
real_time_change_clock(chalet.my_clock);
|
||||
}
|
||||
```
|
||||
#include "trick_source/sim_services/Clock/include/clock_proto.h" for these routines
|
||||
We could also change the ```Trick::Clock``` in our input file as follows:
|
||||
|
||||
```c
|
||||
trick.real_time_change_clock(chalet.my_clock)
|
||||
```
|
||||
|
||||
#### Clock Time
|
||||
<a id=example-implemntation></a>
|
||||
## An Example Implementation of a Trick::Clock
|
||||
|
||||
```
|
||||
long long clock_time() ;
|
||||
The following code is an example implementation of a Trick::Clock, called TPROCTEClock. It provides an interface between Trick's real-time job scheduler and Spectracom's TPRO IRIG-B clock board. This is one of many available time sources that one might use. Note that driver support for timing cards, like the "tpro.h" and "tsync.h" files below, must be acquired from the card's vendor.
|
||||
|
||||
<a id=listing_1_Clock-header-file></a>
|
||||
### TPROCTEClock Header File
|
||||
```c
|
||||
/*
|
||||
PURPOSE: ( TPRO CTE Clock )
|
||||
*/
|
||||
#ifndef TPROCTECLOCK_HH
|
||||
#define TPROCTECLOCK_HH
|
||||
#include <string>
|
||||
#include "trick/Clock.hh"
|
||||
#ifdef _TPRO_CTE
|
||||
extern "C" {
|
||||
#include "tpro.h"
|
||||
#include "tsync.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
class TPROCTEClock : public Trick::Clock {
|
||||
public:
|
||||
TPROCTEClock() ;
|
||||
~TPROCTEClock() ;
|
||||
int clock_init() ;
|
||||
long long wall_clock_time() ;
|
||||
int clock_stop() ;
|
||||
std::string dev_name ;
|
||||
private:
|
||||
#ifdef _TPRO_CTE
|
||||
TPRO_BoardObj *pBoard ; /* ** board handle */
|
||||
#endif
|
||||
} ;
|
||||
#endif
|
||||
```
|
||||
|
||||
```
|
||||
# Python access
|
||||
trick.clock_time()
|
||||
<a id=listing_2_clock-init></a>
|
||||
### TPROCTEClock::clock_init
|
||||
|
||||
Here, we initialize the timing card by opening the device file, getting a device handle. Then we wait for for it to be available. If an error occurs, return a non-zero error code, otherwise we call ```set_global_clock()``` and return 0.
|
||||
|
||||
```c
|
||||
int TPROCTEClock::clock_init() {
|
||||
#ifdef _TPRO_CTE
|
||||
unsigned char rv;
|
||||
/* Open the TPRO/TSAT device */
|
||||
rv = TPRO_open(&pBoard, (char *)dev_name.c_str());
|
||||
/* If unable to open the TPRO/TSAT device... */
|
||||
if (rv != TPRO_SUCCESS) {
|
||||
printf (" Could Not Open '%s'!! [%d]\n", dev_name.c_str(), rv);
|
||||
return (1);
|
||||
}
|
||||
/* Wait until this handle is the first user of the device. */
|
||||
if (TPRO_setPropDelayCorr(pBoard, NULL) != TPRO_SUCCESS) {
|
||||
printf(" Waiting to become first user...\n");
|
||||
while (TPRO_setPropDelayCorr(pBoard, NULL) != TPRO_SUCCESS);
|
||||
}
|
||||
set_global_clock() ;
|
||||
return 0 ;
|
||||
#else
|
||||
printf("ERROR: Not configured for TPRO CTE card.");
|
||||
return -1 ;
|
||||
#endif
|
||||
}
|
||||
```
|
||||
|
||||
Gives you real-time referenced from simulation start. The returned value is in tics.
|
||||
A tic is set amount of time, set by the Trick::Executive, usually 1us.
|
||||
### TPROCTEClock::wall\_clock\_time
|
||||
In this function, we get the time from the timing card, and convert it to microseconds before returning it. If the attempt to get the time fails, we return 0.
|
||||
|
||||
#### Wall Clock Time
|
||||
|
||||
```
|
||||
long long wall_clock_time() ;
|
||||
```c
|
||||
long long TPROCTEClock::wall_clock_time() {
|
||||
#ifdef _TPRO_CTE
|
||||
TSYNC_HWTimeSecondsObj hwTime;
|
||||
/* Send Get Seconds Time message */
|
||||
TSYNC_ERROR err = TSYNC_HW_getTimeSec(pBoard, &hwTime);
|
||||
if (err != TSYNC_SUCCESS) {
|
||||
printf(" Error: %s.\n", tsync_strerror(err));
|
||||
return 0;
|
||||
}
|
||||
/* If sucessful convert the TPRO time to microsconds. */.
|
||||
return hwTime.time.seconds * 1000000LL + (hwTime.time.ns /1000);
|
||||
#else
|
||||
printf("ERROR: Not configured for TPRO CTE card.");
|
||||
return 0 ;
|
||||
#endif
|
||||
}
|
||||
```
|
||||
|
||||
### TPROCTEClock::clock\_stop
|
||||
|
||||
This function simply closes the handle to the device, and returns 0.
|
||||
|
||||
```c
|
||||
int TPROCTEClock::clock_stop() {
|
||||
#ifdef _TPRO_CTE
|
||||
unsigned char rv ;
|
||||
rv = TPRO_close(pBoard);
|
||||
/* If unable to close the TPRO/TSAT device... */
|
||||
if (rv != TPRO_SUCCESS) {
|
||||
printf (" Could Not Close Board!! [%d]\n", rv);
|
||||
}
|
||||
#endif
|
||||
return 0 ;
|
||||
}
|
||||
```
|
||||
# Python access
|
||||
trick.wall_clock_time()
|
||||
<a id=looking-for-sim-time></a>
|
||||
## Looking For The Current Simulation Time ?
|
||||
|
||||
Trick::Clock is a class for creating interfaces between timing hardware, or other time sources and Trick's realtime synchronization subsystem. It does not maintain the simulation time. That's maintained by the Trick Executive.
|
||||
|
||||
What you may be looking for is the function
|
||||
|
||||
```c
|
||||
double exec_get_sim_time(void) ;
|
||||
```
|
||||
|
||||
Gives you the actual time from the clock. The returned value is in tics
|
||||
A tic is set amount of time, set by the Trick::Executive, usually 1us.
|
||||
|
||||
#### Clock Spin
|
||||
|
||||
```
|
||||
int clock_spin(long long ref) ;
|
||||
```
|
||||
defined in ```exec_proto.h```.
|
||||
|
||||
|
||||
```
|
||||
# Python access
|
||||
trick.clock_spin(<ref_time>)
|
||||
```
|
||||
|
||||
Calling clock spin will cause the simulation to enter a loop and wait until
|
||||
realtime catches up to simulation time. This is not typically called by
|
||||
users.
|
||||
|
||||
#### Reset Clock Reference
|
||||
|
||||
```
|
||||
long long clock_reset(long long ref) ;
|
||||
```
|
||||
|
||||
```
|
||||
# Python access
|
||||
trick.clock_reset(<ref_time>)
|
||||
```
|
||||
|
||||
Resetting the clock synchronizes the "reference" time to the real-time clock.
|
||||
The reference time is typically the current simulation time.
|
||||
|
||||
#### Manually Setting Clock Reference
|
||||
|
||||
```
|
||||
int clock_set_reference(long long wall_clock_time) ;
|
||||
```
|
||||
|
||||
```
|
||||
# Python access
|
||||
trick.clock_set_reference(<wall_clock_time>)
|
||||
```
|
||||
|
||||
This manually synchronizes the clock's reference to the incoming wall clock time.
|
||||
This routine is used internally to synchronize the simulation time to a whole
|
||||
second multiple of the real time clock.
|
||||
|
||||
#### Getting the Clock Ratio
|
||||
|
||||
```
|
||||
double clock_get_rt_clock_ratio() ;
|
||||
```
|
||||
|
||||
```
|
||||
# Python access
|
||||
trick.clock_get_rt_clock_ratio()
|
||||
```
|
||||
|
||||
The realtime clock has the ability to run at a ratio to realtime. This routine
|
||||
gets the current set ratio.
|
||||
|
||||
#### Setting the Clock Ratio
|
||||
|
||||
```
|
||||
int clock_set_rt_clock_ratio(double in_rt_clock_ratio) ;
|
||||
```
|
||||
|
||||
```
|
||||
# Python access
|
||||
trick.clock_set_rt_clock_ratio()
|
||||
```
|
||||
|
||||
The realtime clock has the ability to run at a ratio to realtime. This routine
|
||||
sets the current set ratio. A simulation may not be able to run fast enough to
|
||||
honor the set ratio. In this case the simulation will run as fast as possible.
|
||||
|
||||
[Continue to Realtime Timer](Realtime-Timer)
|
||||
|
@ -1,16 +0,0 @@
|
||||
|
||||
#ifndef BC635CLOCK_SM
|
||||
#define BC635CLOCK_SM
|
||||
|
||||
##include "trick/BC635Clock.hh"
|
||||
|
||||
class BC635SimObject : public Trick::SimObject {
|
||||
public:
|
||||
Trick::BC635Clock bc635 ;
|
||||
BC635SimObject() { }
|
||||
}
|
||||
|
||||
BC635SimObject trick_bc635 ;
|
||||
|
||||
#endif
|
||||
|
@ -1,16 +0,0 @@
|
||||
|
||||
#ifndef TPROCLOCK_SM
|
||||
#define TPROCLOCK_SM
|
||||
|
||||
##include "trick/TPROCTEClock.hh"
|
||||
|
||||
class TPROSimObject : public Trick::SimObject {
|
||||
public:
|
||||
Trick::TPROCTEClock tpro_cte ;
|
||||
TPROSimObject() { }
|
||||
}
|
||||
|
||||
TPROSimObject trick_tpro ;
|
||||
|
||||
#endif
|
||||
|
@ -1,171 +0,0 @@
|
||||
/*
|
||||
PURPOSE:
|
||||
( gettimeofday clock )
|
||||
PROGRAMMERS:
|
||||
(((Alex Lin) (NASA) (Feb 2012) (--) (--)))
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "trick/BC635Clock.hh"
|
||||
#include "trick/message_proto.h"
|
||||
#include "trick/message_type.h"
|
||||
#include "trick/release.h"
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Calls the base Clock constructor
|
||||
-# Sets the default device name
|
||||
*/
|
||||
Trick::BC635Clock::BC635Clock() : Clock(1000000, "BC635") {
|
||||
#ifdef _BC635
|
||||
mode = MODE_FREE ;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# This function is empty
|
||||
*/
|
||||
Trick::BC635Clock::~BC635Clock() { }
|
||||
|
||||
void Trick::BC635Clock::set_mode(unsigned int in_mode) {
|
||||
mode = in_mode ;
|
||||
}
|
||||
|
||||
unsigned int Trick::BC635Clock::get_mode() {
|
||||
return mode ;
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Opens the BC635 device
|
||||
-# Returns error if unable to open device
|
||||
-# Waits to be first user.
|
||||
*/
|
||||
int Trick::BC635Clock::clock_init() {
|
||||
#ifdef _BC635
|
||||
h_bc635 = bcStartPci();
|
||||
|
||||
if ( !h_bc635 ) {
|
||||
message_publish( MSG_ERROR, "%s:%s:%d: Error on bcStartPci. Can't open Symmetricom BC635 PCI card.",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
/* We have to use binary time in order to get sub-second time data */
|
||||
if ( bcSetTimeFormat( h_bc635, FORMAT_BINARY ) == FALSE ) {
|
||||
message_publish( MSG_ERROR, "bcSetTimeFormat failed" );
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* Set the clock source to internal.. we're not using an external oscillator */
|
||||
if ( bcSetClkSrc( h_bc635, CLK_INT) == FALSE ) {
|
||||
message_publish( MSG_ERROR, "bcSetClkSrc failed to set the clock source to internal" );
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* Sync the RTC to External Time Data */
|
||||
if ( bcSyncRtc( h_bc635 ) == FALSE ) {
|
||||
message_publish( MSG_ERROR, "bcSyncRtc failed to set the RTC to External Time Data" );
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* Set the mode, e.g. to read input time codes, or freewheel */
|
||||
/* (Note: This function returns void, so can't do error checking) */
|
||||
bcSetMode( h_bc635, mode );
|
||||
|
||||
// Set local time offset to 0 (so we use GMT)
|
||||
bcSetLocalOffsetFlag( h_bc635, LOCAL_OFF_DISABLE );
|
||||
|
||||
if ( bcSetGenCode( h_bc635, TCODE_IRIG_B ) == FALSE ) {
|
||||
message_publish( MSG_ERROR, "bcSetGenCode failed to set output format to IRIG-B" );
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* IRIG B002, B122 (BCD) */
|
||||
if ( bcSetGenCodeEx( h_bc635, TCODE_IRIG_B, TCODE_IRIG_SUBTYPE_2 ) == FALSE ) {
|
||||
message_publish( MSG_ERROR, "bcSetGenCodeEx failed to set output format to IRIG-B" );
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* Set output frequency to 10Mhz */
|
||||
DWORD ctlreg;
|
||||
if ( bcReadReg( h_bc635, PCI_CONTROL_OFFSET, &ctlreg ) == FALSE ) {
|
||||
message_publish( MSG_ERROR, "bcReadReg failed" );
|
||||
return -1 ;
|
||||
}
|
||||
ctlreg &= 0x3F;
|
||||
if ( bcWriteReg( h_bc635, PCI_CONTROL_OFFSET, ctlreg ) == FALSE ) {
|
||||
message_publish( MSG_ERROR, "bcWriteReg failed" );
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
set_global_clock() ;
|
||||
|
||||
return 0 ;
|
||||
#else
|
||||
message_publish(MSG_ERROR, "BC635 card was not enabled when Trick was compiled.\n\
|
||||
Please run ${TRICK_HOME}/configure --bc635=<directory holding CTE>, and recompile Trick\n");
|
||||
return -1 ;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Gets the BC635 time.
|
||||
-# If sucessful convert the BC635 time to tics
|
||||
*/
|
||||
long long Trick::BC635Clock::wall_clock_time() {
|
||||
#ifdef _BC635
|
||||
BOOL ret ;
|
||||
DWORD ulpMaj, ulpMin ;
|
||||
WORD ulpNano;
|
||||
BYTE stat ;
|
||||
long long curr_time ;
|
||||
|
||||
ret = bcReadBinTimeEx( h_bc635, &ulpMaj, &ulpMin, &ulpNano, &stat) ;
|
||||
|
||||
if ( ret == FALSE ) {
|
||||
message_publish(MSG_ERROR, "Could not retrieve time from BC635\n") ;
|
||||
} else {
|
||||
// I believe that ulpMaj = num seconds and ulpMin is num microseconds. How convenient.
|
||||
curr_time = (long long)ulpMaj * 1000000LL + ulpMin ;
|
||||
}
|
||||
|
||||
return (curr_time);
|
||||
#else
|
||||
message_publish(MSG_ERROR, "BC635 card was not enabled at compile time\n");
|
||||
return 0 ;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Get the current real time.
|
||||
-# While the current real time is less than the requested time
|
||||
-# Release the processor momentarily
|
||||
-# Get the current real time.
|
||||
*/
|
||||
long long Trick::BC635Clock::clock_spin(long long req_time) {
|
||||
#ifdef _BC635
|
||||
Trick::Clock::clock_spin(req_time) ;
|
||||
#else
|
||||
message_publish(MSG_ERROR, "BC635 card was not enabled at compile time\n");
|
||||
return req_time ;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# This function is empty
|
||||
*/
|
||||
int Trick::BC635Clock::clock_stop() {
|
||||
#ifdef _BC635
|
||||
// Don't do this because exec_terminate reads the time
|
||||
//bcStopPci( h_bc635 );
|
||||
#endif
|
||||
return 0 ;
|
||||
}
|
||||
|
@ -1,119 +0,0 @@
|
||||
/*
|
||||
PURPOSE:
|
||||
( gettimeofday clock )
|
||||
PROGRAMMERS:
|
||||
(((Alex Lin) (NASA) (Feb 2012) (--) (--)))
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "trick/TPROCTEClock.hh"
|
||||
#include "trick/message_proto.h"
|
||||
#include "trick/message_type.h"
|
||||
#include "trick/release.h"
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Calls the base Clock constructor
|
||||
-# Sets the default device name
|
||||
*/
|
||||
Trick::TPROCTEClock::TPROCTEClock() : Clock(1000000, "TPROCTE") , dev_name("/dev/tsyncpci0") { }
|
||||
|
||||
/**
|
||||
@details
|
||||
-# This function is empty
|
||||
*/
|
||||
Trick::TPROCTEClock::~TPROCTEClock() { }
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Opens the TPRO device
|
||||
-# Returns error if unable to open device
|
||||
-# Waits to be first user.
|
||||
*/
|
||||
int Trick::TPROCTEClock::clock_init() {
|
||||
#ifdef _TPRO_CTE
|
||||
unsigned char rv;
|
||||
|
||||
/* Open the TPRO/TSAT device */
|
||||
rv = TPRO_open(&pBoard, (char *)dev_name.c_str());
|
||||
|
||||
/* If unable to open the TPRO/TSAT device... */
|
||||
if (rv != TPRO_SUCCESS) {
|
||||
printf (" Could Not Open '%s'!! [%d]\n", dev_name.c_str(), rv);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Wait until this handle is the first user of the device. */
|
||||
if (TPRO_setPropDelayCorr(pBoard, NULL) != TPRO_SUCCESS) {
|
||||
printf(" Waiting to become first user...\n");
|
||||
while (TPRO_setPropDelayCorr(pBoard, NULL) != TPRO_SUCCESS);
|
||||
}
|
||||
|
||||
set_global_clock() ;
|
||||
|
||||
return 0 ;
|
||||
#else
|
||||
message_publish(MSG_ERROR, "TPRO CTE card was not enabled when Trick was compiled.\n\
|
||||
Please run ${TRICK_HOME}/configure --with-tpro=<directory holding CTE>, and recompile Trick\n");
|
||||
return -1 ;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Gets the TPRO time.
|
||||
-# If sucessful convert the TPRO time to tics
|
||||
*/
|
||||
long long Trick::TPROCTEClock::wall_clock_time() {
|
||||
#ifdef _TPRO_CTE
|
||||
TSYNC_HWTimeSecondsObj hwTime;
|
||||
|
||||
/* Send Get Seconds Time message */
|
||||
TSYNC_ERROR err = TSYNC_HW_getTimeSec(pBoard, &hwTime);
|
||||
|
||||
if (err != TSYNC_SUCCESS) {
|
||||
printf(" Error: %s.\n", tsync_strerror(err));
|
||||
return 0;
|
||||
}
|
||||
return hwTime.time.seconds * 1000000LL + (hwTime.time.ns /1000);
|
||||
|
||||
#else
|
||||
message_publish(MSG_ERROR, "TPRO CTE card was not enabled at compile time\n");
|
||||
return 0 ;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# Get the current real time.
|
||||
-# While the current real time is less than the requested time
|
||||
-# Release the processor momentarily
|
||||
-# Get the current real time.
|
||||
*/
|
||||
long long Trick::TPROCTEClock::clock_spin(long long req_time) {
|
||||
#ifdef _TPRO_CTE
|
||||
return Trick::Clock::clock_spin(req_time) ;
|
||||
#else
|
||||
message_publish(MSG_ERROR, "TPRO CTE card was not enabled at compile time\n");
|
||||
return req_time ;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@details
|
||||
-# This function is empty
|
||||
*/
|
||||
int Trick::TPROCTEClock::clock_stop() {
|
||||
#ifdef _TPRO_CTE
|
||||
unsigned char rv ;
|
||||
rv = TPRO_close(pBoard);
|
||||
/* If unable to close the TPRO/TSAT device... */
|
||||
if (rv != TPRO_SUCCESS) {
|
||||
printf (" Could Not Close Board!! [%d]\n", rv);
|
||||
}
|
||||
#endif
|
||||
return 0 ;
|
||||
}
|
||||
|
@ -1,90 +0,0 @@
|
||||
|
||||
/******************NOTES**********************************************
|
||||
* The BC635 clock requires special hardware to work. These tests
|
||||
* ensure that the TPRO class properly handles cases in which no
|
||||
* hardware is in use.
|
||||
*
|
||||
* Listed requirements are under requirement Trick-153 (3.7.1.2)
|
||||
* Real-time control shall be able to use an external clock source
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "trick/Clock.hh"
|
||||
#include "trick/clock_proto.h"
|
||||
#include "trick/GetTimeOfDayClock.hh"
|
||||
#include "trick/TPROCTEClock.hh"
|
||||
#include "trick/BC635Clock.hh"
|
||||
#include "trick/JobData.hh"
|
||||
|
||||
// Stub for message_publish
|
||||
extern "C" int message_publish(int level, const char * format_msg, ...) { (void)level; (void)format_msg; return 0; }
|
||||
|
||||
class BC635ClockTest : public ::testing::Test {
|
||||
|
||||
protected:
|
||||
Trick::BC635Clock bcclk;
|
||||
|
||||
BC635ClockTest() {}
|
||||
~BC635ClockTest() {}
|
||||
virtual void SetUp() {}
|
||||
virtual void TearDown() {}
|
||||
|
||||
} ;
|
||||
|
||||
/* Ensure clock initializes correctly */
|
||||
TEST_F(BC635ClockTest, Initialize) {
|
||||
|
||||
// "The BC635 clock shall initialize reference time of 0, and all ratios set to 1.");
|
||||
|
||||
/* General expected clock initialization */
|
||||
EXPECT_EQ(bcclk.get_rt_clock_ratio() , 1.0);
|
||||
EXPECT_EQ(bcclk.sim_tic_ratio, 1.0);
|
||||
EXPECT_EQ(bcclk.ref_time_tics, 0);
|
||||
|
||||
/* BC635 clock initialization tests */
|
||||
EXPECT_STREQ(bcclk.get_name() , "BC635");
|
||||
}
|
||||
|
||||
|
||||
/* Run tests for when no hardware is available */
|
||||
#ifndef _BC635
|
||||
TEST_F(BC635ClockTest, ErrorMessages) {
|
||||
|
||||
//"The BC635 clock shall display error messages when attempting to use its functions with no hardware.");
|
||||
/* curr_time = 0 always */
|
||||
|
||||
long long req_time = rand();
|
||||
|
||||
EXPECT_EQ(bcclk.clock_init(), -1);
|
||||
EXPECT_EQ(bcclk.wall_clock_time(), 0);
|
||||
EXPECT_EQ(bcclk.clock_spin(req_time), req_time);
|
||||
EXPECT_EQ(bcclk.clock_stop(), 0);
|
||||
|
||||
bcclk.set_reference(req_time);
|
||||
EXPECT_EQ(bcclk.clock_time(), -req_time);
|
||||
|
||||
bcclk.adjust_ref_time(req_time);
|
||||
EXPECT_EQ(bcclk.clock_time(), -2*req_time);
|
||||
|
||||
}
|
||||
|
||||
/* Ensure generic clock functions still work when no hardware is available */
|
||||
TEST_F(BC635ClockTest, TestRefTimes) {
|
||||
//"The BC635 clock shall provide the ability to adjust the reference time");
|
||||
|
||||
long long secs_remainder;
|
||||
int tics_per_s = 1000000000;
|
||||
double align_tics_mult = 1.5;
|
||||
|
||||
int clock_unit = int((tics_per_s * align_tics_mult)/(bcclk.rt_clock_ratio * bcclk.sim_tic_ratio));
|
||||
|
||||
bcclk.sync_to_wall_clock(align_tics_mult, tics_per_s);
|
||||
secs_remainder = bcclk.ref_time_tics% clock_unit;
|
||||
EXPECT_EQ(secs_remainder, 0);
|
||||
}
|
||||
#endif
|
@ -20,26 +20,19 @@ endif
|
||||
BASE_OBJECTS = ../object_${TRICK_HOST_CPU}/Clock.o\
|
||||
../object_${TRICK_HOST_CPU}/clock_c_intf.o
|
||||
|
||||
BC635_CLOCK_OBJECTS = ${BASE_OBJECTS} BC635Clock_test.o ../object_${TRICK_HOST_CPU}/BC635Clock.o exec_get_rt_nap_stub.o
|
||||
|
||||
GETTIMEOFDAY_CLOCK_OBJECTS = ${BASE_OBJECTS} GetTimeOfDayClock_test.o ../object_${TRICK_HOST_CPU}/GetTimeOfDayClock.o exec_get_rt_nap_stub.o
|
||||
|
||||
TPROCTE_CLOCK_OBJECTS = ${BASE_OBJECTS} TPROCTEClock_test.o ../object_${TRICK_HOST_CPU}/TPROCTEClock.o exec_get_rt_nap_stub.o
|
||||
|
||||
|
||||
# All tests produced by this Makefile. Remember to add new tests you
|
||||
# created to the list.
|
||||
TESTS = TPROCTEClock_test BC635Clock_test GetTimeOfDayClock_test
|
||||
TESTS = GetTimeOfDayClock_test
|
||||
|
||||
# House-keeping build targets.
|
||||
|
||||
all : $(TESTS)
|
||||
|
||||
# TODO: These tests fail on virtual machine platforms. They need to be reviewed
|
||||
test: $(TESTS)
|
||||
#./GetTimeOfDayClock_test --gtest_output=xml:${TRICK_HOME}/trick_test/GetTimeOfDayClock.xml
|
||||
#./TPROCTEClock_test --gtest_output=xml:${TRICK_HOME}/trick_test/TPROCTEClock.xml
|
||||
#./BC635Clock_test --gtest_output=xml:${TRICK_HOME}/trick_test/BC635Clock.xml
|
||||
./GetTimeOfDayClock_test --gtest_output=xml:${TRICK_HOME}/trick_test/GetTimeOfDayClock.xml
|
||||
|
||||
clean :
|
||||
rm -f $(TESTS) *.o
|
||||
@ -50,17 +43,5 @@ GetTimeOfDayClock_test.o : GetTimeOfDayClock_test.cpp
|
||||
GetTimeOfDayClock_test : ${GETTIMEOFDAY_CLOCK_OBJECTS}
|
||||
$(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ ${LIBS}
|
||||
|
||||
TPROCTEClock_test.o : TPROCTEClock_test.cpp
|
||||
$(TRICK_CXX) $(TRICK_CPPFLAGS) -c $<
|
||||
|
||||
TPROCTEClock_test : ${TPROCTE_CLOCK_OBJECTS}
|
||||
$(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ ${LIBS}
|
||||
|
||||
BC635Clock_test.o : BC635Clock_test.cpp
|
||||
$(TRICK_CXX) $(TRICK_CPPFLAGS) -c $<
|
||||
|
||||
BC635Clock_test : ${BC635_CLOCK_OBJECTS}
|
||||
$(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ ${LIBS}
|
||||
|
||||
exec_get_rt_nap_stub.o : exec_get_rt_nap_stub.cpp
|
||||
$(TRICK_CXX) $(TRICK_CPPFLAGS) -c $<
|
||||
|
@ -1,99 +0,0 @@
|
||||
|
||||
/******************NOTES**********************************************
|
||||
* The TPRO CTE clock requires special hardware to work. These tests
|
||||
* ensure that the TPRO class properly handles cases in which no
|
||||
* hardware is in use.
|
||||
*
|
||||
* Listed requirements are under requirement Trick-153 (3.7.1.2)
|
||||
* Real-time control shall be able to use an external clock source
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "trick/Clock.hh"
|
||||
#include "trick/clock_proto.h"
|
||||
#include "trick/GetTimeOfDayClock.hh"
|
||||
#include "trick/TPROCTEClock.hh"
|
||||
#include "trick/BC635Clock.hh"
|
||||
#include "trick/JobData.hh"
|
||||
|
||||
|
||||
// Stub for message_publish
|
||||
extern "C" int message_publish(int level, const char * format_msg, ...) { (void)level; (void)format_msg; return 0; }
|
||||
|
||||
class TPROCTEClockTest : public ::testing::Test {
|
||||
|
||||
protected:
|
||||
Trick::TPROCTEClock proclk;
|
||||
|
||||
TPROCTEClockTest() {}
|
||||
~TPROCTEClockTest() {}
|
||||
virtual void SetUp() {}
|
||||
virtual void TearDown() {}
|
||||
|
||||
//Trick::RequirementScribe req;
|
||||
} ;
|
||||
|
||||
//std::map< std::string , unsigned int > TPROCTEClockTest::num_reqs;
|
||||
|
||||
/* Ensure clock initializes correctly */
|
||||
TEST_F(TPROCTEClockTest, Initialize) {
|
||||
//"The TPROCTE clock shall initialize reference time of 0, and all ratios set to 1.");
|
||||
|
||||
/* General expected clock initialization */
|
||||
EXPECT_EQ(proclk.get_rt_clock_ratio() , 1.0);
|
||||
EXPECT_EQ(proclk.sim_tic_ratio, 1.0);
|
||||
EXPECT_EQ(proclk.ref_time_tics, 0);
|
||||
|
||||
/* TPROCTEClock initialization tests */
|
||||
EXPECT_STREQ(proclk.get_name() , "TPROCTE");
|
||||
|
||||
}
|
||||
|
||||
/* Run tests for when no hardware is available */
|
||||
#ifndef _TPRO_CTE
|
||||
TEST_F(TPROCTEClockTest, NoHardware) {
|
||||
//"The TPROCTE clock shall display error messages when attempting to use its functions with no hardware");
|
||||
|
||||
long long req_time = rand();
|
||||
|
||||
EXPECT_EQ(proclk.clock_init(), -1);
|
||||
EXPECT_EQ(proclk.wall_clock_time(), 0);
|
||||
EXPECT_EQ(proclk.clock_spin(req_time), req_time);
|
||||
EXPECT_EQ(proclk.clock_stop(), 0);
|
||||
|
||||
proclk.set_reference(req_time);
|
||||
EXPECT_EQ(proclk.clock_time(), -req_time);
|
||||
|
||||
proclk.adjust_ref_time(req_time);
|
||||
EXPECT_EQ(proclk.clock_time(), -2*req_time);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Ensure generic clock functions work properly */
|
||||
TEST_F(TPROCTEClockTest, TestRefTimes) {
|
||||
//"The TPROCTE clock shall provide the ability to adjust the reference time");
|
||||
|
||||
long long secs_remainder;
|
||||
int tics_per_s = 1000000000;
|
||||
double align_tics_mult = 1.5;
|
||||
|
||||
int clock_unit = int((tics_per_s * align_tics_mult)/(proclk.rt_clock_ratio * proclk.sim_tic_ratio));
|
||||
|
||||
proclk.sync_to_wall_clock(align_tics_mult, tics_per_s);
|
||||
secs_remainder = proclk.ref_time_tics% clock_unit;
|
||||
EXPECT_EQ(secs_remainder, 0);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user