= GIET_VM / User-Level System Calls = The [source:soft/giet_vm/giet_libs/stdio.c stdio.c] and [source:soft/giet_vm/giet_libs/stdio.h stdio.h] files define all system calls provided to user applications by the GIET-VM. They are generally prefixed by ''giet_''. [[PageOutline]] 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. == 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. 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 and FROM_COPROC ports, that implement FIFO interfaces. Coprocessor can request to read (or write) one or several bursts of 32 bits words on a TO_COPROC port (FROM_COPROC port for a write), without address. The burst size (generally a cache line) is a global hardware parameter. The number of TO_COPROC and FROM_COPROC ports, and the number of bursts for a given port depends on each coprocessor implementation. Each port define a private communication channel between the coprocessor and an 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 channel implements three transfer modes that can be defined 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 memory and the coprocessor port. 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 burst size. Several channels can simultaneously run in different modes, and the various 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''' : COPROC_TYPE_GCD / COPROC_TYPE_DCT * '''coproc_info''' : nb_to_coprocs = info[7:0] / nb_from_coproc = info[15:8] / nb_config = info[23:16] / nb_status = info[31:24] * '''clusterrequested coprocessor type === 2) void '''giet_coproc_channel_init'''( unsigned int cluster_xy, unsigned int channel, giet_coproc_channel_t* desc ) === === 3) void '''giet_coproc_channel_start'''( unsigned int cluster_xy, unsigned int channel ) === === 4) void '''giet_coproc_channel_stop'''( unsigned int cluster_xy, unsigned int channel ) === == 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 character is read. It ignores non-decimal characters, and displays an echo for each decimal character. The character is interpreted, and previous characters can be cancelled. When the 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 character is interpreted, and the function close the string with a NUL character if is read. The 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. === 11) 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 == An user task can access the frame buffer through a memcpy() or through the chained buffer DMA controller (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_vobj_get_vbase'''( char* vspace_name, char* vobj_name, unsigned int* vbase) === This function returns in argument ''vbase'' the virtual base address of a vobj defined in the mapping_info data structure. The vobj is identified by the two arguments ''vspace_name'' and ''vobj_name''. In case of error (such as undefined vspace or undefined vobj), it makes a giet_exit(). === 6) void '''giet_vobj_get_length'''( char* vspace_name, char* vobj_name, unsigned int* length) === This function returns in argument ''length'' the length (bytes) of a vobj defined in the mapping_info data structure. The vobj is identified by the two arguments ''vspace_name'' and ''vobj_name''. In case of error (such as undefined vspace or undefined vobj), 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().