C シミュレーションと配列 - 2023.2 日本語

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

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

配列が原因で、合成ステップが実行される前であっても、C/C++ シミュレーションで問題が発生することがあります。次の例に示すような非常に大きい配列を指定すると、C/C++ シミュレーションがメモリ不足となり、実行できなくなる可能性があります。

#include "ap_int.h"
   
  int i, acc;
  // Use an arbitrary precision type
  ap_int<32>  la0[10000000], la1[10000000];
   
  for (i=0 ; i < 10000000; i++) {
      acc = acc + la0[i] + la1[i];
  }

シミュレーションはメモリ不足のためエラーになることがあります。これは、配列がメモリに存在するスタックに配置され、OS で管理されローカル ディスクを使用可能なヒープには配置されないためです。この問題は、次の状況で生じる可能性が高くなります。

  • PC では使用可能なメモリが大型の Linux ボックスよりも少ないことがよくあり、使用可能なメモリが少ないことがあります。
  • 上記の例のように任意精度型を使用すると、標準 C/C++ 型よりも多くのメモリがモデル化に必要になるので、この問題が悪化する可能性があります。
  • C++ のより複雑な固定小数点任意精度型を使用すると、さらに多くのメモリが必要となるので、メモリ不足になる可能性があります。

C/C++ コード開発のメモリ リソースを向上するには、リンカー オプションを使用してスタックのサイズを増加するのが標準的な方法です。たとえば、syn.csimflags -z stack-size=10485760 のようにスタック サイズを明示的に設定します。

ただし、マシンに十分なメモリがなく、スタック サイズを増加しても効果がない場合もあります。このような場合、次の例のように、シミュレーションにはダイナミック メモリ割り当てを、合成には固定サイズの配列を使用して、問題を回避してください。この場合、必要なメモリはヒープに割り当てられ、OS で管理されるので、ローカル ディスク空間が使用できるようになります。

#include "ap_int.h"
   
  int i, acc;
#ifdef __SYNTHESIS__
  // Use an arbitrary precision type & array for synthesis
  ap_int<32>  la0[10000000], la1[10000000];
#else
  // Use an arbitrary precision type & dynamic memory for simulation
 ap_int<32> *la0 = malloc(10000000  * sizeof(ap_int<32>));
 ap_int<32> *la1 = malloc(10000000  * sizeof(ap_int<32>));
#endif
  for (i=0 ; i < 10000000; i++) {
      acc = acc + la0[i] + la1[i];
  }

ただし、シミュレーションされたコードと合成されたコードは同じではないため、これは理想的なソリューションではありません。一方で、この方法でしかシミュレーションを完了させることができない可能性があります。この方法を使用する場合は、C/C++ テストベンチで配列へのアクセスに関するすべての面が記述されるようにしてください。cosim_design で実行される RTL シミュレーションでは、合成されたコードでメモリ アクセスが正しいかどうかが検証されます。

注記: __SYNTHESIS__ マクロは、合成されるコードにのみ使用します。このマクロは C/C++ シミュレーションまたは C/C++ RTL 協調シミュレーションでは意味がないため、テストベンチには使用しないでください。このコード例のフル バージョンは、 Vitis-HLS-Introductory-Examples/Pipelining/Functions/hier_func を参照してください。