FIFO インターフェイス - 2023.2 日本語

Vitis 高位合成ユーザー ガイド (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 日本語

Vitis HLS では、配列引数を RTL で FIFO ポートとしてインプリメントできます。FIFO ポートを使用する場合は、配列のアクセスがシーケンシャルであることを確認してください。

注記: インターフェイスでのアクセスがシーケンシャルではない場合、RTL シミュレーション不一致になります。

次のコード例では、ツールでアクセスがシーケンシャルかどうかを判断できません。この例では、d_id_o の両方が合成中に FIFO インターフェイスを使用してインプリメントされるように指定されています。この場合、アクセスがシーケンシャルであることを確認する必要があります。そうしないと、システムにエラーが発生します。

#include "array_FIFO.h"

void array_FIFO (dout_t d_o[4], din_t d_i[4], didx_t idx[4]) {
 int i;
#pragma HLS INTERFACE mode=ap_fifo port=d_i
#pragma HLS INTERFACE mode=ap_fifo port=d_o
 For_Loop: for (i=0;i<4;i++) {
 d_o[i] = d_i[idx[i]];
 }
}

この場合、変数 idx の値により、引数 d_i[] に対して FIFO インターフェイスが正しく作成できるかどうかが決まります。

  • idx の要素の値がシーケンシャルである場合は、FIFO インターフェイスを作成できます。
  • idx にランダムな値が使用されている場合、FIFO インターフェイスは RTL にインプリメントされたときに協調シミュレーションでエラーになり、ランタイム中にもエラーになる可能性があります。
ただし、これらの条件はコンパイル時に検証できないため、Vitis HLS は合成中にメッセージを表示して、FIFO インターフェイスを作成します。
@W [XFORM-124] Array 'd_i': may have improper streaming access(es).

さらに、idx は一度も読み出されません。これは、ap_fifo INTERFACE プラグマがあるために、配列の要素に 0 から開始するシーケンシャル値があると想定されるからです。

注記: FIFO ポートは、同じループまたは関数で読み出しおよび書き込みの両方を実行する配列用には合成できません。入力配列と出力配列は上記の例のように別々に作成する必要があります。

次の一般的な規則は、FIFO インターフェイスでインプリメントされる配列に適用されます。

  • 配列は、そのループまたは関数内でのみ読み出しまたは書き込みされる必要があります。これは FIFO リンクの特性と一致するポイント ツー ポイントの接続に変換される可能性があります。
  • 配列の読み出しは、配列の書き込みと同じ順序で実行される必要があります。FIFO チャネルではランダム アクセスがサポートされないので、配列は先入れ先出し (First In First Out) 動作に従ったプログラムで使用される必要があります。

次の条件は、配列のデータ型が構造体であり、配列がシーケンシャルにアクセスされる場合 (つまり、配列が axis または ap_fifo インターフェイスで指定されているか、STREAM プラグマまたは指示子でマークされる場合) に適用されます。

  • 構造体メンバーには、array-to-stream を使用する I/O 引数、またはストリーミング インターフェイスとしての I/O 引数から直接アクセスすることはできません。構造体のローカル コピーを作成すると、メンバー要素を読み出し/書き込みできます。
  • 次に示すように、シーケンシャル順でアクセスできるようにしてください。
struct A {
  short foo;
  int bar;
};
  
void dut(A in[N], A out[out], bool flag) {
  #pragma HLS interface ap_fifo port=in,out
  for (unsigned i=0; i<N; i++) {
    A tmp = in[i];
    if (flag)
      tmp.bar += 5;
    out[i] = tmp;
  }
}
 
Bad example 1:
void dut(A in[N], A out[out], bool flag) {
  #pragma HLS interface ap_fifo port=in,out
  for (unsigned i=0; i<N; i++) {
    out[i] = in[i];
    if (flag)
      out[i].bar += 5;
  }
}
 
Bad example 2:
void dut(A in[N], A out[out], bool flag) {
  #pragma HLS interface ap_fifo port=in,out
  for (unsigned i=0; i<N; i++) {
    out[i].foo = in[i].foo;
    if (flag)
      out[i].bar = in[i].bar + 5;
    else
      out[i].bar = in[i].bar;
  }
}