FC2カウンター FPGAの部屋 Vivado HLSでのAXI4-Stream のテンプレートを作成する3

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

FPGAの部屋

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

Vivado HLSでのAXI4-Stream のテンプレートを作成する3

Vivado HLSでのAXI4-Stream のテンプレートを作成する2”の続き。

Vivado HLSでのAXI4-Stream のテンプレートを作成する1”で、畳み込み層の特徴マップの個数に対応するために、データを配列にしたのだが、AXI4-Stream にするという制約ではうまくかなかった。よって、”Vivado HLSでのAXI4-Stream のテンプレートを作成する2”でデータを展開して書いたのだけれど、これでは不満が残った。たくさん特徴マップがあった時に書くのが大変だからだ。それに、特徴マップの数を変更することが難しい。配列で書けば配列の数を書き換えると、すぐに特徴マップの数を変更することができる。
その後、AXI4-Stream で各層をつなぐのではなく、HLS ストリームで接続することにしたので、データを配列にできると思う。今日はそのテストをしてみようと思う。

Vivado HLSでのAXI4-Stream のテンプレートを作成する1”の stream_test.cpp を書き換えた。stream_test.cpp を示す。

// stream_test.cpp
// 2018/02/11 by marsee
// 2018/04/12 : DATA_PACK指示子を追加
//

#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <hls_video.h>

#include "stream_test.h"

int stream_test(hls::stream<ap_fixed_axis<16,6,2,1,1,1> >& ins,
        hls::stream<ap_fixed_axis<16,6,2,1,1,1> >& outs, int num){
#pragma HLS DATA_PACK variable=outs
#pragma HLS DATA_PACK variable=ins

    ap_fixed_axis<16,6,2,1,1,1> ins_t;
    ap_fixed_axis<16,6,2,1,1,1> outs_t;

    for(int y=0; y<10; y++){
        for(int x=0; x<56; x++){
#pragma HLS PIPELINE II=1
            ins >> ins_t;
            for(int i=0; i<num; i++){
                outs_t.data[i] = ins_t.data[i] * (ap_fixed<16, 6, AP_TRN, AP_WRAP>)(i+2);
            }
            outs_t.user = 1;
            outs_t.last = 0;

            outs << outs_t;
        }
    }

    return(0);
}

int stream_top(hls::stream<ap_fixed_axis<16,6,2,1,1,1> >& ins,
        hls::stream<ap_fixed_axis<16,6,2,1,1,1> >& outs){
#pragma HLS DATA_PACK variable=outs
#pragma HLS DATA_PACK variable=ins
#pragma HLS DATAFLOW

    hls::stream<ap_fixed_axis<16,6,2,1,1,1> > temp_st;

    stream_test(ins, temp_st, 2);
    stream_test(temp_st, outs, 2);

    return(0);
}


新たに stream_top() 関数を作成して stream_test() を 2 回読んでいる。これは、HLS ストリームの層を複数呼んだことになる。
stream_top() の入力ストリーム、出力ストリームに data_pack 指示子を付けたら、呼ばれた stream_test() の方にも入力ストリーム、出力ストリームに DATA_PACK 指示子を付けないとエラーになった。(stream_top() にだけ DATA_PACK 指示子を付けたらエラーになった)

stream_top.h は ”Vivado HLSでのAXI4-Stream のテンプレートを作成する1”のコードをそのまま使用している。

stream_test プロジェクトを示す。
stream_test2_1_180412.png

C コードの合成結果を示す。
stream_test2_2_180412.png

Estmated は 6.01 ns で十分な性能が出ている。
Latency は 565 クロックで、総ピクセル数が 560 ピクセルなので、ほぼ 1 クロックで 1 ピクセルの処理ができている。

DATA_PACK 指示子を付けた状態でのVHDL の entity 宣言部分を示す。

entity stream_top is
port (
    ins_V_dout : IN STD_LOGIC_VECTOR (39 downto 0);
    ins_V_empty_n : IN STD_LOGIC;
    ins_V_read : OUT STD_LOGIC;
    outs_V_din : OUT STD_LOGIC_VECTOR (39 downto 0);
    outs_V_full_n : IN STD_LOGIC;
    outs_V_write : OUT STD_LOGIC;
    ap_clk : IN STD_LOGIC;
    ap_rst : IN STD_LOGIC;
    ap_done : OUT STD_LOGIC;
    ap_start : IN STD_LOGIC;
    ap_ready : OUT STD_LOGIC;
    ap_idle : OUT STD_LOGIC;
    ap_return : OUT STD_LOGIC_VECTOR (31 downto 0) );
end;


hls::stream<ap_fixed_axis<16,6,2,1,1,1> > がパックされているのがわかる。

DATA_PACK 指示子を取り除いた状態でのVHDL の entity 宣言部分を示す。

entity stream_top is
port (
    ins_V_data_0_V_dout : IN STD_LOGIC_VECTOR (15 downto 0);
    ins_V_data_0_V_empty_n : IN STD_LOGIC;
    ins_V_data_0_V_read : OUT STD_LOGIC;
    ins_V_data_1_V_dout : IN STD_LOGIC_VECTOR (15 downto 0);
    ins_V_data_1_V_empty_n : IN STD_LOGIC;
    ins_V_data_1_V_read : OUT STD_LOGIC;
    ins_V_keep_V_dout : IN STD_LOGIC_VECTOR (1 downto 0);
    ins_V_keep_V_empty_n : IN STD_LOGIC;
    ins_V_keep_V_read : OUT STD_LOGIC;
    ins_V_strb_V_dout : IN STD_LOGIC_VECTOR (1 downto 0);
    ins_V_strb_V_empty_n : IN STD_LOGIC;
    ins_V_strb_V_read : OUT STD_LOGIC;
    ins_V_user_V_dout : IN STD_LOGIC_VECTOR (0 downto 0);
    ins_V_user_V_empty_n : IN STD_LOGIC;
    ins_V_user_V_read : OUT STD_LOGIC;
    ins_V_last_V_dout : IN STD_LOGIC_VECTOR (0 downto 0);
    ins_V_last_V_empty_n : IN STD_LOGIC;
    ins_V_last_V_read : OUT STD_LOGIC;
    ins_V_id_V_dout : IN STD_LOGIC_VECTOR (0 downto 0);
    ins_V_id_V_empty_n : IN STD_LOGIC;
    ins_V_id_V_read : OUT STD_LOGIC;
    ins_V_dest_V_dout : IN STD_LOGIC_VECTOR (0 downto 0);
    ins_V_dest_V_empty_n : IN STD_LOGIC;
    ins_V_dest_V_read : OUT STD_LOGIC;
    outs_V_data_0_V_din : OUT STD_LOGIC_VECTOR (15 downto 0);
    outs_V_data_0_V_full_n : IN STD_LOGIC;
    outs_V_data_0_V_write : OUT STD_LOGIC;
    outs_V_data_1_V_din : OUT STD_LOGIC_VECTOR (15 downto 0);
    outs_V_data_1_V_full_n : IN STD_LOGIC;
    outs_V_data_1_V_write : OUT STD_LOGIC;
    outs_V_keep_V_din : OUT STD_LOGIC_VECTOR (1 downto 0);
    outs_V_keep_V_full_n : IN STD_LOGIC;
    outs_V_keep_V_write : OUT STD_LOGIC;
    outs_V_strb_V_din : OUT STD_LOGIC_VECTOR (1 downto 0);
    outs_V_strb_V_full_n : IN STD_LOGIC;
    outs_V_strb_V_write : OUT STD_LOGIC;
    outs_V_user_V_din : OUT STD_LOGIC_VECTOR (0 downto 0);
    outs_V_user_V_full_n : IN STD_LOGIC;
    outs_V_user_V_write : OUT STD_LOGIC;
    outs_V_last_V_din : OUT STD_LOGIC_VECTOR (0 downto 0);
    outs_V_last_V_full_n : IN STD_LOGIC;
    outs_V_last_V_write : OUT STD_LOGIC;
    outs_V_id_V_din : OUT STD_LOGIC_VECTOR (0 downto 0);
    outs_V_id_V_full_n : IN STD_LOGIC;
    outs_V_id_V_write : OUT STD_LOGIC;
    outs_V_dest_V_din : OUT STD_LOGIC_VECTOR (0 downto 0);
    outs_V_dest_V_full_n : IN STD_LOGIC;
    outs_V_dest_V_write : OUT STD_LOGIC;
    ap_clk : IN STD_LOGIC;
    ap_rst : IN STD_LOGIC;
    ap_done : OUT STD_LOGIC;
    ap_start : IN STD_LOGIC;
    ap_ready : OUT STD_LOGIC;
    ap_idle : OUT STD_LOGIC;
    ap_return : OUT STD_LOGIC_VECTOR (31 downto 0) );
end;


入力ポートごとに empty_n, read ポートがついて、出力ポートごとに full_n, write ポートが生成されている。これは無駄だ。

これから、内部で使用する HLS ストリームのポートに関しては、DATA_PACK 指示子を付けたほうが良さそうだ。付けなくても問題ないかもしれないが。。。
  1. 2018年04月12日 04:45 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/4134-d6b80a8e
この記事にトラックバックする(FC2ブログユーザー)