Home » Eclipse Projects » Papyrus for Real Time » Incrementing time
Incrementing time [message #1769802] |
Thu, 03 August 2017 09:45  |
Eclipse User |
|
|
|
I wonder if it is possible to increment time so timers will time out right after that (rather than waiting for a timer to time out normally). Or, for instance, force a timer to timeout, which in such case all other active timers will be naturally affected.
I'll use this for testing purposes as I cannot wait for a timer to normally times out (assume there are many test cases and some timers take a long time to timeout).
I know that a timer port is not externally visible (it's a SAP port), but how such scenarios should be approached?
Thanks.
[Updated on: Thu, 03 August 2017 13:51] by Moderator
|
|
| |
Re: Incrementing time [message #1769820 is a reply to message #1769802] |
Thu, 03 August 2017 12:37   |
Eclipse User |
|
|
|
What you are looking for is known as a discrete-event simulator or logical-time simulator. The UML-RT runtime in Papyrus-RT is not such a simulator, it is a real-time runtime. When you schedule a timer, the timeout will be triggered according to the (real) "wall" clock of the underlying platform. Internally, this is implemented in umlrtcontroller.cc, in UMLRTController::wait, which calls "select" (see e.g. http://man7.org/linux/man-pages/man2/select.2.html) with a timeout. Therefore, there is no way to do exactly what you want with the Papyrus-RT runtime.
However, there are some possibilities. To achieve what you want, you have three choices:
1) write your own logical time simulator
2) modify the runtime, in particular the UMLRTController::wait method, and rebuild it
3) use abstraction, defining time values separately from where you start the timers, with small enough time values
I assume that you don't want to spend time writing your own simulator, and modifying the runtime might be quite tricky (you'll need to get deep into how it works), so I suggest the third: use abstraction for your timers, so that whenever you setup a timer, use a variable, symbolic constant or macro which you can configure elsewhere, so that when you run your tests, you set the values to very small amounts.
For example, suppose you have a model with two capsules Capsule1 and Capsule2 both of which have a "timing" port, and in Capsule1 you have the following action in State1:
timing.informIn(UMLRTTimespec(3,0));
and in Capsule2 you have the following action in, say, State1 as well:
timing.informIn(UMLRTTimespec(2,500000000l));
Instead of giving specific values to those timers, define constants for them, either as static read-only attributes in a Class, or as macros defined in an Artifact (or a Class). For example, define a Class called "TimersConfiguration" with static, read-only attributes T1 and T2 of type UMLRTTimespec, and default value set to an OpaqueExpression "UMLRTTimespec(3,0)" and "UMLRTTimespec(2,500000000l)" respectively. Then abstract: replace those actions with
timing.informIn(TimersConfiguration::T1);
and in Capsule2 you have the following action in, say, State1 as well:
timing.informIn(TimersConfiguration::T2);
And create a class diagram with your capsules Capsule1, Capsule2, the TimersConfiguration class and a Dependency relation from Capsule1 to TimersConfiguration and Capsule2 to TimersConfiguration as well.
Then you have separated the timing behaviour of your capsules from the concrete values of your timers, and you only need to configure those timers for your tests.
Recall that the parameters of UMLRTTimespec are seconds (the first) and nanoseconds (the second) and both are of type long. So if you replace those timespecs by small values, say, instead of UMLRTTimespec(3,0), you do UMLRTTimespec(0,3000l), then the timer will be really quick.
An alternative to the TimersConfiguration class, is to define those timers in a header file (an Artifact model element).
In any case, the point is to abstract the concrete values of your timers and put them in some separate element (Class or Artifact) which you can easily configure for your tests with small values.
I'm attaching a sample model that contains examples of both styles. Time values T1 and T2 use the first style (for Capsules 1 and 2), defined in a TimersConfiguration class, and T3 and T4 (capsules 3 and 4) are defined as macros in an Artifact called ExternalTimersConfiguration.
The TimersConfiguration class, also has utilities to obtain a string for a timespec and for the current time, which are useful for logging.
|
|
|
Re: Incrementing time [message #1769823 is a reply to message #1769816] |
Thu, 03 August 2017 13:07   |
Eclipse User |
|
|
|
The solutions described by Charles work, but the key is this:
Charles Rivet wrote on Thu, 03 August 2017 11:52[...] if that does not adversely affect the rest of your system...
Using those operations may affect the intended behaviour of your model. The timeAdjustStart method "freezes" the timing service systemwide, so for example, say you have something like a PingPong model with two capsules sending each other messages (Pinger's behaviour is to send ping to Ponger, wait for pong from Ponger and repeat; Ponger's behaviour is to wait for ping; respond with pong and repeat) but they timeout after say 5 seconds that sends them to a "Done" state. So you expect both of them to stop after 5 seconds. If you freeze the timing service with timingAdjustStart, and don't perform timingAdjustComplete, the timers will never fire, the corresponding timeout transitions will never trigger and therefore the two capsules will continue to send each other messages forever, which is a very different behaviour than stopping.
In any case, you have to reason about your model's behaviour to make sure that it is the same with and without timing adjusts. In that case, it might be easier to follow my suggestion to describe a TimersConfiguration separately and use small timing values.
[Updated on: Thu, 03 August 2017 13:10] by Moderator
|
|
| |
Re: Incrementing time [message #1770022 is a reply to message #1769827] |
Mon, 07 August 2017 10:59  |
Eclipse User |
|
|
|
Yes. If you want guarantee that the behaviour of the system is the same, all delays/timers would have to be divided (or multiplied) by the same amount.
Of course there are cases where it may not matter, as the behaviour might be the same regardless of the timer, but in general, to guarantee the same behaviour, the division would be required.
|
|
|
Goto Forum:
Current Time: Fri May 16 17:58:03 EDT 2025
Powered by FUDForum. Page generated in 0.04471 seconds
|