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

Technical questions regarding the XTC tools and programming with XMOS.
Post Reply
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

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

Post by aclassifier »

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;
}


--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
infiniteimprobability
XCore Legend
Posts: 1126
Joined: Thu May 27, 2010 10:08 am
Contact:

Post by infiniteimprobability »

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: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

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;
}
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
infiniteimprobability
XCore Legend
Posts: 1126
Joined: Thu May 27, 2010 10:08 am
Contact:

Post by infiniteimprobability »

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: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

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?
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
infiniteimprobability
XCore Legend
Posts: 1126
Joined: Thu May 27, 2010 10:08 am
Contact:

Post by infiniteimprobability »

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: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

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?
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

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!
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Post Reply