interface notification cost

If you have a simple question and just want an answer.
zjzzjz
New User
Posts: 2
Joined: Thu Oct 15, 2015 4:56 pm

interface notification cost

Post by zjzzjz »

Hi,

I just started to learn XMOS. In between tasks, we can use notification to do asynchronous communication. 

What is the cost of an interface notification in terms of CPU cycles? For example, if the clear_notification defined by client does nothing, how many cycles does it take from the client calls notification to the client finishes clear_notification if the server is able to process the notification when the client calls it.

I wanted to know the best granularity of each task. Intuitively if a task is too small, the communication cost may dominate. If the timing analysis tool can report the time between endpoints, do we document costs of all kinds of XC instructions?

Thank you,

J

User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1164
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

I did a quick test and setting a notfication is in the order of 140ns (4 cores running) and clearing a notification was quite long, for an empty notification clear case - about 380ns.

Remember that setting a notification is an asycchronous event and so you don't have to wait for anything at the client end, however clearing the notification will block until the clears notification case is executed, which maintains synchronisation.

Underneath it uses channels for the mechanism. Here's some test code for your own experiements!

#include <xs1.h>

#include <stdio.h>

 

#define NOTIFICATION  1

 

#define INTERVAL_1    100000  //1ms

#define INTERVAL_2    150000  //1.5ms

 

interface do_things{        

  [[notification]] slave void notify(void);

  int read(int idx);

  [[clears_notification]] void notification_clear(void);

 

};

 

int start_time, end_time;

timer t_perf;

 

static inline void start(void){

  t_perf :> start_time;

}

 

static inline void stop(void){

  t_perf :> end_time;

  printf("Time taken = %d ns\n", 10*(end_time - start_time));

}

 

[[combinable]]

void client_task(client interface do_things i_things){

 

  timer t_interval;

  int next_interval;

  t_interval :> next_interval;

  next_interval += INTERVAL_1;

 

  while (1){

    select{

      case t_interval when timerafter (next_interval) :> void:

        next_interval += INTERVAL_1;

        printf("tick client\n");

 

        break;

 

#if NOTIFICATION

      case i_things.notify():

        int val = i_things.read(0);

        start();

        i_things.notification_clear();

        stop();

      break;

#endif

    }

  }

}

 

[[combinable]]

void server_task(server interface do_things i_things){

 

  timer t_interval;

  int next_interval;

  t_interval :> next_interval;

  next_interval += INTERVAL_2;

 

  while(1){

    select{

      case i_things.read(int idx) -> int val:

        delay_microseconds(1);

        break;

 

      case i_things.notification_clear():

        delay_microseconds(1);

        break;

 

#if NOTIFICATION

      case t_interval when timerafter (next_interval) :> void:

        next_interval += INTERVAL_2;

        printf("tick server\n");

        //start();

        i_things.notify();

        //stop();

        break;

#endif

    }

  }

}

 

 

int main() {

  interface do_things i_things;

//[[combine]]

  par{

    server_task(i_things);

    client_task(i_things);

  }

  return 0;

}

 
Engineer at XMOS