wiki:library_stdio

Version 56 (modified by alain, 9 years ago) (diff)

--

GIET_VM / User-Level System Calls

The stdio.c and stdio.h files define all system calls provided to user applications by the GIET-VM. They are generally prefixed by giet_.

  1. GIET_VM / User-Level System Calls
    1. Processor related system calls
      1. 1) void giet_proc_xyp( unsigned int* cluster_x, unsigned int* …
      2. 2) unsigned int giet_proctime()
      3. 3) unsigned int giet_rand()
    2. User task related system calls
      1. 1) unsigned int giet_proc_task_id()
      2. 2) unsigned int giet_global_task_id()
      3. 3) unsigned int giet_thread_id()
    3. Coprocessors related system calls
      1. 1) void giet_coproc_alloc( unsigned int coproc_type, unsigned …
      2. 2) void giet_coproc_release( unsigned int cluster_xy )
      3. 3) void giet_coproc_channel_init( unsigned int cluster_xy, …
      4. 4) void giet_coproc_channel_start( unsigned int cluster_xy, …
      5. 5) void giet_coproc_channel_stop( unsigned int cluster_xy, …
      6. 6) void giet_coproc_completed( unsigned int cluster_xy )
    4. TTY related system calls
      1. 1) void giet_tty_alloc()
      2. 2) void giet_tty_printf( char* format, ... )
      3. 3) void giet_tty_getc( char* byte )
      4. 4) void giet_tty_getw( unsigned int* val )
      5. 5) void giet_tty_gets( char* buf, unsigned int bufsize )
      6. 6) void giet_shr_printf( char* format, ... )
    5. Timer related system calls
      1. 1) void giet_timer_alloc()
      2. 2) void giet_timer_start( unsigned int period )
      3. 3) void giet_timer_stop( )
    6. File system related system calls
      1. 1) int giet_fat_open( const char* pathname, unsigned int flags )
      2. 2) void giet_fat_read( unsigned int fd, void* buffer, unsigned …
      3. 3) void giet_fat_write( unsigned int fd, void* buffer, unsigned …
      4. 4) void giet_fat_close( unsigned int fd )
    7. Network related system call
      1. 1) unsigned int giet_nic_tx_alloc( unsigned int xmax, unsigned …
      2. 2) unsigned int giet_nic_rx_alloc( unsigned int xmax, unsigned …
      3. 3) void giet_nic_tx_start( unsigned int channel )
      4. 4) void giet_nic_rx_start( unsigned int channel )
      5. 5) void giet_nic_tx_move( unsigned int nic_channel, void* buffer )
      6. 6) void giet_nic_rx_move( unsigned int nic_channel, void* buffer )
      7. 7) void giet_nic_tx_stop( unsigned int channel )
      8. 8) void giet_nic_rx_stop( unsigned int channel )
      9. 9) void giet_nic_rx_clear( unsigned int channel )
      10. 10) void giet_nic_tx_clear( unsigned int channel )
      11. 11) void giet_nic_rx_stats( unsigned int channel )
      12. 12) void giet_nic_tx_stats( unsigned int channel )
    8. Frame Buffer related system calls
      1. 1) void giet_fbf_cma_alloc()
      2. 2) void giet_fbf_cma_start( void* buf0, void* buf1, unsigned int …
      3. 3) void giet_fbf_cma_display( unsigned int buffer )
      4. 4) void giet_fbf_cma_stop( )
      5. 5) void giet_fbf_sync_read( unsigned int offset, void* buffer, …
      6. 6) void giet_fbf_sync_write( unsigned int offset, void* buffer, …
    9. Miscelaneous system calls
      1. 1) void giet_exit( char* string )
      2. 2) void giet_assert( unsigned int condition, char* string )
      3. 3) void giet_context_switch()
      4. 4) void giet_procs_number( unsigned int* x_size , unsigned int* …
      5. 5) void giet_vseg_get_vbase( char* vspace_name, char* …
      6. 6) void giet_vseg_get_length( char* vspace_name, char* …
      7. 7) void giet_heap_info( unsigned int* vaddr, unsigned int* …
      8. 8) void giet_get_xy( void* ptr, unsigned int* px, unsigned int* py )

All these functions use a syscall instruction to enter the system. In case of system call failure (illegal arguments), the calling task is killed with a giet_exit().

Therefore, for all these system calls, the return value has not to be tested by the calling task.

Processor related system calls

1) void giet_proc_xyp( unsigned int* cluster_x, unsigned int* cluster_y unsigned int* lpid )

This function returns the processor identifiers (X,Y,P) from the wired global processor index in CP0_PROCID.

  • cluster_x : X cluster coordinate
  • cluster_y : Y cluster coordinate
  • lpid : local processor index

No error possible, as the fixed format is gpid = ( ( cluster_x << Y_WIDTH + cluster_y ) << P_WIDTH ) + lpid

2) unsigned int giet_proctime()

This function returns the local processor time from the CP0_TIME register (number of cycles from reset). No error possible, as the processor implements a 32 bits wrapping register.

3) unsigned int giet_rand()

This function returns a pseudo-random value derived from both the CP0_PROCID and CP0_TIME registers. No error possible, as the return value is always between 0 & 65535.

User task related system calls

1) unsigned int giet_proc_task_id()

This functions returns (from the calling task context) the local task index, identifying the task amongst all task running on the same processor. No error possible.

2) unsigned int giet_global_task_id()

This functions returns (from the calling task context) the global task id, unique in the system. No error possible.

3) unsigned int giet_thread_id()

This functions returns (from the calling task context) the thread index, identiying the task in a given vspace. No error possible.

Coprocessors related system calls

The GIET_VM allows user applications to use hardware accelerators (called coprocessors). These coprocessors can be distributed in the architecture, but there is at most one coprocessor per cluster, identified by the cluster (x,y) coordinares. To be supported by the GIET_VM, a coprocessor must use the vci_mwmr_dma component, that is a multi-channels DMA controller.

On the coprocessor side, it provides TO_COPROC or FROM_COPROC ports, that implement FIFO interfaces. Coprocessor can request to transfer one or several bursts of 32 bits words on a TO_COPROC or FROM_COPROC port, without address. The burst size (generally a cache line), the number of TO_COPROC and FROM_COPROC ports, and the number of bursts for a given port are hardware parameters. Each port define a private communication channel between the coprocessor and a user memory buffer. The total number of channels cannot be larger than 16. A channel is identified by an index, and the TO_COPROC channels have the smallest indexes.

Each communication channel implements three transfer modes that can be configured by software:

  • In MODE_MWMR, the channel transfer an "infinite" data stream, between the coprocessor port and a MWMR software FIFO in memory. The MWMR_DMA controller implements the 7 steps MWMR protocol.
  • In MODE_DMA_IRQ, the channel transfer a single buffer between the coprocessor port and the memory. The number of VCI burst for a given channel depends on the memory buffer size, and the MWMR_DMA controller signals the transfer completion with an interrupt.
  • The MODE_DMA_NO_IRQ, is similar to the previous one, but the channel stops when the transfer is completed, without rising an interrupt.

WARNING : For all channels, the memory buffer address and size must be multiple of the hardware burst size.

Several channels can simultaneously run in different modes. The VCI transactions corresponding to different channels are interleaved and parallelized on the VCI network.

Besides these communication channels, the vci_mwmr_dma component support up to 16 coprocessor-specific configurarion/status registers. The configuration registers are Read/Write?. The status registers are Read-Only.

The list of supported coprocessors and their characteristics are defined below:

coproc_type nb_to_coproc nb_from_coproc nb_config nb_status
COPROC_TYPE_GCD 2 1 1 0
COPROC_TYPE_DCT 1 1 1 0

1) void giet_coproc_alloc( unsigned int coproc_type, unsigned int* info, unsigned int* cluster_xy )

This function allocates a private coprocessor to the calling task, taking a lock to grant exclusive ownership. In the current implementation, the task exit if there is no coprocessor of requested type in the same cluster as the calling task. In case of success, it returns the coprocessor characteristics in the coproc_info and cluster_xy variables.

  • coproc_type : see supported types above
  • coproc_info : nb_to_coprocs = info[7:0] / nb_from_coproc = info[15:8] / nb_config = info[23:16] / nb_status = info[31:24]
  • cluster_xy : cluster coordinates

2) void giet_coproc_release( unsigned int cluster_xy )

This function releases the coprocessor allocated to the calling task.

  • cluster_xy cluster coordinates

3) void giet_coproc_channel_init( unsigned int cluster_xy, unsigned int channel, giet_coproc_channel_t* desc )

This function initializes a communication channel. It uses the he following structure (defined in the stdio.h file) to specicy the channel parameters:

typedef struct giet_coproc_channel
{
    unsigned int  channel_mode;    // MWMR / DMA_IRQ / DMA_NO_IRQ
    unsigned int  buffer_size;     // memory buffer size
    unsigned int  buffer_vaddr;    // memory buffer virtual address
    unsigned int  mwmr_vaddr;      // MWMR descriptor virtual address
    unsigned int  lock_vaddr;      // lock for MWMR virtual address
} giet_coproc_channel_t;
  • cluster_xy cluster coordinates
  • channel communication channel index
  • desc pointer on the giet_coproc_channel_t structure

4) void giet_coproc_channel_start( unsigned int cluster_xy, unsigned int channel )

This function activates one communication channel for coprocessor in cluster_xy.

  • cluster_xy cluster coordinates
  • channel communication channel index

5) void giet_coproc_channel_stop( unsigned int cluster_xy, unsigned int channel )

This function desactivates one communication channel for coprocessor in cluster_xy.

  • cluster_xy cluster coordinates
  • channel communication channel index

6) void giet_coproc_completed( unsigned int cluster_xy )

This blocking function can be used to synchronize a software task with an hardware coprocessor running in DMA mode. It polls the _coproc_done[x][y] kernel variable, and returns only when this variable has been set by the ISR associated to coprocessor in cluster[x][y].

TTY related system calls

The GIET_VM allows an user task to use a private TTY terminal, or to display log message on a shared TTY terminal.

1) void giet_tty_alloc()

This function allocates a private terminal to the calling task, and registers the terminal index in the task context. The calling task exit if no TTY terminal available.

2) void giet_tty_printf( char* format, ... )

This function print formated text on a private terminal that must have been allocated to the calling task in the mapping (use_tty argument). Therefore, it does not take the TTY lock. Only a limited number of formats are supported:

  • %d : signed decimal
  • %u : unsigned decimal
  • %x : 32 bits hexadecimal
  • %l : 64 bits hexadecimal
  • %c : char
  • %s : string

Task exit if private terminal index not defined, or in case of illegal format.

3) void giet_tty_getc( char* byte )

This blocking function fetches a single character from the private terminal that must have been allocated to the calling task in the application mapping. It uses the TTY_RX_IRQ interrupt, and the associated kernel buffer. Task exit if private TTY index not defined.

4) void giet_tty_getw( unsigned int* val )

This blocking function fetches a string of decimal characters (most significant digit first) to build a 32-bits unsigned integer from the private TTY terminal that must have been allocated to the calling task in the application mapping. It uses the TTY_RX_IRQ interrupt, and the associated kernel buffer. The non-blocking system function _tty_read is called several times, and the decimal characters are written in a 32 characters buffer until a <LF> character is read. It ignores non-decimal characters, and displays an echo for each decimal character. The <DEL> character is interpreted, and previous characters can be cancelled. When the <LF> character is received, the string is converted to an unsigned int value. If the number of decimal digit is too large for the 32 bits range, the zero value is returned. Task exit if private TTY index not defined.

5) void giet_tty_gets( char* buf, unsigned int bufsize )

This blocking function fetches a string from the private terminal that must have been allocated to the calling task in the application mapping. It writes the string to a fixed length buffer. It uses the TTY_RX_IRQ interrupt, and the associated kernel buffer. Up to (bufsize - 1) characters (including the non printable characters) are copied into buffer, and the string is completed by a NUL character. The <LF> character is interpreted, and the function close the string with a NUL character if <LF> is read. The <DEL> character is interpreted, and the corresponding character(s) are removed from the target buffer. It does not provide an echo. Task exit if private TTY index not defined.

6) void giet_shr_printf( char* format, ... )

This function print formated text on the kernel terminal. It takes the TTY lock for exclusive access. It supports the same formats as the giet_tty_printf() function. Task exit in case of illegal format.

Timer related system calls

The GIET_VM allows an user task to activate a private timer channel, generating periodical IRQs. This timer is allocated in the external multi-timers peripheral.

1) void giet_timer_alloc()

This function allocates a private user timer to the calling task, and registers the channel index in the task context. Task exit if no timer channel available

2) void giet_timer_start( unsigned int period )

This function starts the private timer allocated to the calling task. Task exit if no channel allocated.

3) void giet_timer_stop( )

This function stops the private timer allocated to the calling task. Task exit if no channel allocated.

File system related system calls

The Giet-VM supports a FAT32 file system.

1) int giet_fat_open( const char* pathname, unsigned int flags )

This function open a file identified by the pathname argument. The read/write flags are not supported yet: no effect. Return -1 in case or error.

2) void giet_fat_read( unsigned int fd, void* buffer, unsigned int count, unsigned int offset )

Read count sectors from a file identified by the fd argument, skipping offset sectors in file, and writing into the user memory buffer. The user buffer base address should be 64 bytes aligned. In case or error, it makes a giet_exit().

3) void giet_fat_write( unsigned int fd, void* buffer, unsigned int count, unsigned int offset )

Write count sectors into a file identified by the fd argument, skipping offset sectors in file, and reading from the user memory buffer. The user buffer base address should be 64 bytes aligned. In case or error, it makes a giet_exit().

4) void giet_fat_close( unsigned int fd )

Close a file identified by the fd file descriptor.

Network related system call

The GIET_VM allows a user task to get and use a private NIC channel, using the CMA component (chained buffers DMA) to transfer packets to or an user buffer. The NIC channel and the CMA channel are registered in the task context.

1) unsigned int giet_nic_tx_alloc( unsigned int xmax, unsigned int ymax)

This function allocates a private NIC_TX channel (coming with the associated kernel NIC_TX chbuf), and a private CMA channel to the calling task. It registers both indexes in the calling task context, and returns the NIC channel index. This channel can be shared by severals tasks of a parallel multi-tasks application. The packets are transfered by the hardware to the NIC from a distributed kernel chbuf (one 4 Kbytes container per cluster), where the number of involved clusters is defined by the (xmax / ymax) parameters. The (xmax / ymax) arguments cannot be larger than (X_SIZE / Y_SIZE) defining the max number of clusters in the platform, but they can be smaller. The calling task exit if no available NIC_TX channel, if no available CMA channel, if (xmax / ymax) are too large, or if there is not enough memory for the distributed kernel containers in one selected cluster.

2) unsigned int giet_nic_rx_alloc( unsigned int xmax, unsigned int ymax )

This function allocates a private NIC_RX channel (coming with the associated kernel NIC_RX chbuf), and a private CMA channel to the calling task. It registers both indexes in the calling task context, and returns the NIC channel index. This channel can be shared by severals tasks of a parallel multi-tasks application. The packets are transfered by the hardware from the NIC to a distributed kernel chbuf (one 4 Kbytes container per cluster), where the number of involved clusters is defined by the (xmax / ymax) parameters. The (xmax / ymax) arguments cannot be larger than (X_SIZE / Y_SIZE) defining the max number of clusters in the platform, but they can be smaller. The calling task exit if no available NIC_TX channel, if no available CMA channel, if (xmax / ymax) are too large, or if there is not enough memory for the distributed kernel containers in one selected cluster.

3) void giet_nic_tx_start( unsigned int channel )

This function activates both the NIC_TX channel, and the CMA channel allocated to the calling task to transfer packets from the distributed kernel chbuf to the NIC. The calling task exit if no allocated NIC_TX channel or no allocated CMA channel, or if the NIC channel argument does not fit the channel allocated to the calling task.

4) void giet_nic_rx_start( unsigned int channel )

This function activates both the NIC_RX channel, and the CMA channel allocated to the calling task to transfer packets from the NIC to the distributed kernel chbuf. The calling task exit if no allocated NIC_RX channel or no allocated CMA channel.

5) void giet_nic_tx_move( unsigned int nic_channel, void* buffer )

This blocking function transfer one container (GIET_NIC_CHBUF_SIZE bytes) from an user buffer to the kernel chbuf defined by the nic_channel argument.

  • nic_channel define the NIC channel index.
  • buffer is the container base address in user space.

Several user tasks can concurrently access the same chbuf, because the syscall handler takes the lock protecting the chbuf. It returns only when the container has been fully transfered. The calling task exit if the buffer is not in user space, or if the NIC channel is too large, or in case of timeout.

6) void giet_nic_rx_move( unsigned int nic_channel, void* buffer )

This blocking function transfer one container (GIET_NIC_CHBUF_SIZE bytes) from the kernel chbuf defined by the nic_channel argument to an user buffer.

  • nic_channel define the NIC channel index.
  • buffer is the container base address in user space.

Several user tasks can concurrently access the same chbuf, because the syscall handler takes the lock protecting the chbuf. It returns only when the container has been fully transfered. The calling task exit if the buffer is not in user space, or if the NIC channel is too large, or in case of timeout.

7) void giet_nic_tx_stop( unsigned int channel )

This function desactivates both the NIC_TX channel and the CMA channel allocated to the calling task. The calling task exit if no allocated NIC_TX channel or no allocated CMA channel.

8) void giet_nic_rx_stop( unsigned int channel )

This function desactivates both the NIC_RX channel and the CMA channel allocated to the calling task. The calling task exit if no allocated NIC_RX channel or no allocated CMA channel.

9) void giet_nic_rx_clear( unsigned int channel )

This function reset all instrumentation (packets counters) associated to the RX channels.

10) void giet_nic_tx_clear( unsigned int channel )

This function reset all instrumentation (packets counters) associated to the TX channels.

11) void giet_nic_rx_stats( unsigned int channel )

This function display on kernel TTY0 the content of the instrumentation registers associated to the RX channels.

12) void giet_nic_tx_stats( unsigned int channel )

This function display on kernel TTY0 the content of the instrumentation registers associated to the TX channels.

Frame Buffer related system calls

To display images, an user task can access the frame buffer through a memcpy() or through the Chained Buffer DMA controller (called CMA). The four first functions use a private CMA channel that is registered in the task context. The Two last functions use a memcpy().

1) void giet_fbf_cma_alloc()

This function allocates a private CMA channel to the calling task, and registers the channel index in the task context. Task exit if no CMA channel available

2) void giet_fbf_cma_start( void* buf0, void* buf1, unsigned int length )

This function initializes the chained buffer DMA controller (CMA) to transfer a stream of images from two user buffers to the frame buffer. It must be used in conjunction with the giet_fbf_cma_display() function. A CMA channel should have been allocated to the calling task in the application mapping.

  • buf0 is the first user buffer base address
  • buf1 is the second user buffer base address,
  • length is the buffer size (bytes).

3) void giet_fbf_cma_display( unsigned int buffer )

This function enables the transfer of the buffer specified by the buffer argument (0 or 1).

4) void giet_fbf_cma_stop( )

This function desactivates the CMA channel allocated to the calling task.

5) void giet_fbf_sync_read( unsigned int offset, void* buffer, unsigned int length )

This blocking function use a memcopy strategy to transfer data from the frame buffer to an user buffer: offset defines the offset (in bytes) in the frame buffer, buffer is the user buffer base address, length is the number of bytes to be transfered.

6) void giet_fbf_sync_write( unsigned int offset, void* buffer, unsigned int length )

This blocking function use a memcopy strategy to transfer data from an user buffer to the frame buffer: offset defines the offset (in bytes) in the frame buffer, buffer is the user buffer base address, length is the number of bytes to be transfered.

Miscelaneous system calls

1) void giet_exit( char* string )

This function stops execution of the calling task with a TTY message explaining the cause. The user task is descheduled and becomes not runable: it does not consume processor cycles anymore.

2) void giet_assert( unsigned int condition, char* string )

This function uses the giet_exit() system call to kill the calling task if the condition is false.

3) void giet_context_switch()

The user task calling this function is descheduled and the processor is allocated to another task.

4) void giet_procs_number( unsigned int* x_size , unsigned int* y_size , unsigned int* nprocs )

This function returns the actual number of processors in a clusterized 2D mesh architecture.

  • x_size number of clusters containing processors in a row.
  • y_size number of clusters containing processors in a column.
  • nprocs number of processors per cluster.

5) void giet_vseg_get_vbase( char* vspace_name, char* vseg_name, unsigned int* vbase)

This function returns in argument vbase the virtual base address of a vseg defined in the mapping_info data structure. The vseg is identified by the two arguments vspace_name and vseg_name. In case of error (such as undefined vspace or undefined vseg), it makes a giet_exit().

6) void giet_vseg_get_length( char* vspace_name, char* vseg_name, unsigned int* length)

This function returns in argument length the length (bytes) of a vseg defined in the mapping_info data structure. The vseg is identified by the two arguments vspace_name and vseg_name. In case of error (such as undefined vspace or undefined vseg), it makes a giet_exit().

7) void giet_heap_info( unsigned int* vaddr, unsigned int* length, unsigned int x, unsigned int y );

This function supports access to the running task's heap or to a remote heap. If (x < X_SIZE) and (y < Y_SIZE), it returns the base address and length of the heap associated to any task running on cluster(x,y). Otherwise, it returns the base address and length of the heap associated to the calling task. In case of error (such as undefined heap segment in the selected cluster, it returns heap_size = 0).

8) void giet_get_xy( void* ptr, unsigned int* px, unsigned int* py )

This function takes as input a virtual address (ptr argument), and returns through the px,py arguments the coordinates of the cluster containing the physical address associated to ptr. In case of error (unmapped virtual address), it makes a giet_exit().