FC2カウンター FPGAの部屋 2015年04月29日
FC2ブログ

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

FPGAの部屋

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

Vivado HLS 2014.4 でサイドチャネル付き AXI4-Stream をテストする2(C++シミュレーション、高位合成)

Vivado HLS 2014.4 でサイドチャネル付き AXI4-Stream をテストする1(C++ソースコードの公開)”の続き。

今回は、サイドチャネル付き1次元俺様フィルタのC++シミュレーションと高位合成を行う。

最初は、Vivado HLS 2014.4 でC++ シミュレーションを行う。
Run C Simulation アイコンをクリックして、C Simulation を実行した後のVivado HLS 2014.4 の画面を下に示す。
lap_filter_AXIS_19_150429.png

標準出力結果を下に示す。

ins
0
0
0
0
0
3e8
3e8
3e8
3e8
3e8
0
0
0
0
0
3e8
3e8
3e8
3e8
3e8
0
0
0
0
0
3e8
3e8
3e8
3e8
3e8
0
0
0
0
0
3e8
3e8
3e8
3e8
3e8
0
0
0
0
0
3e8
3e8
3e8
3e8
3e8

outs
0x0
0x0
0x0
0x0
0x0
0x0
0x3e8
0x0
0x0
0x0
0x3e8
0x0
0x0
0x0
0x0
0x0
0x3e8
0x0
0x0
0x0
0x3e8
0x0
0x0
0x0
0x0
0x0
0x3e8
0x0
0x0
0x0
0x3e8
0x0
0x0
0x0
0x0
0x0
0x3e8
0x0
0x0
0x0
0x3e8
0x0
0x0
0x0
0x0
0x0
0x3e8
0x0
0x0
0x0
AXI-Stream is end


C Synthesis アイコンをクリックして、高位合成を行った。
lap_filter_AXIS_20_150429.png

Latency と Interval がどちらも ? だった。やはり、TUSER を待っているので、どちらも分からない?ということであろう。
Utilization Estimates を示す。BRAM_18K とDSP48E は使用していない。
lap_filter_AXIS_21_150429.png

Analyze 画面を示す。真ん中下のResource タブをクリックしている。
C3ステートの read をクリックすると、do { } while 内部の AXI4-Stream 入力がヒットした。
lap_filter_AXIS_22_150429.png

C4ステートの read をクリックすると、メインの for () ループの AXI4-Stream 入力がヒットした。
lap_filter_AXIS_23_150429.png
  1. 2015年04月29日 16:27 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

「龍三と七人の子分たち」(映画)を見てきました

今日は一人で「龍三と七人の子分たち」(映画)(リンク先は音が出ます)を見てきました。
コメディでした。面白かったです。笑っちゃいました。でも、一般の人を脅すのは良くないですね。。。
  1. 2015年04月29日 13:02 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2014.4 でサイドチャネル付き AXI4-Stream をテストする1(C++ソースコードの公開)

Vivado HLS 2014.4 で AXI4-Stream をテストする4(1次元のフィルタのテスト3、RTLシミュレーション)”の続き。

今回は、サイドチャネル付きの AXI4-Stream をテストしてみよう。AXI4-Stream のサイドチャネルとはなにか?と言うと、AXI4-Stream には、TKEEP, TSTRB, TUSER, TLALST, TID, TDEST などの信号が定義されている。(”AXI4-Stream のお勉強”を参照のこと)
これを使用して、画像のフレーム同期を取ってみよう。AXI VDMAでは TUSER が MM2S, S2MM とも start-of-frame としてドライブされている。更に TLAST もラインの終わりにアサートされている。(”AXI Video Direct Memory Access v6.2 LogiCORE IP Product Guide Vivado Design Suite PG020 April 1, 2015 ”を参照のこと)
このAXI VDMA の仕様と Vivado HLS 2014.4 で作製するAXI4-Stream IP の仕様を合わせよう。今回作製するAXI4-Stream IP は、1ラインだけの動作サンプルなので、最後に TLAST をアサートする。そして、TUSER が 1 になったストリーム・データの時にフレームがスタートする。

tu1978 さんからサンプルを頂いたので、それを参照しながら作っていこう。(tu1978 さん、いつもありがとうございます~)

それによると、サイドチャネル付きの AXI4-Stream は、ap_axi_sdata.h をインクルードすれば良いそうだ。
ap_axi_sdata.h には、2つのテンプレートがあって、その違いは data が ap_int か ap_uint かの違いになる。 それぞれの構造体名は ap_axis と ap_axiu だ。 ap_axis のテンプレートを下に引用する。

template<int D,int U,int TI,int TD>
  struct ap_axis{
    ap_int<D>    data;
    ap_uint<D/8> keep;
    ap_uint<D/8> strb;
    ap_uint<U>   user;
    ap_uint<1>   last;
    ap_uint<TI>  id;
    ap_uint<TD>  dest;
  };


これを使用して、例によってインチキな myfilter() を書いてみた。その fil_aixs_side_ch.cpp を下に示す。

//
// fil_axis_side_ch.cpp
// 2015/04/29
//

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

#include "fil_axis_side_ch.h"

int my_filter(int sr0, int sr1, int sr2);

int fil_axis_side_ch(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs){
#pragma HLS INTERFACE axis port=ins
#pragma HLS INTERFACE axis port=outs
#pragma HLS INTERFACE s_axilite port=return

    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> val;

    int sreg[3] = {};    // 0にクリア

#pragma HLS array_partition variable=sreg complete

    do {    // user が 1になった時にフレームがスタートする
        ins >> pix;
    } while(pix.user == 0);

    for (int i=0; i<HORIZONTAL_PIXEL_WIDTH; i++){
#pragma HLS PIPELINE
        for (int j=0; j<2; j++){
#pragma HLS UNROLL
                sreg[j] = sreg[j+1];
        }
        if (i != 0)    // 最初の入力はすでに入力されている
            ins >> pix;

        sreg[2] = pix.data;

        val.data = my_filter(sreg[0], sreg[1], sreg[2]);
        if (i == (HORIZONTAL_PIXEL_WIDTH-1))
            val.last = 1;
        else
            val.last = 0;

        outs << val;
    }

    return 1;
}

int my_filter(int sr0, int sr1, int sr2){
    int rv = -sr0 +2*sr1 -sr2;
    if (rv < 0){
        rv = 0;
    }

    return(rv);
}


なお、do { } while 文を下のメインループの for () 文の中に入れてしまうと、TREDY が1回のストリーム・データに付き1回ディアサートされてしまって、ストリームが wait してしまった。
このように、漫然とC++を書いているだけではダメで、書いたコードがどのようにハードウェアに影響を及ぼすのか?を考えながらコードを書いていく必要があるようだ。

次に、fil_aixs_side_ch.h を下に示す。

// fil_aixs_side_ch.h
// 2015/04/29

#define HORIZONTAL_PIXEL_WIDTH 50


これで、Vivado HLS 2014.4 で fil_aixs_side_ch プロジェクトを作製した。
lap_filter_AXIS_18_150429.png

最後に、テストベンチ用のC++ ファイル、fil_aixs_side_ch_tb.cpp を作製した。fil_aixs_side_ch_tb.cpp を下に示す。

// fil_axis_side_ch_tb.cpp
// 2015/04/29

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include <ap_axi_sdata.h>

#include "fil_axis_side_ch.h"

int fil_axis_side_ch(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs);

#define CLOCK_PERIOD 10

int main()
{
    using namespace std;

    hls::stream<ap_axis<32,1,1,1> > ins;
    hls::stream<ap_axis<32,1,1,1> > outs;
    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> vals;

    int m_seq = 1// M系列の値
    int i;
    int xor_shift;

    cout << "ins" << endl;

    for(i=0; i<5; i++){    // dummy data
           pix.user = 0;
         pix.data = i;
        ins << pix;
    }

    for(int i=0; i < HORIZONTAL_PIXEL_WIDTH; i++){
        //xor_shift = (m_seq>>31) ^ ((m_seq>>21)& 1) ^ ((m_seq>>1) & 1) ^ (m_seq & 1); // (32, 22, 2, 1)
        //m_seq = (m_seq<<1) | xor_shift;
        if ((i%CLOCK_PERIOD) < (CLOCK_PERIOD/2))
            m_seq = 0;
        else
            m_seq = 1000;

        pix.data = (ap_int<32>)m_seq;

        if (i == 0)    // 最初のデータの時に TUSER を 1 にする
            pix.user = 1;
        else
            pix.user = 0;

        ins << pix;

        cout << hex << m_seq << endl;
    }


    fil_axis_side_ch(ins, outs);

    cout << endl;
    cout << "outs" << endl;
    for(int i=0; i < HORIZONTAL_PIXEL_WIDTH; i++){
        outs >> vals;
        ap_int<32> val = vals.data;
        cout << hex << val << endl;
        if (vals.last)
            cout << "AXI-Stream is end" << endl;
    }

    return 0;
}

  1. 2015年04月29日 04:21 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0