timerafter parameter Topic is solved

Technical questions regarding the XTC tools and programming with XMOS.
Post Reply
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

timerafter parameter

Post by aclassifier »

In all the examples I have seen timerafter takes uint32_t as a paramter. This is according to the spec in xs1.h:

Code: Select all

void timerafter(unsigned val);
#define timerafter(val)                       __builtin_timer_after(val)
Here is some code from the XMOS Programming guide:

Code: Select all

timer t;
uint32_t time;
const uint32_t period = 100000; // 100000 timer ticks = 1ms
// get the initial timer value t :> time;
while(1) {
    select {
    case t when timerafter(time) :> void:
        // perform periodic task ...
        time += period;
        break;
    } 
}
occam always used signed int here, and there was a PLUS, MINUS and AFTER in the language that allowed overflow without a crash.

A hypothesis of why XC uses unsigned here is that it's associated with arithmetic to get into the future (+) or to find elapsed time by some unsigned number of micro, milli or seconds, so it's so much easier just to use unsigned? Meet me in 120 seconds is unsigned by nature. At 23:59 then meet me in two minutes is at 00:01, "the hour" rather signed.

I noticed this just now, being occamised 25 years ago I have basically done it like this:

Code: Select all

timer tmr;
int timeout;
int current_time;
unsigned int milliseconds;
tmr :> current_time;
timeout = current_time + (int)(milliseconds * XS1_TIMER_KHZ);
tmr when timerafter(timeout) :> void;
What's going on behind the scene here? Has XC caught some C-ish sign-ish handling? Or have I lost the point?

PS.I have blogged about this theme here: http://www.teigfam.net/oyvind/home/tech ... multi-core (no money, no ads, no gifts received, just hobby)


View Solution
henk
Respected Member
Posts: 347
Joined: Wed Jan 27, 2016 5:21 pm

Post by henk »

Hi,

I am not sure there is a difference; both unsigned and signed integers use modulo 0x100000000 arithmetic, the former on the domain [0x00000000..0xFFFFFFFF] the latter on the domain [-0x80000000..0x7FFFFFFF].

In both cases, you can use timerafter, in that it computes the difference between the current time and the timerafter, interprets the difference as a signed number, and a positive value indicates timerafter. Ie, signed -1 is after -3, exactly as unsigned 0xFFFFFFFF is after 0xFFFFFFFFD. Signed 1 is after -1 the same as unsigned 0x00000001 is after 0xFFFFFFFF and signed -0x80000000 is after 0x7FFFFFFE in the same way that unsigned 0x80000000 is after 0x7FFFFFFE. In all these cases, the difference is 0x00000002 which is a positive value.

This limits the timerafter operation to half the domain, i.e., you cannot reason about more than 0x7FFFFFFF ticks ahead (21.47483647 seconds) or 0x80000000 ticks in the past (21.47483648 seconds).

Port counters have only 16 bits, and they are always ahead - i.e., you can reason up to 65535 ticks ahead, and you cannot reason about port timers that are in the past; if you missed them, you will seem to be waiting for them in the future.

Cheers,
Henk
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

henk wrote:Hi,
I am not sure there is a difference; both unsigned and signed integers use modulo 0x100000000 arithmetic, ...
In both cases, you can use timerafter, in that it computes the difference between the current time and the timerafter, interprets the difference as a signed number,...
Yes.

[1] just states that a timer is a 32 bit counter, not how it's seen. As long as it wraps around with the full range it's fine. Had it been a counter that counted 10ns increments for one second and then restarted from zero, that's where things get not as elegant as AFTER, PLUS, MINUS - which sees time as signed.

Do you know the internal type of timer? If it's signed then shouldn't the parameter to timerafter have been signed, too? It's not a "delta" (unsigned) into the future, it is the proper future time (signed?).

[1] http://www.xmos.com/download/private/Pr ... ces(1).pdf
henk
Respected Member
Posts: 347
Joined: Wed Jan 27, 2016 5:21 pm

Post by henk »

[1] just states that a timer is a 32 bit counter, not how it's seen. As long as it wraps around with the full range it's fine. Had it been a counter that counted 10ns increments for one second and then restarted from zero, that's where things get not as elegant as AFTER, PLUS, MINUS - which sees time as signed.

Do you know the internal type of timer? If it's signed then shouldn't the parameter to timerafter have been signed, too? It's not a "delta" (unsigned) into the future, it is the proper future time (signed?).
As far as the architecture is concerned, it is a 32 bit unsigned value; it counts up to 2^31-1 and then back to 0.

However - anybody is welcome to interpret the bits as a signed value instead. In the unsigned case it counts from 0..2^32-1 and back to 0; in the signed case it counts from -2^31..2^31-1 and back to -2^31. In both cases it wraps modulo 2^32, just in one case it uses the definition of modulo to always result in a positive remainder; in the second case it uses a definition of modulo to always end up with the smallest magnitude remainder.

Hence you can use signed or unsigned, in both cases you have a monotonic counter. (note that the starting value is undefined, and not relevant)

As far as the maths is concerned, to make a comparison on whether A is AFTER B, you must compute the following on two values A and B:

Code: Select all

AFTER = A-B < -2^31 OR (A-B > 0 AND A-B < 2^31)
If you happen to have an operator -SM (minus Signed Modulo 2^32) that results in a signed value (i.e., A -SM B = if A-B >= 2^31 then A-B-2^32 elif A-B < -2^31 then A-B+2^32) then you can simplify the definition of AFTER to:

Code: Select all

AFTER = A -SM B >= 0
The architecture has this operator - it is called the SUB instruction, and if you interpret the output as a signed value, then you just have to test the first bit. The - operation in XC is modulo 2^32, and hence does this.
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

I am so impressed by the depth of the answers on xcore! Thanks, Henk!

I also discussed the #define AFTER_F(a,b) ((a-b)>0) macro in my blog note. For most languages it's not portable within the language on different architectures and compilers. I showed examples.

Now I have the precise semantics of timers on the xcore.

I assume that the timer hw implementation of the transputer was the same? A monotonic 32 bit counter that wrapped around at full, and the the AFTER, PLUS, MINUS had signed arithmetic because it's easier(?) to understand? But it was also needed to steer away from arithmetic overflow/underflow of the other operators that did throw exceptions.
henk
Respected Member
Posts: 347
Joined: Wed Jan 27, 2016 5:21 pm

Post by henk »

I assume that the timer hw implementation of the transputer was the same? A monotonic 32 bit counter that wrapped around at full, and the the AFTER, PLUS, MINUS had signed arithmetic because it's easier(?) to understand? But it was also needed to steer away from arithmetic overflow/underflow of the other operators that did throw exceptions.
That would be my guess - you can choose to have one instruction that implements both SUB and AFTER, or you can have two instructions that share the same adder, but that do something different with overflow flags or exception.
Post Reply