• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 17772917031

16 Sep 2025 04:46PM UTC coverage: 55.866% (-0.005%) from 55.871%
17772917031

Pull #1958

github

web-flow
Merge d8200bf04 into ed8b1979f
Pull Request #1958: Resolves potential-for-fpe-in-run_ratio-sample-calcs

10 of 12 new or added lines in 1 file covered. (83.33%)

5 existing lines in 3 files now uncovered.

12352 of 22110 relevant lines covered (55.87%)

267838.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

64.08
/trick_source/sim_services/RealtimeSync/RealtimeSync.cpp
1
/*
2
PURPOSE:
3
    ( RealtimeSync )
4
PROGRAMMERS:
5
     ((Alex Lin) (NASA) (April 2009) (--) (c++ port)))
6
*/
7

8
#include <stdio.h>
9
#include <iostream>
10
#include <sstream>
11
#include <iomanip>
12
#include <cmath>
13
#include "trick/RealtimeSync.hh"
14
#include "trick/exec_proto.h"
15
#include "trick/sim_mode.h"
16
#include "trick/message_proto.h"
17
#include "trick/message_type.h"
18
#include "trick/TrickConstant.hh"
19

20
Trick::RealtimeSync * the_rts = NULL ;
21

22
/**
23
@details
24
-# Start disabled (non-real-time).  Requirement [@ref non-real-time]
25
*/
26
Trick::RealtimeSync::RealtimeSync( Trick::Clock * in_clock , Trick::Timer * in_timer ) {
226✔
27

28
    /* Start disabled (non-real-time). */
29
    enable_flag = false ;
226✔
30
    disable_flag = false ;
226✔
31

32
    active = false ;
226✔
33

34
    rt_max_overrun_cnt = 100000000;
226✔
35
    rt_max_overrun_time = 1.0e37;
226✔
36
    rt_overrun_freeze = false ;
226✔
37

38
    freeze_shutdown = false ;
226✔
39

40
    default_clock = in_clock ;
226✔
41

42
    change_clock(in_clock) ;
226✔
43
    change_timer(in_timer) ;
226✔
44

45
    align_sim_to_wall_clock = false ;
226✔
46
    align_tic_mult = 1.0 ;
226✔
47

48
    sim_start_time = 0 ;
226✔
49
    sim_end_init_time = 0 ;
226✔
50
    sim_end_time = 0 ;
226✔
51

52
    actual_run_ratio = 0.0;
226✔
53

54
    the_rts = this ;
226✔
55

56
}
226✔
57

58
/**
59
@details
60
-# Sets real-time enable flag to true. Requirement [@ref enable]
61
*/
62
int Trick::RealtimeSync::enable() {
4✔
63
    enable_flag = true ;
4✔
64
    return(0) ;
4✔
65
}
66

67
/**
68
@details
69
-# Sets real-time disabled flag to true. Requirement [@ref disable]
70
*/
71
int Trick::RealtimeSync::disable() {
8✔
72
    disable_flag = true ;
8✔
73
    return(0) ;
8✔
74
}
75

76
/**
77
@details
78
-# Sets the real_time clock to the incoming class [@ref disable]
79
*/
80
int Trick::RealtimeSync::change_clock(Trick::Clock * in_clock) {
226✔
81
    int ret ;
82
    ret = in_clock->clock_init() ;
226✔
83
    if ( ret == 0 ) {
226✔
84
        rt_clock = in_clock ;
226✔
85
    }
86
    return ret ;
226✔
87
}
88

89
/**
90
@details
91
-# Sets the real_time clock to the incoming class [@ref disable]
92
*/
93
const char * Trick::RealtimeSync::clock_get_name() {
×
94
    return rt_clock->get_name() ;
×
95
}
96

97
/**
98
@details
99
-# Sets the sleep timer to the incoming class [@ref disable]
100
*/
101
int Trick::RealtimeSync::change_timer(Trick::Timer * in_sleep_timer) {
226✔
102
    sleep_timer = in_sleep_timer ;
226✔
103
    return 0 ;
226✔
104
}
105

106
/**
107
@details
108
-# Calls Trick::Clock::set_rt_clock_ratio
109
-# Set the sleep timer to inactive for this frame as the ratio changes.
110
*/
111
int Trick::RealtimeSync::set_rt_clock_ratio(double in_clock_ratio) {
×
112
    rt_clock->set_rt_clock_ratio(in_clock_ratio) ;
×
113
    sleep_timer->set_active(false) ;
×
114
    return 0 ;
×
115
}
116

117
void Trick::RealtimeSync::get_sim_start_time() {
182✔
118
    sim_start_time = default_clock->wall_clock_time() ;
182✔
119
}
182✔
120

121
void Trick::RealtimeSync::get_sim_end_init_time() {
149✔
122
    sim_end_init_time = default_clock->wall_clock_time() ;
149✔
123
}
149✔
124

125
void Trick::RealtimeSync::get_sim_end_time() {
150✔
126
    sim_end_time = default_clock->wall_clock_time() ;
150✔
127
}
150✔
128

129
/**
130
@details
131
-# If real-time synchronization has been enabled:
132
   -# Set the active flag to true.
133
-# If real-time synchronization has been disabled set the active flag to false.
134
*/
135
int Trick::RealtimeSync::initialize() {
149✔
136

137
    if ( enable_flag ) {
149✔
138
        active = true ;
3✔
139
        enable_flag = false ;
3✔
140
    }
141

142
    if ( disable_flag ) {
149✔
143
        active = false ;
8✔
144
        disable_flag = false ;
8✔
145
    }
146

147
    tics_per_sec =  exec_get_time_tic_value();
149✔
148

149
    /* Start the sleep timer hardware if realtime is active */
150
    start_sleep_timer();
149✔
151

152
    if ( align_sim_to_wall_clock ) {
149✔
153
        rt_clock->clock_reset(0) ;
×
154
        rt_clock->sync_to_wall_clock( align_tic_mult , tics_per_sec ) ;
×
155
        message_publish(MSG_INFO, "Syncing sim to %f second wall clock interval\n", align_tic_mult ) ;
×
156
        rt_clock->clock_spin(0) ;
×
157
        if ( exec_get_mode() == Freeze ) {
×
158
            rt_clock->clock_reset(exec_get_freeze_time_tics()) ;
×
159
        } else {
160
            rt_clock->clock_reset(exec_get_time_tics()) ;
×
161
        }
162
    }
163

164
    return(0) ;
149✔
165
}
166

167
/**
168
@details
169
-# If real-time synchronization is active
170
   -# Call the real-time clock initialization routine [@ref clock_init]
171
   -# Call the sleep timer initialization
172
   -# Set the sleep timer frame period to software frame period
173
   -# Calculate the maximum overrun time in simulation tics.
174
*/
175
int Trick::RealtimeSync::start_sleep_timer() {
150✔
176

177
    if ( active && (exec_get_time_tics() >= 0.0)) {
150✔
178
        /* Call sleep timer init to start sleep timer hardware */
179
        sleep_timer->init() ;
2✔
180

181
        if ( rt_max_overrun_time > 1e36 ) {
2✔
182
            rt_max_overrun_time_tics = TRICK_MAX_LONG_LONG ;
2✔
183
        } else {
184
            rt_max_overrun_time_tics = (long long)(rt_max_overrun_time * tics_per_sec) ;
×
185
        }
186

187
    }
188

189
    return(0) ;
150✔
190
}
191

192
/**
193
@details
194
-# Get the sim_mode
195
-# Reset the real-time clock reference
196
-# If sim_mode is Run
197
   -# Call start_realtime to start the real time clock
198
-# Else if sim_mode is Freeze
199
   -# Call freeze init to set the sleep timer to freeze mode.
200
*/
201
int Trick::RealtimeSync::restart(long long ref_time) {
9✔
202

203
    SIM_MODE sim_mode = exec_get_mode() ;
9✔
204

205
    rt_clock->clock_reset(ref_time) ;
9✔
206
    if ( sim_mode == Run ) {
9✔
207
        start_realtime(exec_get_software_frame() , ref_time) ;
8✔
208
    } else if ( sim_mode == Freeze ) {
1✔
209
        freeze_init(exec_get_freeze_frame()) ;
×
210
    }
211

212
    return 0 ;
9✔
213
}
214

215
/**
216
@details
217
-# If real-time synchronization is active
218
   -# If the sim time is 0 or higher (do not run in real time for negative sim time)
219
      -# Reset the real-time clock to the incoming reference time
220
      -# Save the current real-time as the start of the frame reference
221
      -# Start the sleep timer
222
   -# Else reset active to false and enable_flag to true
223
*/
224
int Trick::RealtimeSync::start_realtime(double in_frame_time , long long ref_time) {
157✔
225

226
    if ( active ) {
157✔
227

228
        /* Only run in real time when sim time reaches 0.0 */
229
        if (ref_time >= 0) {
1✔
230

231
            /* Reset the clock reference time to the desired reference time */
232
            rt_clock->clock_reset(ref_time) ;
1✔
233

234
            /* Start the sleep timer hardware */
235
            start_sleep_timer();
1✔
236

237
            /* Start the sleep timer */
238
            sleep_timer->start(in_frame_time / rt_clock->get_rt_clock_ratio()) ;
1✔
239

240
        } else {
241

242
            /* Reset active and enable_flag so rt_monitor will try and start
243
               real time at the end of next software frame                   */
244
            active = false;
×
245
            enable_flag = true;
×
246
        }
247

248
    }
249

250
    /* Set top of frame time for 1st frame (used in frame logging). */
251
    last_clock_time = rt_clock->clock_time() ;
157✔
252

253
    return(0) ;
157✔
254
}
255

256
template <size_t N>
257
class Run_Ratio {
258
  public:
259
    Run_Ratio() : num_samples(0) {}
146✔
260
    Run_Ratio& operator()(long long sample, double in_rt_ratio)
106,242✔
261
    {
262
        samples[num_samples++ % N] = sample;
106,242✔
263
        rt_ratio = in_rt_ratio;
106,242✔
264
        return *this;
106,242✔
265
    }
266

267
    operator double() const {
106,242✔
268
        if ( num_samples <= 1 ) {
106,242✔
269
            return 0.0 ;
146✔
270
        } else if ( num_samples < N ) {
106,096✔
271
            const long long currSampleVal = samples[num_samples - 1];
1,484✔
272
            const long long firstSampleVal = samples[0];
1,484✔
273
            const long long deltaVal = currSampleVal -firstSampleVal;
1,484✔
274
            if(deltaVal == 0)
1,484✔
275
            {
NEW
276
                return 1.0;
×
277
            } else {
278
                return round(exec_get_software_frame() * (num_samples-1) * exec_get_time_tic_value() * rt_ratio / (double)(deltaVal)*100.0)/100.0 ;
1,484✔
279
            }
280
        } else {
281
            const long long prevSampleVal = samples[(num_samples - 1) % N];
104,612✔
282
            const long long currSampleVal = samples[num_samples % N];
104,612✔
283
            const long long deltaVal = prevSampleVal -currSampleVal;
104,612✔
284
            if(deltaVal == 0)
104,612✔
285
            {
NEW
286
                return 1.0;
×
287
            } else {
288
                return round(exec_get_software_frame() * (N-1) * exec_get_time_tic_value() * rt_ratio / (double)(deltaVal)*100.0)/100.0 ;
104,612✔
289
            }
290
        }
291
    }
292

293
  private:
294
    long long samples[N]{};
295
    size_t num_samples{};
296
    double rt_ratio{};
297
};
298

299
/**
300
@details
301
-# If real-time is not active:
302
   -# If real-time synchronization has been enabled:
303
      -# Set the active flag to true.
304
      -# Start real-time setting the real-time clock to the current simulation time.
305
   -# exit end of frame routine
306
-# If real-time is active:
307
   -# If real-time synchronization has been disabled:
308
      -# Set the active flag to false.
309
-# Get the current real-time.
310
-# Calculate the real-time taken for the last frame of execution.
311
-# if the frame has overrun
312
   -# Increment the number of consecutive overruns
313
   -# If the maximum number of consecutive overrun frames has
314
      been reached or the maximum single overrun time has been exceeded
315
      -# If the freeze/terminate action was set
316
         -# set the freeze_terminate flag
317
         -# freeze the simulation
318
      -# Else terminate the simulation
319
   -# Stop the sleep timer.
320
-# Else the frame has underrun
321
   -# Reset the number of consecutive overruns to 0.
322
   -# Pause for the sleep timer to expire
323
   -# Spin for the real-time clock to match the simulation time
324
   -# Reset the sleep timer for the next frame
325
-# Save the current real-time as the start of the frame reference
326
*/
327
int Trick::RealtimeSync::rt_monitor(long long sim_time_tics) {
106,242✔
328

329
    long long curr_clock_time ;
330
    char buf[512];
331
    static Run_Ratio<100> run_ratio ;
106,242✔
332

333
    /* calculate the current underrun/overrun */
334
    curr_clock_time = rt_clock->clock_time() ;
106,242✔
335
    frame_sched_time = curr_clock_time - last_clock_time ;
106,242✔
336
    frame_time = frame_sched_time * (1.0/tics_per_sec);
106,242✔
337

338
    /* Set the next frame overrun/underrun reference time to the current time */
339
    last_clock_time = curr_clock_time ;
106,242✔
340

341
    /* determine if the state of real-time has changed this frame */
342
    if ( ! active ) {
106,242✔
343
        if ( enable_flag ) {
106,192✔
344
            active = true ;
×
345
            enable_flag = false ;
×
346
            start_realtime(exec_get_software_frame() , sim_time_tics) ;
×
347
        }
348
        if ( disable_flag ) {
106,192✔
349
            disable_flag = false ;
×
350
        }
351
        /* calculate run ratio in non-realtime mode */
352
        actual_run_ratio = run_ratio(curr_clock_time, 1.0);
106,192✔
353
        return(0) ;
106,192✔
354
    }
355
    if ( enable_flag ) {
50✔
356
        enable_flag = false ;
×
357
    }
358
    if ( disable_flag ) {
50✔
359
        active = false ;
×
360
        disable_flag = false ;
×
361
    }
362

363
    frame_overrun_time = curr_clock_time - sim_time_tics ;
50✔
364

365
    frame_overrun = frame_overrun_time * (1.0/tics_per_sec);
50✔
366

367
    /* If the wall clock time is greater than the sim time an overrun occurred. */
368
    if (curr_clock_time > sim_time_tics) {
50✔
369

370
        /* Update the overrun counter and current overrun time */
371
        frame_overrun_cnt++;
×
372
        total_overrun++;
×
373

374
        /* If the number overruns surpass the maximum allowed freeze or shutdown. */
375
        if (frame_overrun_cnt >= rt_max_overrun_cnt || frame_overrun_time >= rt_max_overrun_time_tics) {
×
376

377
            /* If the rt_overrun_freeze flag is set, enter freeze mode else terminate the simulation. */
378
            if (rt_overrun_freeze == true) {
×
379
                freeze_shutdown = true ;
×
380
                message_publish(MSG_ERROR, "\nMaximum overrun condition exceeded:\n"
×
381
                    "consecutive overruns/allowed overruns: %d/%d\n"
382
                    "total overrun time/allowed time: %f/%g\n"
383
                    "Entering Freeze-Shutdown Mode\n" ,
384
                    frame_overrun_cnt, rt_max_overrun_cnt,
385
                    (double)(frame_overrun_time/tics_per_sec), rt_max_overrun_time);
×
386
                exec_freeze() ;
×
387
            } else {
388
                snprintf(buf, sizeof(buf), "\nMaximum overrun condition exceeded:\n"
×
389
                    "consecutive overruns/allowed overruns: %d/%d\n"
390
                    "total overrun time/allowed time: %f/%g\n",
391
                    frame_overrun_cnt, rt_max_overrun_cnt,
392
                    (double)(frame_overrun_time/tics_per_sec), rt_max_overrun_time);
×
393
                exec_terminate_with_return(-1 , __FILE__ , __LINE__ , buf);
×
394
            }
395
        }
396

397
        /* stop the sleep timer in an overrun condition */
398
        sleep_timer->stop() ;
×
399

400
        /* Call clock_spin to allow interrupt driven clocks to service their interrupts */
401
        curr_clock_time = rt_clock->clock_spin(sim_time_tics) ;
×
402

403
    } else {
404

405
        /* Else an underrun condition occurred. */
406

407
        /* Reset consecutive overrun counter frame_overrun_cnt */
408
        frame_overrun_cnt = 0;
50✔
409

410
        /* pause for the timer to signal the end of frame */
411
        sleep_timer->pause() ;
50✔
412

413
        /* Spin to make sure that we are at the top of the frame */
414
        curr_clock_time = rt_clock->clock_spin(sim_time_tics) ;
50✔
415

416
        /* If the timer requires to be reset at the end of each frame, reset it here. */
417
        sleep_timer->reset(exec_get_software_frame() / rt_clock->get_rt_clock_ratio()) ;
50✔
418

419
        /* Calculate the run ratio after sleeping */
420
        actual_run_ratio = run_ratio(curr_clock_time, rt_clock->get_rt_clock_ratio());
50✔
421
    }
422

423
    return(0) ;
50✔
424
}
425

426
/**
427
@details
428
-# If real-time synchronization is active
429
   -# Set the sleep timer frame period to freeze frame period
430
   -# Start real-time setting the real-time clock at 0.
431
*/
432
int Trick::RealtimeSync::freeze_init(double freeze_frame_sec) {
×
433

434
    if ( active ) {
×
435
        sleep_timer->start( freeze_frame_sec / rt_clock->get_rt_clock_ratio()) ;
×
436
    }
437
    freeze_frame = (long long)(freeze_frame_sec * tics_per_sec) ;
×
438
    freeze_time_tics = exec_get_time_tics() ;
×
439
    return 0  ;
×
440
}
441

442
/**
443
@details
444
-# If real-time is not active:
445
   -# If real-time synchronization has been enabled:
446
      -# Set the active flag to true.
447
      -# Set the sleep timer frame period to freeze frame period
448
      -# Start real-time setting the real-time clock at currnent freeze time.
449
   -# exit end of frame routine
450
# If real-time synchronization has been disabled:
451
  -# Set the active flag to false.
452
-# Pause for the sleep timer to expire
453
-# Spin for the real-time clock to match the simulation time
454
-# Advanced freeze time.
455
*/
456
int Trick::RealtimeSync::freeze_pause(double freeze_frame_sec) {
×
457

458
    /* Determine if the state of real-time has changed this frame */
459
    if ( ! active ) {
×
460
        if ( enable_flag ) {
×
461
            active = true ;
×
462
            enable_flag = false ;
×
463
            start_realtime(freeze_frame_sec , freeze_time_tics) ;
×
464
        }
465
        if ( disable_flag ) {
×
466
            disable_flag = false ;
×
467
        }
468
        return(0) ;
×
469
    }
470

471
    if ( enable_flag ) {
×
472
        enable_flag = false ;
×
473
    }
474
    if ( disable_flag ) {
×
475
        active = false ;
×
476
        disable_flag = false ;
×
477
    }
478

479
    /* If a sleep timer has been defined pause for the timer to signal the end of frame */
480
    sleep_timer->pause() ;
×
481

482
    /* Spin to make sure that we are at the top of the frame */
483
    rt_clock->clock_spin(freeze_time_tics + freeze_frame) ;
×
484

485
    /* If the timer requires to be reset at the end of each frame, reset it here. */
486
    sleep_timer->reset(freeze_frame_sec / rt_clock->get_rt_clock_ratio()) ;
×
487

488
    freeze_time_tics += freeze_frame ;
×
489

490
    return(0) ;
×
491

492
}
493

494
/**
495
@details
496
-# If real-time is active:
497
   -# If the freeze_terminate flag is set, terminate the simulation
498
-# Set the sleep timer frame period to software frame period
499
-# Start real-time setting the real-time clock to the current simulation time.
500
*/
501
int Trick::RealtimeSync::unfreeze(long long sim_time_tics, double software_frame_sec) {
×
502

503
    if ( active ) {
×
504

505
        /* If the overrun freeze_shutdown condition was met terminate the simulation */
506
        if (freeze_shutdown) {
×
507
            exec_terminate_with_return(-1 , __FILE__ , __LINE__ , "Freeze-Shutdown condition reached.");
×
508
        }
509

510
        /* Adjust the real-time clock reference by the amount of time we were frozen */
511
        rt_clock->adjust_ref_time(freeze_time_tics - sim_time_tics) ;
×
512

513
        /* Start the sleep timer with the software frame expiration */
514
        sleep_timer->start(software_frame_sec / rt_clock->get_rt_clock_ratio()) ;
×
515

516
    }
517

518
    /* Set top of frame time for 1st frame (used in frame logging). */
519
    last_clock_time = rt_clock->clock_time() ;
×
520

521
    return(0) ;
×
522
}
523

524
/**
525
@details
526
-# If real-time is active:
527
   -# Stop the real-time clock hardware
528
   -# Stop the sleep timer hardware
529
   -# Print the overrun count
530
*/
531
int Trick::RealtimeSync::shutdown() {
150✔
532

533
    if ( active ) {
150✔
534
        /* Stop the clock */
535
        rt_clock->clock_stop() ;
1✔
536

537
        /* If a sleep timer has been defined, stop the timer */
538
        sleep_timer->shutdown() ;
1✔
539
    }
540

541
    std::stringstream os ;
150✔
542
    double actual_time = (sim_end_time - sim_start_time) / (double)default_clock->clock_tics_per_sec ;
150✔
543
    os << "\n" <<
544
     "     REALTIME SHUTDOWN STATS:\n" ;
150✔
545
    if ( active ) {
150✔
546
        os << "     REALTIME TOTAL OVERRUNS: " << std::setw(12) << total_overrun << "\n" ;
1✔
547
    }
548
    if ( sim_end_init_time != 0 ) {
150✔
549
        double init_time = (sim_end_init_time - sim_start_time) / (double)default_clock->clock_tics_per_sec ;
150✔
550
        os <<  "            ACTUAL INIT TIME: " ;
150✔
551
        os <<  std::fixed << std::setw(12) << std::setprecision(3) << init_time << "\n" ;
150✔
552
    }
553
    os <<  "         ACTUAL ELAPSED TIME: " ;
150✔
554
    os << std::fixed << std::setw(12) << std::setprecision(3) << actual_time << "\n" ;
150✔
555
    message_publish(MSG_NORMAL,os.str().c_str()) ;
150✔
556

557
    return(0) ;
300✔
558
}
559

560
bool Trick::RealtimeSync::is_active() {
×
561
    return active;
×
562
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc