error: cannot apply [[combine]] to multi-tile par

Technical questions regarding the xTIMEcomposer, xSOFTip Explorer and Programming with XMOS.
User avatar
aclassifier
Respected Member
Posts: 318
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

error: cannot apply [[combine]] to multi-tile par

Postby aclassifier » Mon Jul 09, 2018 8:09 am

What is a "multi-tile par"? I see "multi-tile main" in an older post (error: multi-tile main must consist of single non-empty par) but now I am at a stage where I, in a larger project, don't seem able to work my way around it (as I was a couple of years ago).

Here's a short code example. There is only tile[0] and there should be no hidden use of any other tile.

Code: Select all

#include <platform.h>
#include <timer.h> // XS1_TIMER_HZ etc

typedef signed int time32_t;

interface ifa {
    void but (int x);
};

[[combinable]]
void button (client interface ifa i_but) {
   timer tmr;
   time32_t time;
   tmr :> time;
   while (1) {
       select {
           case tmr when timerafter(time) :> void: {
               i_but.but(time/XS1_TIMER_KHZ); // ms
               time += XS1_TIMER_HZ;
               break;
           }
       }
   }
}

[[combinable]]
void handle (server interface ifa i_but[3]) {
    while (1) {
        select {
            case i_but[int i].but (int val) : {
                break;
            }
        }
    }
}

int main (void) {
    interface ifa i_but[3];
    par {
        on tile[0].core[0]: handle (i_but);
        [[combine]]
        par {
        // ^~~~~ error: cannot apply [[combine]] to multi-tile par
            on tile[0].core[0]: button (i_but[0]);
            on tile[0].core[0]: button (i_but[1]);
            on tile[0].core[0]: button (i_but[2]);
        }
    }
    return 0;
}

By the way, this also fails:

Code: Select all

int main (void) {
    interface ifa i_but[3];
    [[combine]]
    par {
    // ^~~~~ error: cannot apply [[combine]] to multi-tile par
        on tile[0].core[0]: handle (i_but);
        on tile[0].core[0]: button (i_but[0]);
        on tile[0].core[0]: button (i_but[1]);
        on tile[0].core[0]: button (i_but[2]);
    }
    return 0;
}
User avatar
infiniteimprobability
XCore Legend
Posts: 1116
Joined: Thu May 27, 2010 10:08 am
Contact:

Postby infiniteimprobability » Mon Jul 09, 2018 9:20 am

Tiles can only communicate via channels - there are no shared resources. This includes memory. Combining functions essentially flattens their select cases into one large select running on the same thread (aka logical core). They of course must be in the same memory space - ie. be on the same tile.
So the compiler is right - trying to combine tasks on different tiles is not going to work..
User avatar
aclassifier
Respected Member
Posts: 318
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Postby aclassifier » Mon Jul 09, 2018 9:27 am

infiniteimprobability wrote:Tiles can only communicate via channels - there are no shared resources. This includes memory. Combining functions essentially flattens their select cases into one large select running on the same thread (aka logical core). They of course must be in the same memory space - ie. be on the same tile.
So the compiler is right - trying to combine tasks on different tiles is not going to work..

But have I tried to combine tasks on different tiles? Where is my blind spot?

The channel version also fails:

Code: Select all

#include <platform.h>
#include <timer.h> // XS1_TIMER_HZ etc

 [[combinable]]
 void button (chanend c_out) {
    timer t;
    int s;
    t :> s;
    while (1) {
        select {
            case t when timerafter(s) :> void: {
                c_out <: (s/XS1_TIMER_KHZ); // ms
                s += XS1_TIMER_HZ;
                break;
            }
        }
    }
}

[[combinable]]
void handle (chanend c_but[3]) {
    int val;
    while (1) {
        select {
            case c_but[int i] :> val: {
                break;
            }
        }
    }
}

int main (void) {
    chan c_but[3]; // Using 6 chanends always
    [[combine]]
    par {
    // ^~~~~ error: cannot apply [[combine]] to multi-tile par
        on tile[0].core[0]: handle (c_but);
        on tile[0].core[0]: button (c_but[0]);
        on tile[0].core[0]: button (c_but[1]);
        on tile[0].core[0]: button (c_but[2]);
    }
    return 0;
}
User avatar
infiniteimprobability
XCore Legend
Posts: 1116
Joined: Thu May 27, 2010 10:08 am
Contact:

Postby infiniteimprobability » Mon Jul 09, 2018 9:32 am

I see your point. I think it's because you have the on tile[0] placement directive below a combinable directive. What you have done should be valid though.

You are mixing methods of declaring combinable (.core[0] and [[combine]]) although again what you have declared should be valid. Try raising any tile[n] directives to the first level par and using [[combine]] instead..
User avatar
aclassifier
Respected Member
Posts: 318
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Postby aclassifier » Mon Jul 09, 2018 9:41 am

In the last two examples tile[n] directives are on the top par, as there is only one par. Removing the core[n] does not help. The full on all have to be removed. Hmm?
User avatar
infiniteimprobability
XCore Legend
Posts: 1116
Joined: Thu May 27, 2010 10:08 am
Contact:

Postby infiniteimprobability » Mon Jul 09, 2018 10:02 am

I was thinking this (apologies for poor indenting):

Code: Select all

par {
  on tile[0]:{
    [[combine]]
    par {
        handle (c_but);
        button (c_but[0]);
        button (c_but[1]);
        button (c_but[2]);
    }
}
    return 0;
User avatar
aclassifier
Respected Member
Posts: 318
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Postby aclassifier » Mon Jul 09, 2018 10:24 am

OKAY:-)

Code: Select all

par {
    on tile[0]: {
        [[combine]]
        par {
            handle (i_but);
            button (i_but[0]);
            button (i_but[1]);
            button (i_but[2]);
        }
    }
}
/*
Constraint check for tile[0]:
  Cores available:            8,   used:          1 .  OKAY
  Timers available:          10,   used:          1 .  OKAY
  Chanends available:        32,   used:          0 .  OKAY
  Memory available:       65536,   used:       1816 .  OKAY
    (Stack: 384, Code: 1204, Data: 228)
Constraints checks PASSED.
Build Complete
*/

I hadn't noticed that on tile[n] could be used like that! This made my day! Even zero chanends!

However, the channel version does not compile:

Code: Select all

#include <platform.h>
#include <timer.h> // XS1_TIMER_HZ etc

 [[combinable]]
 void button (chanend c_out) {
    timer t;
    int s;
    t :> s;
    while (1) {
        select {
            case t when timerafter(s) :> void: {
                c_out <: (s/XS1_TIMER_KHZ); // ms
                s += XS1_TIMER_HZ;
                break;
            }
        }
    }
}

[[combinable]]
void handle (chanend c_but[3]) {
    int val;
    while (1) {
        select {
            case c_but[int i] :> val: {
                break;
            }
        }
    }
}

#define DO_PLACED 2

int main (void) {
    chan c_but[3];

    #if (DO_PLACED == 1)
        [[combine]]
        par {
        // ^~~~~ error: cannot apply [[combine]] to multi-tile par
            on tile[0].core[0]: handle (c_but);
            on tile[0].core[0]: button (c_but[0]);
            on tile[0].core[0]: button (c_but[1]);
            on tile[0].core[0]: button (c_but[2]);
        }
    #elif (DO_PLACED == 2)
        par {
            on tile[0]: {
                [[combine]]
                par {
                    handle (c_but);
                    //     ^~~~ note: other end is used here
                    button (c_but[0]);
                    //      ^~~~ error: `c_but' used between two combined tasks
                    button (c_but[1]);
                    //      ^~~~ error: `c_but' used between two combined tasks
                    button (c_but[2]);
                    //      ^~~~ error: `c_but' used between two combined tasks
                }
            }
        }
    #endif
    return 0;
}

Off Topic
Should this be noticed to the compiler guys, that my "wrong" syntax should perhaps still make sense?
User avatar
aclassifier
Respected Member
Posts: 318
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Postby aclassifier » Mon Jul 09, 2018 10:38 am

Just now I think that

Code: Select all

error: components of multi-tile par must have `on' specifier or call a service

probably is just as confusing (to me..?). See example in The combined code: 6 to zero channels!

I've summarised this at “It’s not you” errors - Multi-tile par. Thanks!

Who is online

Users browsing this forum: No registered users and 136 guests