FC2カウンター FPGAの部屋 2018年02月12日

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

FPGAの部屋

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

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

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

前回は、Vivado HLSでAXI4-Stream のデータ幅を拡張するテンプレートを作成して合成してみたが、テンプレートのデータに配列を使ったので、合成できなかった。今回は、データを1次元配列にしてみよう。

(2018/02/12:書き換え)ブログを struct を使用した記述に書き換えました。@ciniml さん、教えて頂いてありがとうございました。

struct で 2 つ要素をまとめました。struct の中を本当は配列にしたかったのですが、配列だとAXI4-Stream でエラーになりました。修正したテンプレートの定義を含んだ stream_test.h を示す。

// stream_test.h
// 2018/02/11 by marsee
//

#ifndef __STREAM_TEST_H__
#define __STREAM_TEST_H__
#include <ap_fixed.h>

template<int W, int I, int U, int TI, int TD>
    struct ap_fixed1_axis{
        struct data {
            ap_fixed<W,I,AP_TRN,AP_WRAP> data0;
        } data;
        ap_uint<(W+7)/8> keep;
        ap_uint<(W+7)/8> strb;
        ap_uint<U>       user;
        ap_uint<1>       last;
        ap_uint<TI>      id;
        ap_uint<TD>      dest;
    };

template<int W, int I, int U, int TI, int TD>
    struct ap_fixed2_axis{
        struct data {
            ap_fixed<W,I,AP_TRN,AP_WRAP> data0;
            ap_fixed<W,I,AP_TRN,AP_WRAP> data1;
        } data;
        ap_uint<(W+7)/8> keep;
        ap_uint<(W+7)/8> strb;
        ap_uint<U>       user;
        ap_uint<1>       last;
        ap_uint<TI>      id;
        ap_uint<TD>      dest;
    };

template<int W, int I, int U, int TI, int TD>
    struct ap_fixed4_axis{
        struct data {
            ap_fixed<W,I,AP_TRN,AP_WRAP> data0;
            ap_fixed<W,I,AP_TRN,AP_WRAP> data1;
            ap_fixed<W,I,AP_TRN,AP_WRAP> data2;
            ap_fixed<W,I,AP_TRN,AP_WRAP> data3;
        } data;
        ap_uint<(W+7)/8> keep;
        ap_uint<(W+7)/8> strb;
        ap_uint<U>       user;
        ap_uint<1>       last;
        ap_uint<TI>      id;
        ap_uint<TD>      dest;
    };

#endif


修正した stream_test.cpp を示す。

// stream_test.cpp
// 2018/02/11 by marsee
//

#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_fixed1_axis<16,6,1,1,1> >& ins,
        hls::stream<ap_fixed2_axis<16,6,1,1,1> >& outs){
#pragma HLS INTERFACE axis register both port=outs
#pragma HLS INTERFACE axis register both port=ins
#pragma HLS INTERFACE s_axilite port=return
    ap_fixed1_axis<16,6,1,1,1> ins_t;
    ap_fixed2_axis<16,6,1,1,1> outs_t;

    for(int y=0; y<10; y++){
        for(int x=0; x<56; x++){
            ins >> ins_t;
            outs_t.data.data0 = ins_t.data.data0 * (ap_fixed<166, AP_TRN, AP_WRAP>)2.0;
            outs_t.data.data1 = ins_t.data.data0 * (ap_fixed<166, AP_TRN, AP_WRAP>)(-3.0);

            outs_t.user = 1;
            outs_t.last = 0;

            outs << outs_t;
        }
    }

    return(0);
}


今回、テストベンチを作成した。テストベンチの multi_test_tb.cpp を示す。

// stream_test_tb.cpp
// 2018/02/11 by marsee
//

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

#include "stream_test.h"

#define DATASIZE    560

int stream_test(hls::stream<ap_fixed1_axis<16,6,1,1,1> >& ins,
        hls::stream<ap_fixed2_axis<16,6,1,1,1> >& outs);

int main(){
    using namespace std;

    ap_fixed1_axis<16,6,1,1,1> in_ts;
    ap_fixed2_axis<16,6,1,1,1> out_ts;

    hls::stream<ap_fixed1_axis<16,6,1,1,1> > instream;
    hls::stream<ap_fixed2_axis<16,6,1,1,1> > outstream;

    for(int i=0; i<DATASIZE; i++){
        in_ts.data.data0 = i % 11;
        instream << in_ts;
    }

    stream_test(instream, outstream);

    for(int i=0; i<DATASIZE; i++){
        outstream >> out_ts;
        printf("i = %d, data1 = %f, data0 = %f\n", i, (float)out_ts.data.data1, (float)out_ts.data.data0);
    }

    return(0);
}


テストベンチができたので、シミュレーションをすることができる。
早速、C シミュレーションを行った。
stream_test_3_180212.png

2 つのデータが、うまく分離できているようだ。

さて、C コードの合成を行った。今度は成功。良かった。
stream_test_4_180212.png

FF と LUT も使われていて大丈夫そうだ。

C/RTL 協調シミュレーションを行った。
stream_test_6_180212.png

エラーで停止してしまった。エラー内容を示す。

F:/Xilinx/Vivado/2017.4/include/ap_stream.h:70:2: warning: #warning AP_STREAM macros are deprecated. Please use hls::stream<> from "hls_stream.h" instead. [-Wcpp]
apatb_stream_test.cpp: In function 'int AESL_WRAP_stream_test(hls::stream<ap_fixed1_axis<16, 6, 1, 1, 1> >&, hls::stream<ap_fixed2_axis<16, 6, 1, 1, 1> >&)':
apatb_stream_test.cpp:425:36: error: 'data' has no member named 'data1'
apatb_stream_test.cpp:478:36: error: 'data' has no member named 'data1'
apatb_stream_test.cpp:480:34: error: 'data' has no member named 'data1'
apatb_stream_test.cpp:2330:34: error: 'data' has no member named 'data1'
apatb_stream_test.cpp:2333:63: error: 'data' has no member named 'data1'
make: *** [obj/apatb_stream_test.o] Error 1
ERROR: [COSIM 212-317] C++ compile error.
ERROR: [COSIM 212-321] EXE file generate failed.
ERROR: [COSIM 212-321] EXE file generate failed.
ERROR: [COSIM 212-331] Aborting co-simulation: C simulation failed, compilation errors.
ERROR: [COSIM 212-4] *** C/RTL co-simulation finished: FAIL ***
command 'ap_source' returned error code
    while executing
"source C:/Users/Masaaki/Documents/VIvado_HLS/ZYBO_Z7-20/test/stream_test/solution1/cosim.tcl"
    invoked from within
"hls::main C:/Users/Masaaki/Documents/VIvado_HLS/ZYBO_Z7-20/test/stream_test/solution1/cosim.tcl"
    ("uplevel" body line 1)
    invoked from within
"uplevel 1 hls::main {*}$args"
    (procedure "hls_proc" line 5)
    invoked from within
"hls_proc $argv"
Finished C/RTL cosimulation

.
通常のAXI4-Stream のテンプレートを使っていなかったためか?でも、修正前は動作したのだが。。。

Export RTL を行った。結果を示す。
なお、Vivado synthesis, place and route にチェックを入れてある。
stream_test_5_180212.png

ちゃんと、FF も LUT もあるので、問題ないだろう?
  1. 2018年02月12日 05:16 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0