6 Using multiple memories from C code

TCE supports accessing multiple address spaces from C code via the __attribute__((address_space(N)) extension. The numerical id from the attribute is used to connect the memory reference to the ADF address space using the XML element numerical-id. There can be one or more numerical ids mapped to a single ADF address space.

The following is from an ADF with three separate data address spaces with numerical ids 0, 1, and 2. The numerical id 0 is reserved for the default data address space which stores the stack, heap and the global constant data.

   <address-space name="data">
    <width>8</width>
    <min-address>0</min-address>
    <max-address>16777215</max-address>
    <numerical-id>0</numerical-id>
  </address-space>

  <address-space name="data1">
    <width>8</width>
    <min-address>0</min-address>
    <max-address>65535</max-address>
    <numerical-id>1</numerical-id>
  </address-space>

  <address-space name="data2">
    <width>8</width>
    <min-address>0</min-address>
    <max-address>16383</max-address>
    <numerical-id>2</numerical-id>
  </address-space>

The address spaces can be referred to from the C program with code like this:

#include <stdio.h>

#define ASIZE 4

volatile int space0[ASIZE] __attribute__((address_space(0)));
volatile int space0_1[ASIZE] __attribute__((address_space(0)));
volatile int space1[ASIZE] __attribute__((address_space(1)));
volatile int space1_1[ASIZE] __attribute__((address_space(1)));
volatile int space2[ASIZE] __attribute__((address_space(2)));
volatile int space2_1[ASIZE] __attribute__((address_space(2)));

int main() {
    int i = 0;

    /* The start addresses of the tables should overlap as
       they are allocated in different address spaces. */
    iprintf("space0@%x space0_1@%x space1@%x space1_1@%x space2@%x space2_1@%x\n",
            (unsigned)space0, (unsigned)space0_1, (unsigned)space1, (unsigned)space1_1,
            (unsigned)space2, (unsigned)space2_1);

    return 0;
}

The effect of having multiple disjoint address spaces is visible when simulating the code as the arrays allocated to the different memories share the same addresses but different storage:

space0@a84 space0_1@a94 space1@4 space1_1@14 space2@4 space2_1@14

The space0 array is stored in the default address space. In the beginning of the default address space there is usually some global data for some C library functions such as the iprintf or the emulation library, thus ending up with the start address of 0xa84 for the array0. For the extra address spaces 1 and 2, the arrays start from 4 which is the first valid storage address in those address spaces. Storing data to address 0 is not done to avoid problems with NULL pointers pointing to valid data (in this case space1 and space2 would have been stored at address 0 = NULL).

When using custom operation calls to manually execute operations that access memory on processors that have multiple data address spaces, it should be done using _TCEAS_OPERATIONNAME macro instead of using _TCE_OPERATIONNAME macro. See section 5.1.2 for more information about these custom operation call macros.

Pekka Jääskeläinen 2018-03-12