FC2カウンター FPGAの部屋 intel HLS の pointer_mm_master を試してみた1
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

intel HLS の pointer_mm_master を試してみた1

intel HLS の F:\intelFPGA_lite\17.1\hls\examples\tutorials\interfaces\pointer_mm_master を試してみた。
ここには、part_1_pointers.cpp、part_2_masters.cpp、part_3_ddr_masters.cpp、part_4_ddr_masters_coalesce.cpp、part_5_ddr_masters_align.cpp の 5 つのAvalon-MM master のサンプルがある。

part_1_pointers.cpp のハードウェア化関数、component void vector_add() コードを引用する。

component void vector_add(int* a,
                          int* b,
                          int* c,
                          int N) {
  for (int i = 0; i < N; ++i) {
    c[i] = a[i] + b[i];
  }
}


通常のポインタ渡しのベクトル加算だ。こう記述すると単独のAvalon-MM Master インターフェースが実装され、a, b のRead と c のWrite はシリアライズされるそうだ。

part_2_masters.cpp のハードウェア化関数、component void vector_add() コードを引用する。

component void vector_add(ihc::mm_master<int, ihc::aspace<1>, ihc::awidth<16>, ihc::dwidth<32> >& a,
                          ihc::mm_master<int, ihc::aspace<2>, ihc::awidth<16>, ihc::dwidth<32> >& b,
                          ihc::mm_master<int, ihc::aspace<3>, ihc::awidth<16>, ihc::dwidth<32> >& c,
                          int N) {
  for (int i = 0; i < N; ++i) {
    c[i] = a[i] + b[i];  
  }
}


mm_master<> クラスを使用してcomponent のAvalon-MM インターフェースを属性を設定できるようです。
aspace<1>、aspace<2>、aspace<3> で、1, 2, 3 の 3 個のスペースを使用しているので、3つのAvalon-MM インターフェースが生成されるようです。
ihc::awidth<16> でアドレスのビット幅を 16 ビット幅にしている。
ihc::dwidth<32> でデータ幅を32 ビットにしている。

part_3_ddr_masters.cpp のハードウェア化関数、component void vector_add() コードを引用する。

component void vector_add(ihc::mm_master<int, ihc::aspace<1>, ihc::awidth<32>, ihc::dwidth<256>, ihc::latency<0>, ihc::maxburst<8>, ihc::waitrequest<true> >& a, // bank 1
                          ihc::mm_master<int, ihc::aspace<1>, ihc::awidth<32>, ihc::dwidth<256>, ihc::latency<0>, ihc::maxburst<8>, ihc::waitrequest<true> >& b, // bank 1
                          ihc::mm_master<int, ihc::aspace<2>, ihc::awidth<32>, ihc::dwidth<256>, ihc::latency<0>, ihc::maxburst<8>, ihc::waitrequest<true> >& c, // bank 2
                          int N) {
  for (int i = 0; i < N; ++i) {
    c[i] = a[i] + b[i];  
  }
}


ihc::aspace<1>、ihc::aspace<1>、ihc::aspace<2>
アドレス・バスが 32 ビット幅、データ・バスが 256 ビット幅となっている。しかし、次のpart_4 と比べるとスループットが小さいので、たぶん計算リソースは32ビットAdder 1 個なのだと思う。
ihc::latency<0> は外部メモリからのRead レイテンシを設定できるようだ。
ihc::maxburst<8> で最大バースト長を 8 に設定している。 ihc::maxburst<> が 2 以上の時に、ihc::waitrequest が必要のようだ。つまり、バーストの途中でデータが無くなったら、もしくはFIFO が一杯になったらデータのやり取りを休止できる。

part_4_ddr_masters_coalesce.cpp のハードウェア化関数、component void vector_add() コードを引用する。

component void vector_add(ihc::mm_master<int, ihc::aspace<1>, ihc::awidth<32>, ihc::dwidth<256>, ihc::latency<0>, ihc::maxburst<8>, ihc::waitrequest<true> >& a, // bank 1
                          ihc::mm_master<int, ihc::aspace<1>, ihc::awidth<32>, ihc::dwidth<256>, ihc::latency<0>, ihc::maxburst<8>, ihc::waitrequest<true> >& b, // bank 1
                          ihc::mm_master<int, ihc::aspace<2>, ihc::awidth<32>, ihc::dwidth<256>, ihc::latency<0>, ihc::maxburst<8>, ihc::waitrequest<true> >& c, // bank 2
                          int N) {
  #pragma unroll 8
  for (int i = 0; i < N; ++i) {
    c[i] = a[i] + b[i];  
  }
}


part_4 は part_3 に比べて「#pragma unroll 8」が追加されているだけだ。これで 8 並列 Adder が実装されるのだと思われる。
結果として、計算時間が 1/8 となり、スループットが向上するものと思われる。

part_5_ddr_masters_align.cpp のハードウェア化関数、component void vector_add() コードを引用する。

component void vector_add(ihc::mm_master<int, ihc::aspace<1>, ihc::awidth<32>, ihc::dwidth<256>, ihc::latency<0>, ihc::maxburst<8>, ihc::align<32>, ihc::waitrequest<true> >& a, // bank 1
                          ihc::mm_master<int, ihc::aspace<1>, ihc::awidth<32>, ihc::dwidth<256>, ihc::latency<0>, ihc::maxburst<8>, ihc::align<32>, ihc::waitrequest<true> >& b, // bank 1
                          ihc::mm_master<int, ihc::aspace<2>, ihc::awidth<32>, ihc::dwidth<256>, ihc::latency<0>, ihc::maxburst<8>, ihc::align<32>, ihc::waitrequest<true> >& c, // bank 2
                          int N) {
  #pragma unroll 8
  for (int i = 0; i < N; ++i) {
    c[i] = a[i] + b[i];  
  }
}


part_4 から part_5 では、ihc::align<32> が増えている。これは、32 バイトつまり、256 ビット幅で整列させることで、余計な回路を削減できるということだ。
例えば、4 バイト、32 バイトの整列がずれていると、8 個の int つまり、4 バイトの演算ができて、32 バイト分の書き込むデータが用意できていても、28 バイト分しか書き込むデータが無い事態に陥ることになる。もう 4 バイト分のデータは次の演算を待つ必要があって、その 4 バイトと一緒にメモリに書き込む必要がある。つまり、アラインがあっていないと面倒なことになる。アラインがあっていれば、8 並列Adder の出力をそのままデータバスに載せて書けば良いのである。

さて、build.bat のDEVICE を例によってCyclone V に変更した。
build default を実行した。
実行した結果 part_2_masters.exe の実行結果がすべてエラーになってしまった。(これは、解決策があるとのこと、後でやってみる)
Intel_HLS_133_171203.png
Intel_HLS_134_171203.png

さて、Verilog HDL のトップ・ファイルを見てみよう。

F:\intelFPGA_lite\17.1\hls\examples\tutorials\interfaces\pointer_mm_master\part_1_pointers.prj\components\vector_add フォルダの vector_add_inst.v のポート宣言部分を引用する。

vector_add vector_add_inst (
  // Interface: clock (clock end)
  .clock               ( ), // 1-bit clk input
  // Interface: reset (reset end)
  .resetn              ( ), // 1-bit reset_n input
  // Interface: call (conduit sink)
  .start               ( ), // 1-bit valid input
  .busy                ( ), // 1-bit stall output
  // Interface: return (conduit source)
  .done                ( ), // 1-bit valid output
  .stall               ( ), // 1-bit stall input
  // Interface: a (conduit sink)
  .a                   ( ), // 64-bit data input
  // Interface: b (conduit sink)
  .b                   ( ), // 64-bit data input
  // Interface: c (conduit sink)
  .c                   ( ), // 64-bit data input
  // Interface: N (conduit sink)
  .N                   ( ), // 32-bit data input
  // Interface: avmm_0_rw (avalon start)
  .avmm_0_rw_address   ( ), // 64-bit address output
  .avmm_0_rw_byteenable( ), // 8-bit byteenable output
  .avmm_0_rw_read      ( ), // 1-bit read output
  .avmm_0_rw_readdata  ( ), // 64-bit readdata input
  .avmm_0_rw_write     ( ), // 1-bit write output
  .avmm_0_rw_writedata ( )  // 64-bit writedata output
);


start, busy, done, stall 信号がある。
a, b, c 入力があるけど、下のAvalon-MM Master でRead/Write するから要らない気がする。avm_0_rw_ のAvalon-MM Master ですべてできるしシミュレーションではやっている。

F:\intelFPGA_lite\17.1\hls\examples\tutorials\interfaces\pointer_mm_master\part_2_masters.prj\components\vector_add フォルダの vector_add_inst.v のポート宣言部分を引用する。

vector_add vector_add_inst (
  // Interface: clock (clock end)
  .clock               ( ), // 1-bit clk input
  // Interface: reset (reset end)
  .resetn              ( ), // 1-bit reset_n input
  // Interface: call (conduit sink)
  .start               ( ), // 1-bit valid input
  .busy                ( ), // 1-bit stall output
  // Interface: return (conduit source)
  .done                ( ), // 1-bit valid output
  .stall               ( ), // 1-bit stall input
  // Interface: a (conduit sink)
  .a                   ( ), // 64-bit data input
  // Interface: b (conduit sink)
  .b                   ( ), // 64-bit data input
  // Interface: c (conduit sink)
  .c                   ( ), // 64-bit data input
  // Interface: N (conduit sink)
  .N                   ( ), // 32-bit data input
  // Interface: avmm_1_rw (avalon start)
  .avmm_1_rw_address   ( ), // 16-bit address output
  .avmm_1_rw_byteenable( ), // 4-bit byteenable output
  .avmm_1_rw_read      ( ), // 1-bit read output
  .avmm_1_rw_readdata  ( ), // 32-bit readdata input
  .avmm_1_rw_write     ( ), // 1-bit write output
  .avmm_1_rw_writedata ( ), // 32-bit writedata output
  // Interface: avmm_2_rw (avalon start)
  .avmm_2_rw_address   ( ), // 16-bit address output
  .avmm_2_rw_byteenable( ), // 4-bit byteenable output
  .avmm_2_rw_read      ( ), // 1-bit read output
  .avmm_2_rw_readdata  ( ), // 32-bit readdata input
  .avmm_2_rw_write     ( ), // 1-bit write output
  .avmm_2_rw_writedata ( ), // 32-bit writedata output
  // Interface: avmm_3_rw (avalon start)
  .avmm_3_rw_address   ( ), // 16-bit address output
  .avmm_3_rw_byteenable( ), // 4-bit byteenable output
  .avmm_3_rw_read      ( ), // 1-bit read output
  .avmm_3_rw_readdata  ( ), // 32-bit readdata input
  .avmm_3_rw_write     ( ), // 1-bit write output
  .avmm_3_rw_writedata ( )  // 32-bit writedata output
);


avmm_1_rw、avmm_2_rw、avmm_3_rw の 3 つのAvalon-MM インターフェースが生成されている。

F:\intelFPGA_lite\17.1\hls\examples\tutorials\interfaces\pointer_mm_master\part_3_ddr_masters.prj\components\vector_add フォルダの vector_add_inst.v のポート宣言部分を引用する。

vector_add vector_add_inst (
  // Interface: clock (clock end)
  .clock                  ( ), // 1-bit clk input
  // Interface: reset (reset end)
  .resetn                 ( ), // 1-bit reset_n input
  // Interface: call (conduit sink)
  .start                  ( ), // 1-bit valid input
  .busy                   ( ), // 1-bit stall output
  // Interface: return (conduit source)
  .done                   ( ), // 1-bit valid output
  .stall                  ( ), // 1-bit stall input
  // Interface: a (conduit sink)
  .a                      ( ), // 64-bit data input
  // Interface: b (conduit sink)
  .b                      ( ), // 64-bit data input
  // Interface: c (conduit sink)
  .c                      ( ), // 64-bit data input
  // Interface: N (conduit sink)
  .N                      ( ), // 32-bit data input
  // Interface: avmm_1_rw (avalon start)
  .avmm_1_rw_address      ( ), // 32-bit address output
  .avmm_1_rw_byteenable   ( ), // 32-bit byteenable output
  .avmm_1_rw_readdatavalid( ), // 1-bit readdatavalid input
  .avmm_1_rw_read         ( ), // 1-bit read output
  .avmm_1_rw_readdata     ( ), // 256-bit readdata input
  .avmm_1_rw_write        ( ), // 1-bit write output
  .avmm_1_rw_writedata    ( ), // 256-bit writedata output
  .avmm_1_rw_waitrequest  ( ), // 1-bit waitrequest input
  .avmm_1_rw_burstcount   ( ), // 4-bit burstcount output
  // Interface: avmm_2_rw (avalon start)
  .avmm_2_rw_address      ( ), // 32-bit address output
  .avmm_2_rw_byteenable   ( ), // 32-bit byteenable output
  .avmm_2_rw_readdatavalid( ), // 1-bit readdatavalid input
  .avmm_2_rw_read         ( ), // 1-bit read output
  .avmm_2_rw_readdata     ( ), // 256-bit readdata input
  .avmm_2_rw_write        ( ), // 1-bit write output
  .avmm_2_rw_writedata    ( ), // 256-bit writedata output
  .avmm_2_rw_waitrequest  ( ), // 1-bit waitrequest input
  .avmm_2_rw_burstcount   ( )  // 4-bit burstcount output
);


part_2 からでは、waitrequest と burstcount 信号が増えている。それに、avmm_3_rw が削除された。avmm_1_rw を a と b のRead で共有する。

F:\intelFPGA_lite\17.1\hls\examples\tutorials\interfaces\pointer_mm_master\part_4_ddr_masters_coalesce.prj\components\vector_add フォルダの vector_add_inst.v のポート宣言部分は、part_3 との変化はない。

F:\intelFPGA_lite\17.1\hls\examples\tutorials\interfaces\pointer_mm_master\part_5_ddr_masters_align.prj\components\vector_add フォルダの vector_add_inst.v のポート宣言部分は、part_3 、 part_4 との変化はない。
  1. 2017年12月03日 17:06 |
  2. intel HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/3992-fdc25197
この記事にトラックバックする(FC2ブログユーザー)