Nanashi-soft○プログラマ専用○Windows gcc SDL○
配列からランダムにデータを取り出したい場合、MFCの DMA転送は 16バイト境界でしか取り出せないので困ります
つまり、メインメモリ上のアドレスが 16で割り切れない箇所のデータは取り出せないのです
そこで、必要なデータを PPE側で 16バイト境界の配列に入れてから SPEに転送する
……という風に考えると私のようにハマります(汗)
そうでは無くて、必要なデータを含む 16バイト境界のデータを SPE側から取り出して、必要なデータのみをコピーする、と言う発想で行います
unsigned char型の2つの配列のポインタを unsigned long型の配列に入れて、引数にして渡す例です
尚、このプログラムは libspe 2.0.1用です
・PPE側の処理
SPEから配列を2つ読むと全く同じですので、そちらを見てください
『全く同じ』と言う点がポイントです
・SPE側の処理
data1の0〜63のうちから、3の倍数の数値(3,6,9,...63)を1つずつ取り出してみます
16バイト境界ではないので、どれ1つとして単体では取り出せません
必要なデータを含む 16バイトを転送して、必要なデータだけをコピーします
#include "stdio.h"
#include "spu_mfcio.h"
unsigned long addrlist[2] __attribute__((aligned(16)));
//データをDMA転送する為のワーク変数
unsigned char work[16] __attribute__((aligned(16)));
//結果を入れる変数(16バイト境界にしなくても良い所がポイント)
unsigned char kekka[21];
int main(unsigned long long spe, unsigned long long argp, unsigned long long envp){
//まずは、アドレスリストを取得
mfc_list_element_t element[1];
element[0].notify = 0;
element[0].reserved = 0;
element[0].size = sizeof(addrlist);
element[0].eal = mfc_ea2h(argp);
int tag=3;
spu_mfcdma64(&addrlist,mfc_ea2l(argp),(unsigned int)(element), sizeof(element), tag,MFC_GETL_CMD);
spu_writech(MFC_WrTagMask, 1 << tag);
spu_mfcstat(MFC_TAG_UPDATE_ALL);
//3の倍数を取得
int i;
int j=0;
for(i=3; i < 64; i += 3){
element[0].notify = 0;
element[0].reserved = 0;
element[0].size = sizeof(work);
//目的のデータを含む、16バイト境界を求めてDMA転送の先頭アドレスにセットする
element[0].eal = mfc_ea2l(addrlist[0]) + (int)(i/16)*16;
spu_mfcdma64(&work,mfc_ea2h(addrlist[0]),(unsigned int)(element), sizeof(element), tag,MFC_GETL_CMD);
spu_writech(MFC_WrTagMask, 1 << tag);
spu_mfcstat(MFC_TAG_UPDATE_ALL);
//受け取ったデータの中から、目的のデータを探して取り出す
kekka[j++] = work[i%16];
}
for(i=0; i < j; i++){
printf("kekka:%d\n", kekka[i]);
}
return 0;
}
このプログラムをビルドして実行すると
kekka:3
kekka:6
...
kekka:63
と表示されるはずです
この方法を用いると 16バイト境界を気にせずにプログラミングを行う事ができます
但し、パフォーマンスは当然落ちます