Initial commit.

This commit is contained in:
2017-10-26 19:57:24 +02:00
commit 9ce8b5485d
1090 changed files with 47036 additions and 0 deletions
+218
View File
@@ -0,0 +1,218 @@
#ifndef MOC_INTERNAL_DOXYGEN_MAIN_H_
#define MOC_INTERNAL_DOXYGEN_MAIN_H_
/**
* \defgroup internal_main Developer Documentation
*
* This section deals with the internal design and functionality. For correct
* understanding knowledge about the functionality of the Cell Broadband Engine
* is needed. So you should read the official CBE documentation before you
* continue.
*
* \note Because we had only access to a playstation, we cannot guarantee correct
* execution on another CBE-machine than a playstation 3.
**/
/**
* \defgroup internal_core Implementation-Core
* \ingroup internal_main
**/
/**
* \defgroup internal_am Address-Macros
* \ingroup internal_core
*
* Predefined Macros for calculating Addresses of Message-Queue and Status-Array.
**/
/**
* \defgroup internal_tm Test-Macros
* \ingroup internal_core
*
* Predefined Macros for testing the validity of parameters.
**/
/**
* \defgroup internal_env Environmental Management
* \ingroup internal_main
*
* Internals about Startup & Shutdown and Error-Handling
**/
/**
* \defgroup internal_init Startup & Shutdown
* \ingroup internal_env
*
* Internals about the startup of the execution-environment and
* SPU-Thread-Management.
*
* \section iinit_start Startup
*
* The PPU-Process creates for every SPU-thread an own thread using the
* pthread-library (see \ref internal_spu_thread). The rank of each prozess,
* the overall process count, the sizes of message-queue and buffer-space
* and the effective base address of the buffer is send to each SPU-thread via
* mailbox-messages. The SPU-threads then send the memory-addresses of their
* message-queues and status-arrays back to the PPU-process which writes this
* data into the prozess-list. After all SPU-Threads have reported back to the
* PPU-process the effective address of the PPU's process-list ist distributed
* among the SPU-processes which then copy the process-list via DMA in their
* local storages.
*
* \section iinit_shut Shutdown
*
* \subsection iinit_shut_ppu PPU
*
* The PPU-process waits till all SPU-threads have signalled that they are also
* executing the finalize-function. After that a signal is send back to each
* SPU-Thread that they can now stop execution. Then local ressources are freed
* and the finalize-function returns.
*
* \subsection iinit_shut_spu SPU
*
* A mailbox-message is send to the PPU to signal that the SPU-process is now
* executing the finalize-function. After that the SPU-process is waiting till
* a mailbox-message from the PPU-process is received. Then local ressources are
* freed and the finalize-function returns.
*
**/
/**
* \defgroup internal_spu_thread SPU-Thread Management
* \ingroup internal_init
*
* This section deals about the creation and management of SPU-threads.
**/
/**
* \defgroup internal_error Error-Handling
* \ingroup internal_env
**/
/**
* \defgroup internal_timer Timers and Synchronization
* \ingroup internal_env
*
* Internals about Time.
*
* On the PPU "gettimeofday()" from time.h is used, because it is the only function
* which seems to work ("clock()" from time.h always returns 0).
*
* On the SPU there are two implementations. One uses also "gettimeofday()" and the
* other uses the spu-timer-library. The reason for this lies in the fact, that the
* spu-timer-library was marked as prototype in Cell SDK 3.0 and the future development
* of this library was uncertain. Cell SDK 3.1 has integrated the spu-timer-library in
* the main-library and so the gettimeofday-implementation is now obsolete.
*
* \note The timebase-constant which is needed to calculate time is hardcoded, because
* there was no according function for retrieving this value in Cell SDK 3.0 and we had
* only access to a playstation 3. Now Cell SDK 3.1 provides a function for retrieving
* the timebase value, but we didn't use it to provide backwards-compatibility. So if
* you plan to use MOC on another platform than playstation 3 keep in mind to check if
* the timebase-value is correct.
*
**/
/**
* \defgroup internal_comm Groups, Context and Communicators
* \ingroup internal_main
*
* At the moment user-defined groups and communicators are not implemented and maybe never
* will be.
* At the moment user-defined groups and communicators are not implemented and maybe never
* will be. Nevertheless user-defined groups and communicators have been taken into
* consideration while making the software-design (e.g. reserved field for communicator
* in message-envelope). So it should be not too hard to implement groups and communicators.
* However a lot of things concerning communicators are hardcoded (e.g. parameter checks).
*
* To save memory only one byte is used to encode the communicator. So if one
* day user-defined communicators are implemented there are only 256 possible
* communicators.
**/
/**
* \defgroup internal_p2p_main Point-to-Point Communication
* \ingroup internal_main
*
* Internals about Point-to-Point Communication.
**/
/**
* \defgroup internal_p2p_dma DMA-Helper Functions
* \ingroup internal_p2p_main
*
* Functions wrapping DMA-Transfers.
*
* The Cell Broadband Engine uses Direct Memory Access (DMA) for communication. Therefore
* data of a MOC-message is transfered using DMA operations. Because programming DMA is
* rather complex, some functions are provided to hide this complexity. One DMA-call can
* only tranfer a maximum of 16KByte of data and the data-size has to be a multiple of
* 16 byte. The provided functions split the data into multiple DMA-calls if needed. If
* the data-size requires it, an intermediate buffer is used into which a separate
* DMA-Call transfers 16 byte containing the piece of data not fitting into the 16-byte
* scheme. Then only the needed bytes are copied into the receive-buffer. But the latter
* only works for a get-operation.
*
* The internal DMA-functions are also made publicly available via wrapping-function
* (see chapter \ref dma_access) which provide parameter checks.
**/
/**
* \defgroup internal_p2p_blocking Blocking Communication
* \ingroup internal_p2p_main
*
* Internals about blocking Point-to-Point Communication.
**/
/**
* \defgroup internal_p2p_synch Synchronous Communication
* \ingroup internal_p2p_blocking
*
* Internals about blocking synchronous Communication.
*
* \image html synchronous_communication_1.png
**/
/**
* \defgroup internal_p2p_buffered Buffered Communication
* \ingroup internal_p2p_blocking
*
* Internals about blocking buffered Communication.
*
* \image html buffered_communication_1.png
**/
/**
* \defgroup internal_p2p_bmalloc Buffer-Management
* \ingroup internal_p2p_buffered
*
* This section shows how the buffer used for buffered communication is managed.
**/
/**
* \defgroup internal_p2p_imm Non-Blocking Communication
* \ingroup internal_p2p_main
*
* Internals about non-blocking communication.
*
* The SPUs are very limited in usage, e.g. only one thread per SPU is supported,
* and so it is hard to make communication non-blocking. In fact only synchronous
* send and receive provide possibilities for non-blocking communication. Because
* we think that the advantages of a non-blocking receive aren't worth the effort,
* only non-blocking send is implemented at the moment. The picture below illustrates
* a non-blocking synchronous communication call.
*
* \image html isyncronous_communication_1.png
**/
/**
* \defgroup internal_collective Collective Communication
* \ingroup internal_main
*
* Internals about Collective Communication
*
* Currently there are only two operations implemented.
*
* \section MOC_Bcast
*
* The root node sends normal messages using the reserved tag MOC_BCAST_TAG, which
* is received by all other nodes.
*
* \section MOC_Barrier
*
* All but the process with the highest rank send a special-message (special-flag set)
* to the latter process. This process then sends another special-message back to
* the others. After that the function returns on all calling processes.
*/
#endif /*MOC_DOXYGEN_MAIN_H_*/
+201
View File
@@ -0,0 +1,201 @@
#ifndef IMOC_H_
#define IMOC_H_
#include <stdint.h>
#include "../moc.h"
#include "imoc_core.h"
/**
* \addtogroup internal_p2p_imm
**/
//@{
/**
* @name Constants for MOC_Request.request_type
*/
//@{
/**
* MOC_Request is associated with a DMA-Communication.
**/
#define MOC_REQ_TYPE_DMA 0
/**
* MOC_Request is associated with aISsend-Communication.
**/
#define MOC_REQ_TYPE_ISSEND 1
//@}
//@}
/**
* \addtogroup internal_p2p_main
**/
//@{
/**
* @name Internal constants
*/
//@{
/**
* Defines a treshold, when to use memcpy and when to use DMA in a get-operation
* on the PPU.
**/
#define MEMCPY_GET_TRESHOLD 156
/**
* Defines a treshold, when to use memcpy and when to use DMA in a put-operation
* on the PPU.
**/
#define MEMCPY_PUT_TRESHOLD 2210
//@}
/**
* @name Internal shared functions
*/
//@{
/**
* Get the next valid message-envelope from "source" with specified "tag" and "comm".
*
* @param source \b in rank of sending node
* @param tag \b in message-tag
* @param comm \b in message-communicator
* @param isSpecial \b in true to return special-message
* @param status \b inout MOC_status-instance to add some information (e.g. source by MOC_ANY_SOURCE)
* @returns pointer to the appropriate message-queue-entry.
**/
moc_message_envelope_t* IMOC_get_entry(int source, int tag, MOC_Comm comm, int isSpecial, MOC_Status *status);
/**
* Get next free entry in message-queue (a local copy of the message-queue has to be used).
* To ensure correct ordering message-tag and -comm and -type has to be specified.
*
* @param pqueue \b in pointer to local copy of remote message-queue
* @param tag \b in message-tag
* @param comm \b in message-communicator
* @param isSpecial \b in true if message should be a special message
* @param index \b out index of free entry
* @return 0 when success otherwise error-code
**/
int IMOC_getFreeEntry ( moc_message_envelope_t* pqueue, uint8_t tag, MOC_Comm comm, int isSpecial, int* index );
/**
* Get free message-ID.
*
* \note Message-ID is index of message-status-array
*
* @param mid \b out free message-ID
* @retval MOC_SUCCESS No error; MPI routine completed successfully.
* @retval MOC_ERR_MESSAGE_EXHAUSTED No further messages possible.
**/
int IMOC_getFreeMID ( int *mid );
/**
* Wait till message with message-ID mid has been received.
*
* Waits till message-status-flag 'outstanding' is 0.
*
* @param mid \b in message-ID
* @return 0 when success otherwise error-code
**/
int IMOC_waitForMessageCompletion ( uint8_t mid );
/**
* Tests if message with message-ID mid has been received.
*
* Tests if message-status-flag 'outstanding' is 0.
*
* @param mid \b in message-ID
* @param status \b out status of message
* @retval MOC_SUCCESS No error; MPI routine completed successfully.
**/
int IMOC_testForMessageCompletion ( uint8_t mid, uint8_t *status );
//@}
//@}
/**
* \addtogroup internal_error
*
* This section deals with error-messages.
*
* An array of type \ref error_strings_struct stores error-messages and
* their corresponding error-codes. \ref MOC_Error_string searches this
* list for a given error-code and returns the error-message.
**/
//@{
/**
* Error-Strings structure.
*
* stores the error-string to a given error-code
**/
typedef struct error_strings_struct
{
int error_code; /**< error-code */
char * text; /**< error-text */
} error_strings_t; /**< typedef for \ref error_strings_struct */
//@}
/**
* \addtogroup internal_p2p_bmalloc
*
* Information about already allocated buffer-space is stored in the
* status-array. But this information has no order which forces us
* everytime we want to allocate buffer-space to create an ordered list
* of already allocated buffer-space. To avoid this we have additionally
* an ordered linked-list. This list orders the indexes (== message-IDs)
* of the status-array-entries in ascending order of the memory-addresses.
* This enables fast searching for free buffer-space.
*
* Allocated buffer-space is cleared by the receiving process by setting
* the appropriate flag in the status-array-entry. This is done by a
* DMA-Transfer and so no collaboration of the sending-process is needed.
* During the next allocation of buffer-space nodes with disabled buffer-flags
* are freed.
**/
//@{
/**
* Node of linked list holding information about allocated buffer-space.
**/
typedef struct moc_internal_buffer_node_struct
{
struct moc_internal_buffer_node_struct *next_node; /**< Pointer to
next entry **/
uint8_t mid; /**< Message-ID of message using buffer-space.
Information about the used buffer-space is stored in the
appropriate message-status-entry (mid is index of entry). **/
} moc_internal_buffer_node_t;
/**
* Allocate buffer-space.
*
* @param size \b in size of buffer-space
* @param mid \b in corresponding message-ID
* @return effective address of allocated buffer-space (16-byte aligned)
**/
uint64_t IMOC_bmalloc ( uint32_t size, uint8_t mid );
//@}
#endif /*IMOC_H_*/
+173
View File
@@ -0,0 +1,173 @@
#ifndef MOC_INTERNAL_CORE_
#define MOC_INTERNAL_CORE_
#include <stdint.h>
/**
* \addtogroup internal_core
*
* This section deals with the data-structures and the basic concepts which
* form the core of this implementation.
*
* \section icore_struct Data-Structures
*
* Basically there are four data-structures. \ref moc_message_envelope_struct
* holds meta-information about a message and \ref moc_message_status_struct holds
* information about used buffer-space and provide means for a receiving proccess
* to send some information back to the sending process.
*
* \ref moc_process_struct stores information every node needs to know about the
* other nodes to successfully communicate with them.
*
* The forth data-structure (actually there are two) \ref moc_node_handle_ppu_struct
* respectively \ref moc_node_handle_spu_struct holds information a node know about
* itself and the execution environment.
*
* \section core_conc Concepts
*
* Every node has (N-1) queues for incoming messages, where N is the overall number
* of node. Each queue is exclusively used by a specific remote node to write
* meta-data about the message to be send into it (queue-entries are of type \ref
* moc_message_envelope_struct). Because there are several independend queues and no
* global time is available, an exact order of all incoming messages cannot be guaranteed.
* Corrent ordering can only be guaranteed for messages from the same source-node.
* The queues are implemented in form of a big array which is divided in (N-1) equally
* sized pieces.
*
* Furthermore every node has an array of size (N-1)*m where m is the size of a
* message-queue (entries are of type \ref moc_message_status_struct).
* This array is used for buffer-management and to report the status of a message
* back to the sender.
* Every message currently under progress has a message-id which is unique in respect
* to the sending-node. This message-id is equal to the index of the corresponding
* entry of the status-array.
*
* In order to communicate with other nodes every node also keeps a list of all nodes
* in the execution environment (entries are of type \ref moc_process_struct).
*
* Pointers to the own arrays and some further information a node needs to know (e.g.
* own rank) is stored in the globally accessible variable \ref node_handle.
**/
//@{
/**
* @name PPU & SPU
**/
//@{
/**
* Default size of the message-queues.
**/
#define MOC_QUEUE_SIZE 4
/**
* Default size of the buffers used for buffered communication.
**/
#define MOC_BUFFER_SIZE 2048
/**
* Message-envelope structure.
*
* Is used to store meta-data about the message in the message-queues of the receiving process.
**/
typedef struct moc_message_envelope_struct
{
uint8_t id; /**< Message-ID. Also index of message-status-array*/
uint8_t tag; /**< Message-tag*/
uint8_t communicator; /**< Communicator of message*/
union
{
struct
{
unsigned int valid : 1; /**< Is the message valid? */
unsigned int signal_back : 1; /**< Should the status be reported back to the
sending process */
unsigned int special : 1; /**< Is this message a special message? */
unsigned int collaborative : 1; /**< Is this message part of a collaborative
communication? */
unsigned int channel : 2; /**< Which channel is used to transport the message? */
unsigned int in_mm : 1; /**< Are the data in Main-Memory? */
unsigned int keep_valid : 1; /**< Should the message-status-entry be invalidated? */
} __attribute__((__packed__)) bits; /**< flag-struct */
uint8_t value; /**< union-value */
} flags; /**< flag-union */
unsigned int size : 24; /**< Message-size in byte*/
unsigned int datatype : 8; /**< Data-type of message-entries */
uint64_t message_address; /**< Effective address of message-data*/
} __attribute__((__packed__)) moc_message_envelope_t;
/**
* Constant for moc_message_envelope_t.flags.channel.
*
* Message is transported via a DMA-Call.
**/
#define IMOC_MESSAGE_CHANNEL_DMA 0
/**
* Constant for moc_message_envelope_t.flags.channel.
*
* Message is embedded in message-envelope.
**/
#define IMOC_MESSAGE_CHANNEL_ENV 1
/**
* Message-status structure.
*
* Is used to store information about the message-status and the buffer used in the
* message-status-array.
**/
typedef struct moc_message_status_struct
{
uint32_t buffer_offset; /**< allocated buffer-offset from buffer-base */
uint32_t message_size; /**< size of message in byte */
uint32_t error_value; /**< optional error-code of message */
union
{
struct
{
unsigned int valid : 1; /**< Is this entry valid? */
unsigned int outstanding : 1; /**< Message is not yet received? */
unsigned int buffer_used : 1; /**< Is Bufferspace used? */
unsigned int reserved : 5; /**< reserved */
} __attribute__((__packed__)) bits; /**< flag-struct */
uint8_t value; /**< union-value */
} flags; /**< flag-union */
uint8_t reserved[3]; /**< reserved */
} __attribute__((__packed__)) moc_message_status_t;
/**
* Constant for moc_process_struct.type.
**/
#define MOC_PPU_PROCESS 0
/**
* Constant for moc_process_struct.type.
**/
#define MOC_SPU_PROCESS 1
/**
* Process-information structure.
*
* Stores information about a MOC-Process. This information is used for communication
* between the processes.
*/
typedef struct moc_process_struct
{
uint8_t type; /**< Process-type (SPU or PPU) */
uint8_t reserved[7]; /**< reserved */
uint64_t inbox_queue_base; /**< effective base-address of message-queues */
uint64_t stat_array_base; /**< effective base-address of message-status-array */
uint64_t ps_base; /**< effective base-address of problem-state (Signals, mailboxes, ...)*/
} __attribute__((__packed__)) moc_process_t;
//@}
//@}
#endif /*MOC_INTERNAL_CORE_*/
+141
View File
@@ -0,0 +1,141 @@
#ifndef MOC_INTERNAL_ADDRESS_MACROS_H_
#define MOC_INTERNAL_ADDRESS_MACROS_H_
/**
* \addtogroup internal_am
**/
//@{
/**
* @name PPU & SPU
**/
//@{
/**
* Effective base-address of own remote queue at node 'rank'.
*
* Address is of type uint64_t
**/
#define IMOC_EA_REMOTE_QUEUE(proc) ( (proc > node_handle.rank) ? node_handle.moc_process_list[proc].inbox_queue_base+sizeof(moc_message_envelope_t)*node_handle.queue_size*node_handle.rank : node_handle.moc_process_list[proc].inbox_queue_base+sizeof(moc_message_envelope_t)*node_handle.queue_size*(node_handle.rank-1) )
/**
* Effective Base-Address of local queue responsible for node 'rank'.
*
* Address is of type moc_message_envelope_t*
**/
#define IMOC_LOCAL_QUEUE(proc) ( (proc < node_handle.rank) ? node_handle.message_queue_base+node_handle.queue_size*(proc) : node_handle.message_queue_base+node_handle.queue_size*(proc-1) )
/**
* Effective base-address of own remote queue-entry at node 'rank'.
*
* Address is of type uint64_t
**/
#define IMOC_EA_REMOTE_QUEUE_ENTRY(proc, index) ( (proc > node_handle.rank) ? node_handle.moc_process_list[proc].inbox_queue_base+sizeof(moc_message_envelope_t)*node_handle.queue_size*node_handle.rank+sizeof(moc_message_envelope_t)*(index) : node_handle.moc_process_list[proc].inbox_queue_base+sizeof(moc_message_envelope_t)*node_handle.queue_size*(node_handle.rank-1)+sizeof(moc_message_envelope_t)*(index) )
/**
* Effective Base-Address of local queue-entry responsible for node 'rank'.
*
* Address is of type moc_message_envelope_t*
**/
#define IMOC_LOCAL_QUEUE_ENTRY(proc, index) ( (proc < node_handle.rank) ? node_handle.message_queue_base+node_handle.queue_size*(proc)+(index) : node_handle.message_queue_base+node_handle.queue_size*(proc-1)+(index) )
/**
* Effective Address of remote status-array entry at node 'rank'.
*
* Address is of type uint64_t
**/
#define IMOC_EA_REMOTE_STATUS_ENTRY(id, rank) ( node_handle.moc_process_list[rank].stat_array_base+sizeof(moc_message_status_t)*(id) )
//@}
//@}
/**
* \addtogroup internal_tm
**/
//@{
/**
* Tests if invalid communicator in a send-operation.
* Calls return with appropriate error-code itself.
**/
#define IMOC_TEST_COMM_SEND(comm) if ( (comm) != MOC_COMM_WORLD && (comm) != MOC_COMM_SELF ) \
{ return MOC_ERR_COMM; }
/**
* Tests if invalid communicator in a recv-operation.
* Calls return with appropriate error-code itself.
**/
#define IMOC_TEST_COMM_RECV(comm) if ( (comm) != MOC_COMM_WORLD && (comm) != MOC_COMM_SELF ) \
{ return MOC_ERR_COMM; }
/**
* Tests if invalid tag in a send-operation.
* Calls return with appropriate error-code itself.
**/
#define IMOC_TEST_TAG_SEND(tag) if ( (tag) > 255 || (tag) < 0 ) \
{ return MOC_ERR_TAG; }
/**
* Tests if invalid tag in a recv-operation.
* Calls return with appropriate error-code itself.
**/
#define IMOC_TEST_TAG_RECV(tag) if ( (tag)!=MOC_ANY_TAG && ((tag) > 255 || (tag) < 0) ) \
{ return MOC_ERR_TAG; }
/**
* Tests if invalid rank.
* Calls return with appropriate error-code itself.
**/
#define IMOC_TEST_RANK(rank) if ( (rank) < 0 || (rank) >= node_handle.comm_size ) \
{ return MOC_ERR_RANK; }
/**
* Tests if invalid rank in a recv-operation.
* Calls return with appropriate error-code itself.
**/
#define IMOC_TEST_RANK_RECV(rank) if ( rank != MOC_ANY_SOURCE && ((rank) < 0 || (rank) >= node_handle.comm_size) ) \
{ return MOC_ERR_RANK; }
/**
* Tests if invalid byte-count in a recv-operation.
* Calls return with appropriate error-code itself.
**/
#define IMOC_TEST_BYTECOUNT(count) if ( (count) < 0 || (count) > MAX_MOC_MESSAGE_SIZE ) \
{ return MOC_ERR_COUNT; }
/**
* Tests if invalid buffer-pointer.
* Calls return with appropriate error-code itself.
**/
#define IMOC_TEST_BUFFER(buf) if ( (buf) == 0 ) \
{ return MOC_ERR_BUFFER; }
/**
* Tests if rank is MOC_PROC_NULL and returns with MOC_SUCCESS itself.
**/
#define IMOC_TEST_PROC_NULL(rank) if ((rank) == MOC_PROC_NULL ) \
{ return MOC_SUCCESS; }
/**
* Tests if rank is own rank and returns with MOC_SUCCESS itself.
**/
#define IMOC_TEST_PROC_SELF(proc) if ( (proc) == node_handle.rank ) \
{ return MOC_SUCCESS; }
/**
* Tests if address is 16-byte aligned.
* Calls return with appropriate error-code itself.
**/
#define IMOC_TEST_ALIGNMENT(address) if ( ((unsigned long)(address)) % 16 != 0 ) \
{ return MOC_ERR_BAD_ALIGNMENT; }
//@}
#endif /*MOC_INTERNAL_ADDRESS_MACROS_H_*/
+132
View File
@@ -0,0 +1,132 @@
#ifndef MOC_INTERNAL_CORE_PPU_H_
#define MOC_INTERNAL_CORE_PPU_H_
#include <stdint.h>
#include <libspe2.h>
#include <pthread.h>
#include "../imoc_core.h"
#include "../../ppu/moc.h"
/**
* \addtogroup internal_core
**/
//@{
/**
* @name PPU only
**/
//@{
/**
* Node-handle structure.
*
* \note PPU only
*
* Information each node knowns about himself and the world.
**/
typedef struct moc_node_handle_ppu_struct
{
uint8_t rank; /**< rank of node */
uint8_t comm_size; /**< number of overall processes */
uint8_t queue_size; /**< Size of a message-queue */
volatile moc_message_envelope_t* message_queue_base; /**< base-address of own message-queues */
volatile moc_message_status_t* status_array_base; /**< base-address of own message-status-array */
void* buffer_base; /**< base-address of own buffer */
uint32_t buffer_size; /**< size of own buffer */
volatile uint32_t* signal_area; /**< address of own signal-area */
volatile moc_process_t* moc_process_list; /**< list of all other MOC-processes
(index is rank of process) */
} moc_node_handle_ppu_t; /**< typedef of \ref moc_node_handle_ppu_struct */
/**
* Information each node knowns about himself and the world.
*
* \note PPU only
*
**/
moc_node_handle_ppu_t node_handle;
//@}
//@}
/**
* \addtogroup internal_spu_thread SPU-Thread Management
*
* \note PPU only
**/
//@{
/**
* SPU-Thread structure.
*
* \note PPU only
*
* Stores information about the SPU-Threads the managing PPU-Process
* needs to know.
**/
typedef struct moc_spu_thread_struct
{
uint8_t rank; /**< rank of SPU-thread */
pthread_t pthread; /**< PThread-handle <*/
spe_context_ptr_t speid; /**< SPE-Context */
spe_stop_info_t stop_info; /**< Error-Information */
uint32_t spe_entry_adress; /**< Spe-entry-address */
void *argp; /**< effective address of user-defined information
in main-memory */
void *envp; /**< Pointer to environment information */
void* buffer_base; /**< base-address of the SPU-Thread's buffer */
uint32_t buffer_size; /**< size of the SPU-Thread's buffer */
uint64_t ls_base; /**< Effective Basis-Address of SPU's local-storage */
uint32_t queue_base_in_ls; /**< Address of message-queue in SPU's local-storage */
uint32_t status_base_in_ls; /**< Address of status-array in SPU's local-storage */
} moc_spu_thread_t; /**< typedef of \ref moc_spu_thread_struct */
/**
* actual number of SPU-Threads.
*
* \note PPU only
**/
uint8_t moc_spu_thread_count;
/**
* actual number of PPU-Threads.
*
* \note PPU only
**/
uint8_t moc_ppu_thread_count;
/**
* init buffer size
**/
uint32_t moc_spu_buffer_size;
/**
* init message-queue size
**/
uint8_t moc_spu_queue_size;
/**
* array of SPU-Threads.
*
* \note PPU only
**/
moc_spu_thread_t moc_spu_thread_list[MOC_SPU_THREAD_MAX];
/**
* PThread-function for creating SPU-Threads
**/
void* moc_spe_pthread_func(void *arg);
//@}
#endif /*MOC_INTERNAL_CORE_PPU_H_*/
+148
View File
@@ -0,0 +1,148 @@
#ifndef MOC_INTERNAL_DATA_TRANSFER_PPU_H_
#define MOC_INTERNAL_DATA_TRANSFER_PPU_H_
#include <stdint.h>
#include "../../moc.h"
/**
* \addtogroup internal_p2p_dma
**/
//@{
/**
* @name PPU-only
**/
//@{
/**
* Internal wrapper-function for a blocking DMA-get operation.
* Data can be of any size, constraints of low-level DMA-functions
* are dealt by this function.
* However data-addresses have to be at least 16-byte aligned.
*
* This function actually always reads a multiple of 16 from the source,
* but copies only size bytes of it to target. This means however that up
* to 15 bytes are read from an invalid location. As it is never written to
* them this should always be safe.
*
* On the ppu the system for tag reservation is not present, so a hardcoded tag is used.
* It has also to be noted that the dma calls are actually initiated on the spu by the ppu.
*
* @param target \b in local-address of buffer
* @param source \b in ea-address of data
* @param size \b in size of data in byte
* @param dest \b in id of source spe
* @return 0 when success otherwise error-code
**/
int IMOC_get_data(void* target, uint64_t source, uint32_t size, int dest);
/**
* Internal wrapper-function for a blocking DMA-put operation.
* Data-size should be a multiple of 16 because of low-level constraints, but
* there is no upper limit of transfer-size.
* Data-addresses have to be at least 16-byte aligned.
*
* This function actually always reads a multiple of 16 from the source, and copies
* it to target. This means however that up to 15 bytes are written to and invalid
* location, so if one wants to use it with invalid sizes precautions have to be taken
* in order to make it safe.
*
* On the ppu the system for tag reservation is not present, so a hardcoded tag is used.
* It has also to be noted that the dma calls are actually initiated on the spu by the ppu.
*
* @param source \b in local-address of data
* @param target \b in ea-address of buffer
* @param size \b in size of data in byte
* @param dest \b in id of source spe
* @return 0 when success otherwise error-code
**/
int IMOC_put_data(void* source, uint64_t target, uint32_t size, int dest);
/**
* Internal wrapper-function for a non-blocking DMA-get operation.
* Data can be of any size, constraints of low-level DMA-functions
* are dealt by this function.
* However data-addresses have to be at least 16-byte aligned.
*
* This function actually always reads a multiple of 16 from the source,
* but copies only size bytes of it to target. This means however that up
* to 15 bytes are read from an invalid location. As it is never written to
* them this should always be safe.
*
* On the ppu the system for tag reservation is not present, so a hardcoded tag is used.
* It has also to be noted that the dma calls are actually initiated on the spu by the ppu.
*
* @param target \b in local-address of buffer
* @param source \b in ea-address of data
* @param size \b in size of data in byte
* @param dest \b in id of source spe
* @param request \b out request-handle
* @return 0 when success otherwise error-code
**/
int IMOC_iget_data(void* target, uint64_t source, uint32_t size, uint32_t dest, imoc_dma_request* request);
/**
* Internal wrapper-function for a non-blocking DMA-put operation.
* Data-size should be a multiple of 16 because of low-level constraints, but
* there is no upper limit of transfer-size.
* Data-addresses have to be at least 16-byte aligned.
*
* This function actually always reads a multiple of 16 from the source, and copies
* it to target. This means however that up to 15 bytes are written to and invalid
* location, so if one wants to use it with invalid sizes precautions have to be taken
* in order to make it safe.
*
* On the ppu the system for tag reservation is not present, so a hardcoded tag is used.
* It has also to be noted that the dma calls are actually initiated on the spu by the ppu.
*
* @param source \b in local-address of data
* @param target \b in ea-address of buffer
* @param size \b in size of data in byte
* @param dest \b in id of source spe
* @param request \b out request-handle
* @return 0 when success otherwise error-code
**/
int IMOC_iput_data(void* source, uint64_t target, uint32_t size, uint32_t dest, imoc_dma_request* request);
/**
* Waits till a IMOC_iget_data or IMOC_iput_data is completed.
*
* @param request \b in request-handle
* @return 0 when success otherwise error-code
**/
int IMOC_wait_dma(imoc_dma_request* request);
/**
* Tests if a IMOC_iget_data or IMOC_iput_data is completed.
*
* @param request \b in request-handle
* @param flag \b out true if operation is completed
* @return 0 when success otherwise error-code
**/
int IMOC_test_dma(imoc_dma_request* request, int *flag);
/**
* Reserves a tag on the ppu, for communication with a given spu.
*
* @param speid \b id of spu to communicate with
* @return tag (0-14) when success otherwise error code
**/
int moc_tag_reserve(unsigned int speid);
/**
* Releases a reserved tag.
*
* @param speid \b id of spu for which the tag was reserved
* @param tag \b tag to be released
* @return 0 when success otherwise error-code
**/
int moc_tag_release(unsigned int speid, int tag);
//@}
//@}
#endif /*MOC_INTERNAL_DATA_TRANSFER_PPU_H_*/
+48
View File
@@ -0,0 +1,48 @@
#ifndef MOC_INTERNAL_ADDRESS_MACROS_PPU_H_
#define MOC_INTERNAL_ADDRESS_MACROS_PPU_H_
#include "../imoc_macros.h"
/**
* \addtogroup internal_am
**/
//@{
/**
* @name PPU-only
**/
//@{
/**
* LS-Address of own remote queue at node 'rank'.
*
* Address is of type uint32_t.
**/
#define IMOC_LS_REMOTE_QUEUE(proc) ( (proc > node_handle.rank) ? moc_spu_thread_list[proc-moc_ppu_thread_count].queue_base_in_ls+sizeof(moc_message_envelope_t)*node_handle.queue_size*node_handle.rank : moc_spu_thread_list[proc-moc_ppu_thread_count].queue_base_in_ls+sizeof(moc_message_envelope_t)*node_handle.queue_size*(node_handle.rank-1) )
/**
* LS-Address of own remote queue-entry at node 'rank'.
*
* Address is of type uint32_t.
**/
#define IMOC_LS_REMOTE_QUEUE_ENTRY(proc, index) ( (proc > node_handle.rank) ? moc_spu_thread_list[proc-moc_ppu_thread_count].queue_base_in_ls+sizeof(moc_message_envelope_t)*node_handle.queue_size*node_handle.rank+sizeof(moc_message_envelope_t)*(index) : moc_spu_thread_list[proc-moc_ppu_thread_count].queue_base_in_ls+sizeof(moc_message_envelope_t)*node_handle.queue_size*(node_handle.rank-1)+sizeof(moc_message_envelope_t)*(index) )
/**
* Effective Address of remote status-array entry at node 'rank'.
*
* Address is of type uint32_t
**/
#define IMOC_LS_REMOTE_STATUS_ENTRY(id, rank) ( moc_spu_thread_list[rank-moc_ppu_thread_count].status_base_in_ls+sizeof(moc_message_status_t)*(id) )
//@}
//@}
#endif /*MOC_INTERNAL_ADDRESS_MACROS_PPU_H_*/
+53
View File
@@ -0,0 +1,53 @@
#ifndef MOC_INTERNAL_CORE_SPU_H_
#define MOC_INTERNAL_CORE_SPU_H_
#include "../imoc_core.h"
/**
* \addtogroup internal_core
**/
//@{
/**
* @name SPU only
**/
//@{
/**
* Node-handle structure.
*
* \note SPU only
*
* Information each node knowns about himself and the world.
**/
typedef struct moc_node_handle_spu_struct
{
uint8_t rank; /**< rank of node */
uint8_t comm_size; /**< number of overall processes */
uint8_t queue_size; /**< Size of a message-queue */
uint64_t ls_base; /**< Effective address of own local-store */
volatile moc_message_envelope_t* message_queue_base; /**< base-address of own message-queues */
volatile moc_message_status_t* status_array_base; /**< base-address of own message-status-array */
uint64_t buffer_base; /**< base-address of own buffer */
uint32_t buffer_size; /**< size of own buffer */
volatile moc_process_t* moc_process_list; /**< list of all other MOC-processes
(index is rank of process) */
} moc_node_handle_spu_t; /**< typedef of \ref moc_node_handle_spu_struct */
/**
* Information each node knowns about himself and the world.
*
* \note SPU only
**/
moc_node_handle_spu_t node_handle;
//@}
//@}
#endif /*MOC_INTERNAL_CORE_SPU_H_*/
+115
View File
@@ -0,0 +1,115 @@
#ifndef MOC_INTERNAL_GET_DATA_H_
#define MOC_INTERNAL_GET_DATA_H_
#include <stdint.h>
#include "../../moc.h"
/**
* \addtogroup internal_p2p_dma
**/
//@{
/**
* @name SPU-only
**/
//@{
/**
* Internal wrapper-function for a blocking DMA-get operation.
* Data can be of any size, constraints of low-level DMA-functions
* are dealt by this function.
* However data-addresses have to be at least 16-byte aligned.
*
* This function actually always reads a multiple of 16 from the source,
* but copies only size bytes of it to target. This means however that up
* to 15 bytes are read from an invalid location. As it is never written to
* them this should always be safe.
*
* @param target \b in ls-address of buffer
* @param source \b in ea-address of data
* @param size \b in size of data in byte
* @return 0 when success otherwise error-code
**/
int IMOC_get_data(void* target, uint64_t source, uint32_t size);
/**
* Internal wrapper-function for a blocking DMA-put operation.
* Data-size should be a multiple of 16 because of low-level constraints, but
* there is no upper limit of transfer-size.
* Data-addresses have to be at least 16-byte aligned.
*
* This function actually always reads a multiple of 16 from the source, and copies
* it to target. This means however that up to 15 bytes are written to and invalid
* location, so if one wants to use it with invalid sizes precautions have to be taken
* in order to make it safe.
*
* @param source \b in ls-address of data
* @param target \b in ea-address of buffer
* @param size \b in size of data in byte
* @return 0 when success otherwise error-code
**/
int IMOC_put_data(void* source, uint64_t target, uint32_t size);
/**
* Internal wrapper-function for a non-blocking DMA-get operation.
* Data can be of any size, constraints of low-level DMA-functions
* are dealt by this function.
* However data-addresses have to be at least 16-byte aligned.
*
* This function actually always reads a multiple of 16 from the source,
* but copies only size bytes of it to target. This means however that up
* to 15 bytes are read from an invalid location. As it is never written to
* them this should always be safe.
*
* @param target \b in ls-address of buffer
* @param source \b in ea-address of data
* @param size \b in size of data in byte
* @param request \b out request-handle
* @return 0 when success otherwise error-code
**/
int IMOC_iget_data(void* target, uint64_t source, uint32_t size, imoc_dma_request* request);
/**
* Internal wrapper-function for a blocking DMA-put operation.
* Data-size should be a multiple of 16 because of low-level constraints, but
* there is no upper limit of transfer-size.
* Data-addresses have to be at least 16-byte aligned.
*
* This function actually always reads a multiple of 16 from the source, and copies
* it to target. This means however that up to 15 bytes are written to and invalid
* location, so if one wants to use it with invalid sizes precautions have to be taken
* in order to make it safe.
*
* @param source \b in ls-address of data
* @param target \b in ea-address of buffer
* @param size \b in size of data in byte
* @param request \b out request-handle
* @return 0 when success otherwise error-code
**/
int IMOC_iput_data(void* source, uint64_t target, uint32_t size, imoc_dma_request* request);
/**
* Waits till a IMOC_iget_data or IMOC_iput_data is completed.
*
* @param request \b in request-handle
* @return 0 when success otherwise error-code
**/
int IMOC_wait_dma(imoc_dma_request* request);
/**
* Tests if a IMOC_iget_data or IMOC_iput_data is completed.
*
* @param request \b in request-handle
* @param flag \b out true if operation is completed
* @return 0 when success otherwise error-code
**/
int IMOC_test_dma(imoc_dma_request* request, int *flag);
//@}
//@}
#endif /*MOC_INTERNAL_GET_DATA_H_*/