FC2カウンター FPGAの部屋 2022年07月
fc2ブログ

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

FPGAの部屋

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

パラレル入出力カメラ用 AXI4-Stream 出力 IP の作成

パラレル入出力カメラ用 AXI4-Stream 出力 IP を作成する。
秋月電子の”OV5642使用500万画素カメラ M12レンズ付き B0020”用の AXI4-Stream 出力インターフェース IP だ。
これは以前作成した mt9d111 カメラ用 IP と同じ HDL コードで行けるので、それのファイル名を変更して Vivado 2022.1 で ZYBO Z7-20 用の paracam2axis プロジェクトを作成する。

Vivado 2022.1 で作成した ZYBO Z7-20 用の paracam2axis プロジェクトを示す。
ZYBO_Z7_PYNQ_84_220730.png

paracam2axis プロジェクトのソースコードは”カメラ-AXI4-Stream出力IPの作製3(論理合成用HDLソースの公開)”の HDL コードを paracam2axis 用に名称を変更した。

disp_timing_parameters.vh は”ビットマップ・ディスプレイ・コントローラの作製19(HDLソースの公開)”に掲載してあるが、ここでは、VGA 解像度に設定されている。それを、SVGA 解像度に変更した。

pixel_fifo は IP Catalog から起動した FIFO Generator で作成した。
そのパラメータを示す。
ZYBO_Z7_PYNQ_91_220730.png

ZYBO_Z7_PYNQ_92_220730.png

ZYBO_Z7_PYNQ_93_220730.png

ZYBO_Z7_PYNQ_94_220730.png

ZYBO_Z7_PYNQ_95_220730.png

Vivado 2022.1 の Tools メニューから Create and Package New IP... を選択して paracam_inf_axis IP を作成した。
Identification 画面を示す。
ZYBO_Z7_PYNQ_85_220730.png

File Groups 画面を示す。
ZYBO_Z7_PYNQ_86_220730.png

Ports and Interface 画面を示す。
ZYBO_Z7_PYNQ_87_220730.png

Customization GUI 画面を示す。
ZYBO_Z7_PYNQ_88_220730.png

Package IP の Review and Package 画面の Edit packaging settings をクリックして、settings ダイアログを表示し、Create archive of IP にチェックを入れた。こうすると IP が ZIP 圧縮される。

Package IP の Review and Package 画面で Package IP ボタンをクリックすると、圧縮された IP の user.org_user_paracam_inf_axis_1.0.zip が出力された。
ZYBO_Z7_PYNQ_89_220730.png

user.org_user_paracam_inf_axis_1.0.zip の中身を示す。
ZYBO_Z7_PYNQ_90_220730.png
  1. 2022年07月30日 04:16 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラをAXI4-Stream対応にする6(Vivado 2022.1 で IP作成)

ビットマップ・ディスプレイ・コントローラをAXI4-Stream対応にする5(IP作成)”の続き。

bitmap_disp_cont_axis は Vivado 2016.2 で IP にしてあったので、あれから 6 年経っているので、改めて Vivado 2022.1 で IP 化を行った。結果としては、ほとんど同じ手順で IP にすることができた。

Vivado 2022.1 の bitmap_disp_cont_axis プロジェクトを示す。
ZYBO_Z7_PYNQ_78_220729.png

bitmap_disp_cont_axis プロジェクトのソースコードは”ビットマップ・ディスプレイ・コントローラをAXI4-Stream対応にする4(ソースコードの公開)”にある。
video_timing_param.vh は”VivadoでZYBOのAXI4 Slave キャラクタ・ディスプレイ・コントローラ11(Verilog HDLソース1)”にある。

bitmap_afifo の作り方は”ビットマップ・ディスプレイ・コントローラをAXI4-Stream対応にする2(bitmap_afifo)”にある。なお FIFO Generator は IP Catalog から起動した。

bitmap_disp_cont_axis IP 作成については、”ビットマップ・ディスプレイ・コントローラをAXI4-Stream対応にする5(IP作成)”の手順で行った。

RGB インターフェースの作成は、”ZYBO_0 を変更1(ブロックデザインの修正)”に従ったが、vid_io_rtl の入っているカテゴリーが違っていた Advanced だったかな?

Package IP の Ports and Interface 、Customization GUI 画面を示す。
ZYBO_Z7_PYNQ_79_220729.png

ZYBO_Z7_PYNQ_80_220729.png

なお、Package IP の Review and Package 画面の Edit packaging settings をクリックして、settings ダイアログを表示し、Create archive of IP にチェックを入れた。こうすると IP が ZIP 圧縮される。
ZYBO_Z7_PYNQ_81_220729.png

Package IP の Review and Package 画面で Package IP ボタンをクリックすると、圧縮された IP の user.org_user_bitmap_disp_cont_axis_1.0.zip が出力された。
ZYBO_Z7_PYNQ_82_220729.png

user.org_user_bitmap_disp_cont_axis_1.0.zip の内容物を示す。
ZYBO_Z7_PYNQ_83_220729.png
  1. 2022年07月29日 05:08 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

トリプル・バッファの AXI4-Stream 出力 DMA 2(DMA2axis_3buf)

トリプル・バッファの AXI4-Stream 出力 DMA 1(DMA2axis_3buf)”の続き。

ZYBO Z7-20 用のトリプル・バッファの AXI4-Stream 出力 DMA (DMA2axis_3buf)を Vitis HLS 2022.1 で作成するということで、前回は、ソースコードとテストベンチ・コードを貼って、DMA2axis_3buf プロジェクトを作成した。今回は、C シミュレーション、C コードの合成、C/RTL 協調シミュレーション、Export RTL、Implementation を行った。

C シミュレーションを行った。結果を示す。
ZYBO_Z7_PYNQ_70_220727.png

C コードの合成を行った。結果を示す。
レイテンシもリソース使用量も良さそうだ。なお、画像サイズを可変にするとリソース使用量が 1 桁程度増えてしまった。。。
ZYBO_Z7_PYNQ_71_220727.png
ZYBO_Z7_PYNQ_72_220727.png
ZYBO_Z7_PYNQ_73_220727.png
ZYBO_Z7_PYNQ_74_220727.png

C/RTL 協調シミュレーション結果を示す。
レイテンシは 480016 クロックで良いと思う。
ZYBO_Z7_PYNQ_75_220727.png

C/RTL 協調シミュレーション波形の一部を示す。
outs_TVALID が 1 にキープされているのが素晴らしい。
ZYBO_Z7_PYNQ_76_220727.png

Export RTL を行った。
DMA2axis_3buf/solution1/impl ディレクトリに export.zip が生成された。

Implementation を行った。結果を示す。
問題ない結果だと思う。vflip_dma_write の時はどうしたんだろうか?バグがある?
ZYBO_Z7_PYNQ_77_220727.png
  1. 2022年07月28日 04:34 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

トリプル・バッファの AXI4-Stream 出力 DMA 1(DMA2axis_3buf)

前回の vflip_dma_write がトリプル・バッファだったので、それと組のトリプル・バッファの AXI4-Stream 出力 DMA (DMA2axis_3buf)を Vitis HLS 2022.1 で作成する。なお DMA2axis_3buf の使用するボードは ZYBO Z7-20 で、SVGA 画像専用とする。

まずは、DMA2axis_3buf.h を示す。

// DMA2axis_3buf.h
// 2022/07/26 by marsee
//

#ifndef __DMA2AXIS_3BUF_H__
#define __DMA2AXIS_3BUF_H__

#define NUM_FRAME_BUFFER    3

#define DMA_WRITE_MODE    0
#define FREE_RUN_MODE    1

#define ROW_SIZE 600
#define COL_SIZE 800

#endif


ソースコードの DMA2axis_3buf.cpp を示す。

// DMA2axis_3buf.cpp
// 2022/07/22 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),3このフレームバッファを順番にDMA Readする
//

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

#include "DMA2axis_3buf.h"

int DMA2axis_3buf(int32_t *fb0, int32_t *fb1, int32_t *fb2, hls::stream<ap_axis<32,1,1,1> >& outs,
        ap_uint<2> active_frame, ap_uint<1> mode){
#pragma HLS DATAFLOW
#pragma HLS INTERFACE mode=s_axilite port=mode
#pragma HLS INTERFACE mode=m_axi depth=480000 port=fb2 offset=slave
#pragma HLS INTERFACE mode=m_axi depth=480000 port=fb1 offset=slave
#pragma HLS INTERFACE mode=m_axi depth=480000 port=fb0 offset=slave
#pragma HLS INTERFACE mode=ap_none port=active_frame register
#pragma HLS INTERFACE mode=axis register_mode=both port=outs register
#pragma HLS INTERFACE mode=s_axilite port=return

    ap_axis<32,1,1,1> vals;
    int32_t *fb;
    static int n = 0;

    if (mode == DMA_WRITE_MODE){
        n = (int)active_frame;
    }else{
        n++;
        if (n > 2)
            n = 0;
    }

    if(n == 0)
        fb = fb2;
    else if(n == 1)
        fb = fb0;
    else // n == 2
        fb = fb1;

    vals.keep = 0x7;
    vals.strb = 0x7;

    for (int y=0; y<ROW_SIZE; y++){
#pragma HLS LOOP_TRIPCOUNT avg=600 max=1080 min=480
        for (int x=0; x<COL_SIZE; x++){
#pragma HLS LOOP_TRIPCOUNT avg=800 max=1920 min=640
#pragma HLS PIPELINE II=1

        vals.data = fb[y*COL_SIZE+x];

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

        if (x == (COL_SIZE-1))
            vals.last = 1;
        else
            vals.last = 0;

            outs << vals;
        }
    }
    return 0;
}


テストベンチの DMA2axis_3buf_tb.cpp を示す。

// DMA2axis_3buf_tb.cpp
// 2022/07/22 by marsee
//

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

#include "DMA2axis_3buf.h"

int DMA2axis_3buf(int32_t *fb0, int32_t *fb1, int32_t *fb2, hls::stream<ap_axis<32,1,1,1> >& outs,
        ap_uint<2> active_frame, ap_uint<1> mode);

int main(){
    using namespace std;

    hls::stream<ap_axis<32,1,1,1> > outs;
    ap_axis<32,1,1,1> vals;
    int32_t *frame_buffer;
    ap_uint<2> active_frame;

    // frame buffer をアロケートする、3倍の領域を取ってそれを3つに分ける
    if ((frame_buffer =(int32_t *)malloc(NUM_FRAME_BUFFER * sizeof(int32_t) * (COL_SIZE * ROW_SIZE))) == NULL){
        fprintf(stderr, "Can't allocate frame_buffer0 ~ 2\n");
        exit(1);
    }

    // フレーム・バッファにデータを入力する
    for(int i=0; i<NUM_FRAME_BUFFER; i++){
        for (int y=0; y<ROW_SIZE; y++){
            for (int x=0; x<COL_SIZE; x++){
                frame_buffer[i*(COL_SIZE * ROW_SIZE)+y*COL_SIZE+x] = y*COL_SIZE+x;
            }
        }
    }

    for(int i=0; i<3; i++){
        active_frame = i;
        DMA2axis_3buf(frame_buffer,
                &frame_buffer[COL_SIZE * ROW_SIZE],
                &frame_buffer[2 * (COL_SIZE * ROW_SIZE)],
                outs, active_frame, DMA_WRITE_MODE);
    }

    // 比較
    for(int i=0; i<NUM_FRAME_BUFFER; i++){
        for(int y=0; y<ROW_SIZE; y++){
            for(int x=0; x<COL_SIZE; x++){
                outs >> vals;
                if(vals.data != y*COL_SIZE+x){
                    printf("vals.data = %x, correct data = %x\n", vals.data, y*COL_SIZE+x);
                    exit(1);
                }
            }
        }
    }

    printf("Success\n");

    //free(frame_buffer);
    return 0;
}


Vitis HLS 2022.1 の DMA2axis_3buf プロジェクトを示す。ZYBO Z7-20 用だ。
ZYBO_Z7_PYNQ_69_220727.png

なお、ZYBO Z7-20 用で 32 ビット・アドレスで十分なため、Solution メニュー -> Solution Settings... を選択して、Solution Settings (solution1) ダイアログを表示させて、config_interface -> m_axi_addr64 のチェックボックスのチェックを外した。
ZYBO_Z7_PYNQ_49_220723.png
  1. 2022年07月27日 04:18 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

垂直方向が反転している画像のDMA5(vflip_dma_write)

垂直方向が反転している画像のDMA4(vflip_dma_write)”の続き。

vflip_dma_write は垂直方向はフリップしているが、水平方向はミラーなしの場合の DMA だ。前回は、画像のサイズを固定にしたコードを作成したが、最後の Implementation でリソースの使用量が大きい値が示された。これではリソース使用量が大きくて使えない。今回は、C コードの合成では、リソース使用量が普通だったのに、Vivado で、論理合成、インプリメンテーションを行うとリソース使用量が大きくなってしまうのは、Vitis HLS 2022.1 特有の現象ではないか?という推測のもとに Vivado HLS 2019.2、Vitis HLS 2020.2、Vitis HLS 2021.2 で vflip_dma_write をやってたが、どれも正常にインプリメンテーションができた。

SVGA 画像用の vflip_dma_write を Vivado HLS 2019.2、Vitis HLS 2020.2、Vitis HLS 2021.2 で Vivado のインプリメンテーションをやってみた結果を示す。
最初に Vivado HLS 2019.2 から。
ZYBO_Z7_PYNQ_64_220726.png

Vitis HLS 2020.2 の結果を示す。
ZYBO_Z7_PYNQ_65_220726.png

Vitis HLS 2021.2 の結果を示す。
ZYBO_Z7_PYNQ_66_220726.png

各 Vivado HLS、Vitis HLS の性能を表にまとめた。
ZYBO_Z7_PYNQ_67_220726.png

表で CP api は CP achieved post-implementation のことだ。Latency は C コードの合成での値を入れた。

表を見ると Vitis HLS 2022.1 のリソース使用量は 1 桁違っている。

検討の結果、一つ前のバージョンの Vitis HLS 2021.2 の IP を使用することにした。
vflip_dma_write の Vitis HLS 2021.2 での C/RTL 協調シミュレーション結果を示す。
ZYBO_Z7_PYNQ_68_220726.png
  1. 2022年07月26日 04:51 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

垂直方向が反転している画像のDMA4(vflip_dma_write)

垂直方向が反転している画像のDMA3(vflip_dma_write)”の続き。

vflip_dma_write は垂直方向はフリップしているが、水平方向はミラーなしの場合の DMA だ。前回は、C シミュレーションと C コードの合成結果を書いたところで、リソースを食いすぎることが分かって、中断した。今回は、画像のサイズを固定にしたコードを作成したが、最後の Implementation でリソースの使用量が大きい値が示された。これではリソース使用量が大きくて使えない。

サイズを固定したソースコード、テストベンチ・コードに変更した。コードを示す。
vflig_dma_write.h から示す。

// vflip_dma_write.h
// 2022/07/21 by marsee


#ifndef __VFLIP_DMA_WRITE_H__
#define __VFLIP_DMA_WRITE_H__

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

#define MAX_WIDTH 800
#define MAX_HEIGHT 600

typedef hls::stream<ap_axiu<32,1,1,1> > AXI_STREAM;
typedef ap_axiu<32,1,1,1> AP_AXIU32;

#endif


ソースコードの vflip_dma_write.cpp を示す。

// vflip_dma_write.cpp
// 2022/07/21 by marsee
// 使用する解像度は 3840 x 2160 まで

#include "vflip_dma_write.h"

int vflip_dma_write(AXI_STREAM & ins, ap_int<32> *fb0, ap_int<32> *fb1, ap_int<32> *fb2,
    volatile ap_uint<2> &active_frame){
#pragma HLS INTERFACE mode=ap_none port=active_frame register
#pragma HLS INTERFACE mode=m_axi depth=480000 port=fb0 offset=slave
#pragma HLS INTERFACE mode=m_axi depth=480000 port=fb1 offset=slave
#pragma HLS INTERFACE mode=m_axi depth=480000 port=fb2 offset=slave
#pragma HLS INTERFACE mode=axis register_mode=both port=ins register
#pragma HLS INTERFACE mode=s_axilite port=return

    AP_AXIU32 pix;
    int max_fb_chk;

    active_frame = 0;

    LOOP_WAIT0: do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        ins >> pix;
    } while(pix.user == 0);

    LOOP_Y0: for (int y=MAX_HEIGHT-1; y>=0; y--){ // vflip
#pragma HLS LOOP_TRIPCOUNT avg=600 max=1080 min=480
        LOOP_X0: for (int x=0; x<MAX_WIDTH; x++){
#pragma HLS LOOP_TRIPCOUNT avg=800 max=1920 min=640
#pragma HLS PIPELINE II=1 rewind
            if (!(x==0 && y==MAX_HEIGHT-1))    // 最初の入力はすでに入力されている
                ins >> pix;    // AXI4-Stream からの入力

            fb0[(y*MAX_WIDTH)+x] = pix.data;
        }
    }

    active_frame = 1;
    LOOP_WAIT1: do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        ins >> pix;
    } while(pix.user == 0);

    LOOP_Y1: for (int y=MAX_HEIGHT-1; y>=0; y--){ // vflip
#pragma HLS LOOP_TRIPCOUNT avg=600 max=1080 min=480
        LOOP_X1: for (int x=0; x<MAX_WIDTH; x++){
#pragma HLS LOOP_TRIPCOUNT avg=800 max=1920 min=640
#pragma HLS PIPELINE II=1 rewind
            if (!(x==0 && y==MAX_HEIGHT-1))    // 最初の入力はすでに入力されている
                ins >> pix;    // AXI4-Stream からの入力

            fb1[(y*MAX_WIDTH)+x] = pix.data;

        }
    }

    active_frame = 2;
    LOOP_WAIT2: do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        ins >> pix;
    } while(pix.user == 0);

    LOOP_Y2: for (int y=MAX_HEIGHT-1; y>=0; y--){ // vflip
#pragma HLS LOOP_TRIPCOUNT avg=600 max=1080 min=480
        LOOP_X2: for (int x=0; x<MAX_WIDTH; x++){
#pragma HLS LOOP_TRIPCOUNT avg=800 max=1920 min=640
#pragma HLS PIPELINE II=1 rewind
            if (!(x==0 && y==MAX_HEIGHT-1))    // 最初の入力はすでに入力されている
                ins >> pix;    // AXI4-Stream からの入力

            fb2[(y*MAX_WIDTH)+x] = pix.data;
        }
    }
end:
    return(0);
}


テストベンチ・コードの vflip_dma_write_tb.cpp を示す。

// vflip_dma_write_tb_tb.cpp
// 2019/01/01 by marsee
//

#include <iostream>
#include <fstream>

#include "vflip_dma_write.h"

int vflip_dma_write(AXI_STREAM & ins, ap_int<32> *fb0, ap_int<32> *fb1, ap_int<32> *fb2,
        volatile ap_uint<2> &active_frame);

#define NUM_FRAME_BUFFER 3

int main()
{
    AXI_STREAM ins;
    AP_AXIU32 pix;

    ap_uint<2> active_frame;
    int *frame_buffer;

    // Mat フォーマットから AXI4 Stream へ変換、3画面分
    for(int i=0; i<NUM_FRAME_BUFFER; i++){
        for (int y=0; y<MAX_HEIGHT; y++){
            for (int x=0; x<MAX_WIDTH; x++){
                pix.data = i*(MAX_WIDTH * MAX_HEIGHT)+y*MAX_WIDTH+x;
                if(y==0 && x==0)
                    pix.user = 1;
                else
                    pix.user = 0;
                ins << pix;
            }
        }
    }

    // frame buffer をアロケートする、3倍の領域を取ってそれを3つに分ける
    if ((frame_buffer =(int *)malloc(NUM_FRAME_BUFFER * sizeof(int) * (MAX_WIDTH * MAX_HEIGHT))) == NULL){
        fprintf(stderr, "Can't allocate frame_buffer0 ~ 2\n");
        exit(1);
    }

    vflip_dma_write(ins, (ap_int<32> *)frame_buffer,
        (ap_int<32> *)&frame_buffer[MAX_WIDTH * MAX_HEIGHT],
        (ap_int<32> *)&frame_buffer[2 * (MAX_WIDTH * MAX_HEIGHT)],
        active_frame);

    // 比較
    for(int i=0; i<NUM_FRAME_BUFFER; i++){
        for(int y=0; y<MAX_HEIGHT; y++){
            for(int x=0; x<MAX_WIDTH; x++){
                int rgb = frame_buffer[i*(MAX_WIDTH * MAX_HEIGHT)+y*MAX_WIDTH+x];
                if(rgb != i*(MAX_WIDTH * MAX_HEIGHT)+(MAX_HEIGHT-1-y)*MAX_WIDTH+x){
                    printf("rgb = %x, correct data = %x\n", rgb, i*(MAX_WIDTH * MAX_HEIGHT)+y*MAX_WIDTH+x);
                    exit(1);
                }
            }
        }
    }
    printf("Success\n");

    //free(frame_buffer);
    return 0;
}


C シミュレーションを行った。結果を示す。
ZYBO_Z7_PYNQ_56_220724.png

C コードの合成を行った。結果を示す。
ZYBO_Z7_PYNQ_58_220724.png
ZYBO_Z7_PYNQ_57_220724.png
ZYBO_Z7_PYNQ_59_220724.png
ZYBO_Z7_PYNQ_60_220724.png

リソース使用量は DSP が 3 個、FF が 2748 個、LUT が 3499 個で普通だ。

C/RTL 協調シミュレーションを行った。結果を示す。
1 個の DMA 辺り 551415 クロックで、約 1.15 クロック/ピクセルの処理能力だった。
ZYBO_Z7_PYNQ_61_220724.png

C/RTL 協調シミュレーション波形を示す。
ZYBO_Z7_PYNQ_62_220724.png

Implementation を行った。
その結果のリソース使用量は LUT が 83439 個、FF が 67186 個だった。リソース使用量が多すぎる。。。これじゃ使えない。。。
ZYBO_Z7_PYNQ_63_220724.png
  1. 2022年07月25日 04:39 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

垂直方向が反転している画像のDMA3(vflip_dma_write)

垂直方向が反転している画像のDMA2(vflip_dma_write)”の続き。

vflip_dma_write は垂直方向はフリップしているが、水平方向はミラーなしの場合の DMA だ。前回は、vflip_dma_write のソースコードとテストベンチ・コードを貼った。今回は、C シミュレーションと C コードの合成結果を書いたところで、リソースを食いすぎることが分かって、中断した。

C シミュレーション結果を示す。
ZYBO_Z7_PYNQ_50_220723.png

C コードの合成結果を示す。
ZYBO_Z7_PYNQ_51_220723.png
ZYBO_Z7_PYNQ_52_220723.png
ZYBO_Z7_PYNQ_53_220723.png
ZYBO_Z7_PYNQ_54_220723.png
ZYBO_Z7_PYNQ_55_220723.png

リソース使用量が膨大になっている。
DSP が 15 個、FF が 53163 個、LUT が 44954 個使用している。これじゃ ZYBO Z7-20 に収まらない。
垂直方向が反転している画像のDMA(vflip_dma_write)”では実装できていたので、画像サイズを固定に戻してみよう。
  1. 2022年07月24日 05:13 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

垂直方向が反転している画像のDMA2(vflip_dma_write)

垂直方向が反転している画像のDMA(vflip_dma_write)”の続き。

vflip_dma_write は垂直方向はフリップしているが、水平方向はミラーなしの場合の DMA だ。なぜこのような DMA を実装するか?というと、OV5642 で垂直方向がフリップしている状態の SVGA 画像しか設定できなかったからだ。
vflip_dma_write を ZYBO Z7-20 用に Vitis HLS 2022.1 で実装する。

なお、”垂直方向が反転している画像のDMA(vflip_dma_write)”のコードには、バグがあったので、コードを修正した。

vflip_dma_write.h を示す。

// vflip_dma_write.h
// 2022/07/21 by marsee


#ifndef __VFLIP_DMA_WRITE_H__
#define __VFLIP_DMA_WRITE_H__

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

typedef hls::stream<ap_axiu<32,1,1,1> > AXI_STREAM;
typedef ap_axiu<32,1,1,1> AP_AXIU32;

#endif


ソースコードの vflip_dma_write.cpp を示す。

// vflip_dma_write.cpp
// 2022/07/21 by marsee

#include "vflip_dma_write.h"

int vflip_dma_write(AXI_STREAM & ins, ap_int<32> *fb0, ap_int<32> *fb1, ap_int<32> *fb2,
    int32_t row_size, int32_t col_size, volatile ap_uint<2> &active_frame){
#pragma HLS INTERFACE mode=s_axilite port=col_size
#pragma HLS INTERFACE mode=s_axilite port=row_size
#pragma HLS INTERFACE mode=ap_none port=active_frame register
#pragma HLS INTERFACE mode=m_axi depth=19200 port=fb0 offset=slave
#pragma HLS INTERFACE mode=m_axi depth=19200 port=fb1 offset=slave
#pragma HLS INTERFACE mode=m_axi depth=19200 port=fb2 offset=slave
#pragma HLS INTERFACE mode=axis register_mode=both port=ins register
#pragma HLS INTERFACE mode=s_axilite port=return

    AP_AXIU32 pix;
    int max_fb_chk;

    active_frame = 0;

    LOOP_WAIT0: do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        ins >> pix;
    } while(pix.user == 0);

    LOOP_Y0: for (int y=row_size-1; y>=0; y--){ // vflip
#pragma HLS LOOP_TRIPCOUNT avg=600 max=1080 min=480
        LOOP_X0: for (int x=0; x<col_size; x++){
#pragma HLS LOOP_TRIPCOUNT avg=800 max=1920 min=640
#pragma HLS PIPELINE II=1 rewind
            if (!(x==0 && y==row_size-1))    // 最初の入力はすでに入力されている
                ins >> pix;    // AXI4-Stream からの入力

            fb0[(y*col_size)+x] = pix.data;
        }
    }

    active_frame = 1;
    LOOP_WAIT1: do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        ins >> pix;
    } while(pix.user == 0);

    LOOP_Y1: for (int y=row_size-1; y>=0; y--){ // vflip
#pragma HLS LOOP_TRIPCOUNT avg=600 max=1080 min=480
        LOOP_X1: for (int x=0; x<col_size; x++){
#pragma HLS LOOP_TRIPCOUNT avg=800 max=1920 min=640
#pragma HLS PIPELINE II=1 rewind
            if (!(x==0 && y==row_size-1))    // 最初の入力はすでに入力されている
                ins >> pix;    // AXI4-Stream からの入力

            fb1[(y*col_size)+x] = pix.data;

        }
    }

    active_frame = 2;
    LOOP_WAIT2: do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        ins >> pix;
    } while(pix.user == 0);

    LOOP_Y2: for (int y=row_size-1; y>=0; y--){ // vflip
#pragma HLS LOOP_TRIPCOUNT avg=600 max=1080 min=480
        LOOP_X2: for (int x=0; x<col_size; x++){
#pragma HLS LOOP_TRIPCOUNT avg=800 max=1920 min=640
#pragma HLS PIPELINE II=1 rewind
            if (!(x==0 && y==row_size-1))    // 最初の入力はすでに入力されている
                ins >> pix;    // AXI4-Stream からの入力

            fb2[(y*col_size)+x] = pix.data;
        }
    }
end:
    return(0);
}


テストベンチの vflip_dma_write_tb.cpp を示す。

// vflip_dma_write_tb_tb.cpp
// 2019/01/01 by marsee
//

#include <iostream>
#include <fstream>

#include "vflip_dma_write.h"

int vflip_dma_write(AXI_STREAM & ins, ap_int<32> *fb0, ap_int<32> *fb1, ap_int<32> *fb2,
    int32_t row_size, int32_t col_size, volatile ap_uint<2> &active_frame);

#define NUM_FRAME_BUFFER 3
#define MAX_HEIGHT  240
#define MAX_WIDTH   320

int main()
{
    AXI_STREAM ins;
    AP_AXIU32 pix;

    ap_uint<2> active_frame;
    int *frame_buffer;

    // Mat フォーマットから AXI4 Stream へ変換、3画面分
    for(int i=0; i<NUM_FRAME_BUFFER; i++){
        for (int y=0; y<MAX_HEIGHT; y++){
            for (int x=0; x<MAX_WIDTH; x++){
                pix.data = i*(MAX_WIDTH * MAX_HEIGHT)+y*MAX_WIDTH+x;
                if(y==0 && x==0)
                    pix.user = 1;
                else
                    pix.user = 0;
                ins << pix;
            }
        }
    }

    // frame buffer をアロケートする、3倍の領域を取ってそれを3つに分ける
    if ((frame_buffer =(int *)malloc(NUM_FRAME_BUFFER * sizeof(int) * (MAX_WIDTH * MAX_HEIGHT))) == NULL){
        fprintf(stderr, "Can't allocate frame_buffer0 ~ 2\n");
        exit(1);
    }

    vflip_dma_write(ins, (ap_int<32> *)frame_buffer,
        (ap_int<32> *)&frame_buffer[MAX_WIDTH * MAX_HEIGHT],
        (ap_int<32> *)&frame_buffer[2 * (MAX_WIDTH * MAX_HEIGHT)],
        MAX_HEIGHT, MAX_WIDTH,
        active_frame);

    // 比較
    for(int i=0; i<NUM_FRAME_BUFFER; i++){
        for(int y=0; y<MAX_HEIGHT; y++){
            for(int x=0; x<MAX_WIDTH; x++){
                int rgb = frame_buffer[i*(MAX_WIDTH * MAX_HEIGHT)+y*MAX_WIDTH+x];
                if(rgb != i*(MAX_WIDTH * MAX_HEIGHT)+(MAX_HEIGHT-1-y)*MAX_WIDTH+x){
                    printf("rgb = %x, correct data = %x\n", rgb, i*(MAX_WIDTH * MAX_HEIGHT)+y*MAX_WIDTH+x);
                    exit(1);
                }
            }
        }
    }
    printf("Success\n");

    //free(frame_buffer);
    return 0;
}


Vitis HLS 2022.1 の vflip_dma_write プロジェクトを示す。ZYBO Z7-20 用だ。
ZYBO_Z7_PYNQ_48_220723.png

なお、ZYBO Z7-20 用で 32 ビット・アドレスで十分なため、Solution メニュー -> Solution Settings... を選択して、Solution Settings (solution1) ダイアログを表示させて、config_interface -> m_axi_addr64 のチェックボックスのチェックを外した。
ZYBO_Z7_PYNQ_49_220723.png
  1. 2022年07月23日 04:12 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20 で PYNQ を使用する5(ソーベル・フィルタを動作させる2)

ZYBO Z7-20 で PYNQ を使用する4(ソーベル・フィルタを動作させる1)”の続き。

前回は、Vivado 2022.1 で ZYBO Z7-20 用の img_filt プロジェクトを作成し、前回作成した sobel_axis_RGB24 IP を使用して、ブロック・デザインを作成して、論理合成、インプリメンテーション、ビットストリームの生成を行って成功した。今回は、前回作成された bit ファイルと hwh ファイル、そして画像ファイルを ZYBO Z7-20 の PYNQ Linux にアップロードする。そして、Jupyter Notebook で sobel.ipynb を作成して実行した。結果としてソーベル・フィルタを動作させることができた。

Ubuntu 18.04 が動作するパソコン上で FileZilla を起動して、ZYBO Z7-20 の PYNQ Linux にアップロードする。
/my_project/sobel_filter ディレクトリを作成した。
img_filt/img_filt.runs/impl_1/img_filt_wrapper.bit をアップロードした。
ZYBO_Z7_PYNQ_40_220722.png

img_filt/img_filt.gen/sources_1/bd/img_filt/hw_handoff/img_filt.hwh をアップロードした。
ZYBO_Z7_PYNQ_41_220722.png

画像ファイルの test2.jpg をアップロードした。
ZYBO_Z7_PYNQ_42_220722.png

ZYBO Z7-20 の PYNQ Linux で Jupyter Notebook を起動した。
sudo jupyter notebook --allow-root

Ubuntu 18.04 のホスト・パソコンで、http://192.168.3.33:9090 を Chrome で表示した。
/my_project/sobel_filter ディレクトリに移動して、New -> Python 3 を選択して、Python 3 の新規ノートブック・ファイルを作成した。
ZYBO_Z7_PYNQ_43_220722.png

ホスト・パソコンの FileZilla で bit ファイルと hwh ファイルの名前を sobel に変更した。
ZYBO_Z7_PYNQ_44_220722.png

新規作成したノートブック・ファイルの名前を sobel.ipynb に変更した。
sobel.ipynb のコードを貼っておく。

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from pynq import allocate, Overlay

sobel_filter = Overlay("./sobel.bit")

dma = sobel_filter.axi_dma_0
sobel = sobel_filter.sobel_axis_RGB24_0

image_path = "./test2.jpg"
original_image = Image.open(image_path)

canvas = plt.gcf()
size = canvas.get_size_inches()
canvas.set_size_inches(size*2)

width, height = original_image.size
print("Image size: {}x{} pixels.".format(width, height))
plt.figure(figsize=(6, 5));
_ = plt.imshow(original_image)

in_buffer = allocate(shape=(height, width, 3), 
                           dtype=np.uint8, cacheable=1)
out_buffer = allocate(shape=(height, width, 3), 
                            dtype=np.uint8, cacheable=1)

in_buffer[:] = np.array(original_image)

def run_kernel():
    dma.sendchannel.transfer(in_buffer)
    dma.recvchannel.transfer(out_buffer)    
    sobel.write(0x00,0x01) # start
    dma.sendchannel.wait()
    dma.recvchannel.wait()

print(height)
print(width)

sobel.register_map.row_size = height
sobel.register_map.col_size = width
sobel.register_map.function_r = 3 # SOBELwAxiDma

run_kernel()
sobel_image = Image.fromarray(out_buffer)

print("Image size: {}x{} pixels.".format(width, height))
plt.figure(figsize=(6, 5));
_ = plt.imshow(sobel_image)

del in_buffer
del out_buffer


sobel.ipynb を実行したところ、ソーベル・フィルタの処理結果を見ることができた。成功だ。。。
ZYBO_Z7_PYNQ_45_220722.png

ZYBO_Z7_PYNQ_46_220722.png

ZYBO_Z7_PYNQ_47_220722.png
  1. 2022年07月22日 05:02 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20 で PYNQ を使用する4(ソーベル・フィルタを動作させる1)

ZYBO Z7-20 で PYNQ を使用する3”の続き。そして、”RGB 24 ビット・データ入出力対応のソーベル・フィルタを Vitis HLS 2022.1 で作成する2”で作成した sobel_axis_RGB24 IP を使用する。

今回は、Vivado 2022.1 で ZYBO Z7-20 用の img_filt プロジェクトを作成し、前回作成した sobel_axis_RGB24 IP を使用して、ブロック・デザインを作成して、論理合成、インプリメンテーション、ビットストリームの生成を行った。

Vivado 2022.1 を使用して、ZYBO Z7-20 用の img_filt プロジェクトを作成した。
ZYBO_Z7_PYNQ_29_220721.png

作成された img_filt ディレクトリの下に sobel_axis_RGB24 ディレクトリを作成した。
sobel_axis_RGB24 ディレクトリの下に”RGB 24 ビット・データ入出力対応のソーベル・フィルタを Vitis HLS 2022.1 で作成する2”で作成した sobel_axis_RGB24 IP をコピー & ペーストした。
ZYBO_Z7_PYNQ_30_220721.png

IP Catalog で Sobel_axis_rgb24 をリポジトリに追加した。これで Sobel_axis_rgb24 IP が使用できるようになった。
ZYBO_Z7_PYNQ_31_220721.png

img_filt ブロック・デザインを作成した。
ZYBO_Z7_PYNQ_32_220721.png

各 IP の設定を示す。
最初に processing_system7_0 の設定を示す。
PS-PL Configuration の HP Slave AXI Interface -> S AXI HP0 interface にチェックを入れた。
ZYBO_Z7_PYNQ_33_220721.png

Clock Configuration の PL Fabric Clocks -> FCLK_CLK0 の周波数を 100 MHz に設定した。
ZYBO_Z7_PYNQ_34_220721.png

axi_dma_0 の設定を示す。
Enable Scatter Gather Engine のチェックボックスのチェックを外した。
Width Buffer Length Register (8-26) を 26 bits に変更した。転送単位はバイトだ。これで HD 解像度まで DMA することができる。
ZYBO_Z7_PYNQ_35_220721.png

axis_dwidth_converter_0 の設定を示す。
Master Interface TDATA Width (bytes) を 3 に変更した。
ZYBO_Z7_PYNQ_36_220721.png

axis_dwidth_converter_1 の設定を示す。
Master Interface TDATA Width (bytes) を 4 に変更した。
ZYBO_Z7_PYNQ_37_220721.png

img_filt ブロック・デザインを Create HDL Wrapper して img_filt_wrapper.v を作成した。(もうすでにビットストリームを生成した後の画像を使用している)
ZYBO_Z7_PYNQ_39_220721.png

論理合成、インプリメンテーション、ビットストリームの生成を行って成功した。
Project Summary を示す。
ZYBO_Z7_PYNQ_38_220721.png
  1. 2022年07月21日 04:46 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

RGB 24 ビット・データ入出力対応のソーベル・フィルタを Vitis HLS 2022.1 で作成する2

RGB 24 ビット・データ入出力対応のソーベル・フィルタを Vitis HLS 2022.1 で作成する1”の続き。

自分で作った回路を ZYBO Z7-20 の PYNQ で動作させるためソーベル・フィルタを実装することにしたということで、前回は、 ZYBO Z7-20 用の RGB 24 ビット・データ入出力対応のソーベル・フィルタを Vitis HLS 2022.1 実装するために Vitis HLS 2022.1 で sobel_axis_RGB24 プロジェクトを作成した。今回は、そのプロジェクトで C シミュレーション、C コードの合成、C/RTL 協調シミュレーション、Export RTL、Implementation を行った。

C シミュレーションを行って成功した。
ZYBO_Z7_PYNQ_21_220720.png

solution1/csim/build ディレクトリに sobel.jpg が生成された。
ZYBO_Z7_PYNQ_22_220720.png

C コードの合成を行った。結果を示す。
ZYBO_Z7_PYNQ_23_220720.png
ZYBO_Z7_PYNQ_24_220720.png
ZYBO_Z7_PYNQ_25_220720.png

C/RTL 協調シミュレーションを行った。
Max Latency は 480036 クロックなので、良好な結果だ。なお、画像サイズは 800 x 600 ピクセル = 480000 ピクセルだった。
ZYBO_Z7_PYNQ_26_220720.png

Export RTL を行った。
solution1/impl に ip ディレクトリと export.zip が生成された。
ZYBO_Z7_PYNQ_27_220720.png

Implementation を行った。
CP achieved post-implementation が 9.320 ns なので、大丈夫だろう?と思う。
ZYBO_Z7_PYNQ_28_220720.png
  1. 2022年07月20日 05:16 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

RGB 24 ビット・データ入出力対応のソーベル・フィルタを Vitis HLS 2022.1 で作成する1

自分で作った回路を ZYBO Z7-20 の PYNQ で動作させるためソーベル・フィルタを実装することにした。
つまり、KV260 でやってきたことを ZYBO Z7-20 でやってみよう。
最初は ZYBO Z7-20 用の RGB 24 ビット・データ入出力対応のソーベル・フィルタを Vitis HLS 2022.1 で実装してみよう。

KV260 用の RGB 24 ビット・データ入出力対応のソーベル・フィルタは以前 Vitis HLS 2021.2 で作成した。
今回はその”RGB 24 ビット・データ入出力対応のソーベル・フィルタを Vitis HLS 2021.2 で作成する3”のソースコードをまるごと使用する。よってソースコードは”RGB 24 ビット・データ入出力対応のソーベル・フィルタを Vitis HLS 2021.2 で作成する3”を参照のこと。

Vitis_HLS/ZYBO_Z7_20/2022.1 ディレクトリに Vitis HLS 2022.1 の sobel_axis_RGB24 プロジェクトを作成した。
ZYBO_Z7_PYNQ_17_220719.png

sobel_axis_RGB24 ディレクトリの様子を示す。
ZYBO_Z7_PYNQ_18_220719.png

今回のテストベンチ・コードでは OpenCV ライブラリを使用している。
Vitis HLS 2021.1 には内蔵された OpenCV は無いので、別にインストールした OpenCV を指定する。
Vitis HLS の Project メニューから Project Settings... を選択して、Project Settings ダイアログを開いた。
Simulation タブを開いて、sobel_axis_RGB24_tb.cpp の CFLAGS に

-I/usr/local/include


を設定した。
Linker Flags に

-L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc


を設定した。
ZYBO_Z7_PYNQ_19_220719.png

更に、 Synthesis をクリックして、 Top Function に sobel_axis_RGB24 を指定した。
ZYBO_Z7_PYNQ_20_220719.png
  1. 2022年07月19日 04:40 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20 で PYNQ を使用する3

ZYBO Z7-20 で PYNQ を使用する3”の続き。

ZYBO Z7 用の PYNQ が”Pynq 2.7 for Zybo-Z7”にあったということで、前回は、PYNQ イメージを書き込んだ MicroSD カードを ZYBO Z7-20 に挿入して、PYNQ Linux を起動し、環境を整備する。更に Jupyter Notebook を起動することができた。今回は、 Jupyter Notebook が動作するかどうか? base/GPIOs_test.ipynb を動作させてみよう。

base ディレクトリの下にある GPIOs_test.ipynb を動作せてみよう。これは、LED、RGB LED とスイッチをテストするノートブックだ。
ZYBO_Z7_PYNQ_14_220718.png

GPIOs_test.ipynb を動作させた。
ZYBO_Z7_PYNQ_15_220718.png
ZYBO_Z7_PYNQ_16_220718.png

途中で LED が点滅したり、RGB LED が点灯した。またスイッチの状態も読めているようだ。

これで Jupyter Notebook が動作することが確認できたので、KV260 の PYNQ のように画像フィルタを Jupyter Notebook で作っていきたい。
  1. 2022年07月18日 05:00 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20 で PYNQ を使用する2

ZYBO Z7-20 で PYNQ を使用する1”の続き。

ZYBO Z7 用の PYNQ が”Pynq 2.7 for Zybo-Z7”にあったということで、前回は、Zybo-Z7-2.7.0.img を MicroSD カードに書き込んだ。今回は、その MicroSD カードを ZYBO Z7-20 に挿入して、PYNQ Linux を起動し、環境を整備する。更に Jupyter Notebook を起動する。

Zybo-Z7-2.7.0.img を書き込んだ MicroSD カードを ZYBO Z7-20 に挿入して電源 ON した。
PYNQ Linux が起動した。
ZYBO_Z7_PYNQ_6_220714.png

ifconfg をすると IP アドレスが割り振られている。(LAN ケーブルは接続してある)
ZYBO_Z7_PYNQ_7_220715.png

ssh で PYNQ Linux に入ることができた。
ssh 192.168.3.33 -X -l xilinx
ZYBO_Z7_PYNQ_8_220715.png

パッケージをアップデートした。
sudo apt update
sudo apt upgrade


nautilus と geany をインストールして起動したら起動できた。
sudo apt install nautilus
sudo apt install geany
nautilus &
geany &

ZYBO_Z7_PYNQ_12_220717.png

ZYBO_Z7_PYNQ_13_220717.png

Jupyter Notebook を起動した。
PYNQ ではビットストリームをダウンロードしたりするので root で Jupyter Notebook を起動する。
sudo jupyter notebook --allow-root
ZYBO_Z7_PYNQ_9_220717.png
ZYBO_Z7_PYNQ_10_220717.png

ホスト・パソコンの chrome ブラウザで 192.168.3.33:9090 にアクセスし、ログインしたら、Jupyter Notebook の画面が表示された。
ZYBO_Z7_PYNQ_11_220717.png

最後に、PYNQ Linux のログを貼っておく。

U-Boot 2020.01 (Apr 29 2022 - 04:00:55 +0000)

CPU:   Zynq 7z020
Silicon: v3.1
DRAM:  ECC disabled 512 MiB
Flash: 0 Bytes
NAND:  0 MiB
MMC:   mmc@e0100000: 0
Loading Environment from SPI Flash... SF: Detected s25fl128s with page size 256 Bytes, erase size 64 KiB, total 16 MiB
*** Warning - bad CRC, using default environment

In:    serial@e0001000
Out:   serial@e0001000
Err:   serial@e0001000
Net:   
ZYNQ GEM: e000b000, mdio bus e000b000, phyaddr 1, interface rgmii-id
SF: Detected s25fl128s with page size 256 Bytes, erase size 64 KiB, total 16 MiB

Warning: ethernet@e000b000 using MAC address from ROM
eth0: ethernet@e000b000
Hit any key to stop autoboot:  0 
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found U-Boot script /boot.scr
1636 bytes read in 12 ms (132.8 KiB/s)
## Executing script at 03000000
5891020 bytes read in 337 ms (16.7 MiB/s)
## Loading kernel from FIT Image at 10000000 ...
   Using 'conf@1' configuration
   Verifying Hash Integrity ... OK
   Trying 'kernel@0' kernel subimage
     Description:  Linux Kernel
     Type:         Kernel Image
     Compression:  uncompressed
     Data Start:   0x100000d4
     Data Size:    5869432 Bytes = 5.6 MiB
     Architecture: ARM
     OS:           Linux
     Load Address: 0x00080000
     Entry Point:  0x00080000
     Hash algo:    sha1
     Hash value:   7beea257b23b2b39f4ac933e0ec614468b0ee346
   Verifying Hash Integrity ... sha1+ OK
## Loading fdt from FIT Image at 10000000 ...
   Using 'conf@1' configuration
   Verifying Hash Integrity ... OK
   Trying 'fdt@0' fdt subimage
     Description:  Flattened Device Tree blob
     Type:         Flat Device Tree
     Compression:  uncompressed
     Data Start:   0x10599140
     Data Size:    19771 Bytes = 19.3 KiB
     Architecture: ARM
     Hash algo:    sha1
     Hash value:   f18dc7415d970642feff826f1fe9f4d261311c87
   Verifying Hash Integrity ... sha1+ OK
   Booting using the fdt blob at 0x10599140
   Loading Kernel Image
   Loading Device Tree to 1eb00000, end 1eb07d3a ... OK

Starting kernel ...

Booting Linux on physical CPU 0x0
Linux version 5.4.0-xilinx-v2020.2 (oe-user@oe-host) (gcc version 9.2.0 (GCC)) #1 SMP PREEMPT Fri Apr 29 02:08:29 UTC 2022
CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
OF: fdt: Machine model: xlnx,zynq-7000
Memory policy: Data cache writealloc
cma: Reserved 128 MiB at 0x16800000
percpu: Embedded 15 pages/cpu s32332 r8192 d20916 u61440
Built 1 zonelists, mobility grouping on.  Total pages: 129920
Kernel command line: root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=1 uio_pdrv_genirq.of_id="generic-uio" clk_ignore_unused
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes, linear)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes, linear)
mem auto-init: stack:off, heap alloc:off, heap free:off
Memory: 374392K/524288K available (8192K kernel code, 269K rwdata, 2360K rodata, 1024K init, 298K bss, 18824K reserved, 131072K cma-reserved, 0K highmem)
rcu: Preemptible hierarchical RCU implementation.
rcu:    RCU restricting CPUs from NR_CPUS=4 to nr_cpu_ids=2.
    Tasks RCU enabled.
rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
efuse mapped to (ptrval)
slcr mapped to (ptrval)
L2C: platform modifies aux control register: 0x72360000 -> 0x72760000
L2C: DT/platform modifies aux control register: 0x72360000 -> 0x72760000
L2C-310 erratum 769419 enabled
L2C-310 enabling early BRESP for Cortex-A9
L2C-310 full line of zeros enabled for Cortex-A9
L2C-310 ID prefetch enabled, offset 1 lines
L2C-310 dynamic clock gating enabled, standby mode enabled
L2C-310 cache controller enabled, 8 ways, 512 kB
L2C-310: CACHE_ID 0x410000c8, AUX_CTRL 0x76760001
random: get_random_bytes called from start_kernel+0x260/0x444 with crng_init=0
zynq_clock_init: clkc starts at (ptrval)
Zynq clock init
sched_clock: 64 bits at 324MHz, resolution 3ns, wraps every 4398046511102ns
clocksource: arm_global_timer: mask: 0xffffffffffffffff max_cycles: 0x4af472fdc8, max_idle_ns: 440795202990 ns
Switching to timer-based delay loop, resolution 3ns
Console: colour dummy device 80x30
printk: console [tty0] enabled
Calibrating delay loop (skipped), value calculated using timer frequency.. 649.99 BogoMIPS (lpj=3249996)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
CPU: Testing write buffer coherency: ok
CPU0: Spectre v2: using BPIALL workaround
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
Setting up static identity map for 0x100000 - 0x100060
rcu: Hierarchical SRCU implementation.
smp: Bringing up secondary CPUs ...
CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
CPU1: Spectre v2: using BPIALL workaround
smp: Brought up 1 node, 2 CPUs
SMP: Total of 2 processors activated (1299.99 BogoMIPS).
CPU: All CPU(s) started in SVC mode.
devtmpfs: initialized
VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 4
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 512 (order: 3, 32768 bytes, linear)
xor: measuring software checksum speed
   arm4regs  :   991.200 MB/sec
   8regs     :   754.800 MB/sec
   32regs    :   797.600 MB/sec
xor: using function: arm4regs (991.200 MB/sec)
pinctrl core: initialized pinctrl subsystem
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
cpuidle: using governor menu
hw-breakpoint: found 5 (+1 reserved) breakpoint and 1 watchpoint registers.
hw-breakpoint: maximum watchpoint size is 4 bytes.
zynq-ocm f800c000.ocmc: ZYNQ OCM pool: 256 KiB @ 0x(ptrval)
e0001000.serial: ttyPS0 at MMIO 0xe0001000 (irq = 26, base_baud = 6249993) is a xuartps
printk: console [ttyPS0] enabled
raid6: int32x8  gen()   102 MB/s
raid6: int32x8  xor()    74 MB/s
raid6: int32x4  gen()    92 MB/s
raid6: int32x4  xor()    76 MB/s
raid6: int32x2  gen()   111 MB/s
raid6: int32x2  xor()   116 MB/s
raid6: int32x1  gen()   109 MB/s
raid6: int32x1  xor()   113 MB/s
raid6: using algorithm int32x2 gen() 111 MB/s
raid6: .... xor() 116 MB/s, rmw enabled
raid6: using intx1 recovery algorithm
vgaarb: loaded
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
mc: Linux media interface: v0.10
videodev: Linux video capture interface: v2.00
pps_core: LinuxPPS API ver. 1 registered
pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
PTP clock support registered
EDAC MC: Ver: 3.0.0
FPGA manager framework
Advanced Linux Sound Architecture Driver Initialized.
clocksource: Switched to clocksource arm_global_timer
thermal_sys: Registered thermal governor 'step_wise'
NET: Registered protocol family 2
tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 6144 bytes, linear)
TCP established hash table entries: 4096 (order: 2, 16384 bytes, linear)
TCP bind hash table entries: 4096 (order: 3, 32768 bytes, linear)
TCP: Hash tables configured (established 4096 bind 4096)
UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
PCI: CLS 0 bytes, default 64
hw perfevents: no interrupt-affinity property for /pmu@f8891000, guessing.
hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7 counters available
Initialise system trusted keyrings
workingset: timestamp_bits=14 max_order=17 bucket_order=3
squashfs: version 4.0 (2009/01/31) Phillip Lougher
jffs2: version 2.2. (NAND) (SUMMARY)  © 2001-2006 Red Hat, Inc.
Key type asymmetric registered
Asymmetric key parser 'x509' registered
io scheduler mq-deadline registered
io scheduler kyber registered
zynq-pinctrl 700.pinctrl: zynq pinctrl initialized
dma-pl330 f8003000.dmac: Loaded driver for PL330 DMAC-241330
dma-pl330 f8003000.dmac:    DBUFF-128x8bytes Num_Chans-8 Num_Peri-4 Num_Events-16
brd: module loaded
loop: module loaded
spi_master spi0: cannot find modalias for /amba/spi@e000d000/flash@0
spi_master spi0: Failed to create SPI device for /amba/spi@e000d000/flash@0
libphy: Fixed MDIO Bus: probed
tun: Universal TUN/TAP device driver, 1.6
CAN device driver interface
libphy: MACB_mii_bus: probed
RTL8211E Gigabit Ethernet e000b000.ethernet-ffffffff:01: attached PHY driver [RTL8211E Gigabit Ethernet] (mii_bus:phy_addr=e000b000.ethernet-ffffffff:01, irq=POLL)
macb e000b000.ethernet eth0: Cadence GEM rev 0x00020118 at 0xe000b000 irq 28 (00:18:3e:02:89:52)
e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci-pci: EHCI PCI platform driver
usbcore: registered new interface driver cdc_acm
cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
usbcore: registered new interface driver cdc_wdm
usbcore: registered new interface driver usb-storage
usbcore: registered new interface driver usbserial_generic
usbserial: USB Serial support registered for generic
usbcore: registered new interface driver usb_serial_simple
usbserial: USB Serial support registered for carelink
usbserial: USB Serial support registered for zio
usbserial: USB Serial support registered for funsoft
usbserial: USB Serial support registered for flashloader
usbserial: USB Serial support registered for google
usbserial: USB Serial support registered for libtransistor
usbserial: USB Serial support registered for vivopay
usbserial: USB Serial support registered for moto_modem
usbserial: USB Serial support registered for motorola_tetra
usbserial: USB Serial support registered for novatel_gps
usbserial: USB Serial support registered for hp4x
usbserial: USB Serial support registered for suunto
usbserial: USB Serial support registered for siemens_mpi
chipidea-usb2 e0002000.usb: e0002000.usb supply vbus not found, using dummy regulator
ULPI transceiver vendor/product ID 0x0424/0x0007
Found SMSC USB3320 ULPI transceiver.
ULPI integrity check: passed.
i2c /dev entries driver
cdns-i2c e0004000.i2c: 100 kHz mmio e0004000 irq 22
cdns-i2c e0005000.i2c: 100 kHz mmio e0005000 irq 23
cdns-wdt f8005000.watchdog: Xilinx Watchdog Timer with timeout 10s
device-mapper: ioctl: 4.41.0-ioctl (2019-09-16) initialised: dm-devel@redhat.com
EDAC MC: ECC not enabled
Xilinx Zynq CpuIdle Driver started
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
sdhci-pltfm: SDHCI platform and OF driver helper
mmc0: SDHCI controller on e0100000.mmc [e0100000.mmc] using ADMA
ledtrig-cpu: registered to indicate activity on CPUs
clocksource: ttc_clocksource: mask: 0xffff max_cycles: 0xffff, max_idle_ns: 551318127 ns
timer #0 at (ptrval), irq=41
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
xlnk xlnk: Major 243
xlnk xlnk: xlnk driver loaded
xlnk xlnk: xlnk_pdev is not null
fpga_manager fpga0: Xilinx Zynq FPGA Manager registered
IPVS: Registered protocols (TCP, UDP)
IPVS: Connection hash table configured (size=4096, memory=32Kbytes)
IPVS: ipvs loaded.
IPVS: [rr] scheduler registered.
Initializing XFRM netlink socket
NET: Registered protocol family 10
Segment Routing with IPv6
sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
NET: Registered protocol family 17
can: controller area network core (rev 20170425 abi 9)
NET: Registered protocol family 29
can: raw protocol (rev 20170425)
can: broadcast manager protocol (rev 20170425 t)
can: netlink gateway (rev 20190810) max_hops=1
Registering SWP/SWPB emulation handler
mmc0: new high speed SDHC card at address 1234
mmcblk0: mmc0:1234 SA16G 14.4 GiB 
Loading compiled-in X.509 certificates
Btrfs loaded, crc32c=crc32c-generic
 mmcblk0: p1 p2
of-fpga-region fpga-full: FPGA Region probed
hctosys: unable to open rtc device (rtc0)
of_cfs_init
of_cfs_init: OK
cfg80211: Loading compiled-in X.509 certificates for regulatory database
cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
clk: Not disabling unused clocks
cfg80211: failed to load regulatory.db
ALSA device list:
  No soundcards found.
EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext4 filesystem) on device 179:2.
devtmpfs: mounted
Freeing unused kernel memory: 1024K
Run /sbin/init as init process
random: fast init done
systemd[1]: System time before build time, advancing clock.
systemd[1]: Failed to find module 'autofs4'
systemd[1]: systemd 245.4-4ubuntu3 running in system mode. (+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=hybrid)
systemd[1]: Detected architecture arm.

Welcome to PynqLinux, based on Ubuntu 20.04!

systemd[1]: Set hostname to <pynq>.
systemd[1]: /lib/systemd/system/dbus.socket:5: ListenStream= references a path below legacy directory /var/run/, updating /var/run/dbus/system_bus_socket → /run/dbus/system_bus_socket; please update the unit file accordingly.
random: systemd: uninitialized urandom read (16 bytes read)
systemd[1]: Created slice system-getty.slice.
[  OK  ] Created slice system-getty.slice.
random: systemd: uninitialized urandom read (16 bytes read)
systemd[1]: Created slice system-modprobe.slice.
[  OK  ] Created slice system-modprobe.slice.
random: systemd: uninitialized urandom read (16 bytes read)
systemd[1]: Created slice system-serial\x2dgetty.slice.
[  OK  ] Created slice system-serial\x2dgetty.slice.
systemd[1]: Created slice User and Session Slice.
[  OK  ] Created slice User and Session Slice.
systemd[1]: Started Dispatch Password Requests to Console Directory Watch.
[  OK  ] Started Dispatch Password …ts to Console Directory Watch.
systemd[1]: Started Forward Password Requests to Wall Directory Watch.
[  OK  ] Started Forward Password R…uests to Wall Directory Watch.
systemd[1]: Condition check resulted in Arbitrary Executable File Formats File System Automount Point being skipped.
systemd[1]: Reached target Local Encrypted Volumes.
[  OK  ] Reached target Local Encrypted Volumes.
systemd[1]: Reached target Remote File Systems.
[  OK  ] Reached target Remote File Systems.
systemd[1]: Reached target Slices.
[  OK  ] Reached target Slices.
systemd[1]: Listening on Syslog Socket.
[  OK  ] Listening on Syslog Socket.
systemd[1]: Listening on initctl Compatibility Named Pipe.
[  OK  ] Listening on initctl Compatibility Named Pipe.
systemd[1]: Condition check resulted in Journal Audit Socket being skipped.
systemd[1]: Listening on Journal Socket (/dev/log).
[  OK  ] Listening on Journal Socket (/dev/log).
systemd[1]: Listening on Journal Socket.
[  OK  ] Listening on Journal Socket.
systemd[1]: Listening on udev Control Socket.
[  OK  ] Listening on udev Control Socket.
systemd[1]: Listening on udev Kernel Socket.
[  OK  ] Listening on udev Kernel Socket.
systemd[1]: Condition check resulted in Huge Pages File System being skipped.
systemd[1]: Mounting POSIX Message Queue File System...
         Mounting POSIX Message Queue File System...
systemd[1]: Mounting Kernel Debug File System...
         Mounting Kernel Debug File System...
systemd[1]: Condition check resulted in Kernel Trace File System being skipped.
systemd[1]: Starting Journal Service...
         Starting Journal Service...
systemd[1]: Starting Restore / save the current clock...
         Starting Restore / save the current clock...
systemd[1]: Condition check resulted in Create list of static device nodes for the current kernel being skipped.
systemd[1]: Condition check resulted in Load Kernel Module drm being skipped.
systemd[1]: Started Nameserver information manager.
[  OK  ] Started Nameserver information manager.
systemd[1]: Reached target Network (Pre).
[  OK  ] Reached target Network (Pre).
systemd[1]: Condition check resulted in Set Up Additional Binary Formats being skipped.
systemd[1]: Starting Load Kernel Modules...
         Starting Load Kernel Modules...
systemd[1]: Starting Remount Root and Kernel File Systems...
         Starting Remount Root and Kernel File Systems...
systemd[1]: Starting udev Coldplug all Devices...
         Starting udev Coldplug all Devices...
systemd[1]: Mounted POSIX Message Queue File System.
[  OK  ] Mounted POSIX Message Queue File System.
systemd[1]: Mounted Kernel Debug File System.
[  OK  ] Mounted Kernel Debug File System.
systemd[1]: Finished Restore / save the current clock.
[  OK  ] Finished Restore / save the current clock.
systemd[1]: Finished Load Kernel Modules.
[  OK  ] Finished Load Kernel Modules.
systemd[1]: Finished Remount Root and Kernel File Systems.
[  OK  ] Finished Remount Root and Kernel File Systems.
systemd[1]: Started Journal Service.
[  OK  ] Started Journal Service.
         Activating swap /var/swap...
         Mounting Kernel Configuration File System...
         Starting Flush Journal to Persistent Storage...
         Starting Load/Save Random Seed...
         Starting Apply Kernel Variables...
systemd-journald[122]: Received client request to flush runtime journal.
         Starting Create System Users...
systemd-journald[122]: File /var/log/journal/236dbcc4a6dba1caa1d5d5bc61955d45/system.journal corrupted or uncleanly shut down, renaming and replacing.
[  OK  ] Mounted Kernel Configuration File System.
Adding 524284k swap on /var/swap.  Priority:-2 extents:1 across:524284k SS
[  OK  ] Activated swap /var/swap.
[  OK  ] Finished udev Coldplug all Devices.
[  OK  ] Reached target Swap.
         Starting Helper to synchronize boot up for ifupdown...
[  OK  ] Finished Apply Kernel Variables.
[  OK  ] Finished Create System Users.
         Starting Create Static Device Nodes in /dev...
[  OK  ] Finished Flush Journal to Persistent Storage.
[  OK  ] Finished Create Static Device Nodes in /dev.
[  OK  ] Reached target Local File Systems (Pre).
[  OK  ] Reached target Local File Systems.
         Starting Enable support fo…l executable binary formats...
         Starting Create Volatile Files and Directories...
         Starting udev Kernel Device Manager...
[  OK  ] Finished Enable support fo…nal executable binary formats.
[  OK  ] Finished Create Volatile Files and Directories.
         Starting Network Name Resolution...
         Starting Network Time Synchronization...
         Starting Update UTMP about System Boot/Shutdown...
[  OK  ] Finished Update UTMP about System Boot/Shutdown.
[  OK  ] Started udev Kernel Device Manager.
uio_pdrv_genirq 43c00000.audio-codec-ctrl: IRQ index 0 not found
[  OK  ] Found device /dev/ttyPS0.
zocl-drm amba:zyxclmm_drm: IRQ index 0 not found
[  OK  ] Started Network Time Synchronization.
[  OK  ] Finished Helper to synchronize boot up for ifupdown.
[  OK  ] Started Network Name Resolution.
[  OK  ] Finished Load/Save Random Seed.
[  OK  ] Reached target Host and Network Name Lookups.
[  OK  ] Reached target System Time Set.
[  OK  ] Reached target System Time Synchronized.
[  OK  ] Started Entropy daemon using the HAVEGE algorithm.
[  OK  ] Reached target System Initialization.
[  OK  ] Started resolvconf-pull-resolved.path.
[  OK  ] Started Daily apt download activities.
[  OK  ] Started Daily apt upgrade and clean activities.
[  OK  ] Started Periodic ext4 Onli…ata Check for All Filesystems.
[  OK  ] Started Discard unused blocks once a week.
[  OK  ] Started Daily rotation of log files.
[  OK  ] Started Daily man-db regeneration.
[  OK  ] Started Message of the Day.
[  OK  ] Started Daily Cleanup of Temporary Directories.
[  OK  ] Reached target Paths.
[  OK  ] Reached target Timers.
[  OK  ] Listening on Avahi mDNS/DNS-SD Stack Activation Socket.
[  OK  ] Listening on D-Bus System Message Bus Socket.
[  OK  ] Listening on UUID daemon activation socket.
[  OK  ] Reached target Sockets.
[  OK  ] Reached target Basic System.
         Starting LSB: automatic crash report generation...
         Starting Avahi mDNS/DNS-SD Stack...
[  OK  ] Started Regular background program processing daemon.
[  OK  ] Started D-Bus System Message Bus.
         Starting Network Manager...
[  OK  ] Started Save initial kernel messages after boot.
         Starting Remove Stale Onli…t4 Metadata Check Snapshots...
[  OK  ] Started ifup for eth0.
         Starting Jupyter Notebook Server...
         Starting LSB: Load kernel …d to enable cpufreq scaling...
         Starting Dispatcher daemon for systemd-networkd...
         Starting Raise network interfaces...
[  OK  ] Started Set the CPU Frequency Scaling governor.
         Starting PYNQ PL Server...
         Starting Authorization Manager...
         Starting Restore /etc/reso… the ppp link was shut down...
         Starting Resize Filesystem on SD card...
         Starting resolvconf-pull-resolved.service...
         Starting System Logging Service...
         Starting Login Service...
[  OK  ] Started PYNQ PL Server.
[  OK  ] Finished Restore /etc/reso…re the ppp link was shut down.
[  OK  ] Finished Resize Filesystem on SD card.
[  OK  ] Started System Logging Service.
[  OK  ] Started LSB: automatic crash report generation.
[  OK  ] Started Avahi mDNS/DNS-SD Stack.
[  OK  ] Started Network Manager.
         Starting Network Manager Wait Online...
[  OK  ] Started LSB: Load kernel m…ded to enable cpufreq scaling.
         Starting LSB: set CPUFreq kernel parameters...
         Starting Hostname Service...
[  OK  ] Started Authorization Manager.
[  OK  ] Finished resolvconf-pull-resolved.service.
         Starting Modem Manager...
[  OK  ] Started LSB: set CPUFreq kernel parameters.
[  OK  ] Started Login Service.
[  OK  ] Started Modem Manager.
[  OK  ] Started Hostname Service.
[  OK  ] Started Dispatcher daemon for systemd-networkd.
         Starting Network Manager Script Dispatcher Service...
[  OK  ] Started Network Manager Script Dispatcher Service.
[  OK  ] Finished Network Manager Wait Online.
[  OK  ] Finished Remove Stale Onli…ext4 Metadata Check Snapshots.
         Stopping Network Name Resolution...
[  OK  ] Stopped Network Name Resolution.
         Starting Network Name Resolution...
[  OK  ] Started Network Name Resolution.
         Starting resolvconf-pull-resolved.service...
[  OK  ] Finished resolvconf-pull-resolved.service.
[  OK  ] Finished Raise network interfaces.
[  OK  ] Reached target Network.
[  OK  ] Reached target Network is Online.
[  OK  ] Started ISC DHCP IPv4 server.
[  OK  ] Started ISC DHCP IPv6 server.
         Starting Samba NMB Daemon...
         Starting OpenBSD Secure Shell server...
         Starting Permit User Sessions...
[  OK  ] Started Unattended Upgrades Shutdown.
[  OK  ] Finished Permit User Sessions.
[  OK  ] Started Getty on tty1.
[  OK  ] Started Serial Getty on ttyPS0.
[  OK  ] Reached target Login Prompts.

PYNQ Linux, based on Ubuntu 20.04 pynq ttyPS0

pynq login: xilinx (automatic login)

Welcome to PYNQ Linux, based on Ubuntu 20.04 (GNU/Linux 5.4.0-xilinx-v2020.2 armv7l)
Last login: Wed Nov 17 20:00:41 UTC 2021 on ttyPS0
xilinx@pynq:~$ 

  1. 2022年07月17日 04:43 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

Vivado 2022.1 でファイルを見ようとすると Initializing Language Saver プログレスバーが表示されてファイルが開かない

Windows10 の Vivado 2022.1 で Create HDL Wrapper で作成した Verilog ファイルを見ようとすると、Initializing Language Saver プログレスバーが表示されてファイルが開かないという現象が起きた。
Vivado_ILS_1_220716.png

なお、xdc ファイルも表示できなかった。

解決策が無いか?検索していると、Vivado 2021.1 だが、”Vivado2021.1でinitializing language server がスタックする問題について”が検索できた。

回避策 1 をやってみる

C:\Users\AppData\Roaming\Xilinx\Vivado\tclapp\mainfest.tcl


Vivado_ILS_2_220716.png

Vivado を閉じて mainfest.tcl を消去して、もう一度 Vivado 2022.1 を起動して、ファイルを開こうとしたが、やはり、Initializing Language Saver プログレスバーが表示されてファイルが開かなかった。

解決策 2 をやってみる
Vivado 2022.1 の Tools -> Settings を選択する。
Vivado_ILS_3_220716.png

Settings ダイアログが表示された。
Tool Settings の Text Editor -> Syntax Checking をクリックする。
Syntax checking は Sigasi に設定されていた。
Vivado_ILS_4_220716.png

Syntax checking を Vivado に変更した。
Vivado_ILS_5_220716.png

OK ボタンをクリックすると、Vivado Settings ダイアログが表示された。
OK ボタンをクリックする。
Vivado_ILS_6_220716.png

これでファイルを開くと、同様に Initializing Language Saver プログレスバーが表示されてファイルが開かないという現象だった。

Vivado を閉じて、再度 Vivado 2022.1 を起動したら、今度は Verilog HDL ファイルを開くことができるようになった。
Vivado_ILS_7_220716.png
  1. 2022年07月16日 20:50 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20 で PYNQ を使用する1

ZYBO Z7 用の PYNQ を見つけたのでやってみようと思う。

ZYBO Z7 用の PYNQ は”Pynq 2.7 for Zybo-Z7”にあった。
dorfell さんという個人の人が作成した ZYBO Z7 用の PYNQ のようだ。

Pynq 2.7 for Zybo-Z7”の”Pynq 2.7 for Zybo-Z7 image”をクリックする。
ZYBO_Z7_PYNQ_1_220714.png

すると、Zybo-Z7-2.7.0.img がダウンロードできた。
ZYBO_Z7_PYNQ_2_220714.png

Zybo-Z7-2.7.0.img を balenaEthcher を起動して、16 GB の MicroSD カードに書き込む。
ZYBO_Z7_PYNQ_3_220714.png

MicroSD カードにイメージを書き込むと、PYNQ ドライブと root ドライブが生成された。
ZYBO_Z7_PYNQ_4_220714.png

ZYBO_Z7_PYNQ_5_220714.png

次は、作成された MicroSD カードを ZYBO Z7-20 に入れてブートしてみよう。
  1. 2022年07月15日 04:51 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

”Deploy Pretrained Vision Detection Model from Darknet on VTA”をやってみる2

”Deploy Pretrained Vision Detection Model from Darknet on VTA”をやってみる1”の続き。

Deploy Pretrained Vision Detection Model from Darknet on VTA”をやってみようということで、Darknet YoloV3-tiny 推論をVTAアクセラレータデザイン上で実行し、画像検出タスクを実行することができた。今回は、”Deploy Pretrained Vision Detection Model from Darknet on VTA”の記述を DeepL 翻訳で訳して、動作を少しは確認してみよう。

ダークネットで事前学習した視覚検出モデルをVTAに展開する
最初の文章を DeepL で翻訳して引用する。

このチュートリアルでは、Darknet YoloV3-tiny推論をVTAアクセラレータデザイン上で実行し、画像検出タスクを実行する方法について、エンドツーエンドデモを提供します。このチュートリアルでは、量子化(VTAはint8/32推論のみをサポート)とグラフパッキング(コアでのテンソル化を可能にするため)を行い、ハードウェアターゲット向けに計算グラフを調整するフロントエンドコンパイラとしてのRelayを紹介します。


pip3 で cffi と opencv-python をインストールする必要があるとのことだが、私の Ubuntu 18.04 にはインストールしてあったようでインストールする必要はなかった。
pip3 install cffi
pip3 install opencv-python


最初に deploy_detection.py のライセンス部分を示す。これから、deploy_detection.py の多用する。
TVM_VTA_175_220712.png

依存関係のインストール
インポートするパッケージを示す。
TVM_VTA_187_220714.png

モデル名からyolo netの設定ファイル、重みファイル、ダークネット・ライブラリ・ファイルのダウンロードを行う。
TVM_VTA_189_220714.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

cfg_path = /home/masaaki/.tvm_test_data/darknet/yolov3-tiny.cfg
weights_path = /home/masaaki/.tvm_test_data/darknet/yolov3-tiny.weights


ホーム・ディレクトリの .tvm_test_data/darknet ディレクトリにファイルが生成されていた。
TVM_VTA_190_220714.png

YOLO のカテゴリー名の coco.name と arial.ttf をダウンロード
TVM_VTA_191_220714.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

coco_path = /home/masaaki/.tvm_test_data/data/coco.names
font_path = /home/masaaki/.tvm_test_data/data/arial.ttf


ホーム・ディレクトリの .tvm_test_data/data ディレクトリにファイルが生成されていた。
TVM_VTA_192_220714.png

プラットフォームとモデル・ターゲットの定義
TVM_VTA_193_220714.png

リモート実行の取得
ターゲットが'pynq'または他のFPGAバックエンドの場合、FPGAとランタイムを再設定する。それ以外の場合、ターゲットが 'sim' であれば、ローカルに実行する。
TVM_VTA_194_220714.png

推論グラフ・エクゼキュータの構築
DeepL 翻訳を引用する。

Gluon model zooからVisionモデルを取得し、Relayでコンパイルします。コンパイルの手順は

1. フロントエンドはMxNetからRelayモジュールに変換。

2. 8ビット量子化の適用:ここでは、CPUのfp32で実行される最初のconv層とdense層をスキップしています。

3. グラフパッキングを行い、テンソル化するためのデータレイアウトを変更する。

4. 定数折りたたみを行い、演算子の数を減らす(例:バッチノルム乗算をなくす)。

5. オブジェクトファイルへのリレービルドを行う。

6. オブジェクトファイルをリモート(FPGAデバイス)にロードする。

7. グラフエクゼキュータmを生成する。


TVM_VTA_195_220714.png
TVM_VTA_196_220714.png

画像検出の推論の実行
テスト画像をダウンロードし、画像に対して推論を実行する。
TVM_VTA_197_220714.png
TVM_VTA_198_220714.png

ターミナルのログを貼っておく。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/pynq/test_program_rpc.py
(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/integration/deploy_detection.py 
cfg_path = /home/masaaki/.tvm_test_data/darknet/yolov3-tiny.cfg
weights_path = /home/masaaki/.tvm_test_data/darknet/yolov3-tiny.weights
coco_path = /home/masaaki/.tvm_test_data/data/coco.names
font_path = /home/masaaki/.tvm_test_data/data/arial.ttf
Reconfigured FPGA and RPC runtime in 3.17s!
/media/masaaki/Ubuntu_Disk/DNN/tvm/python/tvm/driver/build_module.py:263: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  warnings.warn(
[04:32:33] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:33] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:33] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:33] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:32:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
yolov3-tiny inference graph built in 19.06s!

Performed inference in 658.92ms (std = 0.37) for 1 samples
Average per sample inference time: 658.92ms

  1. 2022年07月14日 05:03 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”FPGAの部屋 プレゼンツ Vitis HLS スタートアップ”が開催されます

FPGAの部屋 プレゼンツ Vitis HLS スタートアップ”が開催されます。参加費用は無料です。

開催日 :8月3日 午後1時から午後5時(予定)
費 用 :無償
講 師 :「FPGAの部屋」小野 講師
開催方法:Webex Meetingを使用したオンライン開催


Vitis HLS の概要を解説して、Vitis HLS のデモを実行しながら、基本的な Vitis HLS の使い方を解説していく予定です。
参考になれば幸いです。

一番使用する AXI4-Master インターフェース編と AXI4-Stream インターフェース編は無いですが、Vitis HLS の雰囲気が味わって頂けると思います。こちらは、9 月に有料セミナーを実施する予定なので、そちらでどうぞ。
  1. 2022年07月13日 03:32 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

”Deploy Pretrained Vision Detection Model from Darknet on VTA”をやってみる1

Deploy Pretrained Vision Detection Model from Darknet on VTA”をやってみよう。

Deploy Pretrained Vision Detection Model from Darknet on VTA”は Darknet YoloV3-tiny 推論をVTAアクセラレータデザイン上で実行し、画像検出タスクを実行する。

Deploy Pretrained Vision Detection Model from Darknet on VTA”から deploy_detection.py をダウンロードした。
TVM_VTA_181_220712.png

ホスト・パソコンの tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export/pynq/0_0_2 ディレクトリ に tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_1x16_i8w8a32_15_15_18_17/export/vta.bit をコピーして、1x16_i8w8a32_15_15_18_17.bit に名前を変更済みだ。

ホスト・パソコンで、VTA_CACHE_PATH はすでに設定してある。
export VTA_CACHE_PATH=/media/masaaki/Ubuntu_Disk/DNN/tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export

ホスト・パソコンで環境変数を設定するのだが、すでに設定されているので、やっていない。(ディレクトリは tvm)
export PYTHONPATH=$PYTHONPATH:/media/masaaki/Ubuntu_Disk/DNN/tvm/python:/media/masaaki/Ubuntu_Disk/DNN/tvm/vta/python
export VTA_RPC_HOST=192.168.3.31
export VTA_RPC_PORT=9091

PYNQ-Z1 の ~/tvm ディレクトリで RPC サーバーを起動する。
sudo ./apps/vta_rpc/start_rpc_server.sh

ホスト・パソコン(Ubuntu 18.04 LTS)で test_program_rpc.py を起動した。
python3 vta/tests/python/pynq/test_program_rpc.py

ホスト・パソコンで deploy_detection.py を実行した。
python3 vta/tests/python/integration/deploy_detection.py

deploy_detection.py を実行すると、犬と人間と馬の画像が表示されたが、それを閉じても””Deploy Pretrained Vision Model from MxNet on VTA”をやってみる1”と同様にソフトウェアが進まなくなった。
そこで、deploy_detection.py の 265, 266 行目をコメントアウトした。
これでもう一度、deploy_detection.py を実行した。
TVM_VTA_183_220712.png
TVM_VTA_184_220712.png

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/integration/deploy_detection.py 
Reconfigured FPGA and RPC runtime in 2.88s!
/media/masaaki/Ubuntu_Disk/DNN/tvm/python/tvm/driver/build_module.py:263: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  warnings.warn(
[04:24:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:31] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:31] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:31] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:31] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:32] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:24:32] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
yolov3-tiny inference graph built in 18.91s!

Performed inference in 660.54ms (std = 2.14) for 1 samples
Average per sample inference time: 660.54ms


画像検出結果が表示された。
TVM_VTA_185_220712.png

PYNQ-Z1 の表示を示す。
TVM_VTA_186_220712.png

xilinx@pynq:~$ cd tvm
xilinx@pynq:~/tvm$ sudo ./apps/vta_rpc/start_rpc_server.sh
INFO:RPCServer:bind to 0.0.0.0:9091
INFO:RPCServer:connection from ('192.168.3.10', 43720)
INFO:root:Program FPGA with 1x16_i8w8a32_15_15_18_17.bit 
INFO:RPCServer:Finish serving ('192.168.3.10', 43720)
INFO:RPCServer:connection from ('192.168.3.10', 43722)
INFO:root:Skip reconfig_runtime due to same config.
INFO:RPCServer:Finish serving ('192.168.3.10', 43722)
INFO:RPCServer:connection from ('192.168.3.10', 43724)
INFO:root:Skip reconfig_runtime due to same config.
INFO:root:Program FPGA with 1x16_i8w8a32_15_15_18_17.bit 
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmp9vv5ioxf/graphlib.tar

  1. 2022年07月13日 03:22 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Deploy Pretrained Vision Model from MxNet on VTA”をやってみる2

”Deploy Pretrained Vision Model from MxNet on VTA”をやってみる1”の続き。

前回は、”Deploy Pretrained Vision Model from MxNet on VTA” からダウンロードした deploy_classification.py を実行して成功した。今回は、”Deploy Pretrained Vision Model from MxNet on VTA” の記述を DeepL 翻訳で訳して、動作を少しは確認してみよう。

最初の文章を DeepL で翻訳して引用する。

このチュートリアルでは、ImageNet分類推論をVTAアクセラレータ上で実行し、ImageNet分類タスクを実行する方法について、エンドツーエンド・デモを提供します。このチュートリアルでは、量子化(VTAはint8/32推論のみをサポート)とグラフパッキング(コアでのテンソル化を可能にするため)を行い、ハードウェアターゲットに合わせた計算グラフを作成するフロントエンドコンパイラとしてRelayが紹介されています。


次は pip3 で mxnet をインストールしているようだ。やはり、mxnet をインストールする必要があるようだ。

deploy_classification.py のコードを引用していく。deploy_classification.py のライセンスを貼っておく。
TVM_VTA_175_220712.png

依存関係のインストール
argparse, json, os, requests, sys, time や mxnet, tvm, vta などのライブラリを呼び出している。
TVM_VTA_173_220712.png

プラットフォームとモデルのターゲットの定義
resnet18_v1 から resnet101_v2 のパラメータを pack_dict ディクショナリに登録する。
resnet18_v1 モデルを選択した。
TVM_VTA_174_220712.png

実行リモートの取得
ターゲットが'pynq'の場合、FPGAとランタイムを再設定する。それ以外の場合、ターゲットが 'sim' であれば、ローカルに実行するそうだ。
TVM_VTA_176_220712.png

推論グラフエクゼキュータの構築
DeepL 翻訳を引用する。

Gluon model zooからVisionモデルを取得し、Relayでコンパイルします。コンパイルの手順は

1. フロントエンドはMxNetからRelayモジュールに変換。

2. 8ビット量子化の適用:ここでは、CPUのfp32で実行される最初のconv層とdense層をスキップしています。

3. グラフパッキングを行い、テンソル化するためのデータレイアウトを変更する。

4. 定数折りたたみを行い、演算子の数を減らす(例:バッチノルム乗算をなくす)。

5. オブジェクトファイルへのリレービルドを行う。

6. オブジェクトファイルをリモート(FPGAデバイス)にロードする。

7. グラフエクゼキュータmを生成する。


TVM_VTA_177_220712.png
TVM_VTA_178_220712.png

画像分類の推論の実行
ImageNetの画像サンプルに対して分類を行う。カテゴリファイル、synset.txt、入力テスト画像をダウンロードするだけだそうだ。
TVM_VTA_179_220712.png
TVM_VTA_180_220712.png

結果を下に示す。

resnet18_v1 inference graph built in 26.26s!

Performed inference in 408.14ms (std = 2.18) for 1 samples
Average per sample inference time: 408.14ms

resnet18_v1 prediction for sample 0
    #1: tiger cat
    #2: Egyptian cat
    #3: tabby, tabby cat
    #4: lynx, catamount
    #5: weasel

  1. 2022年07月12日 04:10 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Deploy Pretrained Vision Model from MxNet on VTA”をやってみる1

Deploy Pretrained Vision Model from MxNet on VTA”をやってみよう。今回は、普通に”Deploy Pretrained Vision Model from MxNet on VTA” からダウンロードした deploy_classification.py を実行してみよう。

Deploy Pretrained Vision Model from MxNet on VTA”から deploy_classification.py をダウンロードし、tvm/vta/tests/python/integration ディレクトリにセーブした。
TVM_VTA_172_220711.png

ホスト・パソコンの tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export/pynq/0_0_2 ディレクトリ に tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_1x16_i8w8a32_15_15_18_17/export/vta.bit をコピーして、1x16_i8w8a32_15_15_18_17.bit に名前を変更済みだ。

ホスト・パソコンで、VTA_CACHE_PATH はすでに設定してある。
export VTA_CACHE_PATH=/media/masaaki/Ubuntu_Disk/DNN/tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export

ホスト・パソコンで環境変数を設定するのだが、すでに設定されているので、やっていない。(ディレクトリは tvm)
export PYTHONPATH=$PYTHONPATH:/media/masaaki/Ubuntu_Disk/DNN/tvm/python:/media/masaaki/Ubuntu_Disk/DNN/tvm/vta/python
export VTA_RPC_HOST=192.168.3.31
export VTA_RPC_PORT=9091

PYNQ-Z1 の ~/tvm ディレクトリで RPC サーバーを起動する。
sudo ./apps/vta_rpc/start_rpc_server.sh

ホスト・パソコン(Ubuntu 18.04 LTS)で test_program_rpc.py を起動した。
python3 vta/tests/python/pynq/test_program_rpc.py

ホスト・パソコンで deploy_classification.py を実行した。
python3 vta/tests/python/integration/deploy_classification.py
結果はエラーで原因は mxnet モジュールが無いということだった。
TVM_VTA_167_220710.png

pip3 で mxnet モジュールをインストールする。
pip3 install mxnet
TVM_VTA_168_220710.png

もう一度、ホスト・パソコンで deploy_classification.py を実行した。
python3 vta/tests/python/integration/deploy_classification.py
TVM_VTA_169_220710.png

ここで、ウインドウが表示されて、猫の写真が表示された。
TVM_VTA_170_220710.png

その後は何も実行されなかった。猫のウインドウを消しても何も進まない。
実行ログを示す。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/integration/deploy_classification.py 
Reconfigured FPGA and RPC runtime in 2.89s!
Downloading /home/masaaki/.mxnet/models/resnet18_v1-a0666292.zipefe2e9c7-23b8-4e5f-9eb8-62f6771a59a7 from https://apache-mxnet.s3-accelerate.dualstack.amazonaws.com/gluon/models/resnet18_v1-a0666292.zip...
/media/masaaki/Ubuntu_Disk/DNN/tvm/python/tvm/driver/build_module.py:263: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  warnings.warn(
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:36] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:36] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
[04:08:36] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
vta/tests/python/integration/deploy_classification.py:212: DeprecationWarning: legacy graph executor behavior of producing json / lib / params will be removed in the next release. Please see documents of tvm.contrib.graph_executor.GraphModule for the  new recommended usage.
  graph, lib, params = relay.build(
resnet18_v1 inference graph built in 27.19s!


deploy_classification.py の猫のウインドウ表示部分をコメントアウトした。
253 行目と 254 行目をコメントアウトした。
TVM_VTA_171_220710.png

これで、ホスト・パソコンで deploy_classification.py を実行した。
python3 vta/tests/python/integration/deploy_classification.py
TVM_VTA_172_220710.png

tiger cat と判定された。

resnet18_v1 inference graph built in 26.26s!

Performed inference in 408.14ms (std = 2.18) for 1 samples
Average per sample inference time: 408.14ms

resnet18_v1 prediction for sample 0
    #1: tiger cat
    #2: Egyptian cat
    #3: tabby, tabby cat
    #4: lynx, catamount
    #5: weasel

  1. 2022年07月11日 05:00 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Simple Matrix Multiply”をやってみる4

”Simple Matrix Multiply”をやってみる3”の続き。

Simple Matrix Multiply”のベクトル乗算をやってみるということで、前回は、”Simple Matrix Multiply”の”行列の乗算”から”テンソル化”までを書いた。今回は、”TVMコンパイル”、”関数の実行”、”正しさの検証”を行った。

TVM コンパイル
スケジュールが終わったので、TVM 関数にコンパイルする。
TVM_VTA_164_220710.png

関数の実行
コンパイルされたTVM関数は、簡潔なC APIを使用しており、どの言語からも呼び出すことができるそうだ。
TVMはpythonで配列のAPIを提供し、迅速なテストとプロトタイピングを支援します。この配列APIはDLPack標準に基づいているそうだ。

モジュールを実行する手順
1. リモート・コンテキストを作成する(Pynq でもリモート実行用)
2. tvm.nd.array でデータをフォーマットする
3. f() で計算を実行する
4. numpy()は結果の配列を解釈可能な形式にコピーして返す


TVM_VTA_165_220710.png

正しさの検証
numpyで乗算を計算し、VTA の行列の乗算の出力が本当に正しいかどうかを検証する。
TVM_VTA_166_220710.png

Successful matrix multiply test!

と表示された。乗算は正しい。

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

C_nd.numpy().shape = (1, 16, 1, 16)
[[[[ -98   45 -126    8  101   -6 -124   82  -19  -39   47   53  -74
     -76   -4   84]]

  [[ 120  -69 -106   89 -121   -3  125  103  -51   61  -42  -54  127
     -80 -103   -1]]

  [[  17  103   63   -8 -126    9  -79 -112 -118   17  104  -14  -69
      62 -100  -38]]

  [[ 125  -82   95  115   27    0  -19   21   -8  -28   35  101 -109
     -27  -72 -123]]

  [[  72  -26   34  101  -64   29  -83    8   23  -62  111   52 -117
     -46   50 -118]]

  [[  58  -47 -113   62   29  -78 -101   62 -116  -25   22  -84   37
     -40  -65    4]]

  [[-109   52  -33 -114 -118  -93  106   73  102 -122  -88  -98   64
     -44  -36  -52]]

  [[  84   33  -17  -19  -71  104   67    7 -102   90   91    8 -111
       4  -91   48]]

  [[ -20  116   79   41    8    8   62  -71  -64  -25  -78   13  -72
     -75  -88  -56]]

  [[-110   11  -38  -58  -77  -34   42   69   98  -51  -95  -53  -21
      75  -81    3]]

  [[  78  102   91  -73  -69  -47  -86   16  122   91 -105   -8  106
      37   82 -103]]

  [[ -87   84  116  -25  -64   67  -70   85   36   -3   65   59   14
      26   93  -16]]

  [[  11  -37 -104   -5   43  -94  -78  -71   37  -44  -37 -103  -34
     110   84  -83]]

  [[ 109   81   63   65  -44  122  -77  -57  -24  -72   -4  -99   95
     -26   86   46]]

  [[  92 -127  -55   -1  -46  -79  -18  114   46   64   55  -90  -83
     -93  -79  -77]]

  [[ -32  -31    8   21  -43  -71   50 -126   59   63   69   43  -78
     112   18  116]]]]

  1. 2022年07月10日 03:51 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Simple Matrix Multiply”をやってみる3

”Simple Matrix Multiply”をやってみる2”の続き。

Simple Matrix Multiply”のベクトル乗算をやってみるということで、前回は、”Simple Matrix Multiply”に沿って 1 つ 1 つコードを見ながら実行することにした。”RPC 設定”から”データのレイアウト”までを書いた。今回は、”行列の乗算”から”テンソル化”までを書いた。

なお、翻訳には DeepL 翻訳を使用している。

行列の乗算
DeepL 翻訳を貼っておく。

これで行列の乗算の結果テンソルCを別の計算操作で記述する準備が整った。計算関数はテンソルの形と、テンソルの各位置の計算規則を記述したラムダ関数を受け取る。

行列の乗算を実装するために、ラムダ関数には入力チャンネルの次元軸に対する縮小式が必要である。削減式を作成するには,te.reduce_axisで削減軸を宣言し,削減範囲を取り込みます.te.sumは削減する式と削減軸を取り込み,宣言した範囲内のすべてのkに対する値の総和を計算します.

このリダクションは32ビットenv.acc_dtypeアキュムレータデータ型に対して実行される必要があることに注意してください。

このフェーズでは,計算をどのように行うかを宣言しているだけなので,計算は行われません.


TVM_VTA_157_220709.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

C_buf = Tensor(shape=[1, 16, 1, 16], op.name=C_buf)


結果のキャスト
乗算が終了したら、VTA で計算した結果をメイン・メモリに転送する。
入力活性化データ型(env.inp_dtype)へのタイプ・キャストを行う。
計算宣言部分は終了。
TVM_VTA_158_220709.png

計算のスケジューリング
TVM ではスケジュールという計算の実装をする必要がある。
DeepL 翻訳を貼っておく。

スケジュールとは、元の計算に対する変換の集合であり、正しさに影響を与えることなく計算の実装を変換するものである。この簡単なVTAプログラミングのチュートリアルは、元のスケジュールをVTAハードウェアプリミティブにマップダウンする基本的なスケジュール変換を示すことを目的としています。


デフォルトのスケジュール
スケジュール構築後、デフォルトでの C を計算するスケジュールを示す。
TVM_VTA_160_220709.png

@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int8), int8, [256], []),
             B: Buffer(B_2: Pointer(int8), int8, [65536], []),
             C: Buffer(C_2: Pointer(int8), int8, [256], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int8, [1, 16, 1, 16], []), B_1: B_3: Buffer(B_2, int8, [16, 16, 16, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 16, 1, 16], [])} {
  allocate(A_buf: Pointer(global int8), int8, [256]), storage_scope = global;
  allocate(B_buf: Pointer(global int8), int8, [65536]), storage_scope = global;
  allocate(C_buf: Pointer(global int32), int32, [256]), storage_scope = global {
    for (i1: int32, 0, 16) {
      for (i3: int32, 0, 16) {
        let cse_var_1: int32 = ((i1*16) + i3)
        A_buf_1: Buffer(A_buf, int8, [256], [])[cse_var_1] = A[cse_var_1]
      }
    }
    for (i0: int32, 0, 16) {
      for (i1_1: int32, 0, 16) {
        for (i2: int32, 0, 16) {
          for (i3_1: int32, 0, 16) {
            let cse_var_2: int32 = ((((i0*4096) + (i1_1*256)) + (i2*16)) + i3_1)
            B_buf_1: Buffer(B_buf, int8, [65536], [])[cse_var_2] = B[cse_var_2]
          }
        }
      }
    }
    for (co: int32, 0, 16) {
      for (ci: int32, 0, 16) {
        C_buf_1: Buffer(C_buf, int32, [256], [])[((co*16) + ci)] = 0
        for (ko: int32, 0, 16) {
          for (ki: int32, 0, 16) {
            let cse_var_3: int32 = ((co*16) + ci)
            C_buf_1[cse_var_3] = (C_buf_1[cse_var_3] + (cast(int32, A_buf_1[((ko*16) + ki)])*cast(int32, B_buf_1[((((co*4096) + (ko*256)) + (ci*16)) + ki)])))
          }
        }
      }
    }
    for (i1_2: int32, 0, 16) {
      for (i3_2: int32, 0, 16) {
        let cse_var_4: int32 = ((i1_2*16) + i3_2)
        C[cse_var_4] = cast(int8, C_buf_1[cse_var_4])
      }
    }
  }
}


DeepL 翻訳を貼っておく。

このスケジュールは理にかなっていますが、VTAにコンパイルすることはできません。正しいコード生成のためには、スケジューリングプリミティブとコードアノテーションを適用して、スケジュールをVTAのハードウェアイントリニックスに直接落とせるようなものに変換する必要があるのです。それらは以下の通りです。

・DMAコピーオペレーションは、グローバルにスコープされたテンソルを受け取り、それをローカルにスコープされたテンソルにコピーする。

・行列の乗算を実行するテンソル演算。


バッファのスコープ
バッファのスコープを設定して、バッファが VTA のオンチップ SRAM キャッシュに格納されることを TVM に通知する。
A_buf が VTA のオンチップ入力、B_buf が VTA のオンチップ重み、C_buf が VTA のオンチップ・アキュムレータ・メモリに格納されることを TVM に通知する。

DeepL 翻訳を貼っておく。

VTAのオンチップSRAM

VTAは3種類のメモリスコープを持ち、それぞれが異なるオンチップSRAMバッファに対応しています。

env.inp_scope : 入力バッファ。env.inp_dtype型の形状(env.BATCH, env.BLOCK_IN)の入力マトリクスを格納するリードオンリーのSRAMバッファです。入力バッファには、2 ^ LOG_INP_BUFF_SIZE行列要素(vta_config.jsonファイルで指定されたもの)が格納されます。

env.wgt_scope : env.wgt_dtype 型の形状 (env.BLOCK_OUT, env.BLOCK_IN) のウェイト行列を格納する読み込み専用の SRAM バッファです。ウェイトバッファは2 ^ LOG_WGT_BUFF_SIZE行列要素を含みます。

env.acc_scope : env.acc_dtype 型の形状 (env.BATCH, env.BLOCK_OUT) のアキュムレータ行列を格納するリード/ライト SRAM バッファです。アキュムレータバッファはVTAの汎用レジスタファイルであり,畳み込みや行列の乗算の中間結果や,プーリング,バッチ正規化,活性化レイヤの中間結果などを保持します.アキュムレータバッファは、2 ^ LOG_ACC_BUFF_SIZE の行列要素を含みます。


TVM_VTA_161_220709.png

DMA 転送
DRAMのデータを VTA のオンチップ・バッファに転送するために DMA 転送のスケジュールを組む。
これは、行列の乗算を実行する計算ループにバッファのコピーをネストするcompute_atスケジュールプリミティブを使用して実現することができるそうだ。
dma_copy プラグマを挿入して、コピー操作が DMA 転送で実行されることをコンパイラに示す。
TVM_VTA_162_220709.png

テンソル化
DeepL 翻訳を貼っておく。

スケジュール変換の最後のステップは、スケジュールにテンソル化を適用することである。テンソル化はベクトル化に類似しているが、その概念をより高次元の計算単位に拡張するものである。その結果、テンソル化はデータレイアウトの入力プレースホルダーを宣言するときに説明したように、データレイアウトの制約を課すことになる。我々はすでにテンソルをタイル状に配置したので、次に行うべきことはテンソル化に対応するためのループの再順序付けである。

ここでは、一番外側の縮小軸をずっと外側に移動することにした。このため、まず入力チャネル、次にバッチ次元、最後に出力チャネルを反復処理することになる。最後に、テンソル化スケジューリングプリミティブtensorizeを、最内周の行列乗算テンソルブロックの外軸に沿って適用する。最終的なスケジュールはVTAランタイムJITコンパイラによるコード生成に対応できるように出力される。


TVM_VTA_163_220709.png

@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int8), int8, [256], []),
             B: Buffer(B_2: Pointer(int8), int8, [65536], []),
             C: Buffer(C_2: Pointer(int8), int8, [256], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int8, [1, 16, 1, 16], []), B_1: B_3: Buffer(B_2, int8, [16, 16, 16, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 16, 1, 16], [])} {
  allocate(C_buf: Pointer(local.acc_buffer int32), int32, [256]), storage_scope = local.acc_buffer;
  allocate(A_buf: Pointer(local.inp_buffer int8), int8, [16]), storage_scope = local.inp_buffer;
  allocate(B_buf: Pointer(local.wgt_buffer int8), int8, [16]), storage_scope = local.wgt_buffer {
    for (co: int32, 0, 16) {
      for (ci: int32, 0, 16) {
        C_buf_1: Buffer(C_buf, int32, [256], [], scope="local.acc_buffer", align=16)[((co*16) + ci)] = 0
        for (ko: int32, 0, 16) {
          attr [IterVar(i0: int32, (nullptr), "DataPar", "")] "pragma_dma_copy" = 1;
          for (i3: int32, 0, 16) {
            A_buf_1: Buffer(A_buf, int8, [16], [], scope="local.inp_buffer", align=16)[i3] = A[((ko*16) + i3)]
          }
          attr [IterVar(i0_1: int32, (nullptr), "DataPar", "")] "pragma_dma_copy" = 1;
          for (i3_1: int32, 0, 16) {
            B_buf_1: Buffer(B_buf, int8, [16], [], scope="local.wgt_buffer", align=256)[i3_1] = B[((((co*4096) + (ko*256)) + (ci*16)) + i3_1)]
          }
          for (ki: int32, 0, 16) {
            let cse_var_1: int32 = ((co*16) + ci)
            C_buf_1[cse_var_1] = (C_buf_1[cse_var_1] + (cast(int32, A_buf_1[ki])*cast(int32, B_buf_1[ki])))
          }
        }
      }
    }
    attr [IterVar(i0_2: int32, (nullptr), "DataPar", "")] "pragma_dma_copy" = 1;
    for (i1: int32, 0, 16) {
      for (i3_2: int32, 0, 16) {
        let cse_var_2: int32 = ((i1*16) + i3_2)
        C[cse_var_2] = cast(int8, C_buf_1[cse_var_2])
      }
    }
  }
}

  1. 2022年07月09日 04:29 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Simple Matrix Multiply”をやってみる2

”Simple Matrix Multiply”をやってみる1”の続き。

Simple Matrix Multiply”のベクトル乗算をやってみるということで、前回は、”Simple Matrix Multiply”からダウンロードした matrix_multiply.py をそのまま実行して成功した。今回は、”Simple Matrix Multiply”に沿って 1 つ 1 つコードを見ながら実行してみよう。

なお、翻訳には DeepL 翻訳を使用している。

RPC 設定
Get Started with VTA”では、””Get Started with VTA”をやってみる1”に示すように、”ライブラリ読み込み”、”VTAパラメータの読み込み”、”FPGA プログラミング”が”Simple Matrix Multiply”の”RPC 設定”になっているようだ。
matrix_multiply.py のコードを引用する。
TVM_VTA_150_220707.png
TVM_VTA_151_220707.png

演算のための宣言
Simple Matrix Multiply”の "Computation Declaration" の図を引用する。
TVM_VTA_153_220708.png

上図を説明すると、メインメモリに入力用配列 A, B を定義する。
VTA のオンチップ・バッファの中間配列 A_buf, B_buf を定義する。
A_buf, B_buf の行列の乗算を行って、積行列 C_buf を生成する。
積行列 C_buf を C にキャストして代入する。つまり、DRAM へのコピーを行う。

データのレイアウト
VTAテンソルコアが要求するデータレイアウトに合わせて、プレース・ホルダー配列A、Bをタイル状のデータフォーマットで記述するそうだ。

データタイリング
ここからは DeepL 翻訳の訳文をそのまま引用するが、VTA テンソルコアの部分は、配列の演算をする場合は、重みは転置しないとおかしいと思うのだけれどどうだろうか?

アクセラレータをターゲットとするとき、複雑さの原因の一つは、データレイアウトがアクセラレータ設計によって課されるレイアウトと一致することを確認することです。VTAは、下図に示すように、活性化行列と重み行列の間で1サイクルあたり1回の行列-行列演算を行い、その結果行列をアキュムレータ行列に追加するテンソルコアを中心に設計されている。


Simple Matrix Multiply”の "Computation Declaration" の図を引用する。
TVM_VTA_154_220708.png

その行列と行列の掛け算の次元は、設定ファイル vta_config.json で指定される。活性化行列は(BATCH, BLOCK_IN)、転置ウエイト行列は(BLOCK_OUT, BLOCK_IN)の形状をしており、結果として出力行列は(BATCH, BLOCK_OUT)の形状をしていると推察される。従って、VTAが処理する入力テンソルおよび出力テンソルは、前述の次元に従ってタイリングされる必要がある。


下図は、元々(4, 8)の形状を持つ行列に対して、データのタイリングを行った場合の影響を示している。(2,2)のタイル形状でタイル化することで、各タイル内のデータが連続することが保証される。その結果、タイル化されたテンソルは(2, 4, 2, 2)の形状を持つことになる。


Simple Matrix Multiply”の "Computation Declaration" の図を引用する。
TVM_VTA_155_220708.png

データの種類
VTA のテンソルコアの内部タイルの次元に合わせるだけでなく、VTA が期待する特定のデータ型に合わせることも重要だそうだ。
VTA は固定小数点データ型のみのサポートで、整数ビット幅は vta_config.json ファイルで指定されている。
アクティビティ(入力かな?)は INP_WIDTH で、重みは WGT_WIDTH で指定されている。アキュムレータ・データ型(これは出力の整数ビット幅かな?)は ACC_WIDTH で指定されている。
現在の vta_config.json ファイルで指定されている値は、以下の通り
LOG_INP_WIDTH が 3 つまり、2^3 で 8 ビット幅
LOG_WGT_WIDTH が 3 つまり、2^3 で 8 ビット幅
LOG_ACC_WIDTH が 5 つまり、2^5 で 32 ビット幅

env.inp_dtypeとenv.wgt_dtypeはすべて 8 ビット整数、env.acc_dtype は標準の 32 ビット整数になるそうだ。
TVM_VTA_156_220708.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

env.BATCH = 1
env.BLOCK_OUT = 16
env.BLOCK_IN = 16
A = Tensor(shape=[1, 16, 1, 16], op.name=A)
B = Tensor(shape=[16, 16, 16, 16], op.name=B)
A_buf = Tensor(shape=[1, 16, 1, 16], op.name=A_buf)
B_buf = Tensor(shape=[16, 16, 16, 16], op.name=B_buf)
C_buf = Tensor(shape=[1, 16, 1, 16], op.name=C_buf)

  1. 2022年07月08日 05:01 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Simple Matrix Multiply”をやってみる1

次の TVM/VTA のチュートリアルの”Simple Matrix Multiply”をやってみることにした。

Simple Matrix Multiply”はベクトル乗算だ。最初に”Simple Matrix Multiply”からダウンロードした matrix_multiply.py をそのまま実行してみよう。

Simple Matrix Multiply”から matrix_multiply.py を tvm/vta/tests/python/integration ディレクトリにダウンロードした。
TVM_VTA_146_220707.png

ホスト・パソコンの tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export/pynq/0_0_2 ディレクトリ に tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_1x16_i8w8a32_15_15_18_17/export/vta.bit をコピーして、1x16_i8w8a32_15_15_18_17.bit に名前を変更済みだ。

ホスト・パソコンで、VTA_CACHE_PATH はすでに設定してある。
export VTA_CACHE_PATH=/media/masaaki/Ubuntu_Disk/DNN/tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export

ホスト・パソコンで環境変数を設定するのだが、すでに設定されているので、やっていない。(ディレクトリは tvm)
export PYTHONPATH=$PYTHONPATH:/media/masaaki/Ubuntu_Disk/DNN/tvm/python:/media/masaaki/Ubuntu_Disk/DNN/tvm/vta/python
export VTA_RPC_HOST=192.168.3.31
export VTA_RPC_PORT=9091

PYNQ-Z1 の ~/tvm ディレクトリで RPC サーバーを起動する。
sudo ./apps/vta_rpc/start_rpc_server.sh

ホスト・パソコン(Ubuntu 18.04 LTS)で test_program_rpc.py を起動した。
python3 vta/tests/python/pynq/test_program_rpc.py

ホスト・パソコンで matrix_multiply.py を実行した。
python3 vta/tests/python/integration/matrix_multiply.py
TVM_VTA_148_220707.png
TVM_VTA_147_220707.png

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/integration/matrix_multiply.py 
@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int8), int8, [256], []),
             B: Buffer(B_2: Pointer(int8), int8, [65536], []),
             C: Buffer(C_2: Pointer(int8), int8, [256], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int8, [1, 16, 1, 16], []), B_1: B_3: Buffer(B_2, int8, [16, 16, 16, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 16, 1, 16], [])} {
  allocate(A_buf: Pointer(global int8), int8, [256]), storage_scope = global;
  allocate(B_buf: Pointer(global int8), int8, [65536]), storage_scope = global;
  allocate(C_buf: Pointer(global int32), int32, [256]), storage_scope = global {
    for (i1: int32, 0, 16) {
      for (i3: int32, 0, 16) {
        let cse_var_1: int32 = ((i1*16) + i3)
        A_buf_1: Buffer(A_buf, int8, [256], [])[cse_var_1] = A[cse_var_1]
      }
    }
    for (i0: int32, 0, 16) {
      for (i1_1: int32, 0, 16) {
        for (i2: int32, 0, 16) {
          for (i3_1: int32, 0, 16) {
            let cse_var_2: int32 = ((((i0*4096) + (i1_1*256)) + (i2*16)) + i3_1)
            B_buf_1: Buffer(B_buf, int8, [65536], [])[cse_var_2] = B[cse_var_2]
          }
        }
      }
    }
    for (co: int32, 0, 16) {
      for (ci: int32, 0, 16) {
        C_buf_1: Buffer(C_buf, int32, [256], [])[((co*16) + ci)] = 0
        for (ko: int32, 0, 16) {
          for (ki: int32, 0, 16) {
            let cse_var_3: int32 = ((co*16) + ci)
            C_buf_1[cse_var_3] = (C_buf_1[cse_var_3] + (cast(int32, A_buf_1[((ko*16) + ki)])*cast(int32, B_buf_1[((((co*4096) + (ko*256)) + (ci*16)) + ki)])))
          }
        }
      }
    }
    for (i1_2: int32, 0, 16) {
      for (i3_2: int32, 0, 16) {
        let cse_var_4: int32 = ((i1_2*16) + i3_2)
        C[cse_var_4] = cast(int8, C_buf_1[cse_var_4])
      }
    }
  }
}


@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int8), int8, [256], []),
             B: Buffer(B_2: Pointer(int8), int8, [65536], []),
             C: Buffer(C_2: Pointer(int8), int8, [256], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int8, [1, 16, 1, 16], []), B_1: B_3: Buffer(B_2, int8, [16, 16, 16, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 16, 1, 16], [])} {
  allocate(C_buf: Pointer(local.acc_buffer int32), int32, [256]), storage_scope = local.acc_buffer;
  allocate(A_buf: Pointer(local.inp_buffer int8), int8, [16]), storage_scope = local.inp_buffer;
  allocate(B_buf: Pointer(local.wgt_buffer int8), int8, [16]), storage_scope = local.wgt_buffer {
    for (co: int32, 0, 16) {
      for (ci: int32, 0, 16) {
        C_buf_1: Buffer(C_buf, int32, [256], [], scope="local.acc_buffer", align=16)[((co*16) + ci)] = 0
        for (ko: int32, 0, 16) {
          attr [IterVar(i0: int32, (nullptr), "DataPar", "")] "pragma_dma_copy" = 1;
          for (i3: int32, 0, 16) {
            A_buf_1: Buffer(A_buf, int8, [16], [], scope="local.inp_buffer", align=16)[i3] = A[((ko*16) + i3)]
          }
          attr [IterVar(i0_1: int32, (nullptr), "DataPar", "")] "pragma_dma_copy" = 1;
          for (i3_1: int32, 0, 16) {
            B_buf_1: Buffer(B_buf, int8, [16], [], scope="local.wgt_buffer", align=256)[i3_1] = B[((((co*4096) + (ko*256)) + (ci*16)) + i3_1)]
          }
          for (ki: int32, 0, 16) {
            let cse_var_1: int32 = ((co*16) + ci)
            C_buf_1[cse_var_1] = (C_buf_1[cse_var_1] + (cast(int32, A_buf_1[ki])*cast(int32, B_buf_1[ki])))
          }
        }
      }
    }
    attr [IterVar(i0_2: int32, (nullptr), "DataPar", "")] "pragma_dma_copy" = 1;
    for (i1: int32, 0, 16) {
      for (i3_2: int32, 0, 16) {
        let cse_var_2: int32 = ((i1*16) + i3_2)
        C[cse_var_2] = cast(int8, C_buf_1[cse_var_2])
      }
    }
  }
}


[04:36:57] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int8), int8, [256], []),
             B: Buffer(B_2: Pointer(int8), int8, [65536], []),
             C: Buffer(C_2: Pointer(int8), int8, [256], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int8, [1, 16, 1, 16], []), B_1: B_3: Buffer(B_2, int8, [16, 16, 16, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 16, 1, 16], [])} {
  attr [IterVar(vta: int32, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 2 {
    attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_uop_scope" = "VTAPushGEMMOp" {
      @tir.call_extern("VTAUopLoopBegin", 16, 1, 0, 0, dtype=int32)
      @tir.vta.uop_push(0, 1, 0, 0, 0, 0, 0, 0, dtype=int32)
      @tir.call_extern("VTAUopLoopEnd", dtype=int32)
    }
    @tir.vta.coproc_dep_push(2, 1, dtype=int32)
  }
  for (ko: int32, 0, 16) {
    attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 1 {
      @tir.vta.coproc_dep_pop(2, 1, dtype=int32)
      @tir.call_extern("VTALoadBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), A_2, ko, 1, 1, 1, 0, 0, 0, 0, 0, 2, dtype=int32)
      @tir.call_extern("VTALoadBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), B_2, ko, 1, 16, 16, 0, 0, 0, 0, 0, 1, dtype=int32)
      @tir.vta.coproc_dep_push(1, 2, dtype=int32)
    }
    attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 2 {
      @tir.vta.coproc_dep_pop(1, 2, dtype=int32)
      attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_uop_scope" = "VTAPushGEMMOp" {
        @tir.call_extern("VTAUopLoopBegin", 16, 1, 0, 1, dtype=int32)
        @tir.vta.uop_push(0, 0, 0, 0, 0, 0, 0, 0, dtype=int32)
        @tir.call_extern("VTAUopLoopEnd", dtype=int32)
      }
      @tir.vta.coproc_dep_push(2, 1, dtype=int32)
    }
  }
  @tir.vta.coproc_dep_push(2, 3, dtype=int32)
  @tir.vta.coproc_dep_pop(2, 1, dtype=int32)
  attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 3 {
    @tir.vta.coproc_dep_pop(2, 3, dtype=int32)
    @tir.call_extern("VTAStoreBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), 0, 4, C_2, 0, 16, 1, 16, dtype=int32)
  }
  @tir.vta.coproc_sync(, dtype=int32)
}


[04:36:57] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
/media/masaaki/Ubuntu_Disk/DNN/tvm/python/tvm/driver/build_module.py:263: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  warnings.warn(
Successful matrix multiply test!


PYNQ-Z1 のターミナルの表示を示す。
TVM_VTA_149_220707.png

xilinx@pynq:~/tvm$ sudo ./apps/vta_rpc/start_rpc_server.sh
[sudo] password for xilinx: 
INFO:RPCServer:bind to 0.0.0.0:9091
INFO:RPCServer:connection from ('192.168.3.10', 56482)
INFO:root:Program FPGA with 1x16_i8w8a32_15_15_18_17.bit 
INFO:RPCServer:Finish serving ('192.168.3.10', 56482)
INFO:RPCServer:connection from ('192.168.3.10', 56484)
INFO:root:Skip reconfig_runtime due to same config.
INFO:RPCServer:Finish serving ('192.168.3.10', 56484)
INFO:RPCServer:connection from ('192.168.3.10', 56486)
INFO:root:Skip reconfig_runtime due to same config.
INFO:root:Program FPGA with 1x16_i8w8a32_15_15_18_17.bit 
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpow_b_kzg/gemm.o
INFO:RPCServer:Finish serving ('192.168.3.10', 56486)

  1. 2022年07月07日 04:50 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Get Started with VTA”をやってみる3

”Get Started with VTA”をやってみる2”の続き。

Get Started with VTA”をやってみようということで、前回は、、”結果をキャスト”から”TVM コンパイル”までの項目を行った。今回は、”モジュールの保存”から

翻訳は DeepL 翻訳を使用させていただいている。

モジュールの保存
TVMでは、モジュールをファイルに保存して、後でロードできるようにすることができる。これは先読みコンパイルと呼ばれ、コンパイル時間を短縮することができる。さらに重要なことは、開発マシン上で実行ファイルをクロスコンパイルし、RPC を介して Pynq FPGA ボードに送信して実行できることだ。
TVM_VTA_142_220706.png

モジュールのロード
コンパイルしたモジュールをロードする。なお、このモジュールは後で実行することができる。
TVM_VTA_143_220706.png

モジュールの実行
コンパイルされたTVM関数は、簡潔なC APIを使用しており、どの言語からも呼び出すことができるそうだ。
TVMはpythonで配列のAPIを提供し、迅速なテストとプロトタイピングを支援します。この配列APIはDLPack標準に基づいているそうだ。

モジュールを実行する手順
1. リモート・コンテキストを作成する(Pynq でもリモート実行用)
2. tvm.nd.array でデータをフォーマットする
3. f() で計算を実行する
4. numpy()は結果の配列を解釈可能な形式にコピーして返す


ここでやっと計算が実行されたようだ。
TVM_VTA_144_220706.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

A_orig.shape = (1, 1024)
A_packed.shape = (1, 64, 1, 16)


numpy() の結果と検証
numpy() の結果と比較して VTA の行列加算が正しいか?検証する。
TVM_VTA_145_220706.png

Successful vector add test!

が出力された。

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

C_nd.numpy().shape = (1, 64, 1, 16)
[[[[  26  -75  -59 ...  -76  118   99]]

  [[  22  -98   31 ...  -28   66  -50]]

  [[   8   23   82 ...   -5   -4  120]]

  ...

  [[  36   83    8 ...  -47   45 -105]]

  [[  63  -28   94 ...   69  119  113]]

  [[-116  -31 -124 ... -110  -58  -57]]]]


全ての実行結果を貼っておく。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/integration/vta_get_started.py 
A.shape = [1, 64, 1, 16]
A = Tensor(shape=[1, 64, 1, 16], op.name=A)
B = Tensor(shape=[1, 64, 1, 16], op.name=B)
env.BATCH = 1
env.BLOCK_OUT = 16
A_buf = Tensor(shape=[1, 64, 1, 16], op.name=A_buf)
B_buf = Tensor(shape=[1, 64, 1, 16], op.name=B_buf)
C_buf = Tensor(shape=[1, 64, 1, 16], op.name=C_buf)
C = Tensor(shape=[1, 64, 1, 16], op.name=C)
@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int32), int32, [1024], []),
             B: Buffer(B_2: Pointer(int32), int32, [1024], []),
             C: Buffer(C_2: Pointer(int8), int8, [1024], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int32, [1, 64, 1, 16], []), B_1: B_3: Buffer(B_2, int32, [1, 64, 1, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 64, 1, 16], [])} {
  allocate(A_buf: Pointer(global int32), int32, [1024]), storage_scope = global;
  allocate(B_buf: Pointer(global int32), int32, [1024]), storage_scope = global {
    for (i1: int32, 0, 64) {
      for (i3: int32, 0, 16) {
        let cse_var_1: int32 = ((i1*16) + i3)
        A_buf_1: Buffer(A_buf, int32, [1024], [])[cse_var_1] = A[cse_var_1]
      }
    }
    for (i1_1: int32, 0, 64) {
      for (i3_1: int32, 0, 16) {
        let cse_var_2: int32 = ((i1_1*16) + i3_1)
        B_buf_1: Buffer(B_buf, int32, [1024], [])[cse_var_2] = B[cse_var_2]
      }
    }
    for (i1_2: int32, 0, 64) {
      for (i3_2: int32, 0, 16) {
        let cse_var_3: int32 = ((i1_2*16) + i3_2)
        A_buf_2: Buffer(A_buf, int32, [1024], [])[cse_var_3] = (A_buf_1[cse_var_3] + B_buf_1[cse_var_3])
      }
    }
    for (i1_3: int32, 0, 64) {
      for (i3_3: int32, 0, 16) {
        let cse_var_4: int32 = ((i1_3*16) + i3_3)
        C[cse_var_4] = cast(int8, A_buf_2[cse_var_4])
      }
    }
  }
}


@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int32), int32, [1024], []),
             B: Buffer(B_2: Pointer(int32), int32, [1024], []),
             C: Buffer(C_2: Pointer(int8), int8, [1024], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int32, [1, 64, 1, 16], []), B_1: B_3: Buffer(B_2, int32, [1, 64, 1, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 64, 1, 16], [])} {
  attr [IterVar(vta: int32, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 2 {
    @tir.call_extern("VTALoadBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), A_2, 0, 64, 1, 64, 0, 0, 0, 0, 0, 3, dtype=int32)
    @tir.call_extern("VTALoadBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), B_2, 0, 64, 1, 64, 0, 0, 0, 0, 64, 3, dtype=int32)
    attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_uop_scope" = "VTAPushALUOp" {
      @tir.call_extern("VTAUopLoopBegin", 64, 1, 1, 0, dtype=int32)
      @tir.vta.uop_push(1, 0, 0, 64, 0, 2, 0, 0, dtype=int32)
      @tir.call_extern("VTAUopLoopEnd", dtype=int32)
    }
    @tir.vta.coproc_dep_push(2, 3, dtype=int32)
  }
  attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 3 {
    @tir.vta.coproc_dep_pop(2, 3, dtype=int32)
    @tir.call_extern("VTAStoreBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), 0, 4, C_2, 0, 64, 1, 64, dtype=int32)
  }
  @tir.vta.coproc_sync(, dtype=int32)
}


/media/masaaki/Ubuntu_Disk/DNN/tvm/python/tvm/driver/build_module.py:263: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  warnings.warn(
A_orig.shape = (1, 1024)
A_packed.shape = (1, 64, 1, 16)
Successful vector add test!
C_nd.numpy().shape = (1, 64, 1, 16)
[[[[  26  -75  -59 ...  -76  118   99]]

  [[  22  -98   31 ...  -28   66  -50]]

  [[   8   23   82 ...   -5   -4  120]]

  ...

  [[  36   83    8 ...  -47   45 -105]]

  [[  63  -28   94 ...   69  119  113]]

  [[-116  -31 -124 ... -110  -58  -57]]]]

  1. 2022年07月06日 03:45 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Get Started with VTA”をやってみる2

”Get Started with VTA”をやってみる1”の続き。

Get Started with VTA”をやってみようということで、前回は、初めから、”ベクトル加算”までの項目を行った。今回は、”結果をキャスト”から”TVM コンパイル”までの項目を行った。

なお、英語の翻訳は DeepL 翻訳を使用させていただいている。

結果をキャスト
計算が終わったら、計算結果をメイン・メモリに送り返す必要がある。
env.inp_dtype でキャストされたデータが C に送り返されるようだ?
TVM_VTA_136_220705.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

C = Tensor(shape=[1, 64, 1, 16], op.name=C)


デフォルトのスケジュール
C を計算するスケジュールを構成する。
TVM_VTA_137_220705.png

プリント出力を示す。

@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int32), int32, [1024], []),
             B: Buffer(B_2: Pointer(int32), int32, [1024], []),
             C: Buffer(C_2: Pointer(int8), int8, [1024], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int32, [1, 64, 1, 16], []), B_1: B_3: Buffer(B_2, int32, [1, 64, 1, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 64, 1, 16], [])} {
  allocate(A_buf: Pointer(global int32), int32, [1024]), storage_scope = global;
  allocate(B_buf: Pointer(global int32), int32, [1024]), storage_scope = global {
    for (i1: int32, 0, 64) {
      for (i3: int32, 0, 16) {
        let cse_var_1: int32 = ((i1*16) + i3)
        A_buf_1: Buffer(A_buf, int32, [1024], [])[cse_var_1] = A[cse_var_1]
      }
    }
    for (i1_1: int32, 0, 64) {
      for (i3_1: int32, 0, 16) {
        let cse_var_2: int32 = ((i1_1*16) + i3_1)
        B_buf_1: Buffer(B_buf, int32, [1024], [])[cse_var_2] = B[cse_var_2]
      }
    }
    for (i1_2: int32, 0, 64) {
      for (i3_2: int32, 0, 16) {
        let cse_var_3: int32 = ((i1_2*16) + i3_2)
        A_buf_2: Buffer(A_buf, int32, [1024], [])[cse_var_3] = (A_buf_1[cse_var_3] + B_buf_1[cse_var_3])
      }
    }
    for (i1_3: int32, 0, 64) {
      for (i3_3: int32, 0, 16) {
        let cse_var_4: int32 = ((i1_3*16) + i3_3)
        C[cse_var_4] = cast(int8, A_buf_2[cse_var_4])
      }
    }
  }
}


バッファのスコープ
コピーバッファのスコープを設定する。中間配列がVTAのオンチップSRAMバッファに格納されることをTVMに指示する。
A_buf, B_buf, C_buf が VTA の汎用レジスタファイルとして機能するオンチップ・アキュムレータ・バッファに格納されることを TVM に伝えている。
TVM_VTA_138_220705.png

DMA転送
DRAMのデータを VTA のオンチップ・バッファに転送するために DMA 転送のスケジュールを組む。
dma_copy プラグマを挿入して、コピー操作が DMA 転送で実行されることをコンパイラに示す。
TVM_VTA_139_220705.png

ALU 演算
VTA はベクトル ALU を持ち、アキュムレータバッファのテンソルに対してベクトル演算を行うことができる。ある演算が VTA のベクトル ALU にマップされる必要があることを TVM に伝えるには、 env.alu プラグマでベクトル加算ループに明示的にタグ付けする必要がある。
TVM_VTA_140_220705.png

プリント出力を示す。

@main = primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {A: Buffer(A_2: Pointer(int32), int32, [1024], []),
             B: Buffer(B_2: Pointer(int32), int32, [1024], []),
             C: Buffer(C_2: Pointer(int8), int8, [1024], [])}
  buffer_map = {A_1: A, B_1: B, C_1: C}
  preflattened_buffer_map = {A_1: A_3: Buffer(A_2, int32, [1, 64, 1, 16], []), B_1: B_3: Buffer(B_2, int32, [1, 64, 1, 16], []), C_1: C_3: Buffer(C_2, int8, [1, 64, 1, 16], [])} {
  attr [IterVar(vta: int32, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 2 {
    @tir.call_extern("VTALoadBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), A_2, 0, 64, 1, 64, 0, 0, 0, 0, 0, 3, dtype=int32)
    @tir.call_extern("VTALoadBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), B_2, 0, 64, 1, 64, 0, 0, 0, 0, 64, 3, dtype=int32)
    attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_uop_scope" = "VTAPushALUOp" {
      @tir.call_extern("VTAUopLoopBegin", 64, 1, 1, 0, dtype=int32)
      @tir.vta.uop_push(1, 0, 0, 64, 0, 2, 0, 0, dtype=int32)
      @tir.call_extern("VTAUopLoopEnd", dtype=int32)
    }
    @tir.vta.coproc_dep_push(2, 3, dtype=int32)
  }
  attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 3 {
    @tir.vta.coproc_dep_pop(2, 3, dtype=int32)
    @tir.call_extern("VTAStoreBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), 0, 4, C_2, 0, 64, 1, 64, dtype=int32)
  }
  @tir.vta.coproc_sync(, dtype=int32)
}


これで、スケジュールは終了だそうだ。

TVM コンパイル
スケジュールの指定が終わったら、それをTVM関数にコンパイルする。デフォルトでは、TVM は Python 側から直接呼び出せる型が消去された関数にコンパイルされる。
tvm.build を使って関数を作成する。build関数は、スケジュール、関数のシグネチャ(入力と出力を含む)、コンパイルしたいターゲット言語を受け取る。
TVM_VTA_141_220705.png
  1. 2022年07月05日 04:31 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

”Get Started with VTA”をやってみる1

今まで TVM/VTA のチュートリアルをやってきて、TVM/VTA が動作するというのは分かったが、時分の課題を解決するためにどうやって TVM/VTA を使うのか?ということは分かっていない。そのため、TVM/VTA の使用方法が記述されている”Get Started with VTA”をやってみようと思う。
Get Started with VTA”は今までやってきたのと同じ方法で実行することができた。

Get Started with VTA”はベクトル加算を行うチュートリアルで、手順が丁寧に解説されている。
なお、”Get Started with VTA”からコードを引用している。

Get Started with VTA”から vta_get_started.py を tvm/vta/tests/python/integration にダウンロードした。
TVM_VTA_128_220703.png

ライブラリ読み込み
tvm や vta など必要なライブラリを読み込んでいる。
TVM_VTA_129_220704.png

VTAパラメータの読み込み
VTA のパラメータは tvm/3rdparty/vta-hw/config/vta_config.json に 2 の n 乗の値の n の値が書かれている。つまり log2 の値だ。
TVM ターゲットも "sim" などの値が使用される。現在の値は "pynq" となっている。
TVM_VTA_112_220628.png

FPGA プログラミング
FPGA をプログラミングする。ビットストリームをダウンロードする。
TVM_VTA_131_220704.png

計算について
計算(この場合は、ベクトル加算)を解説する。
Get Started with VTA”から図を引用する。
TVM_VTA_132_220704.png

A, B, C は DRAM 上の配列で、A_buf, B_buf, C_buf は vta のオンチップ・バッファに格納される。
計算結果は C_buf に格納され、DMA で C にコピーされる。

入力プレースホルダ
VTA のベクトル ALU が要求するデータ・レイアウトに合わせて、プレースホルダ配列 A, B を生成する。
VTAの汎用演算であるベクトル加算では、タイルサイズは(env.BATCH, env.BLOCK_OUT)となる。このサイズは、vta_config.json で指定されているということだが、"LOG_BLOCK"のことだろうか?デフォルト値は (1, 16) ということだ。
A, B のデータ型は 32 ビット整数型にする必要がある。
TVM_VTA_133_220704.png

なお、ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

A.shape = [1, 64, 1, 16]
A = Tensor(shape=[1, 64, 1, 16], op.name=A)
B = Tensor(shape=[1, 64, 1, 16], op.name=B)
env.BATCH = 1
env.BLOCK_OUT = 16


バッファへコピー
VTA に計算させるのにプレースホルダ配列 A, B から FPGA 内部?の SRAM に置かれる A_buf, B_buf に配列をコピーする。
TVM_VTA_134_220704.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

A_buf = Tensor(shape=[1, 64, 1, 16], op.name=A_buf)
B_buf = Tensor(shape=[1, 64, 1, 16], op.name=B_buf)


ベクトル加算
DeepL 翻訳での翻訳を引用する。

さて、ベクトル加算結果のテンソルCを別の計算操作で記述する準備が整った。計算関数はテンソルの形と、テンソルの各位置の計算規則を記述したラムダ関数を受け取る。

この段階では、計算をどのように行うかを宣言しているだけであり、計算は行われない。


TVM_VTA_135_220704.png

ピンク枠で囲った部分は、私が挿入した行になる。その結果を示す。

C_buf = Tensor(shape=[1, 64, 1, 16], op.name=C_buf)

  1. 2022年07月04日 04:14 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

TVM/VTA チュートリアルをやってみる6

TVM/VTA チュートリアルをやってみる5”の続き。

前回は、PYNQ-Z1 とホスト・パソコンの tvm/3rdparty/vta-hw/config/vta_config.json の "LOG_BATCH" が 0 で、test_benchmark_topi_dense.py を実行した所、成功したようだ。今回は、最後の test_benchmark_topi_group_conv2d.py をやってみて成功した。最大 GOPS 値は 21.7359 GOPS だった。

ホスト・パソコンの tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export/pynq/0_0_2 ディレクトリ に tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_1x16_i8w8a32_15_15_18_17/export/vta.bit をコピーして、1x16_i8w8a32_15_15_18_17.bit に名前を変更済みだ。

ホスト・パソコンで、VTA_CACHE_PATH はすでに設定してある。
export VTA_CACHE_PATH=/media/masaaki/Ubuntu_Disk/DNN/tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export

ホスト・パソコンで環境変数を設定するのだが、すでに設定されているので、やっていない。(ディレクトリは tvm)
export PYTHONPATH=$PYTHONPATH:/media/masaaki/Ubuntu_Disk/DNN/tvm/python:/media/masaaki/Ubuntu_Disk/DNN/tvm/vta/python
export VTA_RPC_HOST=192.168.3.31
export VTA_RPC_PORT=9091

PYNQ-Z1 の ~/tvm ディレクトリで RPC サーバーを起動する。
sudo ./apps/vta_rpc/start_rpc_server.sh

ホスト・パソコン(Ubuntu 18.04 LTS)で test_program_rpc.py を起動した。
python3 vta/tests/python/pynq/test_program_rpc.py

ホスト・パソコンで test_benchmark_topi_group_conv2d.py を実行した。
python3 vta/tests/python/integration/test_benchmark_topi_group_conv2d.py
TVM_VTA_124_220629.png
TVM_VTA_125_220629.png

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/integration/test_benchmark_topi_group_conv2d.py
GroupConv2DWorkload(batch=1, height=112, width=112, in_filter=32, out_filter=32, groups=2, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)
/media/masaaki/Ubuntu_Disk/DNN/tvm/python/tvm/driver/build_module.py:263: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  warnings.warn(
CPU GROUP CONV2D TEST PASSED: Time cost = 0.285452 sec/op, 0.404991 GOPS
GroupConv2DWorkload(batch=1, height=112, width=112, in_filter=64, out_filter=64, groups=4, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)
CPU GROUP CONV2D TEST PASSED: Time cost = 0.160443 sec/op, 0.36027 GOPS
GroupConv2DWorkload(batch=1, height=56, width=56, in_filter=128, out_filter=128, groups=8, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)
CPU GROUP CONV2D TEST PASSED: Time cost = 0.283096 sec/op, 0.408361 GOPS
GroupConv2DWorkload(batch=1, height=56, width=56, in_filter=128, out_filter=128, groups=8, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)
CPU GROUP CONV2D TEST PASSED: Time cost = 0.077123 sec/op, 0.374744 GOPS
GroupConv2DWorkload(batch=1, height=28, width=28, in_filter=256, out_filter=256, groups=16, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)
CPU GROUP CONV2D TEST PASSED: Time cost = 0.128987 sec/op, 0.448128 GOPS
GroupConv2DWorkload(batch=1, height=28, width=28, in_filter=256, out_filter=256, groups=16, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)
CPU GROUP CONV2D TEST PASSED: Time cost = 0.0342869 sec/op, 0.421464 GOPS
GroupConv2DWorkload(batch=1, height=14, width=14, in_filter=512, out_filter=512, groups=32, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)
CPU GROUP CONV2D TEST PASSED: Time cost = 0.0639032 sec/op, 0.452268 GOPS
GroupConv2DWorkload(batch=1, height=14, width=14, in_filter=512, out_filter=512, groups=32, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)
CPU GROUP CONV2D TEST PASSED: Time cost = 0.0164063 sec/op, 0.440401 GOPS
GroupConv2DWorkload(batch=1, height=7, width=7, in_filter=1024, out_filter=1024, groups=64, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)
CPU GROUP CONV2D TEST PASSED: Time cost = 0.0320891 sec/op, 0.450331 GOPS
GroupConv2DWorkload(batch=1, height=112, width=112, in_filter=32, out_filter=32, groups=2, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)
[04:00:30] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
VTA GROUP CONV2D TEST PASSED: Time cost = 0.00531863 sec/op, 21.7359 GOPS
GroupConv2DWorkload(batch=1, height=112, width=112, in_filter=64, out_filter=64, groups=4, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)
[04:00:31] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
VTA GROUP CONV2D TEST PASSED: Time cost = 0.00412703 sec/op, 14.0059 GOPS
GroupConv2DWorkload(batch=1, height=56, width=56, in_filter=128, out_filter=128, groups=8, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)
[04:00:32] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
VTA GROUP CONV2D TEST PASSED: Time cost = 0.00527315 sec/op, 21.9234 GOPS
GroupConv2DWorkload(batch=1, height=56, width=56, in_filter=128, out_filter=128, groups=8, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)
[04:00:33] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
VTA GROUP CONV2D TEST PASSED: Time cost = 0.00197861 sec/op, 14.6069 GOPS
GroupConv2DWorkload(batch=1, height=28, width=28, in_filter=256, out_filter=256, groups=16, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)
[04:00:34] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
VTA GROUP CONV2D TEST PASSED: Time cost = 0.00267508 sec/op, 21.6079 GOPS
GroupConv2DWorkload(batch=1, height=28, width=28, in_filter=256, out_filter=256, groups=16, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)
[04:00:35] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
VTA GROUP CONV2D TEST PASSED: Time cost = 0.00104579 sec/op, 13.818 GOPS
GroupConv2DWorkload(batch=1, height=14, width=14, in_filter=512, out_filter=512, groups=32, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)
[04:00:36] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
VTA GROUP CONV2D TEST PASSED: Time cost = 0.00162464 sec/op, 17.7894 GOPS
GroupConv2DWorkload(batch=1, height=14, width=14, in_filter=512, out_filter=512, groups=32, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)
[04:00:36] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
VTA GROUP CONV2D TEST PASSED: Time cost = 0.000917008 sec/op, 7.87926 GOPS
GroupConv2DWorkload(batch=1, height=7, width=7, in_filter=1024, out_filter=1024, groups=64, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)
[04:00:37] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
VTA GROUP CONV2D TEST PASSED: Time cost = 0.00141807 sec/op, 10.1904 GOPS


PYNQ-Z1 のターミナルの表示を示す。
TVM_VTA_126_220629.png
TVM_VTA_127_220629.png

xilinx@pynq:~/tvm$ sudo ./apps/vta_rpc/start_rpc_server.sh
INFO:RPCServer:bind to 0.0.0.0:9091
INFO:RPCServer:connection from ('192.168.3.10', 40778)
INFO:root:Program FPGA with 1x16_i8w8a32_15_15_18_17.bit 
INFO:RPCServer:Finish serving ('192.168.3.10', 40778)
INFO:RPCServer:connection from ('192.168.3.10', 40780)
INFO:root:Skip reconfig_runtime due to same config.
INFO:RPCServer:Finish serving ('192.168.3.10', 40780)
INFO:RPCServer:connection from ('192.168.3.10', 40784)
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpaxnl7q04/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpaxnl7q04/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpaxnl7q04/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpaxnl7q04/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpaxnl7q04/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpaxnl7q04/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpaxnl7q04/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpaxnl7q04/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpaxnl7q04/conv2d.o
INFO:RPCServer:Finish serving ('192.168.3.10', 40784)
INFO:RPCServer:connection from ('192.168.3.10', 40786)
INFO:root:Program FPGA with 1x16_i8w8a32_15_15_18_17.bit 
INFO:root:Skip reconfig_runtime due to same config.
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpqkivkeds/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpqkivkeds/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpqkivkeds/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpqkivkeds/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpqkivkeds/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpqkivkeds/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpqkivkeds/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpqkivkeds/conv2d.o
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpqkivkeds/conv2d.o
INFO:RPCServer:Finish serving ('192.168.3.10', 40786)

  1. 2022年07月02日 04:35 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0

TVM/VTA チュートリアルをやってみる5

TVM/VTA チュートリアルをやってみる4”の続き。

前回は、PYNQ-Z1 とホスト・パソコンの tvm/3rdparty/vta-hw/config/vta_config.json の "LOG_BATCH" を 0 にして、もう一度、test_benchmark_topi_conv2d_transpose.py をやってみた。今度は、完走できて、最大 GPOS 値は 49.0348 GOPS だった。今回は、PYNQ-Z1 とホスト・パソコンの tvm/3rdparty/vta-hw/config/vta_config.json の "LOG_BATCH" が 0 で、test_benchmark_topi_dense.py を実行した所、成功したようだ。

ホスト・パソコンの tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export/pynq/0_0_2 ディレクトリ に tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_1x16_i8w8a32_15_15_18_17/export/vta.bit をコピーして、1x16_i8w8a32_15_15_18_17.bit に名前を変更済みだ。

ホスト・パソコンで、VTA_CACHE_PATH はすでに設定してある。
export VTA_CACHE_PATH=/media/masaaki/Ubuntu_Disk/DNN/tvm/3rdparty/vta-hw/build/hardware/xilinx/vivado/pynq_2x16_i8w8a32_15_15_18_17/export

ホスト・パソコンで環境変数を設定するのだが、すでに設定されているので、やっていない。(ディレクトリは tvm)
export PYTHONPATH=$PYTHONPATH:/media/masaaki/Ubuntu_Disk/DNN/tvm/python:/media/masaaki/Ubuntu_Disk/DNN/tvm/vta/python
export VTA_RPC_HOST=192.168.3.31
export VTA_RPC_PORT=9091

PYNQ-Z1 の ~/tvm ディレクトリで RPC サーバーを起動する。
sudo ./apps/vta_rpc/start_rpc_server.sh

ホスト・パソコン(Ubuntu 18.04 LTS)で test_program_rpc.py を起動した。
python3 vta/tests/python/pynq/test_program_rpc.py

ホスト・パソコンで test_benchmark_topi_dense.py を実行した。
python3 vta/tests/python/integration/test_benchmark_topi_dense.py
TVM_VTA_121_220629.png
TVM_VTA_122_220629.png

VTA DENSE TEST PASSED: Time cost = 0.126375 sec/op, 0.130683 GOPS

なので、だいぶ遅い気がする。

(base) masaaki@masaaki-H110M4-M01:/media/masaaki/Ubuntu_Disk/DNN/tvm$ python3 vta/tests/python/integration/test_benchmark_topi_dense.py
Cannot find config for target=ext_dev -keys=vta,cpu -device=vta -model=pynq_1x16_i8w8a32_15_15_18_17, workload=('dense_packed.vta', ('TENSOR', (16, 32, 1, 16), 'int8'), ('TENSOR', (63, 32, 16, 16), 'int8'), None, 'int32'). A fallback configuration is used, which may bring great performance regression.
[03:54:12] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
@main = primfn(data_1: handle, kernel_1: handle, compute_1: handle) -> ()
  attr = {"from_legacy_te_schedule": True, "global_symbol": "main", "tir.noalias": True}
  buffers = {data: Buffer(data_2: Pointer(int8), int8, [8192], []),
             kernel: Buffer(kernel_2: Pointer(int8), int8, [516096], []),
             compute: Buffer(compute_2: Pointer(int8), int8, [16128], [])}
  buffer_map = {data_1: data, kernel_1: kernel, compute_1: compute}
  preflattened_buffer_map = {data_1: data_3: Buffer(data_2, int8, [16, 32, 1, 16], []), kernel_1: kernel_3: Buffer(kernel_2, int8, [63, 32, 16, 16], []), compute_1: compute_3: Buffer(compute_2, int8, [16, 63, 1, 16], [])} {
  @tir.vta.coproc_dep_push(3, 2, dtype=int32)
  for (i0.outer: int32, 0, 16) {
    for (i1.outer: int32, 0, 63) {
      attr [IterVar(vta: int32, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 2 {
        @tir.vta.coproc_dep_pop(3, 2, dtype=int32)
        attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_uop_scope" = "VTAPushGEMMOp";
        @tir.vta.uop_push(0, 1, 0, 0, 0, 0, 0, 0, dtype=int32)
        @tir.vta.coproc_dep_push(2, 1, dtype=int32)
      }
      for (k_o.outer: int32, 0, 32) {
        attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 1 {
          @tir.vta.coproc_dep_pop(2, 1, dtype=int32)
          @tir.call_extern("VTALoadBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), data_2, ((i0.outer*32) + k_o.outer), 1, 1, 1, 0, 0, 0, 0, 0, 2, dtype=int32)
          @tir.call_extern("VTALoadBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), kernel_2, ((i1.outer*32) + k_o.outer), 1, 1, 1, 0, 0, 0, 0, 0, 1, dtype=int32)
          @tir.vta.coproc_dep_push(1, 2, dtype=int32)
        }
        attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 2 {
          @tir.vta.coproc_dep_pop(1, 2, dtype=int32)
          attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_uop_scope" = "VTAPushGEMMOp";
          @tir.vta.uop_push(0, 0, 0, 0, 0, 0, 0, 0, dtype=int32)
          @tir.vta.coproc_dep_push(2, 1, dtype=int32)
        }
      }
      @tir.vta.coproc_dep_pop(2, 1, dtype=int32)
      attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 2 {
        attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_uop_scope" = "VTAPushALUOp";
        @tir.vta.uop_push(1, 0, 0, 0, 0, 3, 1, 8, dtype=int32)
        attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_uop_scope" = "VTAPushALUOp";
        @tir.vta.uop_push(1, 0, 0, 0, 0, 0, 1, 127, dtype=int32)
        attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_uop_scope" = "VTAPushALUOp";
        @tir.vta.uop_push(1, 0, 0, 0, 0, 1, 1, 0, dtype=int32)
        @tir.vta.coproc_dep_push(2, 3, dtype=int32)
      }
      attr [IterVar(vta, (nullptr), "ThreadIndex", "vta")] "coproc_scope" = 3 {
        @tir.vta.coproc_dep_pop(2, 3, dtype=int32)
        @tir.call_extern("VTAStoreBuffer2D", @tir.tvm_thread_context(@tir.vta.command_handle(, dtype=handle), dtype=handle), 0, 4, compute_2, ((i0.outer*63) + i1.outer), 1, 1, 1, dtype=int32)
        @tir.vta.coproc_dep_push(3, 2, dtype=int32)
      }
    }
  }
  @tir.vta.coproc_sync(, dtype=int32)
  @tir.vta.coproc_dep_pop(3, 2, dtype=int32)
}


[03:54:13] /media/masaaki/Ubuntu_Disk/DNN/tvm/src/tir/transforms/arg_binder.cc:95: Warning: Trying to bind buffer to another one with lower alignment requirement  required_alignment=256, provided_alignment=128
/media/masaaki/Ubuntu_Disk/DNN/tvm/python/tvm/driver/build_module.py:263: UserWarning: target_host parameter is going to be deprecated. Please pass in tvm.target.Target(target, host=target_host) instead.
  warnings.warn(
VTA DENSE TEST PASSED: Time cost = 0.126375 sec/op, 0.130683 GOPS


PYNQ-Z1 のターミナルの表示を示す。
TVM_VTA_123_220629.png

xilinx@pynq:~/tvm$ sudo ./apps/vta_rpc/start_rpc_server.sh
INFO:RPCServer:bind to 0.0.0.0:9091
INFO:RPCServer:connection from ('192.168.3.10', 40252)
INFO:root:Program FPGA with 1x16_i8w8a32_15_15_18_17.bit 
INFO:RPCServer:Finish serving ('192.168.3.10', 40252)
INFO:RPCServer:connection from ('192.168.3.10', 40254)
INFO:root:Skip reconfig_runtime due to same config.
INFO:RPCServer:Finish serving ('192.168.3.10', 40254)
INFO:RPCServer:connection from ('192.168.3.10', 40262)
INFO:root:Program FPGA with 1x16_i8w8a32_15_15_18_17.bit 
INFO:root:Skip reconfig_runtime due to same config.
INFO:root:Loading VTA library: /home/xilinx/tvm/vta/python/vta/../../../build/libvta.so
INFO:RPCServer:load_module /tmp/tmpl5cso_hi/dense.o
INFO:RPCServer:Finish serving ('192.168.3.10', 40262)

  1. 2022年07月01日 04:00 |
  2. TVM_VTA
  3. | トラックバック:0
  4. | コメント:0