Page 1 of 1

Multi Core example

Posted: Sat Jun 10, 2017 3:30 pm
by Obtuse
I am trying to understand running something on a separate core of a tile,,, and getting no place.
For the code below, is it even possible to do this? This is only a learning exercise and really don't know what to do.

[combinable], while{ select{, I have no clue as to what goes where.

Code: Select all

/*
 * 3core.xc
 *
 *  Created on: Jun 9, 2017
 *      Author: len
 *
 *      XS1-L16A-128-QF124-C10 Device
 */

#include <xs1.h>
#include <platform.h>
#define DELAY 20000
#define TRUE 1

on tile [1] : port out port1E = XS1_PORT_1E;

// on tile 0 core0.
void worker (chanend ch)
{
  timer tmr;
  unsigned t;
  unsigned workdata = 0;

  while (TRUE)
      {
    tmr :> t;
    tmr when timerafter (t+ DELAY*3) :> void;
    ch <: workdata;
      }
}

//on tile[0}.core[2]
void mimic (chanend dh)
{
  timer tm;
  unsigned t1;
  unsigned count = 1;

  while (TRUE)
      {
    tm :> t1;
    tm when timerafter (t1+ DELAY+1000) :> void;
    dh <: count;
      }
}

// on tile 1 core0
void boss (chanend ch, chanend dh )
{
    unsigned bossdata;
    timer time;
    unsigned d;

    while (TRUE)
    {
       ch :> bossdata;
       port1E <: bossdata;
       time :> d;
       time when timerafter (d+ (DELAY)) :> void;

       dh :> bossdata;
       port1E <: bossdata;
       time :> d;
       time when timerafter (d+ (DELAY*2)) :> void;

    }
}


int main (void)
{
        chan ch; chan dh;
  par {
            on tile [0] : worker ( ch );
            on tile [0] : mimic ( dh );
            //on tile [0].core[2] : mimic ( dh );
            on tile [1] : boss ( ch, dh );
      }
  return 0;
}

Re: Multi Core example

Posted: Sat Jun 10, 2017 5:25 pm
by Gothmag
https://www.xmos.com/support/tools/prog ... nent=17653
Check this PDF. It is the programming manual. It's a short but informative read like K&R C, should help you to understand what you want to do. You can also use it as a quick reference when you need.

Re: Multi Core example

Posted: Sat Jun 10, 2017 7:35 pm
by Obtuse
I have been all through the manuals, many times.
The supplied code has been modified 100s of times. Like most people it is not easy to admit stupidity. However I'm just not putting two and two together. I am stupid, and Qbtuse.

Re: Multi Core example

Posted: Mon Jun 12, 2017 6:31 am
by zhengyang0512
Hi, it's not wise to use the channel across the tiles. Your main process should be

Code: Select all

int main (void)
{
        chan ch; chan dh;
  par {
            on tile [0] : worker ( ch );
            on tile [0] : mimic ( dh );
            //on tile [0].core[2] : mimic ( dh );
            on tile [0] : boss ( ch, dh );
      }
  return 0;
}
I think this should be work.

Re: Multi Core example

Posted: Mon Jun 12, 2017 3:03 pm
by Obtuse
@zhengyang0512

Confusion can be implemented by official statements as in the Programming Guide in the Communication/Channels section.

--------------------------------------------------------------------------------
Channels (both streaming and normal) are the lowest level
of abstraction to the communication hardware available in xC and can be used to
implement quite efficient inter-core communication but have no type-checking and
cannot be used between tasks on the same core.
--------------------------------------------------------------------------------

So unless the compiler assigns tasks to different cores automatically when using channels then the above guidance is confusing.

As for channels across tiles.
This is a simulator exercise and I ask what other inter-tile communication would do the job.?

I really would like to keep this as simple as possible.

Thank You,

P.S. In the real world external signals could be used. In the virtual world...?

Re: Multi Core example

Posted: Mon Jun 12, 2017 3:39 pm
by mon2

Re: Multi Core example

Posted: Mon Jun 12, 2017 5:01 pm
by Obtuse
@mon2

Thanks for the link. I will give it a go. :)

Re: Multi Core example

Posted: Mon Jun 12, 2017 10:14 pm
by plex
Hi,
I can only guess what you are trying to achieve but here are some comments on your code:
The channels inputs and outputs are blocking. You will find in the documentation that they might have some buffering but initially you need to assume they do not, to build your code correctly.
This means that when you send something through a channel the code will block until it is received on the other end. The same goes for receive, it will wait until data arrives.
What this does is force the tasks to synchronize. So the "mimic" task that looks like it should send data every 21000 ticks will actually send data every ~ 60000 ticks because this is the rate at which the receiving task can accept the data.
If you want asynchronous communications then usually you have to used an intermediate task that will act as a repository and the other tasks will send and get data from it.
There is a way to make the receive on channel not blocking by using a "select" statement with a default case.
The programming guide and the examples you can access through the xtimecomposer are very helpful in understanding the xcore devices and language. I had a lot of difficulty as well when I started.
I think that the statement that channels should not be used between tasks on the same core in an error.
The documentation can be confusing at times and I find that details are sometimes missing but a big part of it is very useful.
Regarding your question about other communications interfaces there are streaming channels and at a higher level interfaces. Interfaces are channel communications disguised by the compiler as "functions". The compiler underneath does all the difficult work. When used between tasks on the same core the compiler might not even use actual channels.

Re: Multi Core example

Posted: Tue Jun 13, 2017 1:26 pm
by Obtuse
@plex

Hello,
This was an exercise for me to use the [[combinable]] function in a simple program. It was simply a question that is now answered.

The code itself was stripped from a much larger program that depends on channel blocking for event timing. I simply copied the 'worker' section, renamed it 'mimic', and set about to answer that question. It is sloppy code, that really has no useful purpose other than to demonstrate running code on a separate core of a tile. I have found other programs that do this but not really suitable for running on a simulator for my own education.

I will spend some time cleaning up the mess I created with the code, comment it and post it for others with the same question.

It was just a question, 'How to use a separate core of a tile?' If I had not been reading the programming guide I would not have had the question in the first place. Ignorance is bliss. :-)

Thanks to all for your interest and advice.

Re: Multi Core example

Posted: Wed Jun 14, 2017 8:52 pm
by Obtuse
The code below is derived from the first post in this thread.
It may be of use to some folks looking to play around with the [[combinable]] function on the xTIMEcomposer simulator.

It will run on various Xmos chips and probably some kits, Read the comments in the source file. Channel Blocking and using more than one core per tile where the simple goal of this exercise.

Code: Select all

/*
 * 3core.xc
 *
 *  Created on: Jun 12, 2017
 *      Author: len
 *
 *      Just an example for using [[combinable]], while{ select{case : }}
 *      XS1-L16A-128-QF124-C10 Device and probably others.
 *
 */

#include <xs1.h>
#include <platform.h>
#include <timer.h>
#define DELAY 2000 // Set to 20 million for flashing LEDs on hardware.
#define TRUE 1

on tile [1] : port out port1E = XS1_PORT_1E;

// on tile 0 core0.
void worker (chanend bosswork ) // Send LOWs to the boss.
{
  timer tmr;
  unsigned t;
  unsigned workdata = 0;

  while (TRUE)
      {
    workdata = 0;
    //bosswork <: workdata; // Send a 0 to boss and wait for it to go.
    tmr :> t; //Reset t.
    tmr when timerafter (t+ (DELAY*8)) :> void; // Increase HI time by increasing DELAY multiplier.
    bosswork <: workdata; // Send a 0 to boss and wait for it to go.
    workdata = 1; // Just a test.
      }
}

//on tile[0}.core[1] Send HIs to the boss.
[[combinable]]
void mimic ( chanend bossmimic )
{
  timer tmr2;
  unsigned t1;
  unsigned mimicdata = 1;

  while (1)
  {

      select{
          case tmr2 when timerafter (t1 + DELAY) :> void: // Short DELAY due to lazy programmer.
                 bossmimic <: mimicdata; // Send a 1 to boss.
                 mimicdata = 0; // Just a test.
                 tmr2 :> t1; //reset t1.
                 mimicdata = 1; // Test is over.
               break;
            }
  }
}


// on tile 1 core0
void boss (chanend bosswork, chanend bossmimic )
{
    unsigned bossdata;
    timer time;
    unsigned d;

    while (TRUE)
    {
       bosswork :> bossdata; // Channel blocked until LOW sent by worker.
       port1E <: bossdata; //  Wait for worker to send. Toggle port LOW. Hold LOW till after DELAY.
       time :> d; // Set variable d to present timer ticks
       time when timerafter (d+ (DELAY*2)) :> void; // Up LOW time by increasing multiplier.
       bossmimic :> bossdata; // Get the 1 sent by mimic.
       port1E <: bossdata; // Toggle port1E HI. Hold port1E HI until worker sends LOW.
    }
}


int main (void)
{
        chan bosswork; chan bossmimic;
  par {
            on tile [0] : worker ( bosswork );
            on tile [0].core[1] : mimic (bossmimic);
            on tile [1] : boss ( bosswork, bossmimic );
      }
  return 0;
}