SpursEngineでのSPE起動サンプルです。
Cell/B.E.との主な違いは、
- SPEはビッグエンディアンでホストはx86の場合リトルエンディアンなのでパラメーターやデータの受け渡しの際、エンディアン変換が必要です。
- PCのメインメモリ、SpursEngineのローカルメモリ(128MB)、SPEのLS(1SPEあたり256KB)と3階層のメモリがあるので、まずSpursEngineのローカルメモリに領域を確保し、メインメモリからローカルメモリに転送、その後LSへの転送を行う必要があります。
- CESOFオブジェクトがないのでSPEプログラムはバイナリファイルとして別に出力しておき実行時に読み込むか、独自の方法でホスト側プログラムにデータとしてリンクする必要があります。
ダウンロード:se_hellospe.tar.gz
SPE側プログラム:spe.c
#include <stdio.h>
#include <spurs/spsa/spsa.h>
int main()
{
printf("Hello World from SPE!\n");
return 0;
}
ホスト側プログラム:main.cpp
#include <iostream>
#include <fstream>
#include <memory>
#include <stdlib.h>
#include <spurs/spha/spha.h>
#include <spurs/common/byte_order.h>
#include <spurs/sp3/sp3_cmdif.h>
#define NUM_OF_SPE 4
using namespace std;
// SPEプログラムファイル名
const char * spe_program_name = "spe.elf";
int main(int argc, char ** argv)
{
spha_session_t session;
// セッションの作成
spha_create_session(NULL, &session);
// 通信路を確立
spha_connect_session(session);
// SPEプログラムファイルをオープン
ifstream fp(spe_program_name, ios::binary);
// ファイルサイズを調べる
fp.seekg(0, ios::end);
uint32_t spe_program_size = fp.tellg();
fp.seekg(0, ios::beg);
// バッファサイズを128の倍数に揃える
uint32_t buffer_size = (spe_program_size + 127) & ~127;
// SpursEngine側ローカルメモリ領域の確保
spha_object_t buffer_obj;
spha_create_memory(session, 0, 0, 0, buffer_size, 0, &buffer_obj);
// メモリオブジェクトをマップ
uint32_t buffer_ea;
spha_map_memory(session, buffer_obj, 0, 0, 0, buffer_size, 0, &buffer_ea);
// ホスト側バッファを確保(128バイト・アライン)
char * buffer;
int err = posix_memalign((void **)&buffer, 128, buffer_size);
if (err)
{
abort();
}
// SPEプログラムファイルをロード
fp.read(buffer, spe_program_size);
// SpursEngine側ローカルメモリに転送
uint32_t transfer_size = buffer_size;
spha_data_transfer_to(session, buffer_obj, 0, buffer, &transfer_size);
// ホスト側バッファを解放
free(buffer);
// SPEプログラムローダに与える引数をセット
// エンディアン変換して渡す
uint32_t loader_arg[4];
loader_arg[0] = spurs_convert_ui32(buffer_ea);
loader_arg[1] = spurs_convert_ui32(buffer_size);
loader_arg[2] = 0;
loader_arg[3] = 0;
spha_thread_t spe_th[NUM_OF_SPE];
for (int i = 0; i < NUM_OF_SPE; i++)
{
// SPEスレッドを作成
spha_create_spe_thread(session, ~0, 0, SP3_SPE_LOADER_DEFAULT, loader_arg, sizeof(loader_arg), &spe_th[i]);
// SPEスレッドを実行状態にする
spha_resume_spe_thread(session, spe_th[i], 0, SP3_SPE_THREAD_RESUME_DEFAULT_ENTRY, NULL, 0, NULL, NULL, NULL);
}
for (int i = 0; i < NUM_OF_SPE; i++)
{
// SPEスレッドの終了を待つ
spha_wait_spe_thread(session, spe_th[i], NULL, NULL, NULL);
// SPEスレッドの破棄
spha_delete_spe_thread (session, spe_th[i]);
}
// メモリオブジェクトをアンマップ
spha_unmap_memory(session, buffer_ea, 0);
// SpursEngine側ローカルメモリ領域を解放
spha_delete_object(session, buffer_obj);
// セッションの通信路を切断
spha_close_session(session);
// セッションの破棄
spha_delete_session(session);
return 0;
}
【コンパイル・実行】
SpursEngine Linux SDKはホームディレクトリ直下のSpursEngine_Linux_SDK_v1_5_3_2/にインストールしていることを想定しています。他の場所にインストールしている場合は、Makefileの「SPURSTOP」を修正してください。下記の関連記事でSpursEngine開発環境の構築方法を紹介しています。
tar xzf se_hellospe.tar.gz
cd se_hellospe
make
./hellospe
「Hello World from SPE!」と4回表示されたら成功です。
関連記事
PCにUbuntu 10.04 Lucid Lynxを「軽量」インストールする
PCにSpursEngine Linux SDKをインストールする