Vivado HLS自体には触っていないんだけど、金曜日のTEDセミナーで聞いたことから総括すると・・・
画像処理系はStream系で組んだほうが良さそうだということで、そこからの推察である。
画像を2入力処理
例えば、アルファチャンネルでの画像合成とか・・・
画像Aと画像Bをαチャンネルで合成して、出力がZだとすると下記のようにするわけだよね。
void MAT(stream A, stream B, int α, stream *Z),
streamはAXI Streamってことで、実際にどう宣言しなきゃいけないか知らないで・・・
#多分、unsigned int *Aとかで良いと思ってるけど・・・
Streamを2入力の関数にするということだろう。
要するに下図のようになるわけだね。
MAT関数自体はAとBのStreamを2入力として、出力Zがある。
どう使うかというと、AXI-VDMAでStream側にFIFOを用意して、AXI-VDMAを同期させて入力Aと入力Bにするということなんだろう。
まさか、MAT関数の中で一つのStreamをAとBでバッファリングするというような回路をHLSが吐くとは思えないし。
Filted2Dとかの処理
OpenCVのFilter2Dとかの処理、3x3や5x5でのフィルタするけど単純にCモデルを作ると下記になるよね。
#下記は5x5の参考だけど・・・
for(y=0;y<HEIGHT;y++){
for(x=0;x<WIDTH;x++){
for(q=0;q<5;q++){
for(p=0;p<5;p++){
if((y+q-2>=0) && (x+p-2>=0) && (y+q-2<HEIGHT) && (x+p-2<WIDTH)){
m[q][p]=buf[y+q-2][x+p-2]*c[q][p];
}else{
m[q][p]=0;
}
}
}
for(q=0;q<5;q++){
for(p=0;p<5;p++){
ans[y][x] += m[q][p];
}
}
}
}これって、作っちゃうとHLSではメモリは静的ってことだから回路側に大きな入力バッファを作ることになるのかな?
5ラインごとに1ラインを入力してバッファを巡回してくれる処理する回路を生成してくれるんだろうか?
まさかぁ、そこまでできるとは思わないんだけど・・・
って、ことは下記のようなソースコードにして、Streamで食わせるってこと?
もっと、スマートなやり方はあると思うけどサンプルということで書いてみたが、XとYのfor文は外してバースト入力すれば上記の単純ソースと同じ答えを吐く。
こんなソースコードなんて書くの嫌だなぁ。
これが嫌だからC言語でシーケンシャルで手抜きなソースを書くんじゃないの?
HLS化のためにCソースをわざわざパラレル化しなきゃいけないんだったら、Cソースにこだわる必要はあるのだろうか?
初めからVerilogやVHDLで回路を書けばいいんじゃないの?
// 本体処理
for(y=0;y<HEIGHT+2;y++){
memset(&map,0,5*5),
for(x=0;x<WIDTH+2;x++){
// Xの処理
for(q=0;q<5;q++){
for(p=0;p<5;p++){
m[q][p]=buf[y][x]*c[q][p];
}
}
if(x<WIDTH){
switch(x%5){
case 0:
map[3][3] += m[4][4];
map[3][4] += m[4][3];
map[3][0] += m[4][2];
map[3][1] += m[4][1];
map[3][2] = m[4][0];
map[4][3] += m[3][4];
map[4][4] += m[3][3];
map[4][0] += m[3][2];
map[4][1] += m[3][1];
map[4][2] = m[3][0];
map[0][3] += m[2][4];
map[0][4] += m[2][3];
map[0][0] += m[2][2];
map[0][1] += m[2][1];
map[0][2] = m[2][0];
map[1][3] += m[1][4];
map[1][4] += m[1][3];
map[1][0] += m[1][2];
map[1][1] += m[1][1];
map[1][2] = m[1][0];
map[2][3] += m[0][4];
map[2][4] += m[0][3];
map[2][0] += m[0][2];
map[2][1] += m[0][1];
map[2][2] = m[0][0];
break;
case 1:
map[3][4] += m[4][4];
map[3][0] += m[4][3];
map[3][1] += m[4][2];
map[3][2] += m[4][1];
map[3][3] = m[4][0];
map[4][4] += m[3][4];
map[4][0] += m[3][3];
map[4][1] += m[3][2];
map[4][2] += m[3][1];
map[4][3] = m[3][0];
map[0][4] += m[2][4];
map[0][0] += m[2][3];
map[0][1] += m[2][2];
map[0][2] += m[2][1];
map[0][3] = m[2][0];
map[1][4] += m[1][4];
map[1][0] += m[1][3];
map[1][1] += m[1][2];
map[1][2] += m[1][1];
map[1][3] = m[1][0];
map[2][4] += m[0][4];
map[2][0] += m[0][3];
map[2][1] += m[0][2];
map[2][2] += m[0][1];
map[2][3] = m[0][0];
break;
case 2:
map[3][0] += m[4][4];
map[3][1] += m[4][3];
map[3][2] += m[4][2];
map[3][3] += m[4][1];
map[3][4] = m[4][0];
map[4][0] += m[3][4];
map[4][1] += m[3][3];
map[4][2] += m[3][2];
map[4][3] += m[3][1];
map[4][4] = m[3][0];
map[0][0] += m[2][4];
map[0][1] += m[2][3];
map[0][2] += m[2][2];
map[0][3] += m[2][1];
map[0][4] = m[2][0];
map[1][0] += m[1][4];
map[1][1] += m[1][3];
map[1][2] += m[1][2];
map[1][3] += m[1][1];
map[1][4] = m[1][0];
map[2][0] += m[0][4];
map[2][1] += m[0][3];
map[2][2] += m[0][2];
map[2][3] += m[0][1];
map[2][4] = m[0][0];
break;
case 3:
map[3][1] += m[4][4];
map[3][2] += m[4][3];
map[3][3] += m[4][2];
map[3][4] += m[4][1];
map[3][0] = m[4][0];
map[4][1] += m[3][4];
map[4][2] += m[3][3];
map[4][3] += m[3][2];
map[4][4] += m[3][1];
map[4][0] = m[3][0];
map[0][1] += m[2][4];
map[0][2] += m[2][3];
map[0][3] += m[2][2];
map[0][4] += m[2][1];
map[0][0] = m[2][0];
map[1][1] += m[1][4];
map[1][2] += m[1][3];
map[1][3] += m[1][2];
map[1][4] += m[1][1];
map[1][0] = m[1][0];
map[2][1] += m[0][4];
map[2][2] += m[0][3];
map[2][3] += m[0][2];
map[2][4] += m[0][1];
map[2][0] = m[0][0];
break;
case 4:
map[3][2] += m[4][4];
map[3][3] += m[4][3];
map[3][4] += m[4][2];
map[3][0] += m[4][1];
map[3][1] = m[4][0];
map[4][2] += m[3][4];
map[4][3] += m[3][3];
map[4][4] += m[3][2];
map[4][0] += m[3][1];
map[4][1] = m[3][0];
map[0][2] += m[2][4];
map[0][3] += m[2][3];
map[0][4] += m[2][2];
map[0][0] += m[2][1];
map[0][1] = m[2][0];
map[1][2] += m[1][4];
map[1][3] += m[1][3];
map[1][4] += m[1][2];
map[1][0] += m[1][1];
map[1][1] = m[1][0];
map[2][2] += m[0][4];
map[2][3] += m[0][3];
map[2][4] += m[0][2];
map[2][0] += m[0][1];
map[2][1] = m[0][0];
break;
}
}
// Yの処理
if((x>=2) && (y<HEIGHT)){
switch(y%5){
case 0:
ybuf[3][x-2]+=map[3][(x-2)%5];
ybuf[4][x-2]+=map[4][(x-2)%5];
ybuf[0][x-2]+=map[0][(x-2)%5];
ybuf[1][x-2]+=map[1][(x-2)%5];
ybuf[2][x-2] =map[2][(x-2)%5];
break;
case 1:
ybuf[4][x-2]+=map[4][(x-2)%5];
ybuf[0][x-2]+=map[0][(x-2)%5];
ybuf[1][x-2]+=map[1][(x-2)%5];
ybuf[2][x-2]+=map[2][(x-2)%5];
ybuf[3][x-2] =map[3][(x-2)%5];
break;
case 2:
ybuf[0][x-2]+=map[0][(x-2)%5];
ybuf[1][x-2]+=map[1][(x-2)%5];
ybuf[2][x-2]+=map[2][(x-2)%5];
ybuf[3][x-2]+=map[3][(x-2)%5];
ybuf[4][x-2] =map[4][(x-2)%5];
break;
case 3:
ybuf[1][x-2]+=map[1][(x-2)%5];
ybuf[2][x-2]+=map[2][(x-2)%5];
ybuf[3][x-2]+=map[3][(x-2)%5];
ybuf[4][x-2]+=map[4][(x-2)%5];
ybuf[0][x-2] =map[0][(x-2)%5];
break;
case 4:
ybuf[2][x-2]+=map[2][(x-2)%5];
ybuf[3][x-2]+=map[3][(x-2)%5];
ybuf[4][x-2]+=map[4][(x-2)%5];
ybuf[0][x-2]+=map[0][(x-2)%5];
ybuf[1][x-2] =map[1][(x-2)%5];
break;
}
}
}
if(y>=2){
for(x=0;x<WIDTH;x++){
last[y-2][x]=ybuf[(y-2)%5][x];
}
}
}
なんか、英語できる人がわざわざ日本語で文章を書いて、翻訳機に通した英語を披露するような感じにしか思えない。
パラレルでもシーケンシャルでもごちゃまぜな言語無いかな?
#SystemCは綺麗な言語構成じゃないので違う言語で・・・
#やっぱ、これからはerlangかな?