インテル上位レベルのシンセシス・アクセラレーター機能ユニットのデザイン例のユーザーガイド

ID 683025
日付 11/30/2018
Public
ドキュメント目次

4.1.1.2. HLS AFU Avalon-MMマスター・インターフェイス

AFUには、システムメモリーにアクセスするための2つのAvalon-MMマスター・インターフェイスがある場合があります。1つのAvalon-MMマスターを読み出し専用として構成する必要があります。もう1つは書き込み専用です。 この要件では、コンポーネントの署名とアルゴリズムの両方を変更する必要があります。

AFUがホストメモリーでアクセスできるデータの最小単位は64バイト(512ビット) なので 、HLS ihc :: mm_masterオブジェクトを使用してAvalon-MMマスター・インターフェイスを構成する必要があります。パラメーターの詳細については、 Intel High-Level Synthesis Compiler Reference Manualを参照してください。次に、コード図 19を変更して、必須の512ビットデータバスによって提供される帯域幅を活用し、16個の32ビット値に同時にアクセスする必要があります。

このアクセスサイズの制約は、ベクターの長さが16の倍数(同等に64バイトの倍数)でない場合、ベクターの終わりと次の16の倍数の間のホストメモリーの場所がガベージデータでいっぱいになることを意味します。

最高のパフォーマンスを得るには、read-modify-write動作を試みないでください。デザインには2つの独立したAvalon-MMマスター・インターフェイスがあるため、HLSコンパイラーは別々のアドレススペースを想定し、2つのAvalon-MMマスター・インターフェイス間に依存関係は存在しないと想定します。

HLS AFUデザイン例は、512ビットのAvalon-MMマスター・インターフェイスと接続する方法を示しています。
  • HLSコンパイラーにその詳細を抽象化し、アクセスがフロートであると想定させます。
  • ホストメモリーアクセスは512ビットの符号なし整数であると仮定します。

floatアクセス

また、このコンポーネントを使用すると、HLSコンパイラーがスライス操作を処理できます。署名は、mm_masterタイプがac_int<512, false>ではなくfloatであることを除いて、図 19の署名と同じです。

図 16.  float-ベースのボディー
1.	#pragma unroll 16
2.	for (int itr = 0; itr < 16; itr++)
3.	{
4.		int idx = itr + (loop_idx * 16);
5.		if (idx < size)
6.		{
7.			float readVal = masterRead[idx];
8.			readSum += readVal;
9.			masterWrite[idx] = readVal + 1.0f;
10.      }
11.   }
12.   sum += readSum;

一度に512ビットのループ本体の外側ではなく、展開されたループ本体の内部で一度に32ビットでmm_masterにアクセスします。コンパイラーがすべてを適切に推論することを確認するには、生成されたHLS report.htmlレポートのComponent Viewerセクションを見て、512ビットのバースト結合LSUがあることを確認し、それらが整列していることを確認します。一度に512ビットの負荷が発生することを確認したい場合、シミュレーション波形の図 18を見てください 。

図 17. フロートベースのコンポーネントを示すHLSレポート 合体したAvalon-MMマスター・インターフェイスを観察します。 
図 18.  floatベースのコンポーネントのホスト・メモリー・アクセスを示すModelSim波形 

ac_intアクセス

基になるデータ型として符号なし512ビットac_intを使用してihc :: mm_masterを定義できます。 

図 19.  ac_intベースのコンポーネントの署名 
1. typedef ac_int<512, false> uint512; // 512-bit unsigned integer
2.	typedef ihc::mm_master<uint512, ihc::dwidth<512>, 
3.	                       ihc::awidth<48>, ihc::latency<0>,
4.	                       ihc::aspace<1>, ihc::readwrite_mode<readonly>,  
5.	                       ihc::waitrequest<true>, ihc::align<64>, 
6.	                       ihc::maxburst<4> > MasterReadAcInt;
7.	
8.	typedef ihc::mm_master<uint512, ihc::dwidth<512>, 
9.	                       ihc::awidth<48>, ihc::latency<0>, 
10.	                      ihc::aspace<2>, ihc::readwrite_mode<writeonly>, 
11.	                      ihc::waitrequest<true>, ihc::align<64>, 
12.	                      ihc::maxburst<4> > MasterWriteAcInt;
13.	
14.   component
15.   hls_avalon_slave_component
16.   float fpVectorReduce_ac_int(
17.	  hls_avalon_slave_register_argument MasterReadAcInt &masterRead,
18.	  hls_avalon_slave_register_argument MasterWriteAcInt &masterWrite,
19.	  hls_avalon_slave_register_argument uint64_t size);

これらのパラメーター設定は、インテルのアクセラレーション・スタックに固有のものです。

  • 48-ビット幅のアドレス(awidthパラメーター)
  • DRAMは:変数の待ち時間とwaitrequestは信号( latencywaitrequestは属性)が必要
  • 64の同時バイトを一度に読み出すことができます(alignパラメーター)
  • 最大バーストサイズは4 512ビット読み出す( maxburstパラメーター)
  • 別々の物理Avalonマスタポート(aspaceパラメーター)。読み出し出しよび書き込み専用(それぞれ1つのAvalon-MMマスター)( readwrite_modeパラメーター)

この方法はより冗長ですが、すべてのAvalon-MMマスターアクセスが512ビット幅に合体することを保証します。もしac_intによって提供slcset_slc関数を使用して512ビット幅の読み出し結果の32ビット部分にアクセスすることができます。これらの機能の詳細についてはac_int Reference Manual, Mentor Graphics Corporationを参照してください。このコンポーネントは、512ビットのリードとライトを明示的に実行します(1行目と36行目)。

図 20. ac_int-ベースのボディー
1.  uint512 readVal = masterRead[loop_idx];
2.	uint512 writeVal = 0;
3.	
4.	#pragma unroll 16 // do each loop iteration concurrently.
5.	                  // Use 16 iterations because there are 16
6.	                  // 32-bit slices in each 512-bit word.
7.	for (int itr = 0; itr < 16; itr++)
8.	{
9.		int idx = itr + (loop_idx * 16);
10.      if (idx < size)
11.      {
12.			// grab a 32-bit piece of the 512-bit value that we read
13.			uint32 readVal_32 = readVal.slc<32>(itr * 32); 
14.	
15.			// use explicit type casting to process the bits pointed 
16.			// to by &readVal_32 as a float.
17.			void *readVal_32_ptr = &readVal_32;
18.			float readVal_f;
19.			float *readVal_f_ptr = &readVal_f;
20.			*readVal_f_ptr = *((float *) readVal_32_ptr);
21.			readSum += readVal_f;
22.	
23.			// increment and output
24.			float writeVal_f = readVal_f + 1.0f;
25.	
26.			// use explicit type casting to process the bits pointed 
27.			// to by &writeVal_f as a uint32.
28.			float *writeVal_f_ptr = &writeVal_f;
29.			uint32 *writeVal_32_ptr = (uint32 *) writeVal_f_ptr;
30.			uint32 writeVal32 = *writeVal_32_ptr;
31.	
32.			unsigned int bit_offset = itr * 32;
33.			writeVal.set_slc(bit_offset, writeVal32);
34.      }
35.   }
36.   masterWrite[loop_idx] = writeVal;