Vitis HLS では、インターフェイスの構造体はデフォルトで集約された状態に保たれ、構造体のすべての要素が 1 つの幅の広いベクターにまとめられます。これにより、構造体のすべてのメンバーを同時に読み出しおよび書き込みできます。インターフェイスの構造体は、DISAGGREGATE プラグマまたは指示子を使用して分割できます。構造体に 1 つまたはそれ以上の hls::stream
オブジェクトが含まれる場合、Vitis HLS は、「
hls::stream
要素を含むインターフェイスの構造体」で後述するように、構造体を自動的に分割します。
v++
コマンドで使用するとエラーが発生します。Vitis カーネル フローをサポートするには、構造体を構成要素に手動で分割し、hls::stream
オブジェクトを AXIS インターフェイスで使用するように定義する必要があります。この集約処理の一部として、構造体の要素は Vitis カーネル フローでは 4 バイトで、Vivado IP フローでは 1 バイトで揃えられます。このアライメントでは、構造体のパディングとアライメント に説明されているように、ビット パディングを追加して、データを保持または揃えることが必要な可能性があります。デフォルトでは、集約された構造体はパックされるのではなくパディングされますが、Vivado IP フローで AGGREGATE プラグマまたは指示子の compact=bit
オプションを使用すると、パックできます。ただし、AXI4 インターフェイス (m_axi
、s_axilite
、または axis
) として定義されているポートには compact=bit
を使用できません。
構造体のメンバー要素は C/C++ コードに記述されている順序でベクターに配置されます (構造体の最初の要素がベクターの LSB に、最後の要素がベクターの MSB に配置される)。これにより、1 クロック サイクルでより多くのデータにアクセスできるようになります。構造体の配列は個別の配列要素に分割され、下位から上位の順のベクターに配置されます。
次の例では、struct data_t
がヘッダー ファイルで定義されています。構造体には、2 つのデータ メンバーが含まれます。
-
short
型 (16 ビット) の符号なしベクターvarA
。 - 4 つの
unsigned char
型 (8 ビット) の配列varB
。typedef struct { unsigned short varA; unsigned char varB[4]; } data_t; data_t struct_port(data_t i_val, data_t *i_pt, data_t *o_pt);
構造体をインターフェイスに集約すると、16 ビットの varA
と 4x8 ビットの varB
を含む 1 つの 48 ビット ポートになります。
axis
ストリーミングインターフェイスの場合は 4096 ビットです。Vitis HLS で合成可能な構造体のサイズや複雑さに制限はありません。構造体には必要なだけの配列次元およびメンバーを含めることができます。構造体のインプリメンテーションでの唯一の制限は、ストリーミングとして (たとえば配列が FIFO インターフェイスとして) インプリメントされる場合にあります。この場合、そのインターフェイスの配列に適用するのと同じ一般規則に従う必要があります。
hls::stream 要素を含むインターフェイスの構造体
hls::stream
要素を含むインターフェイスのユーザー定義の構造体は、Vitis HLS で自動的に分割されます。この分割された構造体は、Vivado IP フローでサポートされ、エクスポートされた IP は正しく動作します。ただし、この分割された構造体は Vitis カーネル フローではサポートされず、エクスポートされた出力 (.xo) を v++ --link
コマンドで使用するとエラーが発生します。Vitis カーネル フローをサポートするには、構造体を構成要素に手動で分割し、hls::stream
オブジェクトを AXIS インターフェイスで使用するように定義する必要があります。
自動的に分割される構造体が含まれる場合、Vitis HLS によって分割された構造体の個々の要素に INTERFACE プラグマが適用されます。構造体に対して INTERFACE プラグマが 1 つのみ指定された場合、それが構造体の各要素に適用されます。分割された構造体の各要素に INTERFACE プラグマを定義すると、適宜適用されます。