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

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

FPGAの部屋

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

Vitis HLS 2021.2 で Vitis Vision Library を使用する8(AXI4-Stream 入出力の xf_resize 編 1)

Vitis HLS 2021.2 で Vitis Vision Library を使用する7(AXI4-Stream 入出力の xf_median_blur 編 3)”の続き。

前回、Vitis HLS 2021.2 で Vitis Vision Library を使用して、メディアン・フィルタ IP を実装することができた。今回は、Vitis HLS 2021.2 で Vitis Vision Library を使用して、resize IP を実装することにしたのだが、C コードの合成をしようとしたら、どうやっても file not found が消えなかった。

Vitis_Libraries/vision/L1/examples/resize/ を参照して、とりあえず合成できるかどうか?を確かめるために、xf_resize_axis.h と xf_resize_axis.cpp のソースコードを作成した。 テストベンチ・ファイルは作ったのだが、完成はしていない。

xf_resize_axis.h を貼っておく。

// xf_resize_axis.h
// 2022/01/30 by marsee
// Vitis_Libraries/vision/L1/examples/resize/を参照している
// https://github.com/Xilinx/Vitis_Libraries/tree/master/vision/L1/examples/resize
// Vitis_Libraries/vision/L1/examples/resize/build/xf_config_params.h を引用

#ifndef _XF_RESIZE_AXIS_
#define _XF_RESIZE_AXIS_

#include "hls_stream.h"
#include "ap_int.h"
#include "common/xf_common.hpp"
#include "ap_axi_sdata.h"
#include "common/xf_infra.hpp"
#include "common/xf_axi_io.hpp"

#include "imgproc/xf_resize.hpp"

#define RGB  1
#define GRAY 0

#define NPxPC XF_NPPC1

#if GRAY
#define TYPE XF_8UC1
#define CHANNELS 1
#define STREAMW 8
#else
#define TYPE XF_8UC3
#define CHANNELS 3
#define STREAMW 32
#endif

/*  set the height and weight  */
#define WIDTH  1920
#define HEIGHT 1080
#define WIDTH  1920
#define HEIGHT 1080

/* Interpolation type*/
#define INTERPOLATION 1
// 0 - Nearest Neighbor Interpolation
// 1 - Bilinear Interpolation
// 2 - AREA Interpolation

/* Input image Dimensions */
#define WIDTH 1920  // Maximum Input image width
#define HEIGHT 1080 // Maximum Input image height

/* Output image Dimensions */
#define NEWWIDTH 1920  // Maximum output image width
#define NEWHEIGHT 1080 // Maximum output image height

#endif


xf_resize_axis.cpp を貼っておく。

// xf_resize_axis.cpp
// 2022/01/30 by marsee
// Vitis_Libraries/vision/L1/examples/resize/を参照している
// https://github.com/Xilinx/Vitis_Libraries/tree/master/vision/L1/examples/resize

#include "xf_resize_axis.h"

void resize_accel_axis(AXI_STREAM& _src, AXI_STREAM& _dst,
        int32_t in_height, int32_t in_width, int32_t out_height, int32_t out_width){
#pragma HLS INTERFACE mode=s_axilite port=out_width
#pragma HLS INTERFACE mode=s_axilite port=out_height
#pragma HLS INTERFACE mode=s_axilite port=in_width
#pragma HLS INTERFACE mode=s_axilite port=in_height
#pragma HLS INTERFACE mode=s_axilite port=return
#pragma HLS INTERFACE mode=axis register_mode=both port=_src register
#pragma HLS INTERFACE mode=axis register_mode=both port=_dst register

    xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPxPC> img_in(in_height, in_width);
    xf::cv::Mat<TYPE, NEWHEIGHT, NEWWIDTH, NPxPC> img_out(out_height, out_width);

#pragma HLS DATAFLOW

    xf::cv::AXIvideo2xfMat(_src, img_in);

    xf::cv::xf_resize_axis <INTERPOLATION, TYPE, HEIGHT, WIDTH,
        NEWHEIGHT, NEWWIDTH, NPxPC, MAXDOWNSCALE> (img_in, img_out);

    xf::cv::xfMat2AXIvideo(img_out, _dst);
}


Vitis HLS 2021.2 で xf_resize_axis プロジェクトを作成した。
Vitis_Vision2_132_220131.png

Vitis HLS 2021.2 の Project メニューから Project Settings... を選択して、設定を行う。
Project Settings (xf_resize_axis) ダイアログが開く。
Project Settings (xf_resize_axis) ダイアログの左のウインドウで Synthesis をクリックしxf_resize_axis.cpp の CFLAGS を設定する。(設定方法は、Edit CFLAGS... ボタンをクリックする)

-I/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include -std=c++0x

を設定した。
Vitis_Vision2_133_220131.png

Run C Synthesis を実行した。
エラーが出てしまった。

ERROR: [HLS 207-812] 'common/xf_common.hpp' file not found (xf_resize_axis/xf_resize_axis.h:11:10) xf_resize_axis:solution1 Jan 31, 2022, 4:17:00 AM


Vitis_Vision2_134_220131.png

全ログを示す。

Starting C synthesis ...
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/bin/vitis_hls /media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_resize_axis/solution1/csynth.tcl
INFO: Applying HLS Y2K22 patch v1.2 for IP revision
INFO: [HLS 200-10] Running '/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2021.2/bin/unwrapped/lnx64.o/vitis_hls'
INFO: [HLS 200-10] For user 'masaaki' on host 'masaaki-H110M4-M01' (Linux_x86_64 version 4.15.0-166-generic) on Mon Jan 31 04:16:59 JST 2022
INFO: [HLS 200-10] On os Ubuntu 18.04.6 LTS
INFO: [HLS 200-10] In directory '/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2'
WARNING: [HLS 200-40] Environment variable 'C_INCLUDE_PATH' is set to :/usr/local/cuda/include.
Sourcing Tcl script '/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_resize_axis/solution1/csynth.tcl'
INFO: [HLS 200-1510] Running: open_project xf_resize_axis 
INFO: [HLS 200-10] Opening project '/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_resize_axis'.
INFO: [HLS 200-1510] Running: set_top resize_accel_axis 
INFO: [HLS 200-1510] Running: add_files xf_resize_axis/xf_resize_axis.cpp -cflags -I../../../../../Xilinx_github/Vitis_Libraries/vision/L1/include -std=c++0x 
INFO: [HLS 200-10] Adding design file 'xf_resize_axis/xf_resize_axis.cpp' to the project
INFO: [HLS 200-1510] Running: add_files -tb xf_resize_axis/xf_resize_axis_tb.cpp -cflags -I../../../Xilinx_github/Vitis_Libraries/vision/L1/include -I../../../../../../usr/local/include -std=c++0x -Wno-unknown-pragmas -csimflags -Wno-unknown-pragmas 
INFO: [HLS 200-10] Adding test bench file 'xf_resize_axis/xf_resize_axis_tb.cpp' to the project
INFO: [HLS 200-1510] Running: open_solution solution1 -flow_target vivado 
INFO: [HLS 200-10] Opening solution '/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_resize_axis/solution1'.
INFO: [SYN 201-201] Setting up clock 'default' with a period of 10ns.
INFO: [HLS 200-1611] Setting target device to 'xc7z020-clg400-1'
INFO: [HLS 200-1505] Using flow_target 'vivado'
Resolution: For help on HLS 200-1505 see www.xilinx.com/cgi-bin/docs/rdoc?v=2021.2;t=hls+guidance;d=200-1505.html
INFO: [HLS 200-1510] Running: set_part xc7z020-clg400-1 
INFO: [HLS 200-1510] Running: create_clock -period 10 -name default 
INFO: [HLS 200-1510] Running: csynth_design 
INFO: [HLS 200-111] Finished File checks and directory preparation: CPU user time: 0.02 seconds. CPU system time: 0 seconds. Elapsed time: 0.01 seconds; current allocated memory: 1.125 GB.
INFO: [HLS 200-10] Analyzing design file 'xf_resize_axis/xf_resize_axis.cpp' ... 
ERROR: [HLS 207-812] 'common/xf_common.hpp' file not found (xf_resize_axis/xf_resize_axis.h:11:10)
INFO: [HLS 200-111] Finished Command csynth_design CPU user time: 0.25 seconds. CPU system time: 0.06 seconds. Elapsed time: 0.16 seconds; current allocated memory: 0.000 MB.
command 'ap_source' returned error code
    while executing
"source /media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_resize_axis/solution1/csynth.tcl"
    invoked from within
"hls::main /media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_resize_axis/solution1/csynth.tcl"
    ("uplevel" body line 1)
    invoked from within
"uplevel 1 hls::main {*}$newargs"
    (procedure "hls_proc" line 16)
    invoked from within
"hls_proc [info nameofexecutable] $argv"
INFO: [HLS 200-112] Total CPU user time: 2.47 seconds. Total CPU system time: 0.47 seconds. Total elapsed time: 1.86 seconds; peak allocated memory: 1.125 GB.
Finished C synthesis.


何で 'common/xf_common.hpp' file not found となるのだろう?インクルード・パスは指定してあるのだが。。。
成功した xf_median_blur との違いは何だろう?
xf_median_blur のインクルード・パスは設定した絶対パスで書いてある。xf_resize_axis の方は絶対パスを入力しても相対パスになってしまう。
Vitis_Vision2_135_220131.png

どうしてだろう?

(追記)
そういえば、自分でこの問題をトラブルシュートして、ブログ書いてあったのを忘れていた。orz
Vitis HLS 2021.2 で Vitis Vision Library を使用する2(dilation 編 2)
解決方法は Vitis HLS 2020.2 でプロジェクトを作成してから、そのプロジェクトを Vitis HLS 2021.2 で読み込んで合成する、だった。。。
もう一度、やり直してみよう。
  1. 2022年01月31日 04:45 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis Vision Library L1 の AXI4-Stream 入出力版 medianblur を 実機で動作を確認する 3

Vitis Vision Library L1 の AXI4-Stream 入出力版 medianblur を 実機で動作を確認する 2”の続き。

今まで積み上げてきた IP を使用して、Vitis Vision Library L1 の AXI4-Stream 入出力版 medianblur を 実機で動作を確認してみようとうことで、前回は、制約を追加することで、タイミングエラーを解消した。今回は、Vitis 2021.2 を起動して、プラットフォーム・プロジェクトとアプリケーション・プロジェクトを作成し、アプリケーション・ソフトウェアを作成する。そして、ビルドを行って、実機で動作を確認しよう。

Vivado 2021.2 から Vitis 2021.2 を起動した。
median_vvl_axis プロジェクトのディレクトリに vitis_work を作成して、そこを Vitis の workspace として指定した。
Vitis_Vision2_124_220128.png

median_filter_wrapper プラットフォーム・プロジェクトと median_filter_axis アプリケーション・プロジェクトを作成した。
Vitis_Vision2_125_220128.png

Vitis HLS 2021.2 を使用して画像ファイルを C のヘッダファイルに変換する”で作成した pict_data.h をインポートした。
median_filter_axis.c を作成した。
Vitis_Vision2_126_220129.png

median_filter_axis.c を示す。

// median_filter_axis.c
// 2022/01/29 by marsee
//

#include <stdio.h>
#include "xil_io.h"
#include "xparameters.h"

#include "xmedian_blur_accel_axis.h"
#include "xdma2axis2st.h"
#include "xaxis2dma2st.h"
#include "pict_data.h"

#define FRAME_BUFFER_ADDRESS 0x10000000
#define DMA_DEST_ADDRESS 0x10200000

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600

int bmp_write(unsigned int addr);
void Xil_DCacheFlush(void);

int main(){
    XMedian_blur_accel_axis xmf_axis_ap;
    XDma2axis2st xdma2axis_ap;
    XAxis2dma2st xaxis2dma_ap;
    int inbyte_in;

    XMedian_blur_accel_axis_Initialize(&xmf_axis_ap, 0);
    XDma2axis2st_Initialize(&xdma2axis_ap, 0);
    XAxis2dma2st_Initialize(&xaxis2dma_ap, 0);

    XDma2axis2st_Set_y_size(&xdma2axis_ap, (u32)VERTICAL_LINES);
    XDma2axis2st_Set_x_size(&xdma2axis_ap, (u32)HORIZONTAL_PIXELS);
    XDma2axis2st_Set_sel(&xdma2axis_ap, (u32)0);
    XDma2axis2st_Set_in_r(&xdma2axis_ap, (u32)FRAME_BUFFER_ADDRESS);

    XMedian_blur_accel_axis_Set_img_width(&xmf_axis_ap, (u32)HORIZONTAL_PIXELS);
    XMedian_blur_accel_axis_Set_img_height(&xmf_axis_ap, (u32)VERTICAL_LINES);

    XAxis2dma2st_Set_y_size(&xaxis2dma_ap, (u32)VERTICAL_LINES);
    XAxis2dma2st_Set_x_size(&xaxis2dma_ap, (u32)HORIZONTAL_PIXELS);
    XAxis2dma2st_Set_sel(&xaxis2dma_ap, (u32)0);
    XAxis2dma2st_Set_out_r(&xaxis2dma_ap, (u32)DMA_DEST_ADDRESS);

    bmp_write(FRAME_BUFFER_ADDRESS);
    Xil_DCacheFlush();

    XAxis2dma2st_Start(&xaxis2dma_ap);
    XMedian_blur_accel_axis_Start(&xmf_axis_ap);
    XDma2axis2st_Start(&xdma2axis_ap);

    Xil_Out32(XPAR_BITMAP_DISP_CNTRLER_0_BASEADDR, DMA_DEST_ADDRESS);

    while(1){
        printf("\nPlease input <0> or <1> (<q> : exit) = ");
        fflush(stdout);
        inbyte_in = inbyte();
        printf("%c", inbyte_in);
        fflush(stdout);
        switch(inbyte_in) {
            case '0': //bmp image
                XDma2axis2st_Set_sel(&xdma2axis_ap, (u32)0);
                XAxis2dma2st_Set_sel(&xaxis2dma_ap, (u32)0);

                XAxis2dma2st_Start(&xaxis2dma_ap);
                XMedian_blur_accel_axis_Start(&xmf_axis_ap);
                XDma2axis2st_Start(&xdma2axis_ap);
                break;
            case '1': // filter
                XDma2axis2st_Set_sel(&xdma2axis_ap, (u32)1);
                XAxis2dma2st_Set_sel(&xaxis2dma_ap, (u32)1);

                XAxis2dma2st_Start(&xaxis2dma_ap);
                XMedian_blur_accel_axis_Start(&xmf_axis_ap);
                XDma2axis2st_Start(&xdma2axis_ap);
                break;
            case 'q': // exit
                return(0);
        }
    }
}

int bmp_write(unsigned int addr){
    for(int y=0; y<VERTICAL_LINES; y++){
        for(int x=0; x<HORIZONTAL_PIXELS; x++){
            Xil_Out32(addr+(y*HORIZONTAL_PIXELS+x)*sizeof(int),
                ((int)pict_file_array[y][x][2]<<16)+((int)pict_file_array[y][x][1]<<8)+(int)pict_file_array[y][x][0]);
        }
    }
    return(0);
}


ビルドを行ったところ、成功した。
median_filter_axis.elf が生成された。
Vitis_Vision2_127_220129.png

ZYBO Z7-20 の HDMI ポートをディスプレイに接続し、USB ケーブルを接続して、電源を ON した。
gtk_term をスーバーバイザー・モードで起動した。 115200 bps , 8 bit , 1 stop bit
Explorer の medain_filter_axis_system をクリックして、 Run ボタンをクリックし、FPGA をコンフィギュレーションし、アプリケーション・ソフトウェアを起動した。
gtk_term の画面に”Please input <0> or <1> (<q> : exit) = ”が表示された。
同時にディスプレイにノイズ入りの画像が表示された。
Vitis_Vision2_130_220129.jpg

キーボードで 1 を押すと、メディアン・フィルタが入ってノイズが消えた。成功だ。。。やったぜ。。。
Vitis_Vision2_131_220129.jpg

gtk_term 画面を示す。
Vitis_Vision2_129_220129.png
  1. 2022年01月29日 04:59 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis Vision Library L1 の AXI4-Stream 入出力版 medianblur を 実機で動作を確認する 2

Vitis Vision Library L1 の AXI4-Stream 入出力版 medianblur を 実機で動作を確認する 1”の続き。

今まで積み上げてきた IP を使用して、Vitis Vision Library L1 の AXI4-Stream 入出力版 medianblur を 実機で動作を確認してみようとうことで、前回は、各 IP を IP Catalog に追加して、ブロック・デザインを作成し、回路を完成させた。制約ファイルを追加して、論理合成、インプリメンテーション、ビットストリームの生成を行ったが、タイミングエラーが出てしまった。今回は、そのタイミングエラーを解消しよう。

Open Synthesized Design をクリックする。
Synthesized Design が開いた。
Timing タブをクリックし、Intra-Clock Paths -> pclk_buf to clk_fpga_0 をクリックして、エラー内容を見た。
最初の 1 項目だけスラックがマイナスだった。
Vitis_Vision2_116_220127.png

Other Path Groups -> **async_default** -> clk_fpga_0 to pclk_buf もスラックがマイナスだった。
Vitis_Vision2_117_220127.png

つまり、pclk_buf to clk_fpga_0 と clk_fpga_0 to pclk_buf がダメなようだ。

次に、Clock Domain Crossing のレポートを見てみよう。
Vivado の Reports メニューから Timing -> Report CDC... を選択する。
Report CDC ダイアログが開く。
Clocks の From に pclk_buf を To に clk_fpga_0 を入れて OK ボタンをクリックした。
Unsafe は無いようだ。
Vitis_Vision2_118_220127.png

clk_fpga_0 to pclk_buf を見た。
こちらも Unsafe は無かった。
Vitis_Vision2_119_220127.png

大丈夫そうなので、pclk_buf to clk_fpga_0 と clk_fpga_0 to pclk_buf に false path の設定を行った。
Vitis_Vision2_120_220127.png

変更された制約ファイル median_filter.xdc の内容を示す。

set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_0_B_p_0]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_1_R_p_0]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_2_G_p_0]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_clk_p_0]
set_property PACKAGE_PIN H16 [get_ports TMDS_tx_clk_p_0]
set_property PACKAGE_PIN D19 [get_ports TMDS_tx_0_B_p_0]
set_property PACKAGE_PIN C20 [get_ports TMDS_tx_1_R_p_0]
set_property PACKAGE_PIN B19 [get_ports TMDS_tx_2_G_p_0]

set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks -of_objects [get_pins median_filter_i/bitmap_disp_cntrler_0/inst/dvi_disp_i/BUFR_pixel_clk_io/O]]
set_false_path -from [get_clocks -of_objects [get_pins median_filter_i/bitmap_disp_cntrler_0/inst/dvi_disp_i/BUFR_pixel_clk_io/O]] -to [get_clocks clk_fpga_0]


これで、もう一度、論理合成、インプリメンテーション、ビットストリームの生成を行ったところ、成功した。
Project Summary を示す。
Vitis_Vision2_122_220127.png

ハードウェアをエクスポートして、median_filter_wrapper.xsa ファイルを生成した。
Vitis_Vision2_123_220128.png
  1. 2022年01月28日 04:21 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis Vision Library L1 の AXI4-Stream 入出力版 medianblur を 実機で動作を確認する 1

今まで積み上げてきた IP を使用して、Vitis Vision Library L1 の AXI4-Stream 入出力版 medianblur を 実機で動作を確認してみよう。実機は、ZYBO Z7-20 とする。
今まで積み上げてきたブログ記事を下に示す。
Vitis HLS 2021.2 で Vitis Vision Library を使用する5(AXI4-Stream 入出力の xf_median_blur 編 1)
Vitis HLS 2021.2 で Vitis Vision Library を使用する6(AXI4-Stream 入出力の xf_median_blur 編 2)
Vitis HLS 2021.2 で Vitis Vision Library を使用する7(AXI4-Stream 入出力の xf_median_blur 編 3)
Vitis Vision Library の AXI4-Stream のデータ・フォーマットを検証する
Vitis HLS 2021.2 を使用して画像ファイルを C のヘッダファイルに変換する
AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP を Vitis HLS 2021.2 で作成 1
AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP を Vitis HLS 2021.2 で作成 2
AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP を Vitis HLS 2021.2 で作成 1
AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP を Vitis HLS 2021.2 で作成 2

Vivado 2021.2 で ZYBO Z7-20 ボード用の median_vvl_axis プロジェクトを作成した。
Vitis_Vision2_106_220126.png

median_vvl_axis プロジェクトのディレクトリに DMA2axis2st, axis2DMA2st, xf_median_blur ディレクトリを新規作成して、各 IP をその下にコピー&ペーストした。
Vitis_Vision2_107_220126.png

ビットマップ・ディスプレイ・コントローラの BMDispCaL を median_vvl_axis プロジェクトのディレクトリに コピー&ペーストした。
Vitis_Vision2_108_220126.png

Flow Navigator の PROJECT MANAGER から IP Catalog をクリックして、IP Catlog ダイアログを開いた。
IP Catalog ダイアログの中で右クリックし右クリックメニューから Add Repository... を選択して、4 個の IP をリポジトリに追加した。
Vitis_Vision2_109_220126.png

Flow Navigator の IP INTEGRATOR から Create Block Design を選択して、median_filter ブロック・デザインを生成した。
IP を接続してブロック・デザインを完成させた。
Vitis_Vision2_110_220126.png

processing_system7_0 の設定だが、AXI_HP0 を有効にしてある。
Vitis_Vision2_114_220127.png

クロックは 100 MHz の FCLK_CLK0 とビットマップ・ディスプレイ・コントローラの BMDispCaL に供給するための 25 MHz の FCLK_CLK1 を生成している。
Vitis_Vision2_115_220127.png

Address Editor 画面を示す。
Vitis_Vision2_128_220129.png

source ウインドウで、ブロック・デザインの median_filter_i を右クリックし右クリックメニューから Create HDL Wrapper... を選択して、median_filter_wrapper.v を作成した。
Vitis_Vision2_111_220126.png

Add Source で median_filter.xdc を作成した。
Vitis_Vision2_112_220127.png

現在の median_filter.xdc を貼っておく。

set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_0_B_p_0]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_1_R_p_0]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_2_G_p_0]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_clk_p_0]
set_property PACKAGE_PIN H16 [get_ports TMDS_tx_clk_p_0]
set_property PACKAGE_PIN D19 [get_ports TMDS_tx_0_B_p_0]
set_property PACKAGE_PIN C20 [get_ports TMDS_tx_1_R_p_0]
set_property PACKAGE_PIN B19 [get_ports TMDS_tx_2_G_p_0]


Flow Navigator の PROGRAM AND DEBUG の Generate Bitstream をクリックして、論理合成、インプリメンテーション、ビットファイルを生成した。
Project Summary を示す。
タイミングエラーが出ている。
Vitis_Vision2_113_220127.png
  1. 2022年01月27日 04:12 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP を Vitis HLS 2021.2 で作成 2

AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP を Vitis HLS 2021.2 で作成 1”の続き。

Vitis HLS 2021.2 で”AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP 1”をやってみることにしたということで、前回は、axis2DMA2st プロジェクトを Vitis HLS 2021.2 で作成して、 C シミュレーションを行った。今回は、axis2DMA2st プロジェクトで C コードの合成、C/RTL 協調シミュレーション、Export RTL、Implementation を行った。

Cコードの合成を行った。
Vitis_Vision2_98_220125.png
Vitis_Vision2_99_220125.png
Vitis_Vision2_100_220125.png

Latency は 487806 クロックだった。今回の画像の総ピクセル数は 800 x 600 = 480000 ピクセルなので、
487806 / 480000 ≒ 1.02 クロック / ピクセルとなった。
リソース使用量は BRAM 4 個、DSP 3 個、FF 1459 個、LUT 1523 個だった。

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

Latency は 492004 クロックだった。性能は約 1.03 クロック / ピクセルだった。

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

C/RTL 協調シミュレーションの波形を拡大した。
Vitis_Vision2_103_220125.png

AWLEN が 0f なので、16 バーストになっているようだ。

Export RTL を行った。
axis2DMA2st/solution2/impl に export.zip が生成されている。
Vitis_Vision2_104_220125.png

Implementation を行った。
CP achieved post-implementation が 8.387 ns なので、問題無さそうだ。
Vitis_Vision2_105_220125.png
  1. 2022年01月26日 04:21 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP を Vitis HLS 2021.2 で作成 1

Vitis HLS 2021.2 で”AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP 1”をやってみることにした。これをやるのは Vitis HLS と Vivado HLS の違いを比べたいという欲求と Vitis Vision Library の AXI4-Stream 入出力の xf_median_blur IP を実機でテストしたいからだ。

最初にソースコードの axis2DMA2st.cpp を貼っておく。
(2022/01/25:修正)リソースを食いすぎたので、stdint.h をインクルードして、引数の定義を変更した。

// axis2DMA2st.cpp
// for Vitis HLS 2021.2
// 2022/01/24 by marsee
//

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

int axis2DMA2st(hls::stream<ap_axis<32,1,1,1> >& ins0, hls::stream<ap_axis<32,1,1,1> >& ins1,
    ap_uint<1> sel,  int32_t x_size, int32_t y_size, ap_int<32> *out){
#pragma HLS INTERFACE mode=s_axilite port=y_size
#pragma HLS INTERFACE mode=s_axilite port=x_size
#pragma HLS INTERFACE mode=s_axilite port=sel
#pragma HLS INTERFACE mode=axis register_mode=both port=ins1 register
#pragma HLS INTERFACE mode=axis register_mode=both port=ins0 register
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE m_axi depth=480000 port=out offset=slave
    ap_axis<32,1,1,1> val;

    Loop1 : do {    // user が 1 になった時にスタート
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        if(sel == 0)
            ins0 >> val;
        else
            ins1 >> val;
    } while(val.user == 0);

    for(int y=0; y<y_size; y++){
#pragma HLS LOOP_TRIPCOUNT min=600 max=600 avg=600
        for(int x=0; x<x_size; x++){
#pragma HLS LOOP_TRIPCOUNT min=800 max=800 avg=800
            if(!(y==0 && x==0)){
                if(sel == 0)
                    ins0 >> val;
                else
                    ins1 >> val;
            }
            out[y*x_size+x] = val.data;
        }
    }

    return(0);
}


テストベンチの axis2DMA2st_tb.cpp を貼っておく。

// axis2DMA2st_tb.cpp
// for Vitis HLS 2021.2
// 2022/01/24 by marsee
//

#include <iostream>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"

#include "pict_data.h"

char OUTPUT_PICT_FILE0[] = "test0.jpg";
char OUTPUT_PICT_FILE1[] = "test1.jpg";

int axis2DMA2st(hls::stream<ap_axis<32,1,1,1> >& ins0, hls::stream<ap_axis<32,1,1,1> >& ins1,
    ap_uint<1> sel,  int32_t x_size, int32_t y_size, ap_int<32> *out);

int main(){
    hls::stream<ap_axis<32,1,1,1> > ins0;
    hls::stream<ap_axis<32,1,1,1> > ins1;
    ap_axis<32,1,1,1> axisp;
    ap_int<32> *wr_pict0, *wr_pict1;

    for(int y=0; y<Y_SIZE; y++){
        for(int x=0; x<X_SIZE; x++){
            axisp.data = (ap_int<32>)pict_file_array[y][x][0] | ((ap_int<32>)pict_file_array[y][x][1])<<8 | ((ap_int<32>)pict_file_array[y][x][2])<<16;

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

            if(x == X_SIZE-1)
                axisp.last = 1;
            else
                axisp.last = 0;

            ins0 << axisp;
            ins1 << axisp;
        }
    }

    if((wr_pict0 =(ap_int<32> *)malloc(sizeof(ap_int<32>) * (X_SIZE * Y_SIZE))) == NULL){
        fprintf(stderr, "Can't allocate wr_pict0 memory\n");
        exit(1);
    }

    if((wr_pict1 =(ap_int<32> *)malloc(sizeof(ap_int<32>) * (X_SIZE * Y_SIZE))) == NULL){
        fprintf(stderr, "Can't allocate wr_pict1 memory\n");
        exit(1);
    }

    axis2DMA2st(ins0, ins1, 0, X_SIZE, Y_SIZE, wr_pict0);

    cv::Mat img(Y_SIZE, X_SIZE, CV_8UC3);
    cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
    for (int y=0; y<Y_SIZE; y++){
        for (int x=0; x<X_SIZE; x++){
            ap_int<32> data = wr_pict0[y*X_SIZE+x];
            cv::Vec3b pixel;
            pixel[0] = data & 0xff; // blue
            pixel[1] = (data >> 8) & 0xff; // green
            pixel[2] = (data >> 16) & 0xff; // red
            dst_vec3b(y,x) = pixel;
        }
    }

    cv::imwrite(OUTPUT_PICT_FILE0, img);

    axis2DMA2st(ins0, ins1, 1, X_SIZE, Y_SIZE, wr_pict1);

    for (int y=0; y<Y_SIZE; y++){
        for (int x=0; x<X_SIZE; x++){
            ap_int<32> data = wr_pict1[y*X_SIZE+x];
            cv::Vec3b pixel;
            pixel[0] = data & 0xff; // blue
            pixel[1] = (data >> 8) & 0xff; // green
            pixel[2] = (data >> 16) & 0xff; // red
            dst_vec3b(y,x) = pixel;
        }
    }

    cv::imwrite(OUTPUT_PICT_FILE1, img);

    return(0);
}


他に使用するファイルは、画像ファイルを変換した C のヘッダ・ファイルの pict_data.h だ。

Vitis HLS 2021.2 で ZYBO Z7-20 用の DMA2axis2st プロジェクトを作成した。
画像ファイルを変換した C のヘッダ・ファイルの pict_data.h を axis2DMA2st プロジェクトのディレクトリにコピー&ペーストした。

Vitis HLS 2021.2 の axis2DMA2st プロジェクトを示す。
Vitis_Vision2_94_220124.png

Vitis HLS 2021.2 の Project メニューから Project Settings... を選択して、設定を行う。
Project Settings (axis2DMA2st) ダイアログが開く。
左のウインドウで Simulation をクリックする。
axis2DMA2st_tb.cpp の CFLAGS を設定する。(設定方法は、Edit CFLAGS... ボタンをクリックする)
axis2DMA2st_tb.cpp の CFLAGS に

-I/usr/local/include

を設定した。

Linker Flags に

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

を設定した。
Vitis_Vision2_95_220124.png

ZYBO Z7-20 を使用するので、64 ビットアドレスの DMA を禁止して、 32 ビットアドレスの DMA にする。
Vitis HLS の Solution メニューから Solution Settings... を選択する。
Solution Settings (solution1) ダイアログが開く。
config_interface を展開して、m_axi_addr64 の Value のチェックボックスのチェックを外した。

C シミュレーションを行った。
Vitis_Vision2_96_220124.png

axis2DMA2st/solution1/csim/build ディレクトリを見ると画像ファイルの test0.jpg と test1.jpg が生成されている。
Vitis_Vision2_97_220124.png
  1. 2022年01月24日 04:30 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

私のブログで bmp_header.h を使用する Vitis HLS テストベンチ・ファイルの入力画像縛りの件

私のブログで bmp_header.h を使用する Vitis HLS テストベンチ・ファイルがあるが、残念ながら、コードが足りないためグレースケールの BMP 画像ファイルには対応していない。例えば、”ZynqBerryZero で HDMI にラプラシアン・フィルタ画像を出力する1(Vitis HLS 2020.2編1)”は bmp_header.h 使っているので、この制限がある。
OpenCV の imread() や imwrite() 使っているのは、この制限がない。

gimp に表示されている 2 つの A キャラクタ画像だが、左はグレースケールで、右が 24 ビット RGB だ。
BMP_1_220123.png

左の A キャラクタ画像はグレースケールで、これでは、私の bmp_header.h を使用したテストベンチ・ファイルでは読めない。
BMP_2_220123.png

右の A キャラクタ画像は RGB 画像で、これだと、私の bmp_header.h を使用したテストベンチ・ファイルで読むことができる。
BMP_3_220123.png

gimp では、ファイルメニューから名前を付けてエクスポートを選んで、
”色空間の情報を書き込まない”にチェックを入れて、
詳細設定で” 24 ビット R8 G8 B8 ”のラジオボタンを選択する。
BMP_4_220123.png

  1. 2022年01月23日 15:40 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP を Vitis HLS 2021.2 で作成 2

AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP を Vitis HLS 2021.2 で作成 1”の続き。

Vitis Vision Library の AXI4-Stream 入出力の xf_median_blur IP を実機でテストするために、前回は、Vitis HLS 2021.2 で ZYBO Z7-20 用の DMA2axis2st プロジェクトを作成して、 C シミュレーションを行った。今回は、残りの C コードの合成、C/RTL 協調シミュレーション、Export RTL 、Implementation を行った。

C コードの合成を行った。結果を示す。
Vitis_Vision2_87_220123.png
Vitis_Vision2_88_220123.png

Latency は 487802 クロックだった。ピクセル数は 800 x 600 = 480000 ピクセルなので、
487802 / 480000 ≒ 1.02 クロック / ピクセルだった。悪くない。。。

C/RTL 協調シミュレーションを行った。
レイテンシは 490202 クロックだった。
490202 / 480000 ≒ 1.02 クロック / ピクセルだった。
Vitis_Vision2_89_220123.png

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

一部分拡大した。
Vitis_Vision2_91_220123.png

Export RTL を行った。
solution1/impl に export.zip ができている。ここに IP が凍結されている。
Vitis_Vision2_92_220123.png

Implementation を行った。
CP achieved post-implementation は 6.534 ns で良さそうだ。
Vitis_Vision2_93_220123.png
  1. 2022年01月23日 05:12 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP を Vitis HLS 2021.2 で作成 1

Vitis HLS 2021.2 で”AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP 1”をやってみることにした。これをやるのは Vitis HLS と Vivado HLS の違いを比べたいという欲求と Vitis Vision Library の AXI4-Stream 入出力の xf_median_blur IP を実機でテストしたいからだ。

最初にソースコードの DMA2axis2st.cpp を貼っておく。
Vivado HLS のコードに比べて、PIPELINE 指示子が抜けているが、これは、Vitis HLS が自動的に PIPELINE してくれるからだ。
(2022/01/26 :追記) ブロックレベルのインターフェースを AXI4-Lite インターフェースにするのを忘れていたので、プラグマを追加した。それに応じて、結果が変更されることに注意。

// DMA2axis2st.cpp
// for Vitis HLS 2021.2
// 2022/01/21 by marsee
//

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

int DMA2axis2st(ap_int<32> *in, int sel, int x_size, int y_size,
    hls::stream<ap_axis<32,1,1,1> >& outs0, hls::stream<ap_axis<32,1,1,1> >& outs1){
#pragma HLS INTERFACE mode=s_axilite port=return
#pragma HLS INTERFACE mode=axis register_mode=both port=outs1 register
#pragma HLS INTERFACE mode=axis register_mode=both port=outs0 register
#pragma HLS INTERFACE mode=s_axilite port=y_size
#pragma HLS INTERFACE mode=s_axilite port=x_size
#pragma HLS INTERFACE mode=s_axilite port=sel
#pragma HLS INTERFACE mode=m_axi depth=480000 port=in

    ap_axis<32,1,1,1> out_val;

    for(int y=0; y<y_size; y++){
#pragma HLS LOOP_TRIPCOUNT min=600 max=600 avg=600
        for(int x=0; x<x_size; x++){
#pragma HLS LOOP_TRIPCOUNT min=800 max=800 avg=800
            out_val.data = in[y*x_size+x];
            if(x==0 && y==0)
                out_val.user = 1;
            else
                out_val.user = 0;
            if(x == x_size-1)
                out_val.last = 1;
            else
                out_val.last = 0;
            if(sel == 0)
                outs0 << out_val;
            else
                outs1 << out_val;
        }
    }
    return(0);
}


テストベンチの DMA2axis2st_tb.cpp を貼っておく。

// DMA2axis2st_tb.cpp
// for Vitis HLS 2021.2
// 2022/01/21 by marsee
//

#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"

#include "pict_data.h"

#define Y_SIZE  600
#define X_SIZE  800

char OUTPUT_PICT_FILE0[] = "test0.jpg";
char OUTPUT_PICT_FILE1[] = "test1.jpg";

int DMA2axis2st(ap_int<32> *in, int sel, int x_size, int y_size,
    hls::stream<ap_axis<32,1,1,1> >& outs0, hls::stream<ap_axis<32,1,1,1> >& outs1);

int main(){
    hls::stream<ap_axis<32,1,1,1> > outs0;
    hls::stream<ap_axis<32,1,1,1> > outs1;
    ap_axis<32,1,1,1> axisp;
    ap_int<32> *rd_pict;

    if((rd_pict =(ap_int<32> *)malloc(sizeof(ap_int<32>) * (X_SIZE * Y_SIZE))) == NULL){
        fprintf(stderr, "Can't allocate rd_pict memory\n");
        exit(1);
    }

    for(int y=0; y<Y_SIZE; y++){
        for(int x=0; x<X_SIZE; x++){
            rd_pict[y*X_SIZE+x] = (int)(pict_file_array[y][x][0]) | ((int)(pict_file_array[y][x][1])<<8) | ((int)(pict_file_array[y][x][2]) <<16);
        }
    }

    DMA2axis2st(rd_pict, 0, X_SIZE, Y_SIZE, outs0, outs1);

    cv::Mat img(Y_SIZE, X_SIZE, CV_8UC3);
    cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
    for (int y=0; y<Y_SIZE; y++){
        for (int x=0; x<X_SIZE; x++){
            outs0 >> axisp;
            cv::Vec3b pixel;
            pixel[0] = axisp.data & 0xff; // blue
            pixel[1] = (axisp.data >> 8) & 0xff; // green
            pixel[2] = (axisp.data >> 16) & 0xff; // red
            dst_vec3b(y,x) = pixel;
        }
    }

    cv::imwrite(OUTPUT_PICT_FILE0, img);

    DMA2axis2st(rd_pict, 1, X_SIZE, Y_SIZE, outs0, outs1);

    for (int y=0; y<Y_SIZE; y++){
        for (int x=0; x<X_SIZE; x++){
            outs1 >> axisp;
            cv::Vec3b pixel;
            pixel[0] = axisp.data & 0xff; // blue
            pixel[1] = (axisp.data >> 8) & 0xff; // green
            pixel[2] = (axisp.data >> 16) & 0xff; // red
            dst_vec3b(y,x) = pixel;
        }
    }

    cv::imwrite(OUTPUT_PICT_FILE1, img);

    return(0);
}


他に使用するファイルは、画像ファイルを変換した C のヘッダ・ファイルの pict_data.h だ。

Vitis HLS 2021.2 で ZYBO Z7-20 用の DMA2axis2st プロジェクトを作成した。
画像ファイルを変換した C のヘッダ・ファイルの pict_data.h を DMA2axis2st プロジェクトのディレクトリにコピー&ペーストした。
Vitis_Vision2_81_220121.png

Vitis HLS 2021.2 の DMA2axis2st プロジェクトを示す。
Vitis_Vision2_82_220121.png

Vitis HLS 2021.2 の Project メニューから Project Settings... を選択して、設定を行う。
Project Settings (DMA2axis2st) ダイアログが開く。
左のウインドウで Simulation をクリックする。
DMA2axis2st_tb.cpp の CFLAGS を設定する。(設定方法は、Edit CFLAGS... ボタンをクリックする)
DMA2axis2st_tb.cpp の CFLAGS に

-I/usr/local/include

を設定した。

Linker Flags に

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

を設定した。
Vitis_Vision2_83_220121.png

ZYBO Z7-20 を使用するので、64 ビットアドレスの DMA を禁止して、 32 ビットアドレスの DMA にする。
Vitis HLS の Solution メニューから Solution Settings... を選択する。
Solution Settings (solution1) ダイアログが開く。
config_interface を展開して、m_axi_addr64 の Value のチェックボックスのチェックを外した。
Vitis_Vision2_86_220123.png

C シミュレーションを行った。
Vitis_Vision2_84_220121.png

test0.jpg と test1.jpg が生成されていた。
Vitis_Vision2_85_220121.png

DMA2axis2st/solution1/csim/build ディレクトリを見ると test0.jpg と test1.jpg がちゃんと画像ファイルになっていることが分かった。
  1. 2022年01月22日 04:45 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

画像ファイルをC のヘッダファイルに変換したファイルを Vitis HLS 2021.2 で検証してみた

Vitis HLS 2021.2 を使用して画像ファイルを C のヘッダファイルに変換する”で JPG ファイルを C 言語のヘッダに変換することができたが、本当に画像に戻るのかを今回検証する。このブログは、”BMPファイルをC のヘッダファイルに変換したファイルを検証してみた”を参照している。

Vitis HLS 2021.2 を使用して、pict_header2image プロジェクトを作成した。このプロジェクトは xc7z020clg400-1 の FPGA を使用したプロジェクトとした。

pict_header2image プロジェクトに”Vitis HLS 2021.2 を使用して画像ファイルを C のヘッダファイルに変換する”で作成した pict_data.h をコピー&ペーストした。
Vitis_Vision2_76_220121.png

pict_header2image プロジェクトを示す。
Vitis_Vision2_77_220121.png

ダミーのソースコード、 dummy.cpp を貼っておく。

int dummy(){
    return 0;
}


テストベンチの pict_header2image.cpp を貼っておく。

// pict_header2image.cpp
// 2022/01/21 by marsee
//

#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"

#include "pict_data.h"

char OUTPUT_PICT_FILE[] = "test2.jpg";

int main(){
    cv::Mat img(Y_SIZE, X_SIZE, CV_8UC3);
    cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
    for (int y=0; y<Y_SIZE; y++){
        for (int x=0; x<X_SIZE; x++){
            cv::Vec3b pixel;
            pixel[0] = pict_file_array[y][x][0]; // blue
            pixel[1] = pict_file_array[y][x][1]; // green
            pixel[2] = pict_file_array[y][x][2]; // red
            dst_vec3b(y,x) = pixel;
        }
    }

    cv::imwrite(OUTPUT_PICT_FILE, img);

    return(0);
}


Vitis HLS 2021.2 の Project メニューから Project Settings... を選択して、設定を行う。
Project Settings (pict_header2image) ダイアログが開く。
左のウインドウで Simulation をクリックする。
pict_header2image.cpp の CFLAGS を設定する。(設定方法は、Edit CFLAGS... ボタンをクリックする)
pict_header2image.cpp の CFLAGS に

-I/usr/local/include

を設定した。

Linker Flags に

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

を設定した。
Vitis_Vision2_78_220121.png

C シミュレーションを実行した。
test2.jpg が生成された。
Vitis_Vision2_79_220121.png

test2.jpg を示す。
画像ファイルに変換された。
Vitis_Vision2_80_220121.jpg
  1. 2022年01月21日 04:07 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 を使用して画像ファイルを C のヘッダファイルに変換する

Vivado HLS 2019.1 を使用してBMPファイルをC のヘッダファイルに変換する”というブログを書いたが、それを Vitis HLS 2021.2 でやってみる。また、OpenCV 3.4.9 を使用するので、BMP ファイルじゃなくても問題ない。従ってBMPファイルから画像ファイルにタイトルを変更した。

ソースコードの dummy.cpp を示す。
Vitis HLS 2021.2 では、ソースコードに何らかのファイルが無いと C シミュレーションがエラーになってしまうようだ。そこでダミーのファイルを用意した。このファイルは使わない。

int dummy(){
    return 0;
}


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

// pict_header_file.cpp
// 画像を C のヘッダファイルに変換する
// 2022/01/19 by marsee

#include <iostream>
#include <stdlib.h>
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"

char INPUT_PICT_FILE[] = "test2.jpg";
char OUTPUT_HEADER_FILE[] = "pict_data.h";

int main(){
    uint8_t *red, *green, *blue;
    FILE *fbmpw;

    // 画像ファイルをMat に読み込む
    cv::Mat img = cv::imread(INPUT_PICT_FILE);

    // ピクセルを入れるメモリをアロケートする
    if ((red =(uint8_t *)malloc(sizeof(uint8_t) * (img.rows * img.cols))) == NULL){
        fprintf(stderr, "Can't allocate red memory\n");
        exit(1);
    }
    if ((green =(uint8_t *)malloc(sizeof(uint8_t) * (img.rows * img.cols))) == NULL){
        fprintf(stderr, "Can't allocate green memory\n");
        exit(1);
    }
    if ((blue =(uint8_t *)malloc(sizeof(uint8_t) * (img.rows * img.cols))) == NULL){
        fprintf(stderr, "Can't allocate blue memory\n");
        exit(1);
    }

    cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
    for (int y=0; y<img.rows; y++){
        for (int x=0; x<img.cols; x++){
            cv::Vec3b pixel;
            pixel = dst_vec3b(y,x);
            blue[y*img.cols+x] = pixel[0]; // blue
            green[y*img.cols+x] = pixel[1]; // green
            red[y*img.cols+x] = pixel[2]; // red
        }
    }

    // 画像データのヘッダを画像出力ファイルに書き込む
    if ((fbmpw = fopen(OUTPUT_HEADER_FILE, "w")) == NULL){
        fprintf(stderr, "Can't open bmp header file\n");
        exit(1);
    }

    fprintf(fbmpw, "// %s\n", OUTPUT_HEADER_FILE);
    time_t now = std::time(nullptr);
    struct tm* jst = std::localtime(&now);
    fprintf(fbmpw, "// %04d/%02d/%02d %02d:%02d:%02d by marsee\n", jst->tm_year+1900, jst->tm_mon+1, jst->tm_mday,
            jst->tm_hour, jst->tm_min, jst->tm_sec);
    fprintf(fbmpw, "//\n\n");

    fprintf(fbmpw, "#define X_SIZE %d\n", img.cols);
    fprintf(fbmpw, "#define Y_SIZE %d\n\n", img.rows);

    fprintf(fbmpw, "unsigned char pict_file_array[%d][%d][3] = {\n", img.rows, img.cols);
    for (int y=0; y<img.rows; y++){
        fprintf(fbmpw, "\t{");
        for (int x=0; x<img.cols; x++){
            if (x != 0)
                fprintf(fbmpw, ",");

            fprintf(fbmpw, "{%d,%d,%d}", blue[y*img.cols+x], green[y*img.cols+x], red[y*img.cols+x]);
        }
        if (y == (img.rows-1))
            fprintf(fbmpw, "}\n");
        else
            fprintf(fbmpw, "},\n");
    }
    fprintf(fbmpw, "\n};");

    fclose(fbmpw);

    return(0);
}


変換する画像ファイル test2.jpg を示す。
800 x 600 ピクセルのノイズを付加した画像ファイルだ。
Vitis_Vision2_71_220120.jpg

Vitis HLS 2021.2 で pict_header_file プロジェクトを作成した。合成しないので、使用する FPGA やボードは何でも良いのだが、xc7z020clg400-1 を指定した。
Vitis_Vision2_70_220120.png

Vitis HLS 2021.2 の Project メニューから Project Settings... を選択して、設定を行う。
Project Settings (pict_header_file) ダイアログが開く。
左のウインドウで Simulation をクリックする。
pict_header_file.cpp の CFLAGS を設定する。(設定方法は、Edit CFLAGS... ボタンをクリックする)
pict_header_file.cpp の CFLAGS に

-I/usr/local/include

を設定した。

Linker Flags に

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

を設定した。
Vitis_Vision2_74_220120.png

C シミュレーションを実行した。
pict_data.h が生成された。
Vitis_Vision2_72_220120.png

pict_data.h の一部を見た。
Vitis_Vision2_73_220120.png

pict_data.h の大きさは 6 MB だった。データをテキストにしているので、ファイルが大きくなるのは仕方がない。
Vitis_Vision2_75_220120.png
  1. 2022年01月20日 05:33 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis Vision Library の AXI4-Stream のデータ・フォーマットを検証する

Vitis HLS 2021.2 で Vitis Vision Library を使用する7(AXI4-Stream 入出力の xf_median_blur 編 3)”の続き。

前回、AXI4-Stream 入出力の Vitis Vision Library の xf_median_blur を C/RTL 協調シミュレーションで波形を見ることができた。今回は、AX4-Stream 入出力関数、 xf::cv::AXIvideo2xfMat() 、 xf::cv::xfMat2AXIvideo() 関数のデータのフォーマットを検証する。

最初に自分で 128 x 128 ピクセルの RGBW128x128.png 画像を作成した。
これは、赤、緑、青、白の行に分かれている画像だ。
Vitis_Vision2_66_220117.png

この画像を Input Arguments に設定して C/RTL 協調シミュレーションを行った。
Vitis_Vision2_67_220118.png

C/RTL 協調シミュレーションが終了した。結果を示す。
Vitis_Vision2_68_220118.png

C/RTL 協調シミュレーション波形を観察する。
Vitis_Vision2_69_220118.png

この波形から
23 ビット目から 16 ビット目に Red
15 ビット目から 8 ビット目に Green
7 ビット目から 0 ビット目に Blue
が割り振られているのが分かる。

次回からは、xf_median_blur IP が実際に動作するか?調べてみよう。
  1. 2022年01月19日 04:45 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library を使用する7(AXI4-Stream 入出力の xf_median_blur 編 3)

Vitis HLS 2021.2 で Vitis Vision Library を使用する6(AXI4-Stream 入出力の xf_median_blur 編 2)”の続き。

Vitis HLS 2021.2 で dilation を実装してみることにしたということで、前回は、Vitis HLS 2021.2 を起動して、xf_median_blur プロジェクトを開いて、 C シミュレーション、C コードの合成、C/RTL 協調シミュレーションを行った。しかし、C/RTL 協調シミュレーション波形は見ることができなかった。今回は、画像サイズを 128 x 128 ピクセルに小さくして、C/RTL 協調シミュレーションを行って、波形を確認した。そして、Export RTL と Implementation を行った。

Vitis_Libraries/vision/data/128x128.png を使用して、xf_median_blur の C/RTL 協調シミュレーションを行った。
Vitis_Vision2_56_220116.png

結果を示す。
Latency は 18193 クロックだった。
128 x 128 = 16384 ピクセルなので、18193 / 16384 ≒ 1.11 クロック / ピクセルだった。
Vitis_Vision2_57_220116.png

今回は、波形を見ることができたので、まずは全体波形から示す。
Vitis_Vision2_58_220116.png

拡大した。
Vitis_Vision2_59_220116.png

p_src_TDATA を見ると、46xxxxxx で下 24 ビットにピクセル・データが入っていそうだ。
p_dst_TDATA も 00xxxxxx で下 24 ビットにピクセル・データが入っていることが分かる。
何処のバイト・フィールドが RGB なのか?は次回検証することにする。

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

Implementation を行った。
CP achieved post-implementation が 9.344 ns で危なそうだった。
Vitis_Vision2_60_220116.png
Vitis_Vision2_61_220116.png
Vitis_Vision2_62_220116.png

Vitis HLS メニューから Solution -> Solution Settings... を選択する。
Solution Settings (solution1) ダイアログが開く。
Synthesis を選択し、 Uncertainty を 5 ns にした。
Vitis_Vision2_63_220116.png

これで C コードの合成を行った。
Vitis_Vision2_64_220116.png

Estimated は 5.132 ns になっているが、果たしてどうだろうか?
Implementation を行ったが、以前同様だった。
Vitis_Vision2_65_220116.png

Uncertainty の 5 ns を消して、C コードの合成を行っておいた。結局、元に戻した。
以前の xfOpenCV でも、Uncertainty をいじっても CP achieved post-implementation が改善することは無かった気がする。
  1. 2022年01月18日 03:33 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library を使用する6(AXI4-Stream 入出力の xf_median_blur 編 2)

Vitis HLS 2021.2 で Vitis Vision Library を使用する5(AXI4-Stream 入出力の xf_median_blur 編 1)”の続き。

Vitis HLS 2021.2 で dilation を実装してみることにしたということで、前回は、本命の AXI4-Stream 入出力のメディアン・フィルタをやってみようということで、Vitis HLS 2020.2 で xf_median_blur プロジェクトを作成した。今回は、Vitis HLS 2021.2 を起動して、xf_median_blur プロジェクトを開いて、 C シミュレーション、C コードの合成、C/RTL 協調シミュレーションを行った。

Vitis HLS 2021.2 を起動して、、xf_median_blur プロジェクトを開いた。
C シミュレーションを行った。
Vitis_Vision2_43_220116.png

solution1/csim/build ディレクトリに hls.jpg, out_ocv.jpg, diff_img.jpg が生成されている。
hls.jpg を見ると、test2.jpg のノイズが綺麗に除去されていた。メディアン・フィルタのノイズ除去機能が発揮されている。
Vitis_Vision2_45_220116.jpg

Vitis_Vision2_46_220116.jpg

C コードの合成を行って成功した。
Vitis Vision Library L1 で初めて実用的な AXI4-Stream 入出力の IP の C コードの合成が成功した。嬉しい。。。
Vitis_Vision2_47_220116.png
Vitis_Vision2_48_220116.png
Vitis_Vision2_49_220116.png
Vitis_Vision2_50_220116.png
Vitis_Vision2_51_220116.png
Vitis_Vision2_52_220116.png

Latency は 2096432 クロックだった。
画像は最大の 1920 x 1080 = 2073600 ピクセルだから、2096432 / 2073600 ≒ 1.01 クロック/ピクセルだった。

C/RTL 協調シミュレーションを行った。
Co-Simulation Dialog の Input Argument に test2.jpg を指定して、Dump Trace を all にして、C/RTL 協調シミュレーションを行ったが終了しなかった。

そこで、Dump Trace を port にして C/RTL 協調シミュレーションをやり直したが、これも終了しなかった。
Vitis_Vision2_53_220116.png

Dump Trace を none にしたところ、C/RTL 協調シミュレーションが終了した。
結果を示す。
Vitis_Vision2_54_220116.png

Latency は 932817 クロックだった。
シミュレーションでは実際の画像をメディアン・フィルタ処理した時のクロック数なので、画像は 1280 x 720 = 921600 ピクセルとなる。
932817 / 921600 ≒ 1.01 クロック / ピクセルとなった。
  1. 2022年01月16日 05:21 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library を使用する5(AXI4-Stream 入出力の xf_median_blur 編 1)

Vitis HLS 2021.2 で Vitis Vision Library を使用する4(rgbirbayer 編)”の続き。

Vitis HLS 2021.2 で dilation を実装してみることにしたということで、前回は、rgbirbayer をやってみた。これは、AXI4-Stream 入出力で実装されている。dilation 編同様、Vitis HLS 2020.2 でプロジェクトを作成してから Vitis HLS 2021.2 で C コードの合成をやってみた。なお、入力画像が用意できないので、シミュレーションは無しとする。結果は Vitis HLS 2020.2 では C コードの合成が成功したが、Vitis HLS 2021.2 ではエラーになってしまった。今回は、本命の AXI4-Stream 入出力のメディアン・フィルタをやってみよう。

以前、xfOpenCV で AXI4-Stream 版の medianblur をやってみた。”Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる1
Vitis HLS 2020.2 のときに、この xfOpenCV 版をやってみたが、エラーで合成ができなかった。”Vitis Vision Library で AXI4-Stream 入出力の medianblur を実装する1
今回、AXI4-Stream 入出力のサンプルコードの rgbirbayer が公開されていたので、それに合わせて”Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる1”を変更した。
プロジェクトは Vitis HLS 2020.2 で作成し、そのプロジェクトを Vitis HLS 2021.2 で使用することにする。

xf_median_blur.h を示す。

// xf_median_blur.h
// 2020/03/09 by marsee
// xfopencv/examples/medianblur/xf_median_blur_config.h のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/examples/medianblur/xf_median_blur_config.h
// xfopencv/examples/medianblur/xf_config_params.h のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/examples/medianblur/xf_config_params.h
// 2022/01/10 : for Vitis Vision Library

#ifndef __XF_MEDIAN_BLUR_H__
#define __XF_MEDIAN_BLUR_H__

#include "hls_stream.h"
#include "ap_int.h"
#include "common/xf_common.hpp"
#include "ap_axi_sdata.h"
#include "common/xf_infra.hpp"
#include "common/xf_axi_io.hpp"

#include "imgproc/xf_median_blur.hpp"
//#include "xf_config_params.hpp"

#define NO  1  // Normal Operation
#define RO  0  // Resource Optimized

#define RGB 1
#define GRAY 0

/* Filter window size*/
#define WINDOW_SIZE 3

/*  set the height and weight  */
#define WIDTH  1920
#define HEIGHT 1080

#if NO
#define NPxPC XF_NPPC1
#else
#define NPxPC XF_NPPC8
#endif

#if GRAY
#define TYPE XF_8UC1
#define CHANNELS 1
#define STREAMW 8
#else
#define TYPE XF_8UC3
#define CHANNELS 3
#define STREAMW 32
#endif

typedef hls::stream<ap_axiu<STREAMW,1,1,1> > AXI_STREAM;

#endif


xf_median_blur.cpp を示す。

// xf_median_blur.cpp
// 2020/03/08 by marsee

// xfopencv/HLS_Use_Model/Standalone_HLS_AXI_Example/xf_ip_accel_app.cpp のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/HLS_Use_Model/Standalone_HLS_AXI_Example/xf_ip_accel_app.cpp
// xfopencv/examples/medianblur/xf_median_blur_accel.cpp のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/examples/medianblur/xf_median_blur_accel.cpp
// 2022/01/10 : for Vitis Vision Library

#include "xf_median_blur.h"

void median_blur_accel_axis(AXI_STREAM& _src, AXI_STREAM& _dst, int img_height, int img_width){
#pragma HLS INTERFACE mode=s_axilite port=img_width
#pragma HLS INTERFACE mode=s_axilite port=img_height
#pragma HLS INTERFACE mode=s_axilite port=return
#pragma HLS INTERFACE mode=axis register_mode=both port=_src register
#pragma HLS INTERFACE mode=axis register_mode=both port=_dst register

    xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPxPC> img_in(img_height, img_width);
    xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPxPC> img_out(img_height, img_width);

#pragma HLS DATAFLOW

    xf::cv::AXIvideo2xfMat(_src, img_in);

    xf::cv::medianBlur <WINDOW_SIZE, XF_BORDER_REPLICATE, TYPE, HEIGHT, WIDTH,  NPxPC> (img_in, img_out);

    xf::cv::xfMat2AXIvideo(img_out, _dst);
}


xf_median_blur_tb.cpp を示す。

// xf_median_blur_config_tb.cpp
// 2020/03/08 by marsee

// xfopencv/HLS_Use_Model/Standalone_HLS_AXI_Example/xf_dilation_tb.cpp のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/HLS_Use_Model/Standalone_HLS_AXI_Example/xf_dilation_tb.cpp
// xfopencv/examples/medianblur/xf_median_blur_tb.cpp のコードを引用している
// https://github.com/Xilinx/xfopencv/blob/master/examples/medianblur/xf_median_blur_tb.cpp
// 2022/01/10 : for Vitis Vision Library

#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "xf_median_blur.h"
#include "common/xf_axi.hpp"
#include "common/xf_sw_utils.hpp"

void median_blur_accel_axis(AXI_STREAM& _src, AXI_STREAM& _dst, int img_height, int img_width);

int main(int argc, char** argv)
{

    if(argc != 2)
    {
        fprintf(stderr,"Invalid Number of Arguments!\nUsage:\n");
        fprintf(stderr,"<Executable Name> <input image path> \n");
        return -1;
    }

    cv::Mat out_img,ocv_ref;
    cv::Mat in_img,in_img1,diff;

    // reading in the color image
#if GRAY
    in_img = cv::imread(argv[1], 0);
#else
    in_img = cv::imread(argv[1], 1);
#endif
    if (in_img.data == NULL)
    {
        fprintf(stderr,"Cannot open image at %s\n", argv[1]);
        return 0;
    }
    // create memory for output images
    /*  reading the gray/color image  */
#if GRAY
    ocv_ref.create(in_img.rows,in_img.cols,CV_8UC1);
    out_img.create(in_img.rows,in_img.cols,CV_8UC1);
    diff.create(in_img.rows,in_img.cols,CV_8UC1);
    in_img1.create(in_img.rows,in_img.cols,CV_8UC1);

#else
    ocv_ref.create(in_img.rows,in_img.cols,CV_8UC3);
    out_img.create(in_img.rows,in_img.cols,CV_8UC3);
    diff.create(in_img.rows,in_img.cols,CV_8UC3);
    in_img1.create(in_img.rows,in_img.cols,CV_8UC3);
#endif
    int img_height = in_img.rows;
    int img_width = in_img.cols;

    /////////////////   Opencv  Reference  ////////////////////////
    cv::medianBlur(in_img,ocv_ref,WINDOW_SIZE);
    cv::imwrite("out_ocv.jpg", ocv_ref);

    AXI_STREAM _src,_dst;

    xf::cv::cvMat2AXIvideoxf<NPxPC>(in_img, _src);
    median_blur_accel_axis(_src, _dst, img_height, img_width);
    xf::cv::AXIvideo2cvMatxf<NPxPC>(_dst, in_img1);

    cv::imwrite("hls.jpg", in_img1);
    //////////////////  Compute Absolute Difference ////////////////////

    cv::absdiff(ocv_ref, in_img1, diff);

    float err_per;
    xf::cv::analyzeDiff(diff,0,err_per);
    cv::imwrite("diff_img.jpg",diff);

    in_img.~Mat();
    out_img.~Mat();
    ocv_ref.~Mat();
    in_img.~Mat();
    in_img1.~Mat();
    diff.~Mat();

    if(err_per > 0.0f)
    {
        return 1;
    }

    return 0;
}



Vitis HLS 2020.2 で xf_median_blur プロジェクトを作成した。
Vitis_Vision2_38_220116.png

xf_median_blur ディレクトリに 1280 x 720 ピクセルの test2.jpg 、 xf_median_blur.h, xf_median_blur.cpp, xf_median_blur_tb.cpp をコピーした。
Vitis_Vision2_39_220116.png

test2.jpg を示す。ランダム・ノイズを画像に重畳している。
Vitis_Vision2_45_220116.jpg

Vitis HLS 2021.2 の Project メニューから Project Settings... を選択して、設定を行う。
Project Settings (xf_median_blur) ダイアログが開く。
左のウインドウで Simulation をクリックする。
xf_median_blur_tb.cpp の CFLAGS を設定する。(設定方法は、Edit CFLAGS... ボタンをクリックする)
xf_median_blur_tb.cpp の CFLAGS に

-I/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include -std=c++0x -I/usr/local/include

を設定した。

Linker Flags に

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

を設定した。
Input Arguments に

/media/masaaki/Ubuntu_Disk/Vitis_HLS/ZYBO_Z7_20/2021.2/xf_median_blur/test2.jpg

を設定した。
Vitis_Vision2_41_220116.png

Project Settings (xf_median_blur) ダイアログの左のウインドウで Synthesis をクリックしxf_median_blur.cpp の CFLAGS を設定する。(設定方法は、Edit CFLAGS... ボタンをクリックする)

-I/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include -std=c++0x

を設定した。
Vitis_Vision2_41_220116.png

ZYBO Z7-20 を使用するので、64 ビットアドレスの DMA を禁止して、 32 ビットアドレスの DMA にする。
Vitis HLS の Solution メニューから Solution Settings... を選択する。
Solution Settings (solution1) ダイアログが開く。
config_interface を展開して、m_axi_addr64 の Value のチェックボックスのチェックを外した。
Vitis_Vision2_42_220116.png

これで、Vitis HLS 2020.2 の作業は終了し、次回からは Vitis HLS 2021.2 でプロジェクトを開いて、作業をしていく。
  1. 2022年01月15日 05:20 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library を使用する4(rgbirbayer 編)

Vitis HLS 2021.2 で Vitis Vision Library を使用する3(dilation 編 3)”の続き。

Vitis HLS 2021.2 で dilation を実装してみることにしたということで、前回は、dilation の残りの C/RTL 協調シミュレーションと Export RTL , Implementation を行った。今回は、rgbirbayer をやってみたい。これは、AXI4-Stream 入出力で実装されている。dilation 編同様、Vitis HLS 2020.2 でプロジェクトを作成してから Vitis HLS 2021.2 で C コードの合成をやってみた。なお、入力画像が用意できないので、シミュレーションは無しとする。

Vitis HLS 2020.2 で xf_rgbirbayer プロジェクトを作成した。

Vitis_Libraries/vision/L1/examples/rgbirbayer/ の xf_config_params.h, xf_rgbir_accel_axivideo.cpp, xf_rgbir_config_axivideo.h を xf_rgbirbayer ディレクトリにコピーした。
Vitis_Vision2_31_220113.png

Vitis HLS 2020.2 の sources に xf_rgbir_accel_axivideo.cpp を Add Source した。
xf_rgbir_accel_axivideo.cpp は AXI4-Stream 入出力で、AXI4-Stream と xf::cv::Mat 形式を変換するために xf::cv::AXIvideo2xfMat() と xf::cv::xfMat2AXIvideo() の組を使用している。
Vitis_Vision2_32_220113.png

Vitis HLS 2021.2 の Project メニューから Project Settings... を選択して、設定を行う。
Project Settings (xf_rgbirbayer) ダイアログが開く。
左のウインドウで Synthesis をクリックし、xf_rgbir_accel_axivideo.cpp の CFLAGS を設定する。(設定方法は、Edit CFLAGS... ボタンをクリックする)

-I/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include -std=c++0x

を設定した。

ZYBO Z7-20 を使用するので、64 ビットアドレスの DMA を禁止して、 32 ビットアドレスの DMA にする。
Vitis HLS の Solution メニューから Solution Settings... を選択する。
Solution Settings (solution1) ダイアログが開く。
config_interface を展開して、m_axi_addr64 の Value のチェックボックスのチェックを外した。

一旦、Vitis HLS 2020.2 で C コードの合成を行った。
Estimated が 9.007 ns で Slack がマイナスになってしまったが、合成することができた。
Vitis_Vision2_34_220114.png
Vitis_Vision2_35_220114.png
Vitis_Vision2_36_220114.png

Vitis HLS 2020.2 を落として、Vitis HLS 2021.2 を起動して、 xf_rgbirbayer プロジェクトを読み込んだ。
C コードの合成を行ったところ、エラーが発生した。
Vitis_Vision2_37_220114.png

エラー内容を示す。

ERROR: [SYNCHK 200-61] /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_utility.hpp:66:
unsupported memory access on variable 'tmp_buf' which is (or contains) an array with unknown size at compile time.


Vitis HLS 2021.2 で C コードの合成をすることができなかった。。。
  1. 2022年01月14日 04:32 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library を使用する3(dilation 編 3)

Vitis HLS 2021.2 で Vitis Vision Library を使用する2(dilation 編 2)”の続き。

Vitis HLS 2021.2 で dilation を実装してみることにしたということで、前回は、xf_dilation プロジェクトで C シミュレーション、C コードの合成を行ったが、C コードの合成でエラーになってしまった。しかし、Vitis HLS 2020.2 でプロジェクトを作成してから、そのプロジェクトを Vitis HLS 2021.2 で使用すれば C コードの合成が成功した。今回は、残りの C/RTL 協調シミュレーションと Export RTL , Implementation を行った。

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

Latency は 17834 クロックだった。

C/RTL 協調シミュレーションの波形を示す。
全体波形から。
Vitis_Vision2_27_220113.png
Vitis_Vision2_28_220113.png

拡大する。
Vitis_Vision2_29_220113.png
Vitis_Vision2_30_220113.png

AXI4 Master Read はバーストしているが、AXI4 Master Write はバースト設定にはなっているが、転送間の間が空いている。

Export RTL を行った。
solution1/impl に export.zip が生成された。
Vitis_Vision2_22_220113.png

Implementation を行った。
結果を示す。
Vitis_Vision2_23_220113.png
Vitis_Vision2_24_220113.png
Vitis_Vision2_25_220113.png

Timing Met している。
CP achieved post-implementation は 8.314 ns だった。問題無さそうだ。
  1. 2022年01月13日 05:17 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library を使用する2(dilation 編 2)

Vitis HLS 2021.2 で Vitis Vision Library を使用する1(dilation 編 1)”の続き。

Vitis HLS 2021.2 で dilation を実装してみることにしたということで、前回は、Vitis_Libraries/vision/L1/examples/dilation を Vitis HLS 2021.2 で xf_dilation プロジェクトを作成した。今回は、xf_dilation プロジェクトで C シミュレーション、C コードの合成を行ったが、C コードの合成でエラーになってしまった。
OS は Ubuntu 18.04 LTS を使用している。

xf_dilation プロジェクトで C シミュレーションを行った。
C シミュレーションは成功した。
Vitis_Vision2_6_220112.png

しかし、 dilation/solution1/csim/build ディレクトリの hw_out.jpg を見ると出力がおかしいというのは、前回の”Vitis HLS 2020.2 で Vitis Vision Library を使用する2(dilation 編 2)”と同じ結果だった。
Vitis_Vision2_7_220112.png

C シミュレーションを行ったが、エラーになってしまった。
Vitis_Vision2_8_220112.png

エラー内容は

ERROR: [HLS 207-812] 'common/xf_common.hpp' file not found (xf_dilation/xf_dilation_config.h:22:10)

だった。
Vitis Vision Library L1 の include ディレクトリは指定してあるのだが。。。

なお、Vitis HLS 2021.1 でも xf_dilation プロジェクトを作成して、C コードの合成を行っても同様なエラーが発生した。
Vitis_Vision2_9_220112.png

Vitis HLS 2020.2 で、xf_dilation プロジェクトを作成して、C コードの合成を行うと成功した。
Vitis_Vision2_10_220112.png

それから、不思議なことに、Vitis HLS 2020.2 で xf_dilation_202 プロジェクトを作成し、Vitis HLS 2021.2 で開いて、 C コードの合成を行うと成功した???
Vitis_Vision2_11_220112.png

この結果からすると、Vitis Vision Library L1 を Vitis HLS 2021.X で C コードを合成する時にエラーがでるというバグがあって、それは、プロジェクト作成時に GUI が Synthesis の時の include パスを正常に反映できていないというバグなんじゃないだろうか?

とりあえず Vitis HLS 2021.2 の xf_dilation_202 プロジェクトの合成結果を示す。
Vitis_Vision2_12_220112.png
Vitis_Vision2_13_220112.png
Vitis_Vision2_14_220112.png
Vitis_Vision2_15_220112.png
Vitis_Vision2_16_220112.png
Vitis_Vision2_17_220112.png
Vitis_Vision2_18_220112.png
Vitis_Vision2_19_220112.png
  1. 2022年01月12日 04:40 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で Vitis Vision Library を使用する1(dilation 編 1)

Vitis Vision Library を Vitis HLS 2021.2 を使用してやってみることにした。
きっかけは Vitis_Libraries/vision/L1/examples/rgbirbayer/ を見たことだった。この実装は、 AXI4-Stream を使用して実装されている。 Vitis Vision Library で AXI4-Stream が使えるととっても良い。前回 Vitis Vision Library をやった時は AXI4-Stream 入出力にすることができなかった。
また、”XF_8UC4 を使用して median_blur_accel() を実装する”で失敗したが、 XF_8UC4 が Vitis Vision Library で使用できるととっても良い。XF_8UC4 が使用できるようになっていないだろうか?
とりあえず、現状を知るために Vitis HLS 2021.2 で dilation を実装してみることにした。

Vitis Vision Library を使用する時の Vitis HLS 2020.2 の設定方法(dilation 編 1)”を見て、xf_dilation プロジェクトを Vitis HLS 2021.2 で作成しよう。

Vitis HLS 2021.2 で ZYBO Z7-20 用の xf_dilation プロジェクトを作成した。

Vitis Libraries を もう一度、git clone した。
git clone https://github.com/Xilinx/Vitis_Libraries.git

Vitis HLS 2021.2 で xf_dilation プロジェクトを作成した。

Vitis_Libraries/vision/L1/examples/dilation ディレクトリの 3 つのファイル

xf_dilation_accel.cpp
xf_dilation_config.h
xf_dilation_tb.cpp


を Vitis HLS の dilation プロジェクトのディレクトリにコピーした。

Vitis_Libraries/vision/L1/examples/dilation/build ディレクトリの

xf_config_params.h


も Vitis HLS の dilation プロジェクトのディレクトリにコピーした。
Vitis_Vision2_2_220111.png

Vitis HLS の Explorer で Source に xf_dilation_accel.cpp を Test Bench に xf_dilation_tb.cpp を登録した。
Vitis_Vision2_1_220111.png

Vitis HLS 2021.2 の Project メニューから Project Settings... を選択して、設定を行う。
Project Settings (dilation) ダイアログが開く。
左のウインドウで Simulation をクリックする。
xf_dilation_tb.cpp の CFLAGS を設定する。(設定方法は、Edit CFLAGS... ボタンをクリックする)
xf_dilation_tb.cpp の CFLAGS に

-I/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include -std=c++0x -I/usr/local/include

を設定した。

Linker Flags に

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

を設定した。
Input Arguments に

/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/data/128x128.png

を指定した。
Vitis_Vision2_3_220111.png

Project Settings (dilation) ダイアログの左のウインドウで Synthesis をクリックし、xf_dilation_accel.cpp の CFLAGS を設定する。(設定方法は、Edit CFLAGS... ボタンをクリックする)

-I/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include -std=c++0x

を設定した。
Vitis_Vision2_4_220111.png

最後に ZYBO Z7-20 を使用するので、64 ビットアドレスの DMA を禁止して、 32 ビットアドレスの DMA にする。
Vitis HLS の Solution メニューから Solution Settings... を選択する。
Solution Settings (solution1) ダイアログが開く。
config_interface を展開して、m_axi_addr64 の Value のチェックボックスのチェックを外した。
Vitis_Vision2_5_220111.png
  1. 2022年01月11日 04:53 |
  2. Vitis_Vision
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS, Vitis HLS の 2022 年問題にパッチを当てる

Vivado HLSリビジョンオーバーフロー問題のパッチの当て方”(参考にさせて頂きます)を見て Vivado HLS, Vitis HLS の 2022 年問題のパッチが出ていることに気がついたので、私もやってみることにした。

Vivado HLS, Vitis HLS の 2022 年問題については、”Vivado HLS, Vitis HLS で 2022 年問題発生”を参照のこと。

パッチは”Export IP Invalid Argument / Revision Number Overflow Issue (Y2K22)”にあった。
ファイル名は、y2k22_patch-1.2.zip だった。
HLS_problem_2022_7_220109.png


Ubuntu 18.04 LTS での Vitis HLS 2021.2 のパッチ
y2k22_patch-1.2.zip をダウンロードして展開した。
HLS_problem_2022_8_220109.png

展開された y2k22_patch ディレクトリを確認した。
HLS_problem_2022_9_220109.png

README ファイルを確認した。
パッチのやり方が書いてある。
HLS_problem_2022_10_220109.png

Vitis hLS 2021.2 にパッチを当てよう。
Vivado などのインストール・ディレクトリに移動して LD_LIBRARY_PATH 環境変数を設定して、パッチを当てた。
cd /media/masaaki/Ubuntu_Disk/tools/Xilinx/
export LD_LIBRARY_PATH=$PWD/Vivado/2021.2/tps/lnx64/python-3.8.3/lib/
Vivado/2021.2/tps/lnx64/python-3.8.3/bin/python3 y2k22_patch/patch.py

HLS_problem_2022_11_220109.png
HLS_problem_2022_12_220109.png

これでパッチが当たったはずなので、Vitis HLS 2021.2 を起動して、Export RTL を行ったところ成功した。
HLS_problem_2022_13_220109.png

solution1/impl ディレクトリに export.zip ができている。
HLS_problem_2022_14_220109.png

solution1/impl/ip ディレクトリにも IP が生成されていた。
HLS_problem_2022_20_220109.png


Windows11 のパッチ
Windows11 に y2k22_patch-1.2.zip をダウンロードして解凍した。
HLS_problem_2022_15_220109.png

Windows ターミナルを起動して、C:\Xilinx フォルダに移動した。
Vivado\2021.2\tps\win64\python-3.8.3\python.exe y2k22_patch\patch.py
を実行した。
HLS_problem_2022_16_220109.png

Vitis HLS 2021.2 を起動して Export RTL を実行したところ、Windows11 でも成功した。
HLS_problem_2022_17_220109.png

solution1/impl ディレクトリに export.zip ができている。
HLS_problem_2022_18_220109.png

solution1/impl/ip ディレクトリにも IP が生成されていた。
HLS_problem_2022_19_220109.png

(追加)
Linux の 2019.2 のパッチ・コマンドが間違っていました。正しくは、
Vivado/2019.2/tps/lnx64/python-2.7.5/bin/python2.7 y2k22_patch/patch.py
です。

Linux の 2020.1 のパッチ・コマンドも間違っていました。正しくは、
Vivado/2020.1/tps/lnx64/python-2.7.16/bin/python2.7 y2k22_patch/patch.py
です。

Linux の 2020.2 のパッチ・コマンドも間違っていました。正しくは、
Vivado/2020.2/tps/lnx64/python-3.8.3/bin/python3.8 y2k22_patch/patch.py
です。

Linux の 2020.3 のパッチ・コマンドはやってないですが、間違っているんじゃないでしょうか?


Windows10 の場合
タスクバーから検索を選んで、”コマンドプロンプト”と入力すると、コマンドプロンプトのアイコンが出てくるので、それをクリックして、コマンドプロンプトを立ち上げる。

Xilinx ツールのインストール・フォルダに行く。
私の場合は、cd J:\Xilinx , J:

Windows11 の場合と同様に Windows 用のコマンドを入力する。
Vitis HLS 2021.2 の場合は、
Vivado\2021.2\tps\win64\python-3.8.3\python.exe y2k22_patch\patch.py
HLS_problem_2022_20_220112.png
HLS_problem_2022_21_220112.png
  1. 2022年01月09日 05:23 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する7

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する6”の続き。

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定してみようということで、前回は、FCLK_CLK0 が 100 MHz 、FCLK_CLK1 が 50 MHz で再度やり直したところ、タイミング・エラーは発生しなかった。今回は、実際に動作するか?を調べてみよう。

ハードウェアをエクスポートした。
DMA_pow2_defclk_bd_wrapper.xsa ファイルが生成された。
AXI4-Lite_defclk_43_220107.png

Vivado の Tools メニューから Launch Vitis IDE を選択して、Vitis 2021.2 を起動する。
Vitis IDE Launcher が起動する。
vitis_work ディレクトリを作成して、Launch ボタンをクリックする。
AXI4-Lite_defclk_44_220107.png

Vitis 2021.2 が起動した。
AXI4-Lite_defclk_45_220107.png

Create Application Project をクリックして、DMA_pow2_defclk_test アプリケーション・プロジェクトを作成した。DMA_pow2_defclk_bd_wrapper プラットフォーム・プロジェクトも作成した。
AXI4-Lite_defclk_46_220108.png

DMA_pow2_defclk_test.c を作成した。
AXI4-Lite_defclk_47_220108.png

トンカチアイコンをクリックして、ビルドを行った。
DMA_pow2_defclk_test.elf ファイルが生成された。
AXI4-Lite_defclk_48_220108.png

Explorer で DMA_pow2_defclk_test_system を選択して、Run アイコンをクリックすると ZYBO Z7-20 がコンフィギュレーションされて、DMA_pow2_defclk_test.elf ファイルが実行された。
AXI4-Lite_defclk_49_220108.png

Tera Term に 2 乗したデータが表示された。成功だ。
AXI4-Lite_defclk_50_220108.png

結局、Vitis HLS 2021.2 の AXI4-Lite インターフェースのクロックを独自に生成する機能は、クロック載せ替えがされていないので、特定の周波数しか Vivado でのタイミングがメットしないようだ。今回は、IP 全体の動作周波数が 100 MHz で AXI4-Lite インターフェースが 50 MHz で動作確認した。
  1. 2022年01月09日 04:19 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する6

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する5”の続き。

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定してみようということで、前回は、タイミング・エラーを検証して FCLK_CLK0 が 100 MHz 、FCLK_CLK1 が 75 MHz ではダメそうだということが分かった。今回は、FCLK_CLK0 が 100 MHz 、FCLK_CLK1 が 50 MHz で再度やり直してみよう。

DMA_pow2_defclk_bd ブロック・デザインを再度示す。
AXI4-Lite_defclk_26_220105.png

ブロック・デザインで processing_system7_0 をダブルクリックして設定画面を開く。
FCLK_CLK1 を 50 MHz に設定する。
AXI4-Lite_defclk_38_220107.png

これで、論理合成、インプリメンテーション、ビットストリームの生成を行ったところ、今度はタイミング・エラーが発生しなかった。
Project Summary を示す。
AXI4-Lite_defclk_39_220107.png

Open Implemented Design を開いた。
Inter-Clock Paths も問題ない。
AXI4-Lite_defclk_40_220107.png

Report CDC... をやってみた。
clk_fpga_0 to clk_fpga_1 を示す。
AXI4-Lite_defclk_41_220107.png

これは何も変わっていない。

clk_fpga_1 to clk_fpga_0 を示す。
AXI4-Lite_defclk_42_220107.png

こちらも変わっていない。
  1. 2022年01月08日 04:25 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する5

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する4”の続き。

itis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定してみようということで、前回は、前回 IP を作成できたので、Vivado 2021.2 でプロジェクトを作成し、作成した DMP_pow2_defclk IP を使用して、ブロック・デザインを作成した。そして、論理合成、インプリメンテーション、ビットストリームの生成を行ったが、タイミングでエラーになった。今回は、タイミング・エラーを検証する。

Vivado 2021.2 GUI の Flow Navigator から IMPLEMENTATION -> Open Implemented Design をクリックして起動した。
AXI4-Lite_defclk_29_220106.png

Inter-Clock Paths の”clk_fpga_0 to clk_fpga_1”と”clk_fpga_1 to clk_fpga_0”にエラーが出ている。

”clk_fpga_0 to clk_fpga_1”のエラーを見た。
AXI4-Lite_defclk_30_220106.png

”clk_fpga_1 to clk_fpga_0”のエラーを見た。
AXI4-Lite_defclk_31_220106.png

Clock Domain Crossing のレポートを見てみよう。
Vivado の Reports メニューから Timing -> Report CDC... を選択する。
Report CDC ダイアログが開く。
Clocks の From に clk_fpga_0 を To に clk_fpga_1 を入れて OK ボタンをクリックした。
AXI4-Lite_defclk_32_220106.png

Endpoint は 37 個, Unsafe は 0 個だった。 Unknown は 5 個ある。
AXI4-Lite_defclk_33_220106.png

CDC Details の”clk_fpga_0 to clk_fpga_1”をクリックした。
AXI4-Lite_defclk_34_220106.png

CDC-1 と CDC-15 が出ている。
Vivado Design Suite ユーザー ガイド デザイ ン解析およびク ロージ ャテクニック UG906 (v2018.2) 2018 年 6 月 6 日”の 76 ページの”表 2‐3: CDC ルールおよび説明”によると CDC-1 は

1 ビッ ト CDC CDC-1 クリティカル 1 ビッ ト CDC パスが、 同期化されていないか、 または不明の CDC 回路を含みます。


CDC-15 は

CE 制御の CDC CDC-15 警告 ク ロ ッ ク イネーブルで制御された CDC。

だそうだ。
やはり、ダメっぽい?

次に”clk_fpga_1 to clk_fpga_0”のパスの CDC を見てみよう。
AXI4-Lite_defclk_35_220106.png

こちらは Endpoints が 232 個で、Unknonwn がやはり、232 個になっている。
AXI4-Lite_defclk_36_220106.png

CDC Details の”clk_fpga_1 to clk_fpga_0”をクリックした。
AXI4-Lite_defclk_37_220106.png

全部 CDC-1 だけだった。
これはあまり良くないか。。。
もう一度 AXI4-Lite のクロックを 50 MHz でやってみよう。
  1. 2022年01月07日 04:32 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する4

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する3”の続き。

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定してみようということで、前回は、 C コードの合成の AXI4 Master のアドレス幅が 64 ビットになっていたので、32 ビットに変更し、もう一度 C コードの合成と Export RTL をやり直した。更に C/RTL 協調シミュレーションも Dump Trace の設定を port にしたら成功した。今回は、前回 IP を作成できたので、Vivado 2021.2 でプロジェクトを作成し、作成した DMP_pow2_defclk IP を使用して、ブロック・デザインを作成した。そして、論理合成、インプリメンテーション、ビットストリームの生成を行ったが、タイミングでエラーになった。

Vivado 2021.2 で ZYBO Z7-20 用の DMA_pow2_defclk_test プロジェクトを作成した。
AXI4-Lite_defclk_16_220105.png

IP Catalog に Dma_pow2 IP を登録した。
AXI4-Lite_defclk_17_220105.png

DMA_pow2_defclk_bd ブロック・デザインを作成した。
ZYNQ7 Processing System を Add IP した。
Run Block Automation を行った状態だ。
AXI4-Lite_defclk_18_220105.png

ZYNQ7 Processing System を ダブルクリックして設定画面を開く。
FCLK_CLK0 を 100 MHz に設定した。これは、DMA _pow2 IP の AXI4 Master インターフェースのクロックとする。
FCLK_CLK1 を 75 MHz に設定した。これは、DMA_pow2 IP の AXI4-Lite インターフェースのクロックとする。Vitis HLS の C/RTL 協調シミュレーションのクロックは 50 MHz だったが Vivado でタイミング・エラーがでるかどうか?見るために 75 MHz に設定した。
AXI4-Lite_defclk_19_220105.png

DMA_pow2 を Add IP した。
AXI4-Lite_defclk_20_220105.png

Run Connection Automation で s_axi_control のクロックを FCLK_CLK1 ( 76 MHz ) に設定した。
AXI4-Lite_defclk_21_220105.png

配線が行われた。
AXI4-Lite_defclk_22_220105.png

Run Connection Automation が表示されないかと思っていたら、 ZYNQ7 Processing System に HP Slave AXI interface を追加するのを忘れていた。
ZYNQ7 Processing System をダブルクリックして、設定画面を開く。
PS-PL Configuration をクリックして、HP Slave AXI interface を展開し、S AXI HP0 interface の Select ボックスにチェックを入れた。
AXI4-Lite_defclk_23_220105.png

Run Connection Automation が表示された。
AXI4-Lite_defclk_24_220105.png

Run Connection Automation をクリックした。
S_AXI_HP0 を FCLK_CLK0 ( 100 MHz ) に接続した。
AXI4-Lite_defclk_25_220105.png

ブロック・デザインが完成した。
AXI4-Lite_defclk_26_220105.png

Create HDL Wrapper... でトップの Verilog HDL ファイル DMA_pow2_defclk_bd_wrapper.v を作成した。
AXI4-Lite_defclk_27_220105.png

Flow Navigator の PROGRAM AND DEBUG から Generate Bitstream をクリックして、論理合成、インプリメンテーション、ビットストリームの生成を行った。
Project Summary を示す。
AXI4-Lite_defclk_28_220106.png

タイミング・エラーが出ている。
  1. 2022年01月06日 04:25 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する3

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する2”の続き。

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定してみようということで、前回は、C コードの合成と C/RTL 協調シミュレーションを行ったが、C/RTL 協調シミュレーションがエラーで停止してしまった。Export RTL と Implementation は Vitis HLS 2022 年問題が出てしまった。今回は、前回の C コードの合成の AXI4 Master のアドレス幅が 64 ビットになっていたので、32 ビットに変更し、もう一度 C コードの合成と Export RTL をやり直した。更に C/RTL 協調シミュレーションも Dump Trace の設定を port にしたら成功した。

前回の C コードの合成の AXI4 Master のアドレス幅が 64 ビットになっていたので、32 ビットに変更しよう。
Vitis HLS 2021.2 の Solution メニューから Solution Settings... を選択する。
Solution Settings (solutiojn1) ダイアログが開く。
config_interface を展開して、 m_axi_addr64 の Value のチェックボックスのチェックをクリックして外す。
AXI4-Lite_defclk_8_220105.png

これで、もう一度 C コードの合成を行った。
HW interface -> M_AXI -> m_axi_gmem の Address Width が 32 ビットになった。
AXI4-Lite_defclk_9_220105.png

C/RTL 協調シミュレーションを行う時に、Co-Simulation ダイアログで Dump Trace を port に設定した。(前回は、all に設定してエラーになった)
AXI4-Lite_defclk_11_220105.png

C/RTL 協調シミュレーションが成功した。
AXI4-Lite_defclk_12_220105.png

C/RTL 協調シミュレーションの波形を示す。
ap_clk は 10 ns つまり 100 MHz になっている。
AXI4-Lite_defclk_13_220105.png

axi4l_clk は 20 ns つまり、50 MHz だった。
AXI4-Lite_defclk_14_220105.png

Export RTL を行うと、 Vitis HLS 2022 年問題でエラーになった。
AXI4-Lite_defclk_10_220105.png

Vivado HLS, Vitis HLS で 2022 年問題発生”でエラーを回避して、 IP 化することができた。
AXI4-Lite_defclk_15_220105.png
  1. 2022年01月05日 04:37 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する2

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する”の続き。

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定してみようということで、前回は、Vitis HLS 2021.2 のプロジェクトを作成し、C シミュレーションを行った。今回は、C コードの合成と C/RTL 協調シミュレーションを行ったが、C/RTL 協調シミュレーションがエラーで停止してしまった。Export RTL と Implementation は Vitis HLS 2022 年問題が出てしまった。

最初に C コードの合成を行った。
AXI4-Lite_defclk_3_220103.png

特段変わったことはない。
合成結果の DMA_pow2.v を見ると、クロックが ap_clk と axi4l_clk と 2 つある。リセットも ap_rst_n と ap_rst_n_axi4l_clk と 2 つある。
AXI4-Lite_defclk_5_220103.png
AXI4-Lite_defclk_6_220103.png

AXI4-Lite インターフェースを司る DMA_pow2_control_s_axi.v を見ると ACLK と clk の 2 つのクロックがある。
ACLK がAXI4-Lite インターフェースのクロックで、 clk が内部クロックだ。
AXI4-Lite_defclk_7_220103.png

Verilog HDL ソースコードを見るとクロック載せ替えには注意が払われていないように見える?

C/RTL 協調シミュレーションを行ったが信号が無いと言われてエラーだった。
AXI4-Lite_defclk_4_220103.png

## add_wave /apatb_DMA_pow2_top/m_axi_gmem_BUSER -into $wdata_group -radix hex
ERROR: [Wavedata 42-471] Note: Nothing was found for the following items: /apatb_DMA_pow2_top/m_axi_gmem_BUSER 
ERROR: [Common 17-39] 'add_wave' failed due to earlier errors.

    while executing
"add_wave /apatb_DMA_pow2_top/m_axi_gmem_BUSER -into $wdata_group -radix hex"
    (file "DMA_pow2.tcl" line 103)



Export RTL と Implementation は Vitis HLS 2022 年問題が出てしまった。

最後に AXI4-Lite インターフェースを司る DMA_pow2_control_s_axi.v を貼っておく。

// ==============================================================
// Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2021.2 (64-bit)
// Copyright 1986-2021 Xilinx, Inc. All Rights Reserved.
// ==============================================================
`timescale 1ns/1ps
module DMA_pow2_control_s_axi
#(parameter
    C_S_AXI_ADDR_WIDTH = 6,
    C_S_AXI_DATA_WIDTH = 32
)(
    input  wire                          ACLK,
    input  wire                          ARESET,
    input  wire                          ACLK_EN,
    input  wire [C_S_AXI_ADDR_WIDTH-1:0] AWADDR,
    input  wire                          AWVALID,
    output wire                          AWREADY,
    input  wire [C_S_AXI_DATA_WIDTH-1:0] WDATA,
    input  wire [C_S_AXI_DATA_WIDTH/8-1:0] WSTRB,
    input  wire                          WVALID,
    output wire                          WREADY,
    output wire [1:0]                    BRESP,
    output wire                          BVALID,
    input  wire                          BREADY,
    input  wire [C_S_AXI_ADDR_WIDTH-1:0] ARADDR,
    input  wire                          ARVALID,
    output wire                          ARREADY,
    output wire [C_S_AXI_DATA_WIDTH-1:0] RDATA,
    output wire [1:0]                    RRESP,
    output wire                          RVALID,
    input  wire                          RREADY,
    output wire                          interrupt,
    input  wire                          clk,
    input  wire                          rst,
    output wire                          ap_start,
    input  wire                          ap_done,
    input  wire                          ap_ready,
    input  wire                          ap_idle,
    input  wire [31:0]                   ap_return,
    output wire [63:0]                   in_r,
    output wire [63:0]                   out_r,
    input  wire [0:0]                    ap_local_deadlock
);
//------------------------Address Info-------------------
// 0x00 : Control signals
//        bit 0  - ap_start (Read/Write/COH)
//        bit 1  - ap_done (Read/COR)
//        bit 2  - ap_idle (Read)
//        bit 3  - ap_ready (Read/COR)
//        bit 7  - auto_restart (Read/Write)
//        others - reserved
// 0x04 : Global Interrupt Enable Register
//        bit 0  - Global Interrupt Enable (Read/Write)
//        others - reserved
// 0x08 : IP Interrupt Enable Register (Read/Write)
//        bit 0 - enable ap_done interrupt (Read/Write)
//        bit 1 - enable ap_ready interrupt (Read/Write)
//        bit 5 - enable ap_local_deadlock interrupt (Read/Write)
//        others - reserved
// 0x0c : IP Interrupt Status Register (Read/TOW)
//        bit 0 - ap_done (COR/TOW)
//        bit 1 - ap_ready (COR/TOW)
//        bit 5 - ap_local_deadlock (COR/TOW)
//        others - reserved
// 0x10 : Data signal of ap_return
//        bit 31~0 - ap_return[31:0] (Read)
// 0x18 : Data signal of in_r
//        bit 31~0 - in_r[31:0] (Read/Write)
// 0x1c : Data signal of in_r
//        bit 31~0 - in_r[63:32] (Read/Write)
// 0x20 : reserved
// 0x24 : Data signal of out_r
//        bit 31~0 - out_r[31:0] (Read/Write)
// 0x28 : Data signal of out_r
//        bit 31~0 - out_r[63:32] (Read/Write)
// 0x2c : reserved
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)

//------------------------Parameter----------------------
localparam
    ADDR_AP_CTRL      = 6'h00,
    ADDR_GIE          = 6'h04,
    ADDR_IER          = 6'h08,
    ADDR_ISR          = 6'h0c,
    ADDR_AP_RETURN_0  = 6'h10,
    ADDR_IN_R_DATA_0  = 6'h18,
    ADDR_IN_R_DATA_1  = 6'h1c,
    ADDR_IN_R_CTRL    = 6'h20,
    ADDR_OUT_R_DATA_0 = 6'h24,
    ADDR_OUT_R_DATA_1 = 6'h28,
    ADDR_OUT_R_CTRL   = 6'h2c,
    WRIDLE            = 2'd0,
    WRDATA            = 2'd1,
    WRRESP            = 2'd2,
    WRRESET           = 2'd3,
    RDIDLE            = 2'd0,
    RDDATA            = 2'd1,
    RDRESET           = 2'd2,
    ADDR_BITS                = 6;

//------------------------Local signal-------------------
    reg  [1:0]                    wstate = WRRESET;
    reg  [1:0]                    wnext;
    reg  [ADDR_BITS-1:0]          waddr;
    wire [C_S_AXI_DATA_WIDTH-1:0] wmask;
    wire                          aw_hs;
    wire                          w_hs;
    reg  [1:0]                    rstate = RDRESET;
    reg  [1:0]                    rnext;
    reg  [C_S_AXI_DATA_WIDTH-1:0] rdata;
    wire                          ar_hs;
    wire [ADDR_BITS-1:0]          raddr;
    // internal registers
    reg                           int_ap_idle;
    reg                           int_ap_ready = 1'b0;
    reg                           int_ap_done = 1'b0;
    wire                          ap_done_get;
    reg                           ap_done_ext;
    reg                           int_ap_start = 1'b0;
    wire                          ap_start_set;
    reg                           ap_start_mask;
    reg                           int_auto_restart = 1'b0;
    wire                          auto_restart_set;
    reg                           int_gie = 1'b0;
    reg  [5:0]                    int_ier = 6'b0;
    wire                          ier_toggle;
    reg                           ier_mask;
    reg  [5:0]                    int_isr = 6'b0;
    wire                          isr_toggle;
    reg                           isr_mask;
    reg  [31:0]                   int_ap_return;
    reg  [63:0]                   int_in_r = 'b0;
    reg  [63:0]                   int_out_r = 'b0;

//------------------------Instantiation------------------


//------------------------AXI write fsm------------------
assign AWREADY = (wstate == WRIDLE);
assign WREADY  = (wstate == WRDATA);
assign BRESP   = 2'b00;  // OKAY
assign BVALID  = (wstate == WRRESP);
assign wmask   = { {8{WSTRB[3]}}, {8{WSTRB[2]}}, {8{WSTRB[1]}}, {8{WSTRB[0]}} };
assign aw_hs   = AWVALID & AWREADY;
assign w_hs    = WVALID & WREADY;

// wstate
always @(posedge ACLK) begin
    if (ARESET)
        wstate <= WRRESET;
    else if (ACLK_EN)
        wstate <= wnext;
end

// wnext
always @(*) begin
    case (wstate)
        WRIDLE:
            if (AWVALID)
                wnext = WRDATA;
            else
                wnext = WRIDLE;
        WRDATA:
            if (WVALID)
                wnext = WRRESP;
            else
                wnext = WRDATA;
        WRRESP:
            if (BREADY)
                wnext = WRIDLE;
            else
                wnext = WRRESP;
        default:
            wnext = WRIDLE;
    endcase
end

// waddr
always @(posedge ACLK) begin
    if (ACLK_EN) begin
        if (aw_hs)
            waddr <= AWADDR[ADDR_BITS-1:0];
    end
end

//------------------------AXI read fsm-------------------
assign ARREADY = (rstate == RDIDLE);
assign RDATA   = rdata;
assign RRESP   = 2'b00;  // OKAY
assign RVALID  = (rstate == RDDATA);
assign ar_hs   = ARVALID & ARREADY;
assign raddr   = ARADDR[ADDR_BITS-1:0];

// rstate
always @(posedge ACLK) begin
    if (ARESET)
        rstate <= RDRESET;
    else if (ACLK_EN)
        rstate <= rnext;
end

// rnext
always @(*) begin
    case (rstate)
        RDIDLE:
            if (ARVALID)
                rnext = RDDATA;
            else
                rnext = RDIDLE;
        RDDATA:
            if (RREADY & RVALID)
                rnext = RDIDLE;
            else
                rnext = RDDATA;
        default:
            rnext = RDIDLE;
    endcase
end

// rdata
always @(posedge ACLK) begin
    if (ACLK_EN) begin
        if (ar_hs) begin
            rdata <= 'b0;
            case (raddr)
                ADDR_AP_CTRL: begin
                    rdata[0] <= int_ap_start;
                    rdata[1] <= int_ap_done;
                    rdata[2] <= int_ap_idle;
                    rdata[3] <= int_ap_ready;
                    rdata[7] <= int_auto_restart;
                end
                ADDR_GIE: begin
                    rdata <= int_gie;
                end
                ADDR_IER: begin
                    rdata <= int_ier;
                end
                ADDR_ISR: begin
                    rdata <= int_isr;
                end
                ADDR_AP_RETURN_0: begin
                    rdata <= int_ap_return[31:0];
                end
                ADDR_IN_R_DATA_0: begin
                    rdata <= int_in_r[31:0];
                end
                ADDR_IN_R_DATA_1: begin
                    rdata <= int_in_r[63:32];
                end
                ADDR_OUT_R_DATA_0: begin
                    rdata <= int_out_r[31:0];
                end
                ADDR_OUT_R_DATA_1: begin
                    rdata <= int_out_r[63:32];
                end
            endcase
        end
    end
end


//------------------------Register logic-----------------
assign interrupt        = int_gie & (|int_isr);
assign ap_start         = int_ap_start;
assign ap_start_set     = w_hs && waddr == ADDR_AP_CTRL && WSTRB[0] && WDATA[0];
assign ap_done_get      = ar_hs && raddr == ADDR_AP_CTRL && int_ap_done;
assign auto_restart_set = w_hs && waddr == ADDR_AP_CTRL && WSTRB[0];
assign isr_toggle       = w_hs && waddr == ADDR_ISR && WSTRB[0];
assign in_r             = int_in_r;
assign out_r            = int_out_r;
// ap_start_mask
always @(posedge clk) begin
    if (rst)
        ap_start_mask <= 1'b0;
    else
        ap_start_mask <= ap_start_set;
end
// int_ap_start
always @(posedge clk) begin
    if (rst)
        int_ap_start <= 1'b0;
    else if (ap_start_set == 1'b1 && ap_start_mask == 1'b0)
        int_ap_start <= 1'b1;
    else if (ap_ready)
        int_ap_start <= int_auto_restart; // clear on handshake/auto restart
end
// ap_done_ext
always @(posedge clk) begin
    if (rst)
        ap_done_ext <= 1'b0;
    else
        ap_done_ext <= ap_done_get;
end
// int_ap_done
always @(posedge clk) begin
    if (rst)
        int_ap_done <= 1'b0;
    else if (ap_done)
        int_ap_done <= 1'b1;
    else if (ap_done_get == 1'b0 && ap_done_ext == 1'b1)
        int_ap_done <= 1'b0; // clear on read
end
// int_ap_idle
always @(posedge clk) begin
    if (rst)
        int_ap_idle <= 1'b0;
    else
        int_ap_idle <= ap_idle;
end
// int_ap_ready
always @(posedge clk) begin
    if (rst)
        int_ap_ready <= 1'b0;
    else
        int_ap_ready <= ap_ready;
end
// int_auto_restart
always @(posedge clk) begin
    if (rst)
        int_auto_restart <= 1'b0;
    else if (auto_restart_set == 1'b1)
        int_auto_restart <=  WDATA[7];
end
// int_gie
always @(posedge clk) begin
    if (rst)
        int_gie <= 1'b0;
    else if (w_hs && waddr == ADDR_GIE && WSTRB[0])
        int_gie <= WDATA[0];
end
// int_ier
always @(posedge clk) begin
    if (rst)
        int_ier <= 'b0;
    else if (w_hs && waddr == ADDR_IER && WSTRB[0])
        int_ier <= WDATA[5:0];
    else if (w_hs && waddr == ADDR_IER && WSTRB[0])
        int_ier <= WDATA[5:0];
end
// isr_mask
always @(posedge clk) begin
    if (rst)
        isr_mask <= 1'b0;
    else
        isr_mask <= isr_toggle;
end
// int_isr[0]
always @(posedge clk) begin
    if (rst)
        int_isr[0] <= 1'b0;
    else if (int_ier[0] & ap_done)
        int_isr[0] <= 1'b1;
    else if (isr_toggle == 1'b1 && isr_mask == 1'b0)
        int_isr[0] <= int_isr[0] ^ WDATA[0]; // toggle on write
end
// int_isr[1]
always @(posedge clk) begin
    if (rst)
        int_isr[1] <= 1'b0;
    else if (int_ier[1] & ap_ready)
        int_isr[1] <= 1'b1;
    else if (isr_toggle == 1'b1 && isr_mask == 1'b0)
        int_isr[1] <= int_isr[1] ^ WDATA[1]; // toggle on write
end
// int_isr[5]
always @(posedge clk) begin
    if (rst)
        int_isr[5] <= 1'b0;
    else if (int_ier[5] & ap_local_deadlock)
        int_isr[5] <= 1'b1;
    else if (isr_toggle == 1'b1 && isr_mask == 1'b0)
        int_isr[5] <= int_isr[5] ^ WDATA[5]; // toggle on write
end
// int_ap_return
always @(posedge clk) begin
    if (rst)
        int_ap_return <= 0;
    else if (ap_done)
        int_ap_return <= ap_return;
end
// int_in_r[31:0]
always @(posedge clk) begin
    if (rst)
        int_in_r[31:0] <= 0;
    else if (w_hs && waddr == ADDR_IN_R_DATA_0)
        int_in_r[31:0] <= (WDATA[31:0] & wmask) | (int_in_r[31:0] & ~wmask);
end
// int_in_r[63:32]
always @(posedge clk) begin
    if (rst)
        int_in_r[63:32] <= 0;
    else if (w_hs && waddr == ADDR_IN_R_DATA_1)
        int_in_r[63:32] <= (WDATA[31:0] & wmask) | (int_in_r[63:32] & ~wmask);
end
// int_out_r[31:0]
always @(posedge clk) begin
    if (rst)
        int_out_r[31:0] <= 0;
    else if (w_hs && waddr == ADDR_OUT_R_DATA_0)
        int_out_r[31:0] <= (WDATA[31:0] & wmask) | (int_out_r[31:0] & ~wmask);
end
// int_out_r[63:32]
always @(posedge clk) begin
    if (rst)
        int_out_r[63:32] <= 0;
    else if (w_hs && waddr == ADDR_OUT_R_DATA_1)
        int_out_r[63:32] <= (WDATA[31:0] & wmask) | (int_out_r[63:32] & ~wmask);
end

//------------------------Memory logic-------------------

endmodule

  1. 2022年01月03日 05:10 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS, Vitis HLS で 2022 年問題発生

Microsoft Exchange Server、日付チェック問題でメール配信停止(対処中)”だそうですが、Vivado HLS, Vitis HLS も 2022 年問題で現在、Export RTL ができなくなっています。
これは、ひがしさんの下記のツィートで知りました。

これは、”Vivits HLS 2021.2 在导出IP核时报如下错误,ERROR: '2201011916' is an invalid argument. Please specify an integer value.”という中国語のアンサーに書いてあるそうです。

少なくとも Ubuntu 18.04 版の Vivado HLS 2019.2 と Vitis HLS 2021.2 と Windows の Vitis HLS 2021.1 と 2021.2 は Export RTL が正常終了しません。
Vitis HLS は

ERROR: '2201021549' is an invalid argument. Please specify an integer value.
while executing
"rdi::set_property core_revision 2201021549 {component component_1}"
invoked from within
"set_property core_revision $Revision $core"
(file "run_ippack.tcl" line 1109)


というエラーで止まってしまいます。

Ubuntu 18.04 上での Vitis HLS 2021.2 で Export RTL を実行したら上記のエラーでした。
HLS_problem_2022_1_220102.png

Ubuntu 18.04 上での Vivado HLS 2019.4 で Export RTL を実行したら同様に上記のエラーでした。
HLS_problem_2022_2_220102.png

Vivits HLS 2021.2 在导出IP核时报如下错误,ERROR: '2201011916' is an invalid argument. Please specify an integer value.”という中国語のアンサーによると solution?/impl/ip の run_ippack.tcl の

set Revision "2201021811"(年月日時分)

HLS_problem_2022_3_220102.png

 は 32 ビット integer の値を超えちゃうので、

set Revision "2001012126"

HLS_problem_2022_4_220102.png

にして、tcl スクリプトをコマンドラインから実行すれば良いということです。
そこで、 Vivado 2021.2 の settings64.sh を起動したターミナルで、
vivado -mode tcl -source run_ippack.tcl
HLS_problem_2022_5_220102.png

HLS_problem_2022_6_220102.png

Vivado% プロンプトになりますが、exit コマンドで出られます。

solution?/impl/ip に IP が生成されています。
HLS_problem_2022_7_220102.png

Windows11 上での Vitis HLS 2021.1 で Export RTL を実行したら上記のエラーでした。
HLS_problem_2022_8_220102.png

Windows11 上での Vitis HLS 2021.2 で Export RTL を実行しても上記のエラーでした。
HLS_problem_2022_8_220102.png

Windows11 では、Vivado 2021.2 Tcl Console で solution?/impl/ip の run_ippack.tcl を実行すれば良いと思います。


ひがしさんの対処法記事です。
Vitis HLSでリビジョン番号がオーバーフローしたときの対処法

その後の Xilinx のアンサーの情報を追加します。(2022/01/04)
2022 timestamp overflow: ERROR: '2201011128' is an invalid argument. Please specify an integer value
why vitis hls is not able to export ip
Vivado fails to export IPs with the error message "Bad lexical cast: source type value could not be interpreted as target"
  1. 2022年01月02日 18:32 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定する

Vitis HLS 2021.2 で AXI4-Lite インターフェースのクロックに別のクロックを指定してみよう。
今回は、Vitis HLS 2021.2 のプロジェクトを作成し、C シミュレーションを行った。

Vitis 高位合成ユーザー ガイド (UG1399)の set_directive_interface に clock オプションがある。その説明文を引用する。

-clock
デフォルトでは、AXI4-Lite インターフェイス クロックはシステム クロックと同じです。このオプションを使用すると、AXI4-Lite インターフェイスに別のクロックを指定できます。-bundle オプションを使用して複数の最上位関数引数を 1 つの AXI4-Lite インターフェイスにまとめている場合は、-clock オプションはバンドル メンバーの 1 つにのみ指定します。


-clock オプションを使ってみよう。
Vitis HLS 2021.2 で DMA Readしたデータを2乗し、DMA Writeする KV260 用 IP を作成”の DMA_pow2 プロジェクトを DMA_pow2_defclk プロジェクトとして作り直した。

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

// DMA_pow2_defclk.cpp
// 2022/01/02 by marsee
//

#include <stdint.h>

int DMA_pow2(int32_t *in, int32_t *out){
#pragma HLS INTERFACE mode=s_axilite bundle=control clock=axi4l_clk port=return
#pragma HLS INTERFACE mode=s_axilite bundle=control port=out
#pragma HLS INTERFACE mode=s_axilite bundle=control port=in
#pragma HLS INTERFACE mode=m_axi depth=10 port=out offset=slave
#pragma HLS INTERFACE mode=m_axi depth=10 port=in offset=slave
    for(int i=0; i<10; i++){
        out[i] = in[i] * in[i];
    }
    return(0);
}


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

// DMA_pow2_defclk_tb.cpp
// 2021/01/02 by marsee
//

#include <iostream>
#include <stdint.h>

int DMA_pow2(int32_t *in, int32_t *out);

int main(){
    int32_t data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int32_t result[10];

    DMA_pow2(data, result);

    for(int i=0; i<10; i++){
        std::cout << "data[" << i << "]= " << data[i] <<
                ", result[" << i << "] = " <<
                result[i] << std::endl;
    }
}


Vitis HLS 2021.2 の DMA_pow2_defclk プロジェクトを示す。
AXI4-Lite_defclk_1_220102.png

C シミュレーションを行った。
AXI4-Lite_defclk_2_220102.png
  1. 2022年01月02日 05:55 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

2021 年の”FPGAの部屋”ブログのアクセス数

2021 年の”FPGAの部屋”ブログのアクセス数は 419,328 アクセスでした。
皆さん見ていただいてありがとうございました。
本年も”FPGAの部屋”ブログをよろしくお願いします。
access_num_220101.png
  1. 2022年01月01日 05:44 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

FPGAの部屋のまとめサイトの更新(2022年1月1日)

あけましておめでとうございます。
今年もよろしくお願いします。

FPGAの部屋のまとめサイトを更新しました。
”Microchip社のFPGAツールやボードについて”として、”Libero SoC”、”SmartHLS”、”Hello FPGA”を追加して、その他の記事をまとめました。
  1. 2022年01月01日 05:39 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0