FC2カウンター FPGAの部屋 memcpy() を利用したDMA Read IP 1(memcpy() が 1 個の場合)

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

FPGAの部屋

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

memcpy() を利用したDMA Read IP 1(memcpy() が 1 個の場合)

Vivado HLS で DMA Read IP を作る(絶対アドレス指定版)”は論理シミュレーションでは動作するが、論理合成すると動作しなくなってしまう。

それでは、ということで、DMA Read IP の異なる実装を試してみることにした。Vivado HLS 2016.2 を使用している。
memcpy() を使用して明示的にAXI4 のバースト転送を使用する。
DMA_Read_IP_test_39_160919.png

最初に

memcpy(buf1, (const int*)(&in[dma_index+(y*HORIZONTAL_PIXEL_WIDTH)]), (HORIZONTAL_PIXEL_WIDTH)*4);

で1行分の画像データをRead しようとしたが、これだと、Cコードからの合成で不思議なエラーになってしまう。

Instruction does not dominate all uses!
%in_addr = getelementptr inbounds i32* %in, i64 %tmp_12_mid2, !dbg !1886
%in_addr_1_rd_req = call i1 @_ssdm_op_ReadReq.m_axi.i32P(i32* %in_addr, i32 480000), !dbg !1886
Broken module found, compilation aborted!
R6025
- pure virtual function call


また、不思議なことに、これにDATAFLOW指示子を追加すると、Cコードからの合成が通るようになった。
DMA_Read_IP_test_40_160919.png

Latency が min, max 同じ値で 1462215 だった。
今、800 x 600 ピクセルの画像を 3 回処理しているので、 800 x 600 x 3 = 1440000 なので、1462215 / 1440000 ≒ 1.015 クロック/ピクセルとなっているので、とっても良い具合だ。

DATAFLOW 指示子は関数の並列化だけではなく、for 文にも効くということだった。(kenichio0402さんと同僚の方、ありがとうございます)
なお、UG902 の128ページの「タスクレベルのパイプライン : データ フ ロー最適化」に最適化の例がある。

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

1467869クロックだった。

C/RTL協調シミュレーション波形を示す。連続的にAXI4 Master Read アクセスが出ている。
DMA_Read_IP_test_42_160919.png

DMA_Read_IP_test_43_160919.png

IP 化を行って、
Vivado HLS で生成した AXI4 Master DMA IP を使用したカメラ画像表示システム1(プロジェクト作成)
Vivado HLS で生成した AXI4 Master DMA IP を使用したカメラ画像表示システム2(SDK)
のDMA Read IP に入れ替えて、コンパイルし、実機で動作させてみた。
その結果、ランダム画面が下に表示されたっきりで、カメラ画像は表示できなかった。
DMA_Read_IP_test_44_160919.jpg

カメラ画像システムが悪いのか?それともDMA Read IP が悪いのか?
カメラ画像システムは、他のDMA Read IP で正常とは言えないまでも、映っているので、DMA Read IP が悪いのかもしれない?

現在のDMA_Read_addr.cpp を貼っておく。

// DMA_Read_addr.cpp
// 2016/07/13 by marsee
//
// frame_buffer0, frame_buffer1, frame_buffer2 には3つのフレームバッファのアドレスを入れる
// mode = 0 : DMA Write IP の active_frame を見て、その1つ前のフレームをDMA Readするモード(DMA_WRITE_MODE)
// mode = 1 : フリーラン モード(FREE_RUN_MODE)
// 2016/09/18 : memcpy を使用
//

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

#include "DMA_Read.h"

int DMA_Read_addr(volatile int *in, hls::stream<ap_axis<32,1,1,1> >& outs,
        unsigned int frame_buffer0, unsigned int frame_buffer1,
        unsigned int frame_buffer2, ap_uint<2> & active_frame,
        ap_uint<1> mode){
#pragma HLS INTERFACE s_axilite port=mode
#pragma HLS INTERFACE ap_none port=active_frame
#pragma HLS INTERFACE s_axilite port=frame_buffer0
#pragma HLS INTERFACE s_axilite port=frame_buffer1
#pragma HLS INTERFACE s_axilite port=frame_buffer2
#pragma HLS INTERFACE m_axi depth=5000000 port=in offset=off
#pragma HLS INTERFACE axis port=outs
#pragma HLS INTERFACE s_axilite port=return

    ap_axis<32,1,1,1> pix;
    int dma_index, n;
    int buf[HORIZONTAL_PIXEL_WIDTH];

    for (int i=0; i<MAX_FRAME_NUMBER; i++){
        if (mode == DMA_WRITE_MODE)
            n = (int)active_frame;
        else
            n = i;

        switch (n){ // 1つ前のフレームバッファを読みだす
            case 0 :
                dma_index = frame_buffer2/sizeof(int);
                break;
            case 1 :
                dma_index = frame_buffer0/sizeof(int);
                break;
            case 2 :
                dma_index = frame_buffer1/sizeof(int);
                break;
            default :
                dma_index = frame_buffer0/sizeof(int);
                break;
        } 

        for (int y=0; y<VERTICAL_PIXEL_WIDTH; y++){
#pragma HLS DATAFLOW
            memcpy(buf, (const int*)(&in[dma_index+(y*HORIZONTAL_PIXEL_WIDTH)]), (HORIZONTAL_PIXEL_WIDTH)*4);
            for (int x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS PIPELINE II=1
                pix.data = buf[x];

                if (y==0 && x==0)
                    pix.user = 1;
                else
                    pix.user = 0;

                if (x == (HORIZONTAL_PIXEL_WIDTH-1))
                    pix.last = 1;
                else
                    pix.last = 0;

                outs << pix;
            }
        }
    }

    return 0;
}

  1. 2016年09月19日 10:03 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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