Several questions about XMOS

Non-technical related questions should go here.
Heater
Respected Member
Posts: 296
Joined: Thu Dec 10, 2009 10:33 pm

Post by Heater »

Thanks all for the replies.

Looking at the L and G clock frequency control documents is scary, they are so different.

I guess I'll have to be content with the 1 clock jitter in my experiments I have no way to look at what is happening on actual pins in that detail.

I'll be trying some experiments with cranking up the reference clock to equal the core clock later today.

According to the clock frequency document this is possible on the G devices. However I seem to remember a post in a thread some where that said on G devices the ref clock could only go to half the system clcock.

Also on my experiment list is to check out the effects of divide and mod. David May did hint that these may cause execution jitter of other threads.


User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

Heater wrote:Looking at the L and G clock frequency control documents is scary, they are so different.
Oh? Details vary a bit, but they are quite the same in principle.
I'll be trying some experiments with cranking up the reference clock to equal the core clock later today.
That might well not work, as you say; I suggested clocking the core clock at the same as your ref clock,
not the other way around. That might not be fast enough for your application, but it's good for your
experiments.
Also on my experiment list is to check out the effects of divide and mod. David May did hint that these may cause execution jitter of other threads.
Only other threads that use the division coprocessor as well. A division takes 32 cycles in there, not
pipelined; any following division (from another thread, or the same thread) will have to wait until it's
done. Usually not a problem, code that cares about cycle counting usually needs to run very fast,
and very fast code shouldn't use integer division, since it's slow no matter what.
Heater
Respected Member
Posts: 296
Joined: Thu Dec 10, 2009 10:33 pm

Post by Heater »

I'm not having much luck with this. I have been playing with changing the system and reference frequencies in my .xn file but whatever I do the results come out the same.

Code: Select all

<Node Id="0" Type="XS1-G4B" Oscillator="20MHz" SystemFrequency="100MHz" ReferenceFrequency="100MHz">
Heater
Respected Member
Posts: 296
Joined: Thu Dec 10, 2009 10:33 pm

Post by Heater »

The code below is my experiment to show the effect of the use of divides in threads causing execution jitter.

There are only four threads running.

Code: Select all

#include <stdio.h>
#include <platform.h>

int a = 100;
int b = 10;
int c;

void calc_thread()
{
	  timer tmr;
	  unsigned t;
	  unsigned period;
	  unsigned loops;

	  period = 100000000;
	  tmr :> t;
	  while (1)
	  {
		  tmr when timerafter(t) :> void;
		  t += period;
		  for (loops = 0; loops < 1000000; loops++)
		  {
			  c = a / b;
			  c = c * b;
			  c = a / b;
			  c = c * b;
			  c = a / b;
			  c = c * b;
			  c = a / b;
			  c = c * b;
			  c = a / b;
			  c = c * b;
		  }
	  }
}

void waste_thread()
{
	while(1)
    {
    }
}

int x = 100;
int y = 10;
int f;

void timed_thread()
{
    long startTime, endTime;
    timer t;

    printf ("Determinism test:\n");
    while (1)
    {
    	// Start benchmark timer
    	t :> startTime;

    	f = x / y;
    	f = f * y;
    	f = x / y;
    	f = f * y;
    	f = x / y;
    	f = f * y;

    	// Stop benchmark timer
    	t :> endTime;

    	printf ("Run time = %d timer ticks\n", endTime - startTime);
    }
}

int main()
{
	par
	{
        on stdcore[0]: timed_thread();
        on stdcore[0]: calc_thread();
        on stdcore[0]: waste_thread();
        on stdcore[0]: waste_thread();
	}
 	return 0;
}
Results in this:

Code: Select all

Run time = 107 timer ticks
Run time = 96 timer ticks
Run time = 96 timer ticks
Run time = 96 timer ticks
Run time = 106 timer ticks
Run time = 96 timer ticks
Run time = 96 timer ticks
Run time = 96 timer ticks
Run time = 106 timer ticks
...
Removing the divides from either thread restores determinism.

Still not having any luck changing SystemFrequency of ReferenceFrequency in the .xn file.
m_y
Experienced Member
Posts: 69
Joined: Mon May 17, 2010 10:19 am

Post by m_y »

Heater wrote:Still not having any luck changing SystemFrequency of ReferenceFrequency in the .xn file.
The first thing to check is that you can successfully alter them independently - try flashing LEDs using first instruction cycles then a timer to check that the flash speed changes when you change the appropriate clock rates.
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

Heater wrote:

Code: Select all

<Node Id="0" Type="XS1-G4B" Oscillator="20MHz" SystemFrequency="100MHz" ReferenceFrequency="100MHz">
On an XS1-G device you should ensure that the reference frequency is at least half of the system frequency. So in the example above you should either set the System Freq to 200, or the ref freq to 50MHz.

When you say that you are having trouble with it, does that mean that the results you've posted are not using those figures? If so, what are the settings you are using for the clock?
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

@Heater,

Thanks for posting the code example. A couple of points

1. In the waste threads, can you put the thread into fast mode. These threads may not be issuing instructions otherwise

Code: Select all

set_thread_fast_mode_on();
2. timed_thread and calc_thread both use the divider. Since there is only 1 divide unit that is shared across all threads on the XCore, they will have to arbitrate for the divide unit and you may well see odd behaviour. I would avoid all divide (& rem) operations in all threads when you are performing timing checks, although if you only use them in 1 thread, then the performance will be predictable.

3. printf(). This puts the XCore into debug mode. This means that all the threads stop their current execution, then thread 0 starts executing the debug monitor code and, relatively slowly, performs the printf. When the print stops, the threads return to executing their code. So if you perform a print operation all timing bets are off. To avoid this, create an array of results, then print all of the results from the array when all the iterations of the test have completed.
Heater
Respected Member
Posts: 296
Joined: Thu Dec 10, 2009 10:33 pm

Post by Heater »

@m_y and Woody,

Turns out I have been having a problem with Eclipse. Whilst busy changing from Debug to Release builds I ended up changing the .xn file, rebuilding the correct version but then running the wrong one.
God I hate IDE's.

Working from the command line tools, so we know where we are, confirms that changing SystemFrequency and ReferenceFrequency in the .xn does indeed work and changes by test results as expected. With one strange result:

Code: Select all

Sys Clk Ref Clk Time (secs)
400     400     10
400     300     Not achievable
400     200     5
400     150     Not achievable
400     100     10
400      50     20
Seems a Sys Clock of 400 with Ref Clock of 400 and 100 are the same but the mapper issues no warning/error about that. Both give my jitter like so:

Code: Select all

Run time = 105 timer ticks
Run time = 96 timer ticks
Run time = 96 timer ticks
Run time = 96 timer ticks
Run time = 106 timer ticks
Run time = 96 timer ticks
...

I can see that if I change all divides in my calc_thread the jitter in the timed thread disappears.

@Woody,

I can see no effect when putting my waste_threads into fast mode. But as far as I can tell neither should I. If I understand correctly fast mode only forces threads to issue instructions while they
are waiting on a port/timer/channel instead of sleeping. The waste threads do no such waiting.

Further I would expect fast mode to only have an effect with more than 4 threads when there are actually free cycles for other threads to run when one is sleeping.
2. timed_thread and calc_thread both use the divider. Since there is only 1 divide unit that is shared across all threads on the XCore, they will have to arbitrate for the divide unit and you may well
see odd behaviour. I would avoid all divide (& rem) operations in all threads when you are performing timing checks, although if you only use them in 1 thread, then the performance will be
predictable.
Yes. Here I am basically trying to prove that that is true:) Seems to be so. Removing the divides from the calc_thread restores determinism to the timed_thread as advertised.
3. printf(). This puts the XCore into debug mode....
I'm glad you mentioned that. I have been wondering what goes on when I do a printf. And what happens when many threads do a printf etc.

I my tests there is no timing going on across printf's so I'm not sure that all timing bets are off in this case.
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

1. I wasn't 100% sure that the compiler wouldn't work out it wasn't doing anything and wait. I just wanted to ensure that this wasn't causing a problem. Obviously not.

3. You may be right that it might not cause you a problem. Similar reason to above, but I sometimes see unexpected (to me) artifacts from printing. Worth being aware of anyway.

I think the errors/warnings from the freq setting are issued at slightly different times to when you might expect. I'll leave m_v to explain this.
Heater
Respected Member
Posts: 296
Joined: Thu Dec 10, 2009 10:33 pm

Post by Heater »

Woody,

I get this error out of the mapper when setting a 300MHz ref clock.

Code: Select all

Invoking: Mapper/Linker
xcc -Werror=timing-syntax -o "determinism_test.xe"  ./main.o    ../XC-1A.xn  
../XC-1A.xn:15 Warning: XN11137 300000000Hz reference frequency for node "0" could not be achived. Using 200000000Hz.
../XC-1A.xn:15 Warning: XN11137 300000000Hz reference frequency for node "0" could not be achived. Using 200000000Hz.
xmap: Warning: Node "0" does not have 100Mhz reference clock.
Setting a 100MHz ref is error/warning free of course.

Setting a 400MHz results in only a warning which looks OK:

Code: Select all

xmap: Warning: Node "0" does not have 100Mhz reference clock.
However my timing results come out exactly the same as for 100MHz!!!