Channel Array Use

Technical questions regarding the XTC tools and programming with XMOS.
MarcAntigny
Active Member
Posts: 61
Joined: Tue Feb 13, 2018 2:50 pm

Channel Array Use

Post by MarcAntigny »

Hi all,

Working with the xCore-200, I try to use channel array. First, could someone validate that the current syntax correspond to what I want ?

Code: Select all

chan chanData[NUMBER_OF_CHANNELS];
However when I create threads in a par statement like in the following piece of code, the compiler considers the channel array as only one channel and raise an error `chanData' used in more than two parallel statements (byte range 0..4).

Code: Select all

par{
mytask1(chanData[0], chanData[1]);
mytask2(chanData[1], chanData[2]);
mytask3(chanData[2], chanData[3]);
}
Did someone got the same error (with the byte range part) ? Or is there a good (better ?) way to use channel arrays ?

Thanks a lot for your help,
Marc


User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

Hi. I think the issue is the use of the same channel being index on multiple parallel calls.

Can you try the following and see if this raises any errors?

Code: Select all

par{
mytask1(chanData[0], chanData[1]);
// mytask2(chanData[1], chanData[2]);
mytask3(chanData[2], chanData[3]);
}
MarcAntigny
Active Member
Posts: 61
Joined: Tue Feb 13, 2018 2:50 pm

Post by MarcAntigny »

Hi Mon,
I tried your mod but as expected, it didn't raise any error. However this code doesn't correspond to my goal, I need to connect all of those threads with channels. If I use only different channel to instantiate the threads, I'll get separated threads and not connected ones as I wish.
I also tried :

Code: Select all

par{
mytask1(chanData[0], chanData[1]);
mytask2(chanData[1], chanData[2]);
//mytask3(chanData[2], chanData[3]);
}
This code doesn't raise error either, even the same channel (chanData[2]) is used in multiple parallel statement. So I suspect that the compiler views chanData as a channel (and not an array of channels).
Maybe it is about the channel array definition. I did a lot of search between the docs and xCore forum but there is nowhere a precise explanation of how to use it.
robertxmos
XCore Addict
Posts: 169
Joined: Fri Oct 23, 2015 10:23 am

Post by robertxmos »

Hi
What is the signature of mytask1() etc?
The following, where the tasks each take two chanends (rather than chans) builds fine:

Code: Select all

void mytask(chanend a, chanend b);
void foo() {
  chan chanData[4];
  par{
    mytask(chanData[0], chanData[1]);
    mytask(chanData[1], chanData[2]);
    mytask(chanData[2], chanData[3]);
  }
}
robertxmos
XCore Addict
Posts: 169
Joined: Fri Oct 23, 2015 10:23 am

Post by robertxmos »

p.s.
A 'chan' has two ends, which are tied together for you when you declare a 'chan' variable.
You could instead declare two 'chanend' and tie them together yourself... bad idea :-)
When you pass a 'chan' to a function taking a 'chanend', one of the ends is implicitly passed.
If you pass only one end or more than two ends, the compiler will warn you.

The error you were getting, I suspect, is because you were trying to pass the same resource (chan rather than chanend) to two parallel tasks. Hence the parallel usage error.
MarcAntigny
Active Member
Posts: 61
Joined: Tue Feb 13, 2018 2:50 pm

Post by MarcAntigny »

Hi robert,
The signature is same as yours.

Code: Select all

void mytask(chanend a, chanend b);
To be more precise the code is more similar to this :

Code: Select all

void mytask(chanend a, chanend b);
void foo() {
  chan chanData[4];
  int indexData[4];
  par{
    mytask(chanData[indexData[0]], chanData[indexData[1]]);
    mytask(chanData[indexData[1]], chanData[indexData[2]]);
    mytask(chanData[indexData[2]], chanData[indexData[3]]);
  }
}
where the indexData array is only an array of int which index the channel to connect between tasks.
robertxmos
XCore Addict
Posts: 169
Joined: Fri Oct 23, 2015 10:23 am

Post by robertxmos »

In the case of 'indexData' there is only one end! Hence you have parallel usage issues.
I will need to look more carefully what is happening, as your intent looks reasonable.
MarcAntigny
Active Member
Posts: 61
Joined: Tue Feb 13, 2018 2:50 pm

Post by MarcAntigny »

So you mean the array indexing doesn't work for thread instantiation ? chanData[indexData[N]] being not seen as chanData["the value in indexData Nst cell"] but as chanData["the value in indexData 0st cell"].
Do you think it could be better if I modify the code to the following :

Code: Select all

void mytask(chanend a, chanend b);
void foo() {
  chan chanData[4];
  int indexData[4];
  par{
  {
    int indexData_0 = indexData[0];
    int indexData_1 = indexData[1];
    mytask(chanData[indexData_0], chanData[indexData_1]);
   }
  {
    int indexData_1 = indexData[1];
    int indexData_2 = indexData[2];
    mytask(chanData[indexData_1], chanData[indexData_2]);
   }
  {
    int indexData_2 = indexData[2];
    int indexData_3 = indexData[3];
    mytask(chanData[indexData_2], chanData[indexData_3]);
   }
  }
}
(which is really ugly).
Thanks for your hint.
robertxmos
XCore Addict
Posts: 169
Joined: Fri Oct 23, 2015 10:23 am

Post by robertxmos »

I think the problem is that the value of 'indexData[0]' can't be known, therefore it is assuming it could be 0,1,2,or 3 - and is reporting the error for all 4 'chanData' array elements for me.
Should this be a warning rather than an error... only if people respect the warning and do something about it!
Thus, moving the variable from an array into an integer wont help.
The compiler wants to make sure that each element of chanData is used exactly twice on different logical cores - and it can't be sure.
It is a shame the xC language does not collapse the indexData[] into a const literal during the compilation (e.g. 'static const' parameters for array sizes).

The work around is to use the preprocessor if you want comiler time variablitiy.
or you may be able to cast the type away and pass the chanend id as an integer and reform it at the other end.... if you can get past the compilers strict enforcement :-/
MarcAntigny
Active Member
Posts: 61
Joined: Tue Feb 13, 2018 2:50 pm

Post by MarcAntigny »

Ok I understand what you mean.
In my case I can't use preprocessor instructions because the whole system is dynamic (mytask() ends with a command, the indexData array is modified by another thread and read via unsafe pointers...). I didn't expand the whole code to make it more readable for the forum.
I tried passing chanend through channel but I couldn't find any doc to explain the channel structure. And global chan array are not allowed.
If you know any way to send the chanend id, let me know.
Thanks again.
Post Reply