Chapter 4. RASC Abstraction Layer

This section describes the Reconfigurable Application-Specific Computing (RASC) Abstraction Layer and covers the following topics:

RASC Abstraction Layer Overview

The RASC Abstraction Layer provides an application programming interface (API) for the kernel device driver and the RASC hardware. It provides a similar level of support for application development as the standard open/close/read/write/ioctl calls for IO peripherals.

The Abstraction Layer is actually implemented as two layers. The lowest level is the COP (Co-Processor) level. This provides calls to function individual devices. The upper level, which is built on top of the COP level, is the algorithm level. Here, the application treats a collection of devices as a single, logical algorithm implementation. The Abstraction Layer manages data movement to and from the devices, spreading work across multiple devices to implement scaling.

As an application develops, you must decide which level you are programming to. They are mutually exclusive. You can use one or the other, but never both.

Figure 4-1 illustrates the interactions between the pieces and layers of the system.

Figure 4-1. Abstraction Layer Software Block Diagram

Abstraction Layer Software Block Diagram

RASC Abstraction Layer Calls

Function entry points can be called from either C or Fortran90 software language modules. The same basic entry point names are used for both languages; except that, the Fortran90 interfaces have the _F suffix appended to the C name. Fortran90 names are, of course, case insensitive. The same information must be passed to either the C or Fortran90 functions, however, basic differences in the languages may require slightly different formats for the argument lists. Both languages return the same values from a function call.

All function prototypes, data structures, and constants are defined in the rasclib.h. file for C calls or in the rasclib_definitions.mod file for Fortran90 calls.

Table 4-1 contains a summary of the abstraction layer function definitions.

Table 4-1. Abstraction Layer Function Definitions - Summary

Function

Description

rasclib_resource_reserve

Sends a request to the device manager to reserve a number of devices for the calling application.

rasclib_resource_release

Releases the reservation on a number of devices and then moves the devices from the reservation pool to the free pool.

rasclib_resource_configure

Loads the given bitstream into a device and marks the device as in use.

rasclib_resource_return

Returns a configured device to its reservation pool.

rasclib_resource_alloc

Sends a request to the device manager to allocate/reserve devices for the application. This routine has been deprecated and will be removed in a future RASC release. You should use rasclib_resource_reserve and rasclib_resource_configure in its place.

rasclib_resource_free

Returns devices to the device manager's free pool. This routine has been deprecated and will be removed in a future RASC release. You should use rasclib_resource_return and rasclib_resource_release in its place.

rasclib_algorithm_open

Notifies the rasclib library that the user wants to use all of the reserved devices loaded with the bitstream associated with al_id as a single logical device.

rasclib_algorithm_send

Queues up a command that will move data from host memory to the device input buffer identified by algo_array_id.

rasclib_algorithm_get_num_cops

Returns the number of physical devices that are participating in the algorithm.

rasclib_algorithm_receive

Queues up a command that will move data from the device output buffer to host memory.

rasclib_algorithm_go

Queues up a command to tell the bitstream compute engine to begin computation.

rasclib_algorithm_commit

Causes the rasclib library to send all queued commands to the kernel driver for execution on the device.

rasclib_algorithm_wait

Blocks until all commands that have been sent to the driver have completed execution.

rasclib_algorithm_close

Releases all host resources associated with the algorithm.

rasclib_algorithm_reg_multi_cast

Writes the same data word to all FPGAs that constitute the algorithm.

rasclib_algorithm_reg_read

Reads data from the registers of the FPGAs.

rasclib_algorithm_reg_write

Writes data to the registers of the FPGAs.

rasclib_algorithm_exception_hand ler_register

Registers an application exception handler for application-defined FPGA logic exception events

rasclib_algorithm_malloc

Allocates contiguous memory for an algorithm.

rasclib_algorithm_mfree

Frees contiguous memory for an algorithm.

rasclib_cop_open

Notifies rasclib that the user wants to use one of the reserved devices loaded with the bitstream associated with al_id.

rasclib_cop_send

Queues up a command that will move data from host memory to the device input buffer identified by algo_array_id.

rasclib_cop_receive

Queues up a command that will move data from the device output buffer to host memory.

rasclib_cop_go

Queues up a command to tell the bitstream compute engine to begin computation.

rasclib_cop_commit

Causes rasclib to send all queued commands to the kernel driver for execution on the device

rasclib_cop_wait

Blocks until all commands that have been sent to the kernel driver have completed execution.

rasclib_cop_close

Releases all host resources associated with the algorithm.

rasclib_cop_reg_read

Reads data from the FPGA register.

rasclib_cop_reg_write

Writes data to the FPGA register.

rasclib_cop_exception_handler_re gister

Registers an application exception handler for application-defined FPGA logic exception events.

rasclib_perror

Prints error message.

rasclib_error_dump

Prints all error messages.

rasclib_cop_malloc

Allocates contiguous memory for a COP.

rasclib_cop_mfree

Frees contiguous memory for a COP.


rasclib_resource_reserve Function

The rasclib_resource_reserve function is, as follows:

SYNOPSIS

C:

int rasclib_resource_reserve(int ncops, const char *reserve_name);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_RESOURCE_RESERVE_F(NCOPS, RESERVE_NAME)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_RESOURCE_RESERVE_F
 INTEGER(KIND=4), INTENT(IN) :: NCOPS
 CHARACTER(LEN=*), INTENT(IN) :: RESERVE_NAME
 END FUNCTION RASCLIB_RESOURCE_RESERVE_F
END INTERFACE

DESCRIPTION

rasclib_resource_reserve() sends a request to the device manager to reserve a number of devices for the calling application. The application must make only a single call to rasclib_resource_alloc() (though this is not enforced) to avoid deadlock conditions.

ncops is the number of devices to reserve. reserve_name is the name that the device manager will give to the reservation pool that contains the reserved devices. If reserve_name is NULL, rasclib will generate a reservation pool name with the following call:

snprintf(resrv_name, sizeof(resrv_name), "app_%d", getpid());

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_MULTI_ALLOC if rasclib_resource_reserve() is called when there is a current reservation with devices still un-released.

Returns RASCLIB_NODEVICE_REQUESTED if ncops == 0

Returns RASCLIB_RESERVE_FAILED if the device manager cannot satisfy the reservation request.

rasclib_resource_release Function

The rasclib_resource_release is, as follows:

SYNOPSIS

C:

int rasclib_resource_release(int ncops, const char *reserve_name);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_RESOURCE_RELEASE_F(NCOPS, RESERVE_NAME)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_RESOURCE_RELEASE_F
 INTEGER(KIND=4), INTENT(IN) :: NCOPS
 CHARACTER(LEN=*), INTENT(IN) :: RESERVE_NAME
 END FUNCTION RASCLIB_RESOURCE_RELEASE_F
END INTERFACE

DESCRIPTION

rasclib_resource_release() releases the reservation on a number of devices. That is, it moves devices from the reservation pool to the free pool.

ncops is the number of devices to release.

reserve_name is a character string and is the name of the reservation pool from which to release. If reserve_name is NULL, then a reserve name is constructed by rasclib using the following function call:

snprintf(resrv_name, sizeof(resrv_name), "app_%d", getpid()); 

There must be a reservation pool with this name for release to work.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_RELEASE_FAILED if the device manager cannot satisfy the request.

rasclib_resource_ configure Function

The rasclib_resource_configure function is, as follows:

SYNOPSIS

C:

int rasclib_resource_configure(const char * al_id, int ncops, const char *reserve_name);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_RESOURCE_CONFIGURE_F(AL_ID, NCOPS, RESERVE_NAME)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_RESOURCE_CONFIGURE_F
 CHARACTER(LEN=*), INTENT(IN) :: AL_ID
 INTEGER(KIND=4), INTENT(IN) :: NCOPS
 CHARACTER(LEN=*), INTENT(IN) :: RESERVE_NAME
 END FUNCTION RASCLIB_RESOURCE_CONFIGURE_F
END INTERFACE

DESCRIPTION

rasclib_resource_configure() loads the given bitstream into a device and marks the device as in use.

al_id is the algorithm identifier as presented to the device manager at bitstream registration time.

ncops is the number of devices to be loaded with the given bitstream.

reserve_name is a char pointer that gives the name of the reservation pool from which to choose the device to be loaded. If reserve_name is NULL, rasclib will build a reservation pool name using the following call:

snprintf(resrv_name, sizeof(resrv_name), "app_%d", getpid()); 

There must be a reservation pool with the given name for the configure to succeed.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_ALLOCATION_FAILED if the device manager cannot satisfy the request.

rasclib_resource_ return Function

The rasclib_resource_return function is, as follows:

SYNOPSIS

C:

int rasclib_resource_return(const char *al_id, int ncops);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_RESOURCE_RETURN_F(AL_ID, NCOPS)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_RESOURCE_RETURN_F
 CHARACTER(LEN=*), INTENT(IN) :: AL_ID
 INTEGER(KIND=4), INTENT(IN) :: NCOPS
 END FUNCTION RASCLIB_RESOURCE_RETURN_F
END INTERFACE

DESCRIPTION

rasclib_resource_return() returns a configured device to its reservation pool. It is still reserved, but can no longer be used by the application until it is again configured.

al_id is the algorithm identifier as presented to the device manager at bitstream registration time.

ncops is the number of devices that are loaded with the given bitstream that will be returned to their reservation pool.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_FREE_FAILED if the device manager cannot satisfy the request.

rasclib_resource_alloc Function


Note: This routine has been deprecated and will be removed in a future RASC release. You should use rasclib_resource_reserve and rasclib_resource_configure in its place.

The rasclib_resource_alloc function is, as follows:

SYNOPSIS

C:

int rasclib_resource_alloc(rasclib_algorithm_request_t *al_request, int num_cops);

Fortran90:

No Fortran interface declaration exists.

Use rasclib_resource_reserve_f and rasclib_resource_configure_f in place of this function.

DESCRIPTION

rasclib_resource_alloc() sends a request to the device manager to allocate/reserve devices for the application. The application must make only a single call to rasclib_resource_alloc() (though this is not enforced) to avoid deadlock conditions.

al_request is a pointer to an array of rasclib_algorithm_request_t requests. A rasclib_algorithm_request_t is defined as:

typedef struct rasclib_algorithm_request_s {
char * algorithm_id;
int num_devices;
        }rasclib_algorithm_request_t;

The algorithm_id identifies which bitstream should be loaded. It is given to the device manager at bitstream registration and can be obtained from the device manager user interface.

The num_devices argument tells the device manager how many devices should be loaded with the bitstream.

num_cops is the number of elements in the array of requests.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_NODEVICE_REQUESTED if no devices are requested.

Returns RASCLIB_RESERVE_FAILED if the device reservation fails.

Returns RASCLIB_ALLOCATION_FAILED if the device allocation fails.

rasclib_resource_free Function


Note: This routine has been deprecated and will be removed in a future RASC release. You should use rasclib_resource_return and rasclib_resource_release in its place.

The rasclib_resource_free function is, as follows:

SYNOPSIS

C:

int rasclib_resource_free(rasclib_algorithm_request_t *al_request, int num_cops);

Fortran90:

No Fortran interface declaration exists.

Use rasclib_resource_return_f and rasclib_resource_release_f in place of this function.

DESCRIPTION

rasclib_resource_free() returns devices to the device manager's free pool. The arguments and their meaning are the same as the rasclib_resource_alloc() function.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

rasclib_algorithm_malloc Function

The rasclib_algorithm_malloc function is, as follows:

SYNOPSIS

C:

void *rasclib_algorithm_malloc(int algo_desc, long size, unsigned flags)

DESCRIPTION

rasclib_algorithm_malloc() allocates a block of contiguous memory for each COP participating in the algorithm and returns a pointer to those blocks of memory. It is intended that the user application use this pointer to send and receive data to/from the algorithm.

algo_desc is the algorithm descriptor returned by rasclib_algorithm_open. size is the size in bytes of the data area. flags can be one of the following:

  • RASCLIB_HUGE_ALLOC tells rasclib to use huge pages.

  • RASCLIB_STANDARD_ALLOC tells rasclib to use standard virtual memory pages.

DIAGNOSTICS

RASCLIB_HUGE_MAP: rasclib was unable to map a huge page.

RASCLIB_MALLOC_FAILED: rasclib was unable to allocate an internal data structure.

NULL ptr: rasclib was unable to malloc memory.

rasclib_algorithm_mfree Function

The rasclib_algorithm_mfree function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_mfree(int algo_desc, void *ptr);

DESCRIPTION

rasclib_algorithm_mfree() returns the memory pointed to by ptr to the system. If the memory is normal memory, it is returned with the libc free() function. If the memory is a huge page, it is returned by unmapping the page. Any references to an unmapped page result in a SEGV.

algo_desc is an algorithm descriptor, returned from rasclib_algorithm_open(). ptr is the pointer to the memory to be freed.

This routine is thread safe.

DIAGNOSTICS

RASCLIB_SUCCESS for successful completion.

rasclib_algorithm_open Function

The rasclib_algorithm_open function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_open(rasclib_algorithm_id_t al_id,io_control);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_OPEN_F(AL_ID, IO_CONTROL)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_ALGORITHM_OPEN_F
 CHARACTER(LEN=*), INTENT(IN) :: AL_ID
 INTEGER(KIND=4), INTENT(IN) :: IO_CONTROL
 END FUNCTION RASCLIB_ALGORITHM_OPEN_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_open() notifies rasclib that the user wants to use all of the reserved devices loaded with the bitstream associated with al_id as a single logical device. The rasclib library initializes all necessary data structures and returns a small integer referred to as an algorithm descriptor. This is similar in concept to a UNIX file descriptor. It is used internally in the library to identify a particular algorithm.

al_id is the same as the algorithm id in the allocate and free routines.

io_control indicates the mode of data transfer that is performed. Permitted values are RASCLIB_BUFFERED_IO, RASCLIB_DIRECT_IO,or RASCLIB_IGNORE_PARITY.

If the RASCLIB_IGNORE_PARITY flag is set, the driver will not kill the process if a parity error is sensed. When the flag is not set (the default case), if a process attempts an SRAM memory access that results in a parity error, the process is killed.

On the screen, you will only see "Killed" printed on their screen. The syslog will have a fairly detailed record of what happened, what the error is classified as (correctable or uncorrectable) and if the process was killed, similar to the following:

Sep 14 16:05:03 kernel: RASC Error Exception Event:
Sep 14 16:05:03 kernel:     nasid                   9
Sep 14 16:05:03 kernel:     PID                     21025
Sep 14 16:05:03 kernel:     cm_status               0x9e08040f20200000
Sep 14 16:05:03 kernel:     cm_error_status         0x0000000000800000
Sep 14 16:05:03 kernel:     cm_error_detail         0x0000000000000000
Sep 14 16:05:03 kernel:     cm_error_detail1        0x0000000000000000
Sep 14 16:05:03 kernel: RASC Error Exception - uncorrectable error: process 21025 killed

DIAGNOSTICS

Returns RASCLIB_FAIL on failure, an algorithm descriptor (which is greater than or equal to zero) on success.

rasclib_algorithm_send Function

The rasclib_algorithm_send function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_send(int algo_desc, rasclib_algo_array_id_t algo_array_id, void *buf, int count);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_SEND_F(ALGO_DESC, ALGO_ARRAY_ID, BUF, COUNT)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_ALGORITHM_SEND_F
 INTEGER(KIND=4), INTENT(IN) :: ALGO_DESC
 CHARACTER(LEN=*), INTENT(IN) :: ALGO_ARRAY_ID
 CHARACTER(LEN=*), INTENT(IN) :: BUF
 INTEGER(KIND=4), INTENT(IN) :: COUNT
 END FUNCTION RASCLIB_ALGORITHM_SEND_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_send() queues up a command that will move data from host memory to the device input buffer identified by algo_array_id.

algo_desc is the value returned by the rasclib_algorithm_open() function .

algo_array_id identifies the input data area and is specified in the configuration file associated with the bitstream.

buf is a pointer to the data in host memory.

count is the number of bytes in the data. Count must be an integral multiple of the size of the data area on the device.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_ARRAY_NOTFOUND if the input array name cannot be found in the configuration data.

Returns RASCLIB_READONLY_SRAM when it is asked to send data to a read-only SRAM.

Returns RASCLIB_ASYMETRIC_DATA when the data size of the send and receive do not match up.

rasclib_algorithm_get_num_cops Function

The rasclib_algorithm_get_num_cops function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_get_num_cops(int al_desc);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_GET_NUM_COPS_F(AL_DESC)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_ALGORITHM_GET_NUM_COPS_F
 INTEGER(KIND=4), INTENT(IN) :: AL_DESC
 END FUNCTION RASCLIB_ALGORITHM_GET_NUM_COPS_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_get_num_cops gets the number of COPs that are participating in the algorithm referred to by al_desc.

DIAGNOSTICS

Returns the number of COPs involved in the algorithm or RASCLIB_FAIL on failure.

rasclib_algorithm_receive Function

The rasclib_algorithm_receive function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_receive(int algo_desc, rasclib_algo_array_id_t algo_array_id, void *buf, int count);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_RECEIVE_F(ALGO_DESC, ALGO_ARRAY_ID, BUF, COUNT)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_ALGORITHM_RECEIVE_F
 INTEGER(KIND=4), INTENT(IN) :: ALGO_DESC
 CHARACTER(LEN=*), INTENT(IN) :: ALGO_ARRAY_ID
 CHARACTER(LEN=*), INTENT(OUT) :: BUF
 INTEGER(KIND=4), INTENT(IN) :: COUNT
 END FUNCTION RASCLIB_ALGORITHM_RECEIVE_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_receive() queues up a command that will move data from the device output buffer to host memory.

algo_desc is the value returned by the rasclib_algorithm_open() function.

algo_array_id identifies the output data area and is specified in the configuration file associated with the bitstream.

buf is a pointer to the data buffer in host memory that will receive the data.

count is the number of bytes in the data. Count must be an integral multiple of the size of the data area on the device.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_ARRAY_NOTFOUND if the input array name cannot be found in the configuration data.

Returns RASCLIB_WRITEONLY_SRAM when it is asked to receive data from a write-only SRAM.

Returns RASCLIB_ASYMETRIC_DATA when the data size of the send and receive do not match up.

rasclib_algorithm_go Function

The rasclib_algorithm_go function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_go(int al_desc);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_GO_F(AL_DESC)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_ALGORITHM_GO_F
 INTEGER(KIND=4), INTENT(IN) :: AL_DESC
 END FUNCTION RASCLIB_ALGORITHM_GO_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_go() issues a command to tell the bitstream compute engine to begin computation.

al_desc is the value returned by rasclib_algorithm_open().

DIAGNOSTICS

Returns RASCLIB_FAIL on failure, RASCLIB_SUCCESS on success.

rasclib_algorithm_commit Function

The rasclib_algorithm_commit function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_commit(int al_desc, void(*rasclib_algo_callback)(int, char*, unsigned long));

Fortran90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_COMMIT_F(AL_DESC, RASCLIB_ALGO_CALLBACK) RESULT (RES)
 IMPLICIT NONE
 INTEGER(KIND=4), INTENT(IN) :: AL_DESC
 EXTERNAL :: RASCLIB_ALGO_CALLBACK
 OPTIONAL :: RASCLIB_ALGO_CALLBACK
 INTEGER(KIND=4) :: RES
 END FUNCTION RASCLIB_ALGORITHM_COMMIT_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_commit() causes rasclib to send all queued commands to the kernel driver for execution on the device. The commands are sent as a single command list. Until a commit is done, all user buffers are still in use and may not be reused without the (almost certain) risk of data corruption.

al_desc is the value returned by rasclib_algorithm_open().

rasclib_algo_callback is a function provided by the user to handle situations such as data overruns or data underruns. It is called by rasclib when user intervention is required. Currently, it is not called, therefore, this parameter should always be NULL.

DIAGNOSTICS

Returns RASCLIB_FAIL on failure, RASCLIB_SUCCESS on success.

rasclib_algorithm_wait Function

The rasclib_algorithm_wait function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_wait(int al_desc);

Fortan90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_WAIT_F(AL_DESC)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_ALGORITHM_WAIT_F
 INTEGER(KIND=4), INTENT(IN) :: AL_DESC
 END FUNCTION RASCLIB_ALGORITHM_WAIT_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_wait() blocks until all commands that have been sent to the driver have completed execution. There is an implied commit associated with the wait. That is, before the thread of execution waits, it sends all queued commands to the kernel driver for execution (see rasclib_algorithm_commit). After the wait call returns, all outstanding data transfers have occurred and the application may do any buffer management that it may require.

al_desc is the value returned by the rasclib_algorithm_open() function.

DIAGNOSTICS

Returns RASCLIB_FAIL on failure, RASCLIB_SUCCESS on success.

rasclib_algorithm_close Function

The rasclib_algorithm_close function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_close(int al_desc);

Fortan90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_CLOSE_F(AL_DESC)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_ALGORITHM_CLOSE_F
 INTEGER(KIND=4), INTENT(IN) :: AL_DESC
 END FUNCTION RASCLIB_ALGORITHM_CLOSE_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_close() releases all host resources associated with the algorithm. It does not release any allocated devices (see rasclib_resource_free).

al_desc is the value returned by the rasclib_algorithm_open() function.

DIAGNOSTICS

Returns the value of al_desc.

rasclib_algorithm_reg_multi_cast Function

The rasclib_algorithm_reg_multi_cast function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_reg_multi_cast(int al_desc, char *alg_reg, unsigned long *data, int ndata_elements, unsigned flags);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_REG_MULTI_CAST_F(AL_DESC, ALG_REG, DATA, NDATA_ELEMENTS, FLAGS)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_ALGORITHM_REG_MULTI_CAST_F
 INTEGER(KIND=4), INTENT(IN) :: AL_DESC
 CHARACTER(LEN=*), INTENT(IN) :: ALG_REG
 INTEGER(KIND=8), DIMENSION(*), INTENT(IN) :: DATA
 INTEGER(KIND=4), INTENT(IN) :: NDATA_ELEMENTS
 INTEGER(KIND=4), INTENT(IN) :: FLAGS
 END FUNCTION RASCLIB_ALGORITHM_REG_MULTI_CAST_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_reg_multi_cast sends the same data to all of the FPGAs that implement the algorithm.

al_desc is the algorithm descriptor returned from the rasclib_algorithm_open function.

alg_reg is the name of the register.

data is a pointer to the data to be written to the register.

flags can be either RASCLIB_QCMD or RASCLIB_IMMED_CMD.

If flags is RASCLIB_QCMD, the command is queued in rasclib to be sent to the driver to be executed in order within the command list.

If flags is RASCLIB_IMMED_CMD, the register writes are done before rasclib_algorithm_reg_multi_cast returns to the user.

The rasclib_algorithm_reg_multi_cast function supports fat registers. A fat register is register that spans multiple FPGA registers. Their length in bits must be an integral multiple of 64 and they must begin at the beginning of a physical register. Therefore, a fat register exactly spans an integral number of physical registers. It is assumed that the data array supplied is large enough to hold all the data for a fat register. The rasclib library does not support partial reads or writes to fat registers.

DIAGNOSTICS

Returns RASCLIB_SUCCESS. Exits with exit status RASCLIB_MALLOC_FAILED if rasclib cannot allocate memory.

rasclib_algorithm_reg_read Function

The rasclib_algorithm_reg_read function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_reg_read(int al_desc, char *alg_reg, unsigned long *data, int ndata_elements, unsigned flags);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_REG_READ_F(AL_DESC, ALG_REG, DATA, NDATA_ELEMENTS, FLAGS)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_ALGORITHM_REG_READ_F
 INTEGER(KIND=4), INTENT(IN) :: AL_DESC
 CHARACTER(LEN=*), INTENT(IN) :: ALG_REG
 INTEGER(KIND=8), DIMENSION(*), INTENT(OUT) :: DATA
 INTEGER(KIND=4), INTENT(IN) :: NDATA_ELEMENTS
 INTEGER(KIND=4), INTENT(IN) :: FLAGS
 END FUNCTION RASCLIB_ALGORITHM_REG_READ_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_reg_read reads a register from each of the FPGAs that implement an algorithm.

It is assumed that there is enough space in the array pointed to by data to handle all of the data. See “rasclib_algorithm_get_num_cops Function”.

al_desc is the algorithm descriptor returned from the rasclib_algorithm_open function.

alg_reg is the name of the register.

data is a pointer to the data where the data read from the register will be placed.

flags can be either RASCLIB_QCMD or RASCLIB_IMMED_CMD.

If flags is RASCLIB_QCMD, the command is queued in rasclib to be sent to the driver to be executed in order within the command list.

If flags is RASCLIB_IMMED_CMD, the register reads are done before rasclib_algorithm_reg_read returns to the user.

The rasclib_algorithm_reg_read function supports fat registers. A fat register is register that spans multiple FPGA registers. Their length in bits must be an integral multiple of 64 and they must begin at the beginning of a physical register. Therefore, a fat register exactly spans an integral number of physical registers. It is assumed that the data array supplied is large enough to hold all the data for a fat register. The rasclib library does not support partial reads or writes to fat registers

DIAGNOSTICS

Returns RASCLIB_SUCCESS.

Returns RASCLIB_NO_REG_DATA: Couldn't find the named register in config file

Returns RASCLIB_DATA_SIZE_ERROR: Size mismatch in register access request

Returns RASCLIB_INVAL_FLAG: Invalid flag passed to rasclib routine

rasclib_algorithm_reg_write Function

The rasclib_algorithm_reg_write function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_reg_write(int al_desc, char *alg_reg, unsigned long *data, int ndata_elements, unsigned flags);

Fortan90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_REG_WRITE_F(AL_DESC, ALG_REG, DATA, NDATA_ELEMENTS, FLAGS)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_ALGORITHM_REG_WRITE_F
 INTEGER(KIND=4), INTENT(IN) :: AL_DESC
 CHARACTER(LEN=*), INTENT(IN) :: ALG_REG
 INTEGER(KIND=8), DIMENSION(*), INTENT(IN) :: DATA
 INTEGER(KIND=4), INTENT(IN) :: NDATA_ELEMENTS
 INTEGER(KIND=4), INTENT(IN) :: FLAGS
 END FUNCTION RASCLIB_ALGORITHM_REG_WRITE_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_reg_write writes the supplied data to the FPGAs that implement the algorithm. It is assumed that there is enough data supplied to satisfy one register write for each FPGA in the algorithm (see “rasclib_algorithm_get_num_cops Function”).

al_desc is the algorithm descriptor returned from the rasclib_algorithm_open function.

alg_reg is the name of the register.

data is a pointer to the data to be written to the register.

flags can be either RASCLIB_QCMD or RASCLIB_IMMED_CMD.

If flags is RASCLIB_QCMD, the command is queued in rasclib to be sent to the driver to be executed in order within the command list.

If flags is RASCLIB_IMMED_CMD, the register writes are done before rasclib_algorithm_reg_write returns to the user.

The rasclib_algorithm_reg_write function supports fat registers. A fat register is a register that spans multiple FPGA registers. Their length in bits must be an integral multiple of 64 and they must begin at the beginning of a physical register. Therefore, a fat register exactly spans an integral number of physical registers. It is assumed that the data array supplied is large enough to hold all the data for fat register. The rasclib library does not support partial reads or writes to fat registers

DIAGNOSTICS

Returns RASCLIB_SUCCESS.

Returns RASCLIB_NO_REG_DATA: Couldn't find the named register in config file

Returns RASCLIB_DATA_SIZE_ERROR: Size mismatch in register access request

Returns RASCLIB_INVAL_FLAG: Invalid flag passed to rasclib routine

rasclib_algorithm_exception_handler_register Function

The rasclib_algorithm_exception_handler_register function is, as follows:

SYNOPSIS

C:

int rasclib_algorithm_exception_handler_register(int algo_desc, int (*exception_handler)(void))

Fortran90:

INTERFACE
 FUNCTION RASCLIB_ALGORITHM_EXCEPTION_REGISTER_F(AL_DESC, EXCEPTION_HANDLER) RESULT (RES)
 IMPLICIT NONE
 INTEGER(KIND=4), INTENT(IN) :: AL_DESC
 EXTERNAL :: EXCEPTION_HANDLER
 INTEGER(KIND=4) :: RES
 END FUNCTION RASCLIB_ALGORITHM_EXCEPTION_REGISTER_F
END INTERFACE

DESCRIPTION

rasclib_algorithm_exception_handler_register function registers an application exception handler that will be invoked when the FPGA logic drives the ALG_EVENT0 signal.

It is intended for application-defined FPGA logic exception events.

The FPGA logic is paused for the duration of the exception processing. The exception handler returns 0 if the FPGA logic can continue or 1 to stop the current logic run.

The algorithm registration function registers the handler for each FPGA represented by algo_desc.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_UNSUPPORTED if Core Services does not support exception processing. This is the case for releases prior to the RASC 2.1 release.

rasclib_cop_open Function

The rasclib_cop_open function is, as follows:

SYNOPSIS

C:

int rasclib_cop_open(rasclib_algorithm_id_t as_id,io_control);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_COP_OPEN_F(AS_ID, IO_CONTROL)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_COP_OPEN_F
 CHARACTER(LEN=*), INTENT(IN) :: AS_ID
 INTEGER(KIND=4), INTENT(IN) :: IO_CONTROL
 END FUNCTION RASCLIB_COP_OPEN_F
END INTERFACE

DESCRIPTION

rasclib_cop_open() notifies rasclib that the user wants to use one of the reserved devices loaded with the bitstream associated with al_id. The rasclib library initializes all necessary data structures and returns a small integer referred to as an COP descriptor. This is similar in concept to a UNIX file descriptor. It is used internally in the library to identify a particular COP.

al_id is the same as the algorithm ID in the allocate and free routines.

io_control indicates the mode of data transfer that is performed. Permitted values are RASCLIB_BUFFERED_IO or RASCLIB_DIRECT_IO.

DIAGNOSTICS

Returns a cop_desc >= 0 on success.

Returns RASCLIB_NO_HANDLE if no cop handle can be found for alg_id.

Returns RASCLIB_NO_DESC_NUM if no descriptor can be found.

Returns RASCLIB_DEV_OPEN_FAILED if an open system call failed.

Returns RASCLIB_MALLOC_FAILED if a malloc call failed.

rasclib_cop_send Function

The rasclib_cop_send function is, as follows:

SYNOPSIS

C:

int rasclib_cop_send(int cop_desc, rasclib_algo_array_id_t algo_array_id, void *buf, int count);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_COP_SEND_F(COP_DESC, ALGO_ARRAY_ID, BUF, COUNT)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_COP_SEND_F
 INTEGER(KIND=4), INTENT(IN) :: COP_DESC
 CHARACTER(LEN=*), INTENT(IN) :: ALGO_ARRAY_ID
 CHARACTER(LEN=*), INTENT(IN) :: BUF
 INTEGER(KIND=4), INTENT(IN) :: COUNT
 END FUNCTION RASCLIB_COP_SEND_F
END INTERFAC

DESCRIPTION

rasclib_cop_send() queues up a command that will move data from host memory to the device input buffer identified by algo_array_id.

cop_desc is the value returned by rasclib_cop_open().

algo_array_id identifies the input data area and is specified in the configuration file associated with the bitstream.

buf is a pointer to the data in host memory.

count is the number of bytes in the data. Count must be equal to the size of the data area on the device.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_NO_DESC if cop_desc cannot be translated into a descriptor pointer.

Returns RASCLIB_MALLOC_FAILED if a malloc call failed.

Returns RASCLIB_NO_ARRAY if the input array name cannot be found in the configuration data.

Returns RASCLIB_READONLY_SRAM when it is asked to send data to a read-only SRAM.

Returns RASCLIB_SIZE_MISMATCH if the input size does not match the SRAM buffer size.

rasclib_cop_receive Function

The rasclib_cop_receive function is, as follows:

SYNOPSIS

C:

int rasclib_cop_receive(int cop_desc, rasclib_algo_array_id_t algo_array_id, void *buf, int count);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_COP_RECEIVE_F(COP_DESC, ALGO_ARRAY_ID, BUF, COUNT)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_COP_RECEIVE_F
 INTEGER(KIND=4), INTENT(IN) :: COP_DESC
 CHARACTER(LEN=*), INTENT(IN) :: ALGO_ARRAY_ID
 CHARACTER(LEN=*), INTENT(OUT) :: BUF
 INTEGER(KIND=4), INTENT(IN) :: COUNT
 END FUNCTION RASCLIB_COP_RECEIVE_F
END INTERFACE

DESCRIPTION

rasclib_cop_receive() queues up a command that will move data from the device output buffer to host memory.

cop_desc is the value returned by rasclib_cop_open().

algo_array_id identifies the output data area and is specified in the configuration file associated with the bitstream.

buf is a pointer to the data buffer in host memory that will receive the data.

count is the number of bytes in the data. Count must be equal to the size of the data area on the device.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_NO_DESC if cop_desc cannot be translated into a descriptor pointer.

Returns RASCLIB_MALLOC_FAILED if a malloc call failed.

Returns RASCLIB_NO_ARRAY if the input array name cannot be found in the configuration data.

Returns RASCLIB_WRITEONLY_SRAM when it is asked to receive data from a write-only SRAM.

Returns RASCLIB_SIZE_MISMATCH if the input size does not match the SRAM buffer size.

rasclib_cop_malloc Function

The rasclib_cop_malloc function is as follows:

SYNOPSIS

C:

void *rasclib_cop_malloc(int cop_desc, long size, unsigned flags);

DESCRIPTION

rasclib_cop_malloc() allocates a block of memory on the node that is closest (in a topological sense) to the COP in question. If allocating huge pages for contiguous memory, it will allocate exactly one huge page for the COP.

cop_desc is the COP descriptor return from rasclib_cop_open(). size is the size of the data area requested. flags can be one of the following:

  • RASCLIB_HUGE_ALLOC allocate a huge page.

  • RASCLIB_STANDARD_ALLOC allocate normal memory pages.

DIAGNOSTICS

RASCLIB_HUGE_MAP rasclib cannot mmap a huge page.

RASCLIB_MALLOC_FAILED rasclib cannot malloc memory for an internal data structure.

NULL ptr rasclib cannot malloc the requested space.

rasclib_cop_mfree Function

The rsaclib_cop_mfree function is, as follows:

SYNOPSIS

C:

int rasclib_cop_mfree(int cop_desc, void *ptr);

DESCRIPTION

rasclib_cop_mfree() returns memory allocated by rasclib_cop_malloc() to the system. If the memory is regular memory, it is freed by the libc free() call. If the memory is a huge page, it is unmapped. If unmapped memory is referenced, it results in a SEGV.

cop_desc is a COP descriptor returned by rasclib_cop_open(). ptr is a pointer to memory that has been allocated by rasclib_cop_malloc. This routine is thread safe.

DIAGNOSTICS

Returns RASCLIB_SUCCESS

rasclib_cop_go Function

The rasclib_cop_go function is, as follows:

SYNOPSIS

rasclib_algorithm_mfreeC:

int rasclib_cop_go(int cop_desc);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_COP_GO_F(COP_DESC)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_COP_GO_F
 INTEGER(KIND=4), INTENT(IN) :: COP_DESC
 END FUNCTION RASCLIB_COP_GO_F
END INTERFACE

DESCRIPTION

rasclib_cop_go() issues a command to tell the bitstream compute engine to begin computation.

cop_desc is the value returned by rasclib_cop_open().

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_MALLOC_FAILED if a malloc call failed.

rasclib_cop_commit Function

The rasclib_cop_commit function is, as follows:

SYNOPSIS

C:

int rasclib_cop_commit (int cop_desc, int(*rasclib_cop_callback)(int, char *, unsigned long, char *buf));

Fortran90

INTERFACE
 FUNCTION RASCLIB_COP_COMMIT_F(COP_DESC, RASCLIB_COP_CALLBACK) RESULT (RES)
 IMPLICIT NONE
 INTEGER(KIND=4), INTENT(IN) :: COP_DESC
 EXTERNAL :: RASCLIB_COP_CALLBACK
 OPTIONAL :: RASCLIB_COP_CALLBACK
 INTEGER(KIND=4) :: RES
 END FUNCTION RASCLIB_COP_COMMIT_F
END INTERFACE

DESCRIPTION

rasclib_cop_commit() causes the rasclib library to send all queued commands to the kernel driver for execution on the device. The commands are sent as a single command list. Until a commit call is done, all user buffers are still in use and may not be reused without the (almost certain) risk of data corruption.

cop_desc is the value returned by rasclib_cop_open().

rasclib_cop_callback is a function provided by the user to handle situations such as data overruns or data underruns. This callback is ONLY called for streaming DMA engines, never for block DMAs. The status argument contains either RASCLIB_STREAM_SEND_COMPLETE or RASCLIB_STREAM_RECEIVE_COMPLETE. The RASCLIB_STREAM_SEND_COMPLETE argument says that a stream, identified by the second argument, has completed a SEND call. The RASCLIB_STREAM_RECEIVE_COMPLETE arguement says that a stream, identified by the second argument, has completed a RECEIVE call. The function should always return either RASCLIB_CALLBACK_NORMAL (for a normal return) or RASCLIB_CALLBACK_UNREGISTER (to unregister the callback so that no further calls will be made). Below is a simple example, for informational purposes only, that illustrates how the callback is used:

pthread_mutex_t callback_lock = PTHREAD_MUTEX_INITIALIZER;

int alg12_callback(int cop_desc, char *name, char *buf, unsigned long status) {
        int i;
        char *p = buf;
        static  done_wr = 0, done_rd = 0;


        pthread_mutex_lock(&callback_lock);
        if (done_rd && done_wr){
                pthread_mutex_unlock(&callback_lock);
                return RASCLIB_CALLBACK_UNREGISTER;
        }
        buf += (SIZE/2 * sizeof(unsigned long));
        if (status == RASCLIB_STREAM_SEND_COMPLETE) {
                rasclib_cop_send(cop_desc, name, buf, (SIZE/2 *                     sizeof(unsigned long)));
                rasclib_cop_commit(cop_desc, alg12_callback);
                done_rd  = 1;
        } else {
                rasclib_cop_receive(cop_desc, name, buf, (SIZE/2 * sizeof(unsigned long)));
                rasclib_cop_commit(cop_desc, alg12_callback);
                done_wr = 1;
        }
        pthread_mutex_unlock(&callback_lock);
        return RASCLIB_CALLBACK_NORMAL;
}

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_NO_DESC if cop_desc cannot be translated into a descriptor pointer.

Returns RASCLIB_MALLOC_FAILED if a malloc call failed.

rasclib_cop_wait Function

The rasclib_cop_wait function is, as follows:

SYNOPSIS

C:

int rasclib_cop_wait(int cop_desc);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_COP_WAIT_F(COP_DESC)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_COP_WAIT_F
 INTEGER(KIND=4), INTENT(IN) :: COP_DESC
 END FUNCTION RASCLIB_COP_WAIT_F
END INTERFACE

DESCRIPTION

rasclib_cop_wait() blocks until all commands that have been sent to the kernel driver have completed execution. There is an implied commit associated with the wait. That is, before the thread of execution waits, it sends all queued commands to the kernel driver for execution (see rasclib_cop_commit). After the wait call returns, all outstanding data transfers have occurred and the application may do any buffer management that it may require.

cop_desc is the value returned by rasclib_cop_open().

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_NO_DESC if cop_desc cannot be translated into a descriptor pointer.

Returns RASCLIB_MALLOC_FAILED if a malloc call failed.

rasclib_cop_close Function

The rasclib_cop_close function is, as follows:

SYNOPSIS

C:

int rasclib_cop_close(int cop_desc);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_COP_CLOSE_F(COP_DESC)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_COP_CLOSE_F
 INTEGER(KIND=4), INTENT(IN) :: COP_DESC
 END FUNCTION RASCLIB_COP_CLOSE_F
END INTERFACE

DESCRIPTION

rasclib_cop_close() releases all host resources associated with the algorithm. It does not release any allocated devices (see rasclib_resource_free).

DIAGNOSTICS

cop_desc is the value returned by rasclib_cop_open().

rasclib_cop_reg_read Function

The rasclib_cop_reg_read function is, as follows:

SYNOPSIS

C:

int rasclib_cop_reg_read(int cop_desc, char *alg_reg, unsigned long *data, int ndata_elements, unsigned flags);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_COP_REG_READ_F(COP_DESC, ALG_REG, DATA, NDATA_ELEMENTS, FLAGS)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_COP_REG_READ_F
 INTEGER(KIND=4), INTENT(IN) :: COP_DESC
 CHARACTER(LEN=*), INTENT(IN) :: ALG_REG
 INTEGER(KIND=8), DIMENSION(*), INTENT(OUT) :: DATA
 INTEGER(KIND=4), INTENT(IN) :: NDATA_ELEMENTS
 INTEGER(KIND=4), INTENT(IN) :: FLAGS
 END FUNCTION RASCLIB_COP_REG_READ_F
END INTERFACE

DESCRIPTION

rasclib_cop_reg_read() reads a register from a single FPGA, as specified by cop_desc.

It is assumed that there is enough space in the array pointed to by data to handle all of the data.

cop_desc is the cop descriptor returned from the rasclib_cop_open function.

alg_reg is the name of the register.

data is a pointer to the data where the data read from the register will be placed.

flags can be either RASCLIB_QCMD or RASCLIB_IMMED_CMD.

If flags is RASCLIB_QCMD, the command is queued in rasclib to be sent to the driver to be executed in order within the command list.

If flags is RASCLIB_IMMED_CMD, the register reads are done before rasclib_cop_reg_read returns to the user.

The rasclib_cop_reg_read function supports fat registers. A fat register is register that spans multiple FPGA registers. Their length in bits must be an integral multiple of 64 and they must begin at the beginning of a physical register. Therefore, a fat register exactly spans an integral number of physical registers. It is assumed that the data array supplied is large enough to hold all the data for a fat register. The rasclib library does not support partial reads or writes to fat registers

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_INVAL_FLAG if the flag value is invalid.

rasclib_cop_reg_write Function

The rasclib_cop_reg_write function is, as follows:

SYNOPSIS

C:

int rasclib_cop_reg_write(int cop_desc, char *alg_reg, unsigned long *data, int ndata_elements, unsigned flags);

Fortran90:

INTERFACE
 FUNCTION RASCLIB_COP_REG_WRITE_F(COP_DESC, ALG_REG, DATA, NDATA_ELEMENTS, FLAGS)
 IMPLICIT NONE
 INTEGER(KIND=4) :: RASCLIB_COP_REG_WRITE_F
 NTEGER(KIND=4), INTENT(IN) :: COP_DESC
 CHARACTER(LEN=*), INTENT(IN) :: ALG_REG
 INTEGER(KIND=8), DIMENSION(*), INTENT(IN) :: DATA
 INTEGER(KIND=4), INTENT(IN) :: NDATA_ELEMENTS
 INTEGER(KIND=4), INTENT(IN) :: FLAGS
 END FUNCTION RASCLIB_COP_REG_WRITE_F
END INTERFACE

DESCRIPTION

rasclib_cop_reg_write() writes to a register of a single FPGA, as specified by cop_desc.

It is assumed that there is enough space in the array pointed to by data to fill the register.

cop_desc is the cop descriptor returned from the rasclib_cop_open function.

alg_reg is the name of the register.

data is a pointer to the data area where the data to be written resides.

flags can be either RASCLIB_QCMD or RASCLIB_IMMED_CMD.

If flags is RASCLIB_QCMD, the command is queued in rasclib to be sent to the driver to be executed in order within the command list.

If flags is RASCLIB_IMMED_CMD, the register reads are done before rasclib_cop_reg_write returns to the user.

The rasclib_cop_reg_write function supports fat registers. A fat register is register that spans multiple FPGA registers. Their length in bits must be an integral multiple of 64 and they must begin at the beginning of a physical register. Therefore, a fat register exactly spans an integral number of physical registers. It is assumed that the data array supplied is large enough to hold all the data for fat register. The rasclib library does not support partial reads or writes to fat registers

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_INVAL_FLAG if the flag value is invalid.

rasclib_cop_ exception_handler_register Function

The rasclib_cop_exception_handler_register function is, as follows:

SYNOPSIS

C:

int rasclib_cop_exception_handler_register(int cop_desc, int (*exception_handler)(void))

Fortran90:

INTERFACE
 FUNCTION RASCLIB_COP_EXCEPTION_REGISTER_F(COP_DESC, EXCEPTION_HANDLER) RESULT (RES)
 IMPLICIT NONE
 INTEGER(KIND=4), INTENT(IN) :: COP_DESC
 EXTERNAL :: EXCEPTION_HANDLER
 INTEGER(KIND=4) :: RES
 END FUNCTION RASCLIB_COP_EXCEPTION_REGISTER_F
END INTERFACE

DESCRIPTION

rasclib_cop_exception_handler_register function registers an application exception handler that is invoked when the FPGA logic drives the ALG_EVENT0 signal.

It is intended for application-defined FPGA logic exception events.

The FPGA logic is paused for the duration of the exception processing. The exception handler returns 0 if the FPGA logic can continue or 1 to stop the current logic run.

The algorithm registration function registers the handler for each FPGA represented by cop_desc.

DIAGNOSTICS

Returns RASCLIB_SUCCESS when all goes well.

Returns RASCLIB_UNSUPPORTED if Core Services does not support exception processing. This is the case for releases prior to the RASC 2.1 release.

rasclib_perror Function

The rasclib_perror function is, as follows:

SYNOPSIS

C:

void rasclib_perror(char *string, int ecode);

Fortran90:

INTERFACE
 SUBROUTINE RASCLIB_PERROR_F(STRING, ECODE)
 IMPLICIT NONE
 CHARACTER(LEN=*), INTENT(IN) :: STRING
 INTEGER(KIND=4), INTENT(IN) :: ECODE
 END SUBROUTINE RASCLIB_PERROR_F
ENDINTERFACE

DESCRIPTION

rasclib_perror prints an error string and a description of the error code.

string is a descriptive character string supplied by the caller.

ecode is an error code returned by a rasclib routine.

rasclib_error_dump Function

The rasclib_error_dump function is, as follows:

SYNOPSIS

C:

void rasclib_error_dump(void);

Fortran90:

INTERFACE
 SUBROUTINE RASCLIB_ERROR_DUMP_F
 IMPLICIT NONE
 END SUBROUTINE RASCLIB_ERROR_DUMP_F
END INTERFACE

DESCRIPTION

rasclib_error_dump prints the last three errors detected by rasclib. The rasclib library maintains a number of three-deep circular buffer of errors encountered by rasclib. One is a global buffer, one is associated with each algorithm, and one is associated with each co-processor (cop). rasclib_error_dump first prints the global errors, then the algorithm errors, and then the cop errors.

How the RASC Abstraction Layer Works

The rasclib library provides an asynchronous interface to the FPGA devices. That is, each call into the interface to perform some action on the device (send, go, receive) queues thethe command to the RASC abstraction layer. Commands are not actually sent to the driver (and, thus, to the device) until a commit call is done. At commit call time, all queued commands are sent to the driver as a list of commands. The driver sends the commands to the device. This takes advantage of any parallelism that may be available in the DMA engines or compute section. The user application cannot make any assumptions as to when the committed commands have finished executing. The user application must execute a wait call to make sure all committed commands have finished. The wait call blocks until all outstanding commands have completed. When the wait call returns, all user data buffers have either been completely read from or completely filled, depending on their use.

The algorithm layer also exists for ease of use. The application can reserve as many devices as it can get with the allocate call, then allow the abstraction layer to use them as efficiently as it can, spreading the data across as many devices as there are available and looping over the devices until all the data is consumed. The primary purpose is related to the above. By spreading the data across all the devices, the abstraction layer implements wide scaling. That is, multiple devices participate in the calculation in parallel. Deep scaling, or chaining the output of one device to the input of another device without having to stage the data through host memory, is left for later.

The input/output data buffers are assumed to be at least 16 KBs in size. Currently, user data requests to the algorithm layer are assumed to be an integral multiple of the data buffer in size and user data requests to the COP layer are assumed to be exactly the size of the data buffer.

So, given the above, here is how it all works. Assume a C-like program:

unsigned long A[SIZE],B[SIZE],C[SIZE];
main() {
        comput(A,B,C);
}

Where A and B are inputs to some function and C is the output. If the developer were to implement the function “compute” in an FPGA, then he would transform the above to:

unsigned long A[SIZE],B[SIZE],C[SIZE];
main() {

int al_desc,
int num_devices = N;
int res;

res = rasclib_resource_reserve(num_devices, NULL);
if (res != RASCLIB_SUCCESS) {
    fprintf(stderr,"reserve failed at %d: %d\n", __LINE__, res);
    rasclib_perror("reserve", res);
    return 1;
}

res = rasclib_resource_configure("compute", num_devices, NULL);
if (res != RASCLIB_SUCCESS) {
    fprintf(stderr,"configure failed at %d: %d\n", __LINE__, res);
    rasclib_perror("configure", res);
    return 1;
}
al_desc = rasclib_algorithm_open("compute");
if (al_desc == RASCLIB_FAIL) {
                exit(1);
        }

if (rasclib_algorithm_send(al_desc, "input_one", A, SIZE * sizeof(unsigned long)) != RASCLIB_SUCCESS) {
                exit(1);
        }

        if (rasclib_algorithm_send(al_desc, "input_two", B, SIZE * sizeof(unsigned long)) != RASCLIB_SUCCESS) {
                exit(1);
        }

        if (rasclib_algorithm_go(al_desc) != RASCLIB_SUCCESS) {
                exit(1);
        }

        if (rasclib_algorithm_receive(al_desc, "output", C, SIZE * sizeof(unsigned long)) != RASCLIB_SUCCESS) {
                exit(1);
        }

        if (rasclib_algorithm_commit(al_desc) != RASCLIB_SUCCESS) {
                exit(1);
        }

        if (rasclib_algorithm_wait(al_desc) != RASCLIB_SUCCESS) {
                exit(1);
        }
        rasclib_resource_return("compute", num_devices);
        rasclib_resource_release(num_devices, NULL);
} 

The rasclib_resource_reserve and rasclib_resource_configure calls reserve and configure devices through the device manager. The application must request all of the devices it needs for the life of the application in one call or deadlocks may result. The rasclib_algorithm_open tells the abstraction layer to allocate all necessary internal data structures for a logical algorithm. The two rasclib_algorithm_send calls pull data down to the input data areas on the COP. The rasclib_algorithm_go starts execution of the COP. The rasclib_algorithm_receive call pushes the result back out to host memory. The rasclib_algorithm_commit causes all of the commands that have been queued up by the previous four calls to be sent to the devices. The data is broken up on data area size boundaries and spread out over all available COPs. The rasclib_algorithm_wait blocks until all the command that were sent to all of the devices are complete, then returns.

The rasclib_resource_return and rasclib_resource_release calls tell the device manager that the application is done with the devices and that they can be allocated to other applications.