FC2カウンター FPGAの部屋 2019年12月05日
FC2ブログ

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

FPGAの部屋

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

AXI4 MasterとAXI4 Streamインターフェースがあって、AXI4 Masterにmemcpy()を使用しているVivado HLSの回路

AXI4 Master インターフェースと AXI4 Stream インターフェースを持っているVivado HLS で作成した回路でAXI4 Master に memcpy() を使用していると合成時のレポートがでないということをツィッターで聞いた。ツィッターでつぶやいていたのは、 @lp6m2 さんで、聞いていみると、Xilinx のCommunity Forums にも、”Is it possible to set internal BRAM values using AXI4 protocol in HLS IP using AXI-Stream protocol?”で質問しているそうだ。

私も試してみることにした。ソースコードはmemcpy() の代わりに for() 文でコピーする行も追加させていただいた。今はコメントアウトしてある。bram_setparam_test.cpp を示す。

#include "hls_video.h"
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <iostream>
#include <string.h>

void bram_setparam_test(bool mode, int *inputparam,
        hls::stream<ap_axiu<32,1,1,1> >& instream, hls::stream<ap_axiu<32,1,1,1> >& outstream){
#pragma HLS INTERFACE axis port = instream
#pragma HLS INTERFACE axis port = outstream
#pragma HLS INTERFACE s_axilite port = mode
#pragma HLS INTERFACE m_axi port = inputparam offset=slave depth=100
#pragma HLS INTERFACE s_axilite port = mode
#pragma HLS INTERFACE s_axilite port = return
    static int internal_param[100];
#pragma HLS RESOURCE variable=internal_param core=RAM_1P_BRAM
    if(mode == true){
        //AXI4 set parameter mode
        memcpy(internal_param, inputparam, sizeof(int) * 100);
        /*for(int i=0; i<100; i++){
#pragma HLS PIPELINE II=1
            internal_param[i] = inputparam[i];
        }*/
    }else{
        //AXI4-stream MODE
        for(int i = 0; i < 100; i++){
#pragma HLS PIPELINE II=1
            int inval = instream.read().data;
            ap_axiu<32,1,1,1> outval;
            outval.data = inval * internal_param[i];
            outval.last = (i == 99 ? 1 : 0);
            outstream.write(outval);
        }
    }
}


自分なりにテストベンチのbram_setparam_test_tb.cpp を作ったので、それを示す。

// bram_setparam_test_tb.cpp
// 2019/12/04 by marsee
//

#include "hls_video.h"
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <iostream>
#include <string.h>

void bram_setparam_test(bool mode, int* inputparam,
        hls::stream<ap_axiu<32,1,1,1> >& instream, hls::stream<ap_axiu<32,1,1,1> >& outstream);

int inputparam[100];

int main(){
    using namespace std;

    hls::stream<ap_axiu<32,1,1,1> > ins;
    hls::stream<ap_axiu<32,1,1,1> > outs;
    ap_axiu<32,1,1,1> streamd;
    ap_axiu<32,1,1,1> vals;

    for(int i=0; i<100; i++){
        inputparam[i] = i;
    }

    bram_setparam_test(true, inputparam, ins, outs);

    for(int i=0; i<100; i++){
        streamd.data = i;
        if(i == 0)
            streamd.user = 1;
        else
            streamd.user = 0;
        if(i == 100-1)
            streamd.last = 1;
        else
            streamd.last = 0;
        ins << streamd;
    }

    bram_setparam_test(false, inputparam, ins, outs);

    for(int i=0; i<100; i++){
        outs >> vals;
        if((int)vals.data != i*i){
            fprintf(stderr, "Error: i = %d, i^2 = %d; outs = %d\n", i, i*i, (int)vals.data);
            exit(1);
        }
        printf("i = %d, i^2 = %d; outs = %d\n", i, i*i, (int)vals.data);
    }
    return(0);
}


Vivado HLS 2019.2 のプロジェクトを示す。
Vivado_HLS_MS_memcpy_2_191205.png

C シミュレーションを行って成功した。結果を示す。
Vivado_HLS_MS_memcpy_1_191205.png

C コードの合成を行った。この結果はスカスカだった。レポートが表示されない。
Vivado_HLS_MS_memcpy_3_191205.png

C/RTL 協調シミュレーションを行った。結果を示す。
Vivado_HLS_MS_memcpy_4_191205.png

波形を見ると、正常に動作しているようだ。
Vivado_HLS_MS_memcpy_5_191205.png

Vivado_HLS_MS_memcpy_6_191205.png

Export RTL もそれらしく動いている。
Vivado_HLS_MS_memcpy_7_191205.png

レポートの結果にも問題は無いようだ。

次に、memcpy() をコメントアウトして、for() を活かしてみよう。

 if(mode == true){
  //AXI4 set parameter mode
  //memcpy(internal_param, inputparam, sizeof(int) * 100);
  for(int i=0; i<100; i++){
#pragma HLS PIPELINE II=1
   internal_param[i] = inputparam[i];
  }
 }else{


これでC コードの合成を行った。結果を示す。今度はちゃんとレポートが出た。
Vivado_HLS_MS_memcpy_8_191205.png

C/RTL 協調シミュレーションのレイテンシも memcpy() の場合と同一だ。
Vivado_HLS_MS_memcpy_9_191205.png

Export RTL を示す。memcpy() とあまり変わりがない。
Vivado_HLS_MS_memcpy_10_191205.png

今までも memcpy() は使っていたので、それだけの原因では無いと思う。
AXI4 Master を memcpy() でやっている時に、AXI4 Stream インターフェースを使ったことは無いので、その時にC コードの合成のレポートが消えてしまうのかも知れない?
なお、Vivado HLS 2018.3 でも、Vivado HLS 2017.4 でも、同様にC コードの合成のレポートが消えてしまう。
  1. 2019年12月05日 05:44 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0