ソフトウェアとは異なりハードウェア システムは並列性が高いので、ストリーミング データの利点を活かすことができます。データはデザインに連続して供給され、デザインから連続して出力されます。RTL デザインは既存データを処理し終わる前に新しいデータを受信できます。
揮発性データの理解 に示すように、ソフトウェアでのストリーミング データの記述は、特に既存のハードウェア インプリメンテーション (既に並列/ストリーミング処理機能が存在し、記述する必要あり) を表すソフトウェアを記述する際に重要です。
これには、次のような複数の方法があります。
- マルチアクセス
volatile
ポインター インターフェイスの例に示すように、volatile 修飾子を追加します。テストベンチには固有の読み出しおよび書き込みが記述されていないので、元の C/C++ テストベンチを使用した RTL シミュレーションはエラーになりますが、トレース ファイルの波形を確認すると、正しい読み出しおよび書き込みが実行されています。 - 固有の読み出しおよび書き込みを明示的に記述するようにコードを変更します。次に例を示します。
- ストリーミング データ型を使用するようにコードを変更します。ストリーミング データ型を使用すると、ストリーミング データを使用してハードウェアが適切に記述されるようになります。
次に、テストベンチから 4 つの異なる値を読み出し、2 つの異なる値を書き込むようにアップデートしたコードを示します。ポインターのアクセスはシーケンシャルでロケーション 0 から開始するので、合成ではストリーミング インターフェイスが使用されます。
#include "pointer_stream_good.h"
void pointer_stream_good ( volatile dout_t *d_o, volatile din_t *d_i) {
din_t acc = 0;
acc += *d_i;
acc += *(d_i+1);
*d_o = acc;
acc += *(d_i+2);
acc += *(d_i+3);
*(d_o+1) = acc;
}
関数が各トランザクションで 4 つの固有の値を読み出すことを記述するように、テストベンチがアップデートされます。このテストベンチは、1 つのトランザクションのみを記述しています。複数のトランザクションを記述するには、入力データ セットを増加し、関数を複数回呼び出す必要があります。
#include "pointer_stream_good.h"
int main () {
din_t d_i[4];
dout_t d_o[4];
int i, retval=0;
FILE *fp;
// Create input data
for (i=0;i<4;i++) {
d_i[i] = i;
}
// Call the function to operate on the data
pointer_stream_good(d_o,d_i);
// Save the results to a file
fp=fopen(result.dat,w);
for (i=0;i<4;i++) {
if (i<2)
fprintf(fp, %d %d\n, d_i[i], d_o[i]);
else
fprintf(fp, %d \n, d_i[i]);
}
fclose(fp);
// Compare the results file with the golden results
retval = system(diff --brief -w result.dat result.golden.dat);
if (retval != 0) {
printf(Test failed !!!\n);
retval=1;
} else {
printf(Test passed !\n);
}
// Return 0 if the test
return retval;
}
このテストベンチにより、次のような結果のアルゴリズムが検証されます。
- 1 つのトランザクションから 2 つの出力が生成されます。
- 出力は最初の 2 つの入力読み出しが累算されたものと、次の 2 つの入力読み出しと最初の出力が累算されたものになります。
Din Dout 0 1 1 6 2 3
- ポインターが関数インターフェイスで複数回アクセスされる際に注意すべき最後の問題は、RTL シミュレーションの記述です。