ラベル Ultra96v2 の投稿を表示しています。 すべての投稿を表示
ラベル Ultra96v2 の投稿を表示しています。 すべての投稿を表示

2021年5月14日金曜日

ultra96v2でVitis 2020.2を使用してORB_SLAM2のFASTとDistirbuteOctTree処理をカーネル化していく話その2

続けて間引き処理をカーネルに追加していく。

フレームを4分割したサブフレームでの最大値を探索して、最後に結果を出力する。
メモリアクセスのコスト下げるためにコーナースコアは最終ワードにまとめた。
気休めだと思うけどレジスタに配置されるよう個別に宣言して全てif文で比較する。
カーネルの探索範囲を40x40の領域に限定すると32bitに全ての情報載せられそうだけど、改善は微々たるものと思うのでとりあえず保留。

カーネル部分のコードは以下の通り。

#include "xf_fast_and_dist_config.h"

template <int PW, int SRC_T, int ROWS, int COLS, int NPC>
void fastResult2Vec(xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& in_img, ap_uint<32>* vec_out){

    int read_index = 0;
    ap_uint<32> vec0 = 0;
    ap_uint<8> vec_resp0 = 0;
    ap_uint<32> vec1 = 0;
    ap_uint<8> vec_resp1 = 0;
    ap_uint<32> vec2 = 0;
    ap_uint<8> vec_resp2 = 0;
    ap_uint<32> vec3 = 0;
    ap_uint<8> vec_resp3 = 0;

    for (int row = 0; row < in_img.rows; row++) {
#pragma HLS PIPELINE
        for (int col = 0; col < in_img.cols; col++) {
            ap_uint<8> temp = in_img.read(read_index++);
            if(temp != 0){
                if ((col <= COLS/2) && (row <= ROWS/2) && (temp > vec0)){vec0 = 0x80000000 + (row << 15) + col; vec_resp0 = temp;}
                if ((col >  COLS/2) && (row <= ROWS/2) && (temp > vec1)){vec1 = 0x80000000 + (row << 15) + col; vec_resp1 = temp;}
                if ((col <= COLS/2) && (row >  ROWS/2) && (temp > vec2)){vec2 = 0x80000000 + (row << 15) + col; vec_resp2 = temp;}
                if ((col >  COLS/2) && (row >  ROWS/2) && (temp > vec3)){vec3 = 0x80000000 + (row << 15) + col; vec_resp3 = temp;}
            }
        }
    }
    vec_out[0] = vec0;
    vec_out[1] = vec1;
    vec_out[2] = vec2;
    vec_out[3] = vec3;
    vec_out[4] = (vec_resp3 << 24) + (vec_resp2 << 16) + (vec_resp1 << 8) + vec_resp0;
    return;
}

extern "C" {

void fast_and_dist_accel(   ap_uint<PTR_WIDTH>* img_in, unsigned char threshold, /*ap_uint<PTR_WIDTH>* img_out,*/ int rows, int cols,
                            ap_uint<32>* vec_out) {
// clang-format off
    #pragma HLS INTERFACE m_axi      port=img_in        offset=slave  bundle=gmem0
    
//    #pragma HLS INTERFACE m_axi      port=img_out       offset=slave  bundle=gmem1
    #pragma HLS INTERFACE m_axi      port=vec_out       offset=slave  bundle=gmem1
    #pragma HLS INTERFACE s_axilite  port=rows
    #pragma HLS INTERFACE s_axilite  port=cols
    #pragma HLS INTERFACE s_axilite  port=threshold
    #pragma HLS INTERFACE s_axilite  port=return
    // clang-format on

    xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPC1> imgInput(rows, cols);
    xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPC1> imgOutput(rows, cols);
// clang-format off
    #pragma HLS DATAFLOW
    // clang-format on

    // Retrieve xf::cv::Mat objects from img_in data:
    xf::cv::Array2xfMat<PTR_WIDTH, TYPE, HEIGHT, WIDTH, NPC1>(img_in, imgInput);

    // Run xfOpenCV kernel:
    xf::cv::fast<NMS, TYPE, HEIGHT, WIDTH, NPC1>(imgInput, imgOutput, threshold);

    // Convert _dst xf::cv::Mat object to output array:
    //xf::cv::xfMat2Array<PTR_WIDTH, TYPE, HEIGHT, WIDTH, NPC1>(imgOutput, img_out);

    // Convert _dst xf::cv::Mat objecto to output vector
    fastResult2Vec<PTR_WIDTH, TYPE, HEIGHT, WIDTH, NPC1>(imgOutput, vec_out);

    return;
} // End of kernel

} // End of extern C

ビルドは以下の通り。hashはfcf6cdc2661a448b21190a7dd9b710e9b507f545

git clone https://github.com/akira-nishiyama/orb_slam_2_ros.git -b feature-fpga
cd orb_slam_2_ros
mkdir build
cd build
source <vitis-installation-path>/settings64.sh
source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
export AMENT_PREFIX_PATH=$OECORE_NATIVE_SYSROOT/usr:$OECORE_TARGET_SYSROOT/usr
export PYTHONPATH=$OECORE_NATIVE_SYSROOT/usr/lib/python3.7/site-packages:$OECORE_TARGET_SYSROOT/usr/lib/python3.7/site-packages
cmake .. -DCMAKE_INSTALL_SO_NO_EXE=0 -DBUILD_TESTING=OFF -DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 -GNinja -DCMAKE_INSTALL_PREFIX=<path-to-sd-root> -DPLATFORM_COMPONENTS_PATH=<path-to-components> -DBUILD_TEST_TARGETS=OFF -DBUILD_TARGET=hw -DCMAKE_BUILD_TYPE=Debug -DENABLE_KRNL_CHECK=OFF -DBUILD_FAST_TEST=OFF -DBUILD_FAST_AND_DIST_TEST=ON -DDISABLE_RESIZE_KRNL=ON -DDISABLE_FAST_KRNL=OFF

実行結果は次の通り。
時間はそこそこ短くなったけど全然及ばないなぁ。
hostプログラムのclone処理が悪いと思うが。。。

root@ultra96v2-zynqmp:~# time ./orb_slam2_ros_mono_tum_test /usr/share/orb_slam2_ros/orb_slam2/Vocabulary/ORBvoc.txt /home/root/tum-dataset           

ORB-SLAM2 Copyright (C) 2014-2016 Raul Mur-Artal, University of Zaragoza.
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions. See LICENSE.txt.

OpenCV version : 3.4.3
Major version : 3
Minor version : 4
Subminor version : 3
Input sensor was set to: Monocular

Loading ORB Vocabulary.
Vocabulary loaded!


Camera Parameters: 
- fx: 517.306
- fy: 516.469
- cx: 318.643
- cy: 255.314
- k1: 0.262383
- k2: -0.953104
- k3: 0.002628
- p1: 1.16331
- p2: -0.005358
- fps: 30
- bf: 0
- color order: RGB (ignored if grayscale)
Found Platform
Platform Name: Xilinx
INFO: Device found - edge
Loading: '/usr/bin/xclbin/resize_krnl.xclbin'
file size:5625745
actual read size:5625745
program xclbin.
program xclbin Done.
create resize_accel kernel.
create resize_accel kernel Done.
Found Platform
Platform Name: Xilinx
INFO: Device found - edge
Loading: '/usr/bin/xclbin/resize_krnl.xclbin'
file size:5625745
actual read size:5625745
program xclbin.
program xclbin Done.
create resize_accel kernel.
create resize_accel kernel Done.

ORB Extractor Parameters: 
- Number of Features: 1000
- Scale Levels: 8
- Scale Factor: 1.2
- Initial Fast Threshold: 20
- Minimum Fast Threshold: 7

-------
Start processing sequence ...
Images in the sequence: 798

-------

median tracking time: 0.188161
mean tracking time: 0.188687

Saving keyframe trajectory to KeyFrameTrajectory.txt ...

trajectory saved!

real    2m56.512s
user    2m35.888s
sys 0m55.475s

2021年5月13日木曜日

ultra96v2でVitis 2020.2を使用してORB_SLAM2のFASTとDistirbuteOctTree処理をカーネル化していく話

fastとcomputeDistributeOctTreeを一つにしたfast_and_distカーネルを作っていく話。
アクセラレータにDistribution機能を移すに際して、アルゴリズムを変更し、動作確認を行った。

環境

  • ubuntu:20.04
  • vitis:2020.2
  • yocto:zeus(https://github.com/akira-nishiyama/petalinux-ros2-manifests feature-v2020.2ブランチ)
  • board:ultra96v2(https://github.com/akira-nishiyama/ultra96v2_4z.git feature-v2020.2ブランチ)

変更内容

現状のcomputeDistributeOctTreeは全ての特徴点を分割したノードに割付ていき、
分割の限界となった場合には、各々のノードで最も明確な特徴点を残し、残りは削除して処理を終了する。
または、各ノードに一つの特徴点が配置された状態となった場合に処理を終了する。
(https://www.acri.c.titech.ac.jp/wordpress/archives/7776)

これをHW処理しやすいようにノードサイズをFASTの抽出単位と揃えて固定し、そのノードを更に4分割し、
4分割ノードそれぞれで最も明確な特徴点を選出して間引くこととした。
最小ノードのサイズが同じであれば、ほぼ同じ結果が得られることが期待される。

考え方はおおよそACRiの記事と同じ。
一方でそのままだとultra96v2には乗らないので、改変する。
アルゴリズムは細かく書くと次の通りとなる。

(1)フレームを規定のサイズに分割する。(とりあえずは40x40)
(2)各フレームのFAST特徴点をiniThFASTのしきい値で抽出する。
(3)特徴点が見つからない場合にはminThFASTのしきい値で抽出する。
(4)得られた特徴点はフレームを4分割したサブフレームに割付け、サブフレームで最も明確な特徴点を一つ選び出す。

試してみるとtum-datasetでは同一頂点が抽出されるので問題無く使用できると考えられる。2つのしきい値を同時にチェックする方法もHWコストの割に高速化に効きそうなので考えておく。

build

まずはカーネルを使用せずに評価してみる。
-DDISABLE_NEW_DISTRIBUTION=OFF -DENABLE_KRNL_CHECK=ONとすると変更前後を比較して結果を標準出力するようになる。
また、-DDISABLE_NEW_DISTRIBUTION=ON -DENABLE_KRNL_CHECK=OFFとすると、オリジナルコードに近い状態で動作する。  

hashは2d04944a46ee3d2c71e5c108a376b92a5655770cで確認。

2021/5/20:比較が間違っていたので修正版を作成中

git clone https://github.com/akira-nishiyama/orb_slam_2_ros.git -b feature-fpga
cd orb_slam_2_ros
mkdir build
cd build
source <vitis-installation-path>/settings64.sh
source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
export AMENT_PREFIX_PATH=$OECORE_NATIVE_SYSROOT/usr:$OECORE_TARGET_SYSROOT/usr
export PYTHONPATH=$OECORE_NATIVE_SYSROOT/usr/lib/python3.7/site-packages:$OECORE_TARGET_SYSROOT/usr/lib/python3.7/site-packages
cmake .. -DCMAKE_INSTALL_SO_NO_EXE=0 -DBUILD_TESTING=OFF -DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 -GNinja -DCMAKE_INSTALL_PREFIX=<path-to-sd-root> -DPLATFORM_COMPONENTS_PATH=<path-to-components> -DBUILD_TEST_TARGETS=OFF -DBUILD_TARGET=hw -DCMAKE_BUILD_TYPE=Debug -DENABLE_KRNL_CHECK=ON -DBUILD_FAST_TEST=OFF -DBUILD_FAST_AND_DIST_TEST=ON -DDISABLE_RESIZE_KRNL=ON -DDISABLE_FAST_KRNL=ON -DDISABLE_NEW_DISTRIBUTION=OFF

result

変更後

root@ultra96v2-zynqmp:~# time ./orb_slam2_ros_mono_tum_test /usr/share/orb_slam2_ros/orb_slam2/Vocabulary/ORBvoc.txt /home/root/tum-dataset

ORB-SLAM2 Copyright (C) 2014-2016 Raul Mur-Artal, University of Zaragoza.
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions. See LICENSE.txt.

OpenCV version : 3.4.3
Major version : 3
Minor version : 4
Subminor version : 3
Input sensor was set to: Monocular

Loading ORB Vocabulary.
Vocabulary loaded!


Camera Parameters: 
- fx: 517.306
- fy: 516.469
- cx: 318.643
- cy: 255.314
- k1: 0.262383
- k2: -0.953104
- k3: 0.002628
- p1: 1.16331
- p2: -0.005358
- fps: 30
- bf: 0
- color order: RGB (ignored if grayscale)
Found Platform
Platform Name: Xilinx
INFO: Device found - edge
Loading: '/usr/bin/xclbin/resize_krnl.xclbin'
file size:5634881
actual read size:5634881
program xclbin.
program xclbin Done.
create resize_accel kernel.
create resize_accel kernel Done.
Found Platform
Platform Name: Xilinx
INFO: Device found - edge
Loading: '/usr/bin/xclbin/resize_krnl.xclbin'
file size:5634881
actual read size:5634881
program xclbin.
program xclbin Done.
create resize_accel kernel.
create resize_accel kernel Done.

ORB Extractor Parameters: 
- Number of Features: 1000
- Scale Levels: 8
- Scale Factor: 1.2
- Initial Fast Threshold: 20
- Minimum Fast Threshold: 7

-------
Start processing sequence ...
Images in the sequence: 798

-------

median tracking time: 0.0999473
mean tracking time: 0.0991993

Saving keyframe trajectory to KeyFrameTrajectory.txt ...

trajectory saved!

real    1m45.135s
user    1m54.849s
sys 0m5.194s
real    1m43.408s
user    1m55.425s
sys 0m4.890s

オリジナル

実行時間だけ書いておく。
少し早くなっているかな?

real    2m1.869s
user    2m13.626s
sys 0m5.523s
real    2m0.575s
user    2m13.668s
sys 0m5.611s

2021年5月5日水曜日

ultra96v2でVitis 2020.2を使用してcv::fastをxf::cv::fastに置き換えて見た話

xf::cv::fastはコーナ部分をMatで固定値255として出力してくる。ORB_SLAM2ではコーナスコアを使用して特徴点の数を間引くので、そのままだと不都合がある。

そこでcv::fastで出力している特徴点リストと、明確さ(CornerScore)をxf::cv::fastから出力するように変更する。直接変更座標を出力するようにしたほうがリソースと速度の面から有利かもしれないので、後の改善項目として検討する。

この後は間引き処理もカーネルに取り込み、全体の並列動作を調整していく。

環境

  • ubuntu:20.04
  • vitis:2020.2
  • yocto:zeus(https://github.com/akira-nishiyama/petalinux-ros2-manifests feature-v2020.2ブランチ)
  • board:ultra96v2(https://github.com/akira-nishiyama/ultra96v2_4z.git feature-v2020.2ブランチ)

変更点

デフォルトではコーナースコアが出力されないので、以下のように変更する。

diff --git a/hw/hw_kernel/vision/include/features/xf_fast.hpp b/hw/hw_kernel/vision/include/features/xf_fast.hpp
index a7aa1b1..935c0a2 100644
--- a/hw/hw_kernel/vision/include/features/xf_fast.hpp
+++ b/hw/hw_kernel/vision/include/features/xf_fast.hpp
@@ -201,7 +201,8 @@ void xFfastProc(XF_PTNAME(DEPTH) OutputValues[XF_NPIXPERCYCLE(NPC)],
         // NMS Score Computation
         if (iscorner) {
             xFCoreScore(flag_d[i], _threshold, &core);
-            pack_corners.range(ix + 7, ix) = 255;
+            //pack_corners.range(ix + 7, ix) = 255;
+            pack_corners.range(ix + 7, ix) = core;
         } else
             pack_corners.range(ix + 7, ix) = 0;
         ix += 8;
@@ -570,7 +571,8 @@ void xFnmsProc(XF_PTNAME(DEPTH) OutputValues[XF_NPIXPERCYCLE(NPC)],
         if ((src_buf[1][1] > src_buf[1][0]) && (src_buf[1][1] > src_buf[1][2]) && (src_buf[1][1] > src_buf[0][0]) &&
             (src_buf[1][1] > src_buf[0][1]) && (src_buf[1][1] > src_buf[0][2]) && (src_buf[1][1] > src_buf[2][0]) &&
             (src_buf[1][1] > src_buf[2][1]) && (src_buf[1][1] > src_buf[2][2])) {
-            pix = 255;
+            //pix = 255;
+            pix = src_buf[1][1];
         } else {
             pix = 0;
         }

sw_emu

build

OpenCVの結果と比較するテストプログラムで確認する。 hashは85f0af60868b7a0ba831647bcfd453f4b6b19c6c

git clone https://github.com/akira-nishiyama/orb_slam_2_ros.git -b feature-fpga
cd orb_slam_2_ros
mkdir build
cd build
source <vitis-installation-path>/settings64.sh
source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
export AMENT_PREFIX_PATH=$OECORE_NATIVE_SYSROOT/usr:$OECORE_TARGET_SYSROOT/usr
export PYTHONPATH=$OECORE_NATIVE_SYSROOT/usr/lib/python3.7/site-packages:$OECORE_TARGET_SYSROOT/usr/lib/python3.7/site-packages
cmake .. -DCMAKE_INSTALL_SO_NO_EXE=0 -DBUILD_TESTING=OFF -DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 -GNinja -DCMAKE_INSTALL_PREFIX=/media/akira/usr -DPLATFORM_COMPONENTS_PATH=/home/akira/work/ultra96v2 -DBUILD_TEST_TARGETS=OFF -DBUILD_TARGET=sw_emu -DCMAKE_BUILD_TYPE=Debug -DENABLE_KRNL_CHECK=OFF -DBUILD_FAST_TEST=OFF -DBUILD_FAST_AND_DIST_TEST=ON -DDISABLE_RESIZE_KRNL=ON -DDISABLE_FAST_KRNL=OFF
ninja -j4

run

cd hw/hw_link/package_sw_emu/
source <vitis-installation-path>/settings64.sh
./launch_sw_emu.sh -pid-file emulation.pid -no-reboot -forward-port 2222 22

ターミナルで以下の通り実行する。

cd /mnt/sd-mmcblk0p1
export LD_LIBRARY_PATH=/mnt/sd-mmcblk0p1:/tmp:$LD_LIBRARY_PATH
export XCL_EMULATION_MODE=sw_emu
export XILINX_XRT=/usr
export XILINX_VITIS=/mnt/sd-mmcblk0p1
./xf_fast_and_dist_tb 128x128_1.png

result

============ xf_fast_and_dist test starts ============
INFO: Running OpenCL section.
Found Platform
Platform Name: Xilinx
INFO: Device found - avnet_com_av_ULTRA96V2_1_0
XCLBIN File Name: krnl_fast
INFO: Importing xclbin/krnl_fast.xclbin
Loading: 'xclbin/krnl_fast.xclbin'
ocv_result:511
hls_result:511
Test Passed
The maximum depth reached by any of the 2 hls::stream() instances in the design is 16384

2021年4月25日日曜日

ultra96v2上でcv::fastをaccelerationするテストを実行した話

cv::fastをaccelerationするテストを実行した話。
nonmaxSupressionは有効とし、Resource Optimizaitonも有効とする。
基本的にはVitis_Librariesのfastをそのまま持ってきて動かしただけ。
他のライブラリも同じようにして導入できそうなことが分かってきた。

準備

前回と同じ

src

vision/L2/examples/fast配下から次のファイルを配置する。

  • xf_fast_accel.cpp
  • xf_fast_config.h
  • xf_fast_tb.cpp
  • xf_config_params.h

extやdataフォルダの中身はresizeと共通して使用できる。
他のものも同じようにして導入できそう。

sw_emu

build(sw_emu)

hashは3eec9b91c8ceba52e219e4b8d0be5e64c1ec1f30
git clone https://github.com/akira-nishiyama/orb_slam_2_ros.git -b feature-fpga
cd hw
mkdir build
cd build
source <vitis-installation-path>/settings64.sh
source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
cmake .. -GNinja -DPLATFORM_COMPONENTS_PATH=<path-to-platform-components> -DBUILD_TARGET=sw_emu -DBUILD_FAST_TEST=ON

run(sw_emu)

エミュレータを起動する。次はビルドディレクトリからのコマンド例である。

cd hw/hw_link/package_sw_emu/
source <vitis-installation-path>/settings64.sh
./launch_sw_emu.sh -pid-file emulation.pid -no-reboot -forward-port 1440 1534 -forward-port 2222 22

ターミナルで次の通り実行する。 必要なファイルは/mnt/sd-mmcblk0p1にある。

root@ultra96v2-zynqmp:~# cd /mnt/sd-mmcblk0p1/
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# export LD_LIBRARY_PATH=/mnt/sd-mmcblk0p1:/tmp:$LD_LIBRARY_PATH
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# export XCL_EMULATION_MODE=sw_emu
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# export XILINX_XRT=/usr
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# export XILINX_VITIS=/mnt/sd-mmcblk0p1
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# mkdir xclbin
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# cp binary_container_1_sw_emu.xclbin xclbin/krnl_fast.xclbin
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# ./xf_fast_tb 128x128_1.png

result(sw_emu)

INFO: Running OpenCL section.
Found Platform
Platform Name: Xilinx
INFO: Device found - avnet_com_av_ULTRA96V2_1_0
XCLBIN File Name: krnl_fast
INFO: Importing xclbin/krnl_fast.xclbin
Loading: 'xclbin/krnl_fast.xclbin'
ocvpoints:511=
INFO: Verification results:
    Common = 511
    Success = 100
    Loss = 0
    Gain = 0
Test Passed
The maximum depth reached by any of the 4 hls::stream() instances in the design is 2048

hw

build(hw)

ビルドディレクトリからのコマンドを示す。

source <vitis-installation-path>/settings64.sh
source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
cmake .. -GNinja -DPLATFORM_COMPONENTS_PATH=<path-to-platform-components> -DBUILD_TARGET=hw -DBUILD_FAST_TEST=ON

run(hw)

sdカードはビルドディレクトリから以下の通り作成可能。 sd-deviceはdmesg等で調べたsdカードのデバイスファイルを指定する。

sudo dd if=hw/hw_link/package_hw/sd_card.img of=<sd-device>

ultra96のwifiに接続し、以下の通りsshアクセスを行う。

ssh -l root 192.168.2.1

ターミナルでは次のようにコマンドを実行する。

root@ultra96v2-zynqmp:~# cd /mnt/sd-mmcblk0p1/
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# export LD_LIBRARY_PATH=/mnt/sd-mmcblk0p1:/tmp:$LD_LIBRARY_PATH
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# export XILINX_XRT=/usr
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# export XILINX_VITIS=/mnt/sd-mmcblk0p1
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# mkdir xclbin
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# cp binary_container_1_hw.xclbin xclbin/krnl_fast.xclbin
root@ultra96v2-zynqmp:/mnt/sd-mmcblk0p1# ./xf_fast_tb 128x128_1.png 

result(hw)

INFO: Running OpenCL section.
Found Platform
Platform Name: Xilinx
INFO: Device found - edge
XCLBIN File Name: krnl_fast
INFO: Importing xclbin/krnl_fast.xclbin
Loading: 'xclbin/krnl_fast.xclbin'
ocvpoints:511=
INFO: Verification results:
    Common = 511
    Success = 100
    Loss = 0
    Gain = 0
Test Passed

2021年4月23日金曜日

ultra96v2+orb_slam2のaccelerationでcv::resizeを置き換えてみた話

ultra96v2+orb_slam2のaccelerationでcv::resizeをハードウェアカーネルに置き換えてみた話。 単純に置き換えるだけじゃやっぱりだめだよねっていう結果が得られた。

環境

  • ubuntu:20.04
  • vitis:2020.2
  • yocto:zeus(https://github.com/akira-nishiyama/petalinux-ros2-manifests feature-v2020.2ブランチ)
  • board:ultra96v2(https://github.com/akira-nishiyama/ultra96v2_4z.git feature-v2020.2ブランチ)

準備

前回と同じ

変更内容

とりあえずの対象はACRiの記事で示されているExtractORBとする。
記事に記載の内容を実装してみることとするが、ultra96v2向けにはリソース使用量から考えて記事に記載の回路そのままは入らないと考えられるため並列処理数は減らしていく方向で検討する。
とりあえずはcv::resizeを回路に置き換えてみて様子を見る。
このためにORBExtractor.ccとORBExtractor.hを変更した。
主にOpen CLのランタイム環境設定と、cv::resizeに対してカーネル呼び出しコードの追加を行った。
(参考:https://japan.xilinx.com/html_docs/xilinx2020_2/vitis_doc/devhostapp.html#ariaid-title2)

sw_emu

build

sw_emuでは簡単に動作を見ていく。 そのためにENABLE_KRNL_CHECKオプションを有効にする。 ENABLE_KRNL_CHECKオプションはKRNL_CHECKをdefineして必要な処理をORBExtractorに追加している。

hashは9fd1ad11b8982927366b687b527595651a82d8a9。将来変更となると思うので。

git clone https://github.com/akira-nishiyama/orb_slam_2_ros.git -b feature-fpga
cd orb_slam_2_ros
mkdir build
cd build
source <vitis-installation-path>/settings64.sh
source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
export AMENT_PREFIX_PATH=$OECORE_NATIVE_SYSROOT/usr:$OECORE_TARGET_SYSROOT/usr
export PYTHONPATH=$OECORE_NATIVE_SYSROOT/usr/lib/python3.7/site-packages:$OECORE_TARGET_SYSROOT/usr/lib/python3.7/site-packages
cmake .. -DCMAKE_INSTALL_SO_NO_EXE=0 -DBUILD_TESTING=OFF -DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 -GNinja -DCMAKE_INSTALL_PREFIX=<path-to-sdcard>/usr -DPLATFORM_COMPONENTS_PATH=<path-to-platform-components> -DBUILD_TEST_TARGETS=ON -DBUILD_TARGET=sw_emu -DCMAKE_BUILD_TYPE=Debug -DENABLE_KRNL_CHECK=ON
ninja -j4

run

エミュレータを起動する。次はビルドディレクトリからのコマンド例である。

cd hw/hw_link/package_sw_emu/
source <vitis-installation-path>/settings64.sh
./launch_sw_emu.sh -pid-file emulation.pid -no-reboot -forward-port 1440 1534 -forward-port 2222 22

エミュレータが起動したら必要なファイルを転送する。
リポジトリのトップからの転送コマンドを示す。

ssh -p 2222 root@localhost "mkdir -p /usr/bin/xclbin"
scp -P 2222 build/orb_slam2_ros_mono_tum_test root@localhost:/home/root/
scp -P 2222 orb_slam2/lib/liborb_slam2_ros_core.so root@localhost:/usr/lib/liborb_slam2_ros_core.accel.so
scp -P 2222 build/hw/hw_link/orbslam2_accel_sw_emu.xclbin root@localhost:/usr/bin/xclbin/resize_krnl.xclbin

エミュレータ上でプログラムを実行する。(参考:https://japan.xilinx.com/html_docs/xilinx2020_2/vitis_doc/runemulation1.html#ariaid-title6)
オリジナルのliborb_slam2_ros_core.soはsoft実行用に保存し、新たにacceleration向けのものをリンクしておきこれを実行する。

export LD_LIBRARY_PATH=/mnt/sd-mmcblk0p1:/tmp:$LD_LIBRARY_PATH
export XCL_EMULATION_MODE=sw_emu
export XILINX_XRT=/usr
export XILINX_VITIS=/mnt/sd-mmcblk0p1
mv /usr/lib/liborb_slam2_ros_core.so /usr/lib/liborb_slam2_ros_core.soft.so
ln -s -f /usr/lib/liborb_slam2_ros_core.accel.so /usr/lib/liborb_slam2_ros_core.so
cp /mnt/sd-mmcblk0p1/emconfig.json .
./orb_slam2_ros_mono_tum_test /usr/share/orb_slam2_ros/orb_slam2/Vocabulary/ORBvoc.txt ./tum-dataset

result

一生かかっても終わる気配が無かったので途中で中断している。 opencvと同じ結果が得られているようなのでとりあえずよしとする。 (意図的にfailさせてないのでテストプログラムが正しいかは少し心配)

root@ultra96v2-zynqmp:~# ./orb_slam2_ros_mono_tum_test /usr/share/orb_slam2_ros/orb_slam2/Vocabulary/ORBvoc.txt ./tum-dataset

ORB-SLAM2 Copyright (C) 2014-2016 Raul Mur-Artal, University of Zaragoza.
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions. See LICENSE.txt.

OpenCV version : 3.4.3
Major version : 3
Minor version : 4
Subminor version : 3
Input sensor was set to: Monocular

Loading ORB Vocabulary.
Vocabulary loaded!


Camera Parameters: 
- fx: 517.306
- fy: 516.469
- cx: 318.643
- cy: 255.314
- k1: 0.262383
- k2: -0.953104
- k3: 0.002628
- p1: 1.16331
- p2: -0.005358
- fps: 30
- bf: 0
- color order: RGB (ignored if grayscale)
Found Platform
Platform Name: Xilinx
INFO: Device found - avnet_com_av_ULTRA96V2_1_0
Loading: '/usr/bin/xclbin/resize_krnl.xclbin'
Found Platform
Platform Name: Xilinx
INFO: Device found - avnet_com_av_ULTRA96V2_1_0
Loading: '/usr/bin/xclbin/resize_krnl.xclbin'

ORB Extractor Parameters: 
- Number of Features: 1000
- Scale Levels: 8
- Scale Factor: 1.2
- Initial Fast Threshold: 20
- Minimum Fast Threshold: 7

-------
Start processing sequence ...
Images in the sequence: 798

here! level=1
in_height:480,in_width:640
out_height:400,out_width:533
    Minimum error in intensity = 0
    Maximum error in intensity = 0
    Percentage of pixels above error threshold = 0
Check Passed 
here! level=2
in_height:400,in_width:533
out_height:333,out_width:444
    Minimum error in intensity = 0
    Maximum error in intensity = 0
    Percentage of pixels above error threshold = 0
Check Passed 
here! level=3
in_height:333,in_width:444
out_height:278,out_width:370
    Minimum error in intensity = 0
    Maximum error in intensity = 0
    Percentage of pixels above error threshold = 0
Check Passed 
here! level=4
in_height:278,in_width:370
out_height:231,out_width:309
    Minimum error in intensity = 0
    Maximum error in intensity = 0
    Percentage of pixels above error threshold = 0
Check Passed 
here! level=5
in_height:231,in_width:309
out_height:193,out_width:257
    Minimum error in intensity = 0
    Maximum error in intensity = 0
    Percentage of pixels above error threshold = 0
Check Passed 
here! level=6
in_height:193,in_width:257
out_height:161,out_width:214
    Minimum error in intensity = 0
    Maximum error in intensity = 0
    Percentage of pixels above error threshold = 0
Check Passed 
here! level=7
in_height:161,in_width:214
out_height:134,out_width:179
    Minimum error in intensity = 0
    Maximum error in intensity = 0
    Percentage of pixels above error threshold = 0
Check Passed 
here! level=1
in_height:480,in_width:640
out_height:400,out_width:533
    Minimum error in intensity = 0
    Maximum error in intensity = 0
    Percentage of pixels above error threshold = 0
Check Passed 
here! level=2
in_height:400,in_width:533
out_height:333,out_width:444
    Minimum error in intensity = 0
    Maximum error in intensity = 0
    Percentage of pixels above error threshold = 0
Check Passed 
here! level=3
in_height:333,in_width:444
out_height:278,out_width:370
^C
root@ultra96v2-zynqmp:~# 

hw

build

buildディレクトリで以下のように実行。 環境変数設定済の場合はcmake以降を実行すれば良い。

source <vitis-installation-path>/settings64.sh
source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
export AMENT_PREFIX_PATH=$OECORE_NATIVE_SYSROOT/usr:$OECORE_TARGET_SYSROOT/usr
export PYTHONPATH=$OECORE_NATIVE_SYSROOT/usr/lib/python3.7/site-packages:$OECORE_TARGET_SYSROOT/usr/lib/python3.7/site-packages
cmake .. -DCMAKE_INSTALL_SO_NO_EXE=0 -DBUILD_TESTING=OFF -DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 -GNinja -DCMAKE_INSTALL_PREFIX=<path-to-sdcard>/usr -DPLATFORM_COMPONENTS_PATH=<path-to-platform-components> -DBUILD_TEST_TARGETS=ON -DBUILD_TARGET=hw -DCMAKE_BUILD_TYPE=Debug -DENABLE_KRNL_CHECK=OFF
ninja -j4

run

ビルドディレクトリから以下の通り実行してsdカードを作成する。

sudo dd if=hw/hw_link/package_hw/sd_card.img of=<path-to-sd-device>

sdをultra96v2に挿して起動させれば良い。 wifiは有効なはずなので、これに接続すれば、次のコマンドでターミナルにアクセスできる。

ssh 192.168.2.1 -l root

sdに直接書いてもいいが、何度かビルドと変更を繰り返すことになると思うので ホストで次のコマンドを実行して必要なファイルを転送する。 実行はリポジトリのトップから行っている。

ssh root@192.168.2.1 "mkdir -p /usr/bin/xclbin"
scp build/orb_slam2_ros_mono_tum_test root@192.168.2.1:/home/root/
scp orb_slam2/lib/liborb_slam2_ros_core.so root@192.168.2.1:/usr/lib/liborb_slam2_ros_core.accel.so
scp build/hw/hw_link/orbslam2_accel_sw_emu.xclbin root@192.168.2.1:/usr/bin/xclbin/resize_krnl.xclbin

ultra96v2のターミナルで以下のコマンドを入力してオリジナルの状態を確認する。

root@ultra96v2-zynqmp:~# export LD_LIBRARY_PATH=/mnt/sd-mmcblk0p1:/tmp:$LD_LIBRARY_PATH
root@ultra96v2-zynqmp:~# export XILINX_XRT=/usr
root@ultra96v2-zynqmp:~# export XILINX_VITIS=/mnt/sd-mmcblk0p1
root@ultra96v2-zynqmp:~# mv /usr/lib/liborb_slam2_ros_core.so /usr/lib/liborb_slam2_ros_core.soft.so
root@ultra96v2-zynqmp:~# ln -s -f /usr/lib/liborb_slam2_ros_core.soft.so /usr/lib/liborb_slam2_ros_core.so
root@ultra96v2-zynqmp:~# time ./orb_slam2_ros_mono_tum_test /usr/share/orb_slam2_ros/orb_slam2/Vocabulary/ORBvoc.txt ./tum-dataset

result

liborb_slam2_ros_core.soft.soを実行した場合の結果は次の通りだった。

ORBvoc.txt ./tum-dataset

ORB-SLAM2 Copyright (C) 2014-2016 Raul Mur-Artal, University of Zaragoza.
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions. See LICENSE.txt.

OpenCV version : 3.4.3
Major version : 3
Minor version : 4
Subminor version : 3
Input sensor was set to: Monocular

Loading ORB Vocabulary.
Vocabulary loaded!


Camera Parameters: 
- fx: 517.306
- fy: 516.469
- cx: 318.643
- cy: 255.314
- k1: 0.262383
- k2: -0.953104
- k3: 0.002628
- p1: 1.16331
- p2: -0.005358
- fps: 30
- bf: 0
- color order: RGB (ignored if grayscale)

ORB Extractor Parameters: 
- Number of Features: 1000
- Scale Levels: 8
- Scale Factor: 1.2
- Initial Fast Threshold: 20
- Minimum Fast Threshold: 7

-------
Start processing sequence ...
Images in the sequence: 798

-------

median tracking time: 0.129078
mean tracking time: 0.129074

Saving keyframe trajectory to KeyFrameTrajectory.txt ...

trajectory saved!

real    2m9.262s
user    2m19.686s
sys 0m5.226s
root@ultra96v2-zynqmp:~# cat KeyFrameTrajectory.txt 
root@ultra96v2-zynqmp:~# 

accelerationを使用した場合の結果は次の通りであった。

root@ultra96v2-zynqmp:~# ln -s -f /usr/lib/liborb_slam2_ros_core.accel.so /usr/lib/liborb_slam2_ros_core.so
root@ultra96v2-zynqmp:~# time ./orb_slam2_ros_mono_tum_test /usr/share/orb_slam2_ros/orb_slam2/Vocabulary/ORBvoc.txt ./tum-dataset

ORB-SLAM2 Copyright (C) 2014-2016 Raul Mur-Artal, University of Zaragoza.
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions. See LICENSE.txt.

OpenCV version : 3.4.3
Major version : 3
Minor version : 4
Subminor version : 3
Input sensor was set to: Monocular

Loading ORB Vocabulary.
Vocabulary loaded!


Camera Parameters: 
- fx: 517.306
- fy: 516.469
- cx: 318.643
- cy: 255.314
- k1: 0.262383
- k2: -0.953104
- k3: 0.002628
- p1: 1.16331
- p2: -0.005358
- fps: 30
- bf: 0
- color order: RGB (ignored if grayscale)
Found Platform
Platform Name: Xilinx
INFO: Device found - edge
Loading: '/usr/bin/xclbin/resize_krnl.xclbin'
Found Platform
Platform Name: Xilinx
INFO: Device found - edge
Loading: '/usr/bin/xclbin/resize_krnl.xclbin'

ORB Extractor Parameters: 
- Number of Features: 1000
- Scale Levels: 8
- Scale Factor: 1.2
- Initial Fast Threshold: 20
- Minimum Fast Threshold: 7

-------
Start processing sequence ...
Images in the sequence: 798

-------

median tracking time: 0.148386
mean tracking time: 0.148938

Saving keyframe trajectory to KeyFrameTrajectory.txt ...

trajectory saved!

real    2m25.290s
user    2m20.827s
sys 0m5.976s
root@ultra96v2-zynqmp:~# cat KeyFrameTrajectory.txt 
root@ultra96v2-zynqmp:~# 

2021年1月30日土曜日

Vitis 2020.2でvector additionサンプルをコマンドラインからライブラリとしてビルドできるようにしてデバッグ方法を確認した

vector additionサンプルをコマンドラインからライブラリとしてビルドできるようにしてデバッグ方法を確認した話。

環境

  • ubuntu:20.04
  • vitis:2020.2
  • yocto:zeus(https://github.com/akira-nishiyama/petalinux-ros2-manifests feature-v2020.2ブランチ)
  • board:ultra96v2(https://github.com/akira-nishiyama/ultra96v2_4z.git feature-v2020.2ブランチ)

ビルド方法

githubにvadd_lib_sampleリポジトリを用意するので、 xsaとboot componentを用意してsdカードのパスを確認して以下の通り実行すればok。なお、サンプルはVitis-Tutorialsを参考にさせてもらっている。

git clone https://github.com/akira-nishiyama/vitis_library_compilation_sample.git
cd vitis_library_compilation_sample

platform設定は用意したxsaとboot componentに合わせて修正が必要。 guiでプラットフォーム作るときと同じようにパスを指定すれば良い。

  • platform/platform.tcl
platform create -name {ultra96v2_platform}\
-hw {/home/akira/work/ultra96v2/xsa_dir/ultra96v2_4z/ultra96v2_4z.xsa}\
-proc {psu_cortexa53} -os {linux} -arch {64-bit} -no-boot-bsp -fsbl-target {psu_cortexa53_0} -out {.}

platform write
platform active {ultra96v2_platform}
domain config -bif {/home/akira/work/ultra96v2/vitis_args/linux.bif}
platform write
domain config -boot {/home/akira/work/ultra96v2/boot}
platform write
domain config -image {/home/akira/work/ultra96v2/boot}
platform write
domain config -rootfs {/home/akira/work/ultra96v2/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.ext4}
platform write
domain config -sysroot {/home/akira/work/ultra96v2/sdk/sysroots/aarch64-xilinx-linux}
platform write
domain config -qemu-data {/home/akira/work/ultra96v2/vitis_args}
platform write
domain config -qemu-data {/home/akira/work/ultra96v2/boot}
platform write
domain config -qemu-args {/home/akira/work/ultra96v2/vitis_args/qemu_args.txt}
platform write
domain config -pmuqemu-args {/opt/Xilinx/Vitis/2020.2/data/emulation/platforms/zynqmp/sw/a53_linux/qemu/pmu_args.txt}
platform write
domain config -pmuqemu-args {/home/akira/work/ultra96v2/vitis_args/pmu_args.txt}
platform write
domain config -qemu-data {/home/akira/work/ultra96v2/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp}
platform write
platform generate

<sd-device>,<sd-device-root>は環境に合わせて指定すること。

source <vitis-installation-path>/settings.sh
source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
export PATH_TO_SD=<path-to-sd>
mkdir build
cd build
cmake .. -DBUILD_TARGET=hw
sudo dd if=hw_link/package_hw/sd_card.img of=<sd-device>
mkdir rootfs
sudo mount <sd-device-root> rootfs
sudo cp host/test_vecadd rootfs/home/root
sudo cp hw_link/binary_container_2_hw.xclbin rootfs/home/root
sudo cp host/libvecadd.so rootfs/usr/lib

sdをultra96v2に挿して起動後、次のコマンドを実行するとTEST PASSEDの文字が確認できる。

# ./vecadd_test binary_container_2_hw.xclbin 
Loading: 'binary_container_2_hw.xclbin'
TEST PASSED

また、BUILD_TARGETをsw_emu,hw_emuとするとbuild配下のhw_link/package_sw_emuやhw_link/package_hw_emuにエミュレーション用のファイル出来上がるので、それぞれのフォルダでterminalを2つ用意し、次の通り実行するとデバッグ可能。(https://japan.xilinx.com/html_docs/xilinx2020_1/vitis_doc/debugappproj.html#rme1587072841352)

なお、実行に際してはxrt.iniを自分で用意する必要がある。(https://www.xilinx.com/html_docs/xilinx2020_2/vitis_doc/obl1532064985142.html)

[Debug] 
profile=true
timeline_trace=true
trace_buffer_size=1M

ライブラリのパスをどうやって解決しているのかはよくわからない。

sw_emu

build/package_sw_emuに移動して次のコマンドを実行する。

  • terminal1
./launch_sw_emu.sh -pid-file emulation.pid -no-reboot -forward-port 1440 1534

ログインプロンプトが表示されたら次のコマンドを実行する。 デバッグしないなら/mnt/sd-mmcblk0p1においてあるテストプログラムを実行すれば結果が得られる。 ただし、export XCL_EMULATION_MODE=sw_emuの実行(xrt.iniに書いても可かも)と、libvecadd.soを/usr/libにコピーする必要がある。

  • terminal2
vitis -debug -flow embedded_accel -target sw_emu -exe ../../host/vecadd_test -program-args binary_container_2_sw_emu.xclbin -kernels vadd

実行後、vitisが立ち上がるので、vaddにブレークポイントを設定する。


 

メニューからFile->Open fileしてline break pointを指定しても良い。


 

実行するとbreak pointにひっかかる。


 

無事に終了。


 

profileデータなどはbuild/package_sw_emu/reportに保存されるのでvitis_analyzerで開けば確認できる。

vitis_analyzer reports



hw_emu

build/package_hw_emuに移動して次のコマンドを実行する。 -sim-guiは波形でバッグしない場合は不要。

  • terminal1
./launch_hw_emu.sh -pid-file emulation.pid -sim-gui -no-reboot -forward-port 1440 1534

ログインプロンプトが表示されたら次のコマンドを実行する。 デバッグしないなら/mnt/sd-mmcblk0p1においてあるテストプログラムを実行すれば結果が得られる。

  • terminal2
vitis -debug -flow embedded_accel -target hw_emu -exe ../../host/vecadd_test -program-args binary_container_2_hw_emu.xclbin -kernels vadd

メニューからFile->Open fileしてline break pointを指定できる。 HWカーネルはCソースレベルではブレークできないようだが、 vivado_simと同じ使い方でブレークさせることは可能そう。


 

構成

まず、vitisのembedded accelerationはplatform部と、host部と、hw_kernel部と、hw_link部に分けることができる。

platformは必要なファイルを集めて固定のshell部分を作っている。

host部はクロスコンパイラを使用してxilinxopencl,pthread,rt,stdc++,gmp,xrt_coreとリンクすれば良い。インクルードディレクトリはsdkの環境セットアップすれば解決される。通常のC++などと同じに扱えるのでライブラリはそれで作成可能。 (https://japan.xilinx.com/html_docs/xilinx2020_1/vitis_doc/debugappproj.html#rme1587072841352)

hw_kernel部はv++ -cを動作させて.xoを作成している。

hw_link部ではv++ -lで.xoを必要な個数接続している。また、パッケージ化もついでに行っている。

2021年1月19日火曜日

ros2 eloquent + orb_slam2_rosをクロスコンパイルして動かした話

ultra96v2とros2 eloquentでorb_slam2を動かした際のメモ。 能力不足なのか、マッピングが動かなかった。

vitisで性能改善させるのにsdkでのクロスコンパイル環境必要かと思ったので整えた。

レシピはここのfeature-v2020.2ブランチから一式取得できる。 もしくはここのfeature-v2020.2ブランチにレシピ類がまとめてある。

レシピの変更

クロスコンパイル用のパッケージにはnativesdkをBBCLASSEXTENDに追加する必要がある。 そのため、/sources/meta-ros/meta-ros-common/classes/ros_superflore_generated.bbclassを変更する。

# BBCLASSEXTEND_append = "${@bb.utils.contains('ROS_SUPERFLORE_GENERATED_BUILDTOOLS', '${BPN}-native', ' native', '', d)}"
BBCLASSEXTEND_append = "${@bb.utils.contains('ROS_SUPERFLORE_GENERATED_BUILDTOOLS', '${BPN}-native', ' native nativesdk', '', d)}"

次のファイルはFILES_${PN} += "*"を追加する。 そのままだとament-cmake向けファイル等がインストールされない模様。
recipes-ros2/ament-index-python/ament-index-python_%.bbappend
recipes-ros2/ament-package/ament-package_%.bbappend
recipes-ros2/domain-coordinator/domain-coordinator_%.bbappend

python3-lark-parserはBsuperfloreのBUILDTOOL登録されていないため、nativesdk化されない。 なのでbbappendでBBCLASSEXTEND_appendにnativesdkを追加する。 recipes-ros2/python3-lark-parser/python3-lark-parser_%.bbappend

rviz-ogre-vendorがmesaに依存しているけど、 zynqではmesa-glを使用するので、mesaを削除してmesa-glを追加する。
recipes-ros2/rviz/rviz-ogre-vendor_%.bbappend

ROS_BUILD_DEPENDS_remove = "mesa"
ROS_BUILD_DEPENDS_append = " mesa-gl"
ROS_EXPORT_DEPENDS_remove = "mesa"
ROS_EXPORT_DEPENDS_append = " mesa-gl"
ROS_EXEC_DEPENDS_remove = "mesa"
ROS_EXEC_DEPENDS_append = " mesa-gl"

あとはpackage.xmlを参考にopencv-camとros2-sharedのレシピを作成する。
recipes-ros2/opencv-cam/opencv-cam_git.bb
recipes-ros2/ros2-shared/ros2-shared_git.bb

あとはSDKのためにTOOLCHAIN_TARGET_TASK_appendとTOOLCHAIN_HOST_TASK_appendを recipes-core/images/petalinux-image-minimal-ultra96v2ros2.bbに追加していく。
yoctoは自動的に依存関係収集してくれないようなので、クロスコンパイルしたい対象の依存関係を手動で解決していく。
*-nativeに依存している場合はnativesdk-*をTOOLCHAIN_HOST_TASK_appendに追加する。
無印の場合にはTOOLCHAIN_TARGET_TASK_appendに該当パッケージを追加する。
クロスコンパイル実行時にライブラリが不足などのメッセージが出た場合には-staticdevや-devなどをTOOLCHAIN_TARGET_TASK_appendに追加する。
(で合ってるはず。自信は無い。)

ビルド

MACHINE=ultra96v2-zynqmp bitbake petalinux-image-minimal-ultra96v2ros2
MACHINE=ultra96v2-zynqmp bitbake petalinux-image-minimal-ultra96v2ros2 -c do_populate_sdk

orb-slam2-rosの実行

まずはカメラ画像の確認。 USBのHOSTにwebカメラを接続する。 使用するのはlogicoolのc270n。 ついでにCPU使用率を確認する。

ssh 192.168.2.1 -l root
root@ultra96v2-zynqmp:~# source ros_setup.sh
root@ultra96v2-zynqmp:~# ros2 run opencv_cam opencv_cam_main --ros-args --param index:=0 --param camera_info_path:=camera-info-logicool-c270n.ini &
root@ultra96v2-zynqmp:~# top

topで動作を確認。

top - 23:11:54 up 11:33,  2 users,  load average: 0.86, 1.13, 1.63
Tasks: 103 total,   3 running, 100 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.2 us,  2.3 sy,  0.0 ni, 97.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   1974.4 total,   1682.3 free,    124.8 used,    167.3 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   1780.4 avail Mem 

大したことはなさそう。

orb-slam2-rosを動かす。

root@ultra96v2-zynqmp:~# ros2 run orb_slam2_ros orb_slam2_ros_mono --ros-args --remap /camera/image_raw:=/image_raw --remap /camera/camera_info:=/camera_info --param params_file:=/usr/share/orb_slam2_ros/ros/config/params_d435_mono.yaml --param voc_file:=/usr/share/orb_slam2_ros/orb_slam2/Vocabulary/ORBvoc.txt &

同じくtopで確認。1オプションでCPU毎の負荷も確認しておく。

top - 23:50:13 up 12:11,  2 users,  load average: 3.71, 3.16, 2.74
Tasks: 108 total,   2 running, 106 sleeping,   0 stopped,   0 zombie
%Cpu0  : 85.9 us,  2.0 sy,  0.0 ni, 11.8 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu1  : 21.5 us,  5.0 sy,  0.0 ni, 73.2 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu2  : 48.1 us,  6.5 sy,  0.0 ni, 45.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  :  3.2 us, 26.4 sy,  0.0 ni, 70.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   1974.4 total,   1089.0 free,    665.8 used,    219.6 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   1239.2 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                 
 1628 root      20   0 1790424 505660  21916 R 121.2  25.0  26:20.67 orb_slam2_ros_m                                                                         
 1277 root      20   0  516600  47812  23240 S  47.4   2.4  12:44.68 opencv_cam_main                                                                         
 4034 root       0 -20       0      0      0 I  31.8   0.0   3:38.79 kworker/u9:2-uvcvideo                                                                   
 1258 root      20   0  415052  37020  15196 S   1.0   1.8   0:24.32 python3                                                                                 
 6384 root      20   0    3320   2024   1564 R   0.7   0.1   0:02.39 top                                                                                     

CPUごとに見ると1つのCPUの負荷が高く、orb_slam2_rosプロセスの負荷が高い。 load averageも高めで能力足りてないと見ればいいかな。

クロスコンパイル

sdkをインストールしたあと

/sysroots/x86_64-petalinux-linux/usr/share/cmake/OEToolchainConfig.cmake を次のように編集する。 $ENV{OECORE_NATIVE_SYSROOT}が無いとnativeツールが発見できないため

set( CMAKE_FIND_ROOT_PATH "\$ENV{OECORE_TARGET_SYSROOT};\$ENV{OECORE_NATIVE_SYSROOT}" )

sysroots/aarch64-xilinx-linux/usr/share/fastrtps/cmake/fastrtps-targets.cmakeの検索パスが間違っているので修正。 レシピから修正したほうがいいだろうけど、とりあえずなんとかなるから後回し。

#set_target_properties(fastrtps PROPERTIES
#  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
#  INTERFACE_LINK_LIBRARIES "fastcdr;foonathan_memory;-lpthread;dl;/home/akira/work/ultra96v2/petalinux/build/tmp/work/aarch64-xilinx-linux/fastrtps/1.9.3-2-r0/recipe-sysroot/usr/lib/libtinyxml2.so;\$<\$<BOOL:1>:OpenSSL::SSL\$<SEMICOLON>OpenSSL::Crypto>;\$<\$<BOOL:>:iphlpapi\$<SEMICOLON>Shlwapi>"
#)
set_target_properties(fastrtps PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "fastcdr;foonathan_memory;-lpthread;dl;$ENV{OECORE_TARGET_SYSROOT}/usr/lib/libtinyxml2.so;\$<\$<BOOL:1>:OpenSSL::SSL\$<SEMICOLON>OpenSSL::Crypto>;\$<\$<BOOL:>:iphlpapi\$<SEMICOLON>Shlwapi>"
)

buildの実行。インストールパスはsd-cardのrootをマウントした場所を指定する。

source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
export AMENT_PREFIX_PATH=$OECORE_NATIVE_SYSROOT/usr:$OECORE_TARGET_SYSROOT/usr
export PYTHONPATH=$OECORE_NATIVE_SYSROOT/usr/lib/python3.7/site-packages:$OECORE_TARGET_SYSROOT/usr/lib/python3.7/site-packages
cd <path-to-orb_slam2_ros-repository>
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_SO_NO_EXE=0 -DBUILD_TESTING=OFF -DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 -GNinja -DCMAKE_INSTALL_PREFIX=<sd-card-root>
cmake --build
sudo ninja install

同じようにtopを実行してみると似た結果が得られている。

top - 00:12:13 up 12 min,  2 users,  load average: 3.12, 1.92, 0.98
Tasks: 109 total,   4 running, 105 sleeping,   0 stopped,   0 zombie
%Cpu(s): 45.3 us, 14.8 sy,  0.0 ni, 39.5 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
MiB Mem :   1974.4 total,   1059.6 free,    636.4 used,    278.5 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   1249.7 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                 
 1212 root      20   0 1785152 499480  21788 R 125.2  24.7   0:15.17 orb_slam2_ros_m                                                                         
  812 root      20   0  516588  47672  22840 S  67.5   2.4   1:58.91 opencv_cam_main                                                                         
  133 root       0 -20       0      0      0 R  46.4   0.0   0:50.66 kworker/u9:0+uvcvideo                                                                   
 1211 root      20   0    3320   2064   1616 R   0.7   0.1   0:00.10 top                         

また、rviz2でdebug_imageを確認するとorb_slam2_rosから出力されているのでクロスコンパイル版もしっかり動作している模様。

2020年12月9日水曜日

ultra96v2でVitis_AIを試してみた(2020.2)

ultra96v2でVitis_AIを試してみた話。

参考ページ

sdイメージの作成はここ

MNISTの実行はここ

日本語ならここ

環境

Ubuntu 20.04
Vitis 2020.2
Vivado 2020.2
Petalinux 2020.2

準備

ここに書いてあるplatformを準備する。 petalinuxのイメージは記事から変更している。(Vitis-AI関連とparted関連) vitis-ai-devパッケージは念の為入れといたけど動かす分には不要そう。(試して無いのでリポジトリはそのまま)

Platformの作成

VItis-AIにあるDPU-TRDをultra96v2向けに設定する。

cd <path-to-work-dir>
git clone https://github.com/Xilinx/Vitis-AI.git -b v1.2.1
cd DPU-TRD/prj/Vitis

そのままだと合成できなかったので以下3つのファイルを変更した。

  • DPU-TRD/prj/Vitis/Makefile そのままの設定だとultra96v2に乗らないので、Configを変更する。 また、pre-builtの環境を使用しないので指定できるように変更する。

hwhファイルのパスが変更となっているのか、取得できなかったので合わせて修正している。

-XOCC_OPTS = -t ${TARGET} --platform ${SDX_PLATFORM} --save-temps --config ${DIR_PRJ}/config_file/prj_config_102_3dpu_LPD --xp param:compiler.userPostSysLinkOverlayTcl=${DIR_PRJ}/syslink/strip_interconnects.tcl 
+XOCC_OPTS = -t ${TARGET} --platform ${SDX_PLATFORM} --save-temps --config ${DIR_PRJ}/config_file/prj_config --xp param:compiler.userPostSysLinkOverlayTcl=${DIR_PRJ}/syslink/strip_interconnects.tcl

-   v++ -t ${TARGET} --platform ${SDX_PLATFORM} -p binary_container_1/dpu.xclbin --package.out_dir binary_container_1 --package.rootfs $(EDGE_COMMON_SW)/rootfs.ext4 --package.sd_file $(EDGE_COMMON_SW)/Image 
-   cp ./binary_*/link/vivado/vpl/prj/prj.srcs/sources_1/bd/*/hw_handoff/*.hwh ./binary_*/sd_card
+   v++ -t ${TARGET} --platform ${SDX_PLATFORM} -p binary_container_1/dpu.xclbin --package.out_dir binary_container_1 --package.rootfs $(ROOTFS) --package.sd_file $(IMAGE)
+   cp ./binary_*/link/vivado/vpl/prj/*/sources_1/bd/*/hw_handoff/*.hwh ./binary_*/sd_card
  • DPU-TRD/prj/Vitis/config_file/prj_config DPUを1個に設定する。
-freqHz=300000000:DPUCZDX8G_2.aclk
-freqHz=600000000:DPUCZDX8G_2.ap_clk_2
+#freqHz=300000000:DPUCZDX8G_2.aclk
+#freqHz=600000000:DPUCZDX8G_2.ap_clk_2

-sp=DPUCZDX8G_2.M_AXI_GP0:HPC0
-sp=DPUCZDX8G_2.M_AXI_HP0:HP2
-sp=DPUCZDX8G_2.M_AXI_HP2:HP3
+#sp=DPUCZDX8G_2.M_AXI_GP0:HPC0
+#sp=DPUCZDX8G_2.M_AXI_HP0:HP2
+#sp=DPUCZDX8G_2.M_AXI_HP2:HP3

-nk=DPUCZDX8G:2
+nk=DPUCZDX8G:1
  • DPU-TRD/prj/Vitis/dpu_conf.vh b/DPU-TRD/prj/Vitis/dpu_conf.vh DPUの型式を変更する。
-`define B4096 
+`define B512

修正したらmakeする。

source <vitis_install_path>/2020.2/settings.sh
make KERNEL=DPU_SM DEVICE=ultra96v2 SDX_PLATFORM=<path-to-platform>/ultra96v2-platform.xpfm ROOTFS=<path-to-rootfs>/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.ext4 IMAGE=<path-to-image>/Image

ビルドが終了したらsdカードを作成する。

dd if=binary_container_1/sd_card.img of=/dev/sdX

MNIST実行ファイルの作成

Vitis-AI-Tutorialを利用する。 dockerのsetupは必要。 理由は不明だが、vitis-ai-cpu:latestはdletがうまく動作しなかったので、 xilinx/vitis-ai:latestを使用。2020.2を使用しているからか?

cd <path-to-work-dir>
git clone https://github.com/Xilinx/Vitis-AI-Tutorials.git -b MNIST=Classification-TensorFlow
    cd Vitis-AI-Tutorials/files
cp <path-to-work-dir>/Vitis-AI/DPU-TRD/prj/Vitis/binary_container_1/sd_card/ultra96v2_4z.hwh .
wget https://www.fpga.co.jp/u96v2_vitisai_2020.1/u96v2.json
./docker_run xilinx/vitis-ai:latest

vitis-aiが起動したらTutorialに従い以下の通り実行する。 6_compileと7_make_targetはultra96v2向けに変更が必要。

source 0_setenv.sh
dlet -f ultra96v2_4z.hwh
export COMPILE_u96v2=${BUILD}/compile_u96v2
export TARGET_u96v2=${BUILD}/target_u96v2
source 1_train.sh
source 2_freeze.sh
source 3_eval_frozen_graph.sh
source 4_quant.sh
source 5_eval_quant_graph.sh

#source 6_compile_u96v2.sh
rm -rf ${COMPILE_u96v2}
mkdir -p ${COMPILE_u96v2}
vai_c_tensorflow --frozen_pb  ${QUANT}/deploy_model.pb --arch ./u96v2.json --output_dir ${COMPILE_u96v2} --net_name ${NET_NAME}

#source 7_make_target_u96v2.sh
# remove previous results
rm -rf ${TARGET_u96v2}
mkdir -p ${TARGET_u96v2}/model_dir

# copy application to target folder
cp ${APP}/*.py ${TARGET_u96v2}
echo "  Copied application to target folder"

# copy elf to target folder
cp ${COMPILE_u96v2}/*.elf ${TARGET_u96v2}/model_dir/.
echo "  Copied elf file(s) to target folder"

# create image files and copy to target folder
mkdir -p ${TARGET_u96v2}/images

python generate_images.py  \
    --dataset=mnist \
    --image_dir=${TARGET_u96v2}/images \
    --image_format=jpg \
    --max_images=10000

ultra96v2の電源を投入し、ログインしてSDのパーティションを広げる。 wifiを有効にしているので、wifi経由でアクセスする場合にはネットワーク接続したあと以下の通り実行する。

ssh 192.168.2.1 -l root
parted
resizepart
2
Yes
100%
quit
resize2fs /dev/mmcblk0p2

このあと、ホストから必要なファイルを転送してチュートリアルを実行する。

cd <path-to-work-dir>/Vitis-AI-Tutorials/files
tar cvfz target_u96v2.tar.gz build/target_u96v2
scp target_u96v2.tar.gz root@192.168.2.1:~/

ターゲット側で以下の通り実行して動作確認する。 2スレッド実行時は-t 2を指定する。

tar xzvf target_u96v2.tar.gz
cd build/target_u96v2
python3 app_mt.py -m model_dir/dpu_customcnn.elf

実行結果

root@ultra96v2-zynqmp:~/build/target_u96v2# python3 app_mt.py -m model_dir/dpu_customcnn.elf 
Command line options:
 --image_dir :  images
 --threads   :  1
 --model     :  model_dir/dpu_customcnn.elf
Pre-processing 10000 images...
Starting 1 threads...
FPS=2679.56, total frames = 10000 , time=3.7320 seconds
Correct: 980 Wrong: 9020 Accuracy: 0.098

root@ultra96v2-zynqmp:~/build/target_u96v2# python3 app_mt.py -m model_dir/dpu_customcnn.elf -t 2
Command line options:
 --image_dir :  images
 --threads   :  2
 --model     :  model_dir/dpu_customcnn.elf
Pre-processing 10000 images...
Starting 2 threads...
FPS=3346.35, total frames = 10000 , time=2.9883 seconds
Correct: 980 Wrong: 9020 Accuracy: 0.098

2020年12月4日金曜日

ultra96v2のembedded acceleration platformをvitis2020.2で作成してみた話その2

ultra96v2のembedded platformをvitis 2020.2で作成した話。 VitisのVecaddを動かすまで。 前回の続き。

準備

vitisで使用するlinux_bifとqemu_args.txtとpmu_args.txtを準備する。

cd <work-dir-path>
mkdir vitis_args

vitis_argsにlinux.bifとqemu_args.txtとpmu_args.txtを保存する。内容は以下の通り。

  • linux.bif
/* linux */
the_ROM_image:
{
    [fsbl_config] a53_x64
    [bootloader] <fsbl-ultra96v2-zynqmp.elf>
    [destination_device=pl] <bitstream>
    [pmufw_image] <pmu-firmware-ultra96v2-zynqmp.elf>
    [destination_cpu=a53-0, exception_level=el-3, trustzone] <arm-trusted-firmware.elf>
    [load=0x100000] <system.dtb>
    [destination_cpu=a53-0, exception_level=el-2] <u-boot.elf>
}
  • qemu_args.txt
    system.dtbは2020.1からBOOT.binで書き込むようにしている模様。
    ##work-dir-path##は環境に合わせて置き換えてください。
-M arm-generic-fdt
-net nic -net nic -net nic
-serial /dev/null -serial mon:stdio
-display none
-device loader,file=##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/arm-trusted-firmware.elf,cpu-num=0
-device loader,file=<u-boot.elf>
-device loader,file=##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/system.dtb,addr=0x100000
-drive file=##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.wic.qemu-sd,if=sd,id=sd0,format=raw,index=0
-boot mode=3
-global xlnx,zynqmp-boot.cpu-num=0
-global xlnx,zynqmp-boot.use-pmufw=true
-m 4G
  • pmu_args.txt
    ##work-dir-path##は環境に合わせて置き換えてください。
-M microblaze-fdt
-serial /dev/null -serial /dev/null
-display none
-device loader,file=##work-dir-path##/build/tmp/deploy/images/ultra96v2-zynqmp/pmu-ultra96v2-zynqmp.elf
-device loader,addr=0xfd1a0074,data=0x1011003,data-len=4
-device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4

Platformの作成

ここを参考にplatformを作成していく。 日本語ならこちら

export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu
source <path-to-vitis-installation>/2020.2/settings64.sh
cd <work-dir-path>
mkdir vitis_pfm
cd vitis_pfm
mkdir wksp1
vitis -workspace wksp1

create platformを行い、platform名はultra96v2-platform、xsaは/xsa_dir/ultra96v2_4z/ultra96v2_4z.xsaを指定する。

linux domainの設定を以下のように行う。

Bif File: <work-dir-path>/vitis_args/linux.bif
Boot Components Directory:<work-dir-path>/boot
Linux Image Directory:<work-dir-path>/boot
Linux Rootfs:<work-dir-path>/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.ext4
Bootmode:SD
Sysroot Directory:<work-dir-path>/sdk/sysroots/aarch64-xilinx-linux
QEMU Data:<work-dir-path>/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp
QEMU Arguments:<work-dir-path>/vitis_args/qemu_args.txt
PMU QEMU Arguments:<work-dir-path>vitis_args/pmu_args.txt

platformをbuildする。Application projectを作成するところまでは同じだが、その後のUIが少し変わっている。


 

vecadd_systemを開いてActive Build Configurationを変更してAssistant上でBuildする。

また、最初にリソースファイルを作成するようになったためか、buildボタンを押してしばらく反応が無かったりする。ビルドが始まるまで気長に待つ必要があった。 ビルドの際にkernelとhw_linkとhostプログラムを分けてビルドしてくれるようになったり、変更後のビルドで影響ある部分だけビルドしてくれたりと少し賢くなったけど、初動は遅くなったイメージを持った。

Platformのテスト

ここを参考にplatformのテストを行う。 日本語ならこちら

application project nameはvecaddとした。 途中、Kernel Imageが空欄となっているので、/boot/Imageを指定しておく。

Emulation-SW

まずはvecadd_systemを開いてActive Build ConfigurationをEmulation-SWに変更してBuildする。 Launch on Emulatorを試す。 RunかDebugのボタンを押し、Launch SW Emulatorを選択する。 Application Timelineはデフォルトで有効になっていないので、有効にする場合はRun ConfigurationsからXilinx Runtime ProfilingのConfigurationをEditして、OpenCL detailed profile summary and timeline traceを選択する。


 
 

結果は以前と変化ないので省略。

また、2020.2ではEmulation-SWのLaunch on Hardwareに相当する操作はできなくなっていた。 アクセラレーション前の実行時間を計測するのに便利そうと思っていたのに。 直接動かしたり、コマンドラインからのデバッグ実行ならばいけるかもしれないので、後で試す。 (または、Emulatorが起動したとしてもTCFの接続先を実機にしておけば目的は達成されるかも)

Emulation-HW

vecadd_systemを開いてActive Build ConfigurationをEmulation-HWに変更してBuildする。 Launch Emulator in GUI modeを選択するとvivado simulatorが立ち上がるのが見える。


 

GUI modeの場合は手動で実行されるまでQEMUは実行を待機している模様。必要な信号線をaddした後にrun allすることを想定しているのかな。


 

今回Emulation-HWの動作が期待通りとなることを確認したけど、v2020.1でEmulation-HW(Launch on Hardware)は何をやっていたことになるのか謎。 Timelineあったけど、普通にHardwareの動作していただけ?

Hardware

vecadd_systemを開いてActive Build ConfigurationをHardwareに変更してBuildする。 SDの準備はv2020.1と同じ。sd_card.imgをddすれば良い。

また、これもv2020.1の時と同じであるが、Lunch Target Connectionで実機に接続できるように設定を行う。Emulation-SWのLaunch Target Connectionを参照。

実行結果はTEST PASSEDが出るだけで特別言うことも無いので省略。

Vitis Analyzer 

それぞれの実行結果を記載する。
Emulation-HWの結果がエラい長いけどこんな感じでいいのか?

Emulation-SW



 

Emulation-HW

 


Hardware



 

 

2020年12月3日木曜日

ultra96v2のembedded acceleration platformをvitis2020.2で作成してみた話その1

ultra96v2のembedded platformを作成した話。 今回はHW-ComponentとSW-Componentを作成するところまで。 やり方はは2020.1のときと同じ

準備

使用するのは以下のもの。 

  • cmake
  • make
  • repo
  • Vivado 2020.2
  • Vitis 2020.2

cmake と repoが無い場合は以下の通り入手可能。

apt install cmake
curl -k https://storage.googleapis.com/git-repo-downloads/repo > repo
chmod a+x repo
sudo mv repo /usr/local/bin/

HW-Componentの作成

ここを参考にしてブロックデザインを作成している。 日本語ならこちら

なお、Emulation-HWを実行するためにひと手間加えている。 参考にしたのは公式ドキュメントの、 “Enabling Hardware Emulation for Extensible XSA”。
明確にEmbedded環境に関する話は書いていないが、Versal向けの設定をEmbedded環境向けに適用してみたところ、 期待通りにEmulation動作したので採用した。 (公式の記載通りではないので使用する際は自己責任です) 行った内容はブロックデザインを開き以下の通りplatform_stateの設定と、 PS部のSELECTED_SIM_MODELをrtl=>tlmに変更した。 この変更をしないとEmulation-HW実行時にQEMUが動作開始できないのだと思う。

set_property platform.platform_state "pre_synth" [current_project]
set_property SELECTED_SIM_MODEL tlm [get_bd_cells /zynq_ultra_ps_e_0]

 


公式ドキュメントに記載されているwrite_hw_platformのオプション-hw_emuは2020.1以降は多分不要。(どこかで非推奨と書いてあったような気もする。つけて無くても必要なファイルは出力されるっぽい) 

ただ、2019.2だと必要と思われる。(オプションのあるなしでファイルサイズがだいぶ違ったので) 

GUIだと、Vivado File > Export > Export Platform からHardware and hardware emulationを選択すれば問題はなさそう。このときpre_synthの設定もされる。(はず。tclで設定してしまったのでよくわからない。)

以下の手順はすでに実施済のものを生成し、xsa_dirにxsaファイルをコピーする。

cd <work-dir-path>
source <path-to-vivado-installation>/2020.1/settings64.sh
git clone https://github.com/akira-nishiyama/vivado_cmake_helper.git
git clone https://github.com/akira-nishiyama/ultra96v2_4z.git -b v2020.2
source vivado_cmake_helper/setup.sh
mkdir xsa_dir
cd ultra96v2_4z
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=../../xsa_dir
make
make install
cd ../../

buildディレクトリ以下にvivadoのプロジェクトが作られるので、これを操作してカスタマイズも可能。カスタマイズ後はscriptsフォルダにExport Blockdesignをアップデートする必要がある。また、ソース等を編集、追加した場合はsrcフォルダにRTLファイルをコピーしてバージョン管理しないと再生成できない。(ソースファイルなどはプロジェクトにインポートしておかないとxsaファイルが作成できないことが理由)

SW-Componentの作成

mkdir petalinux
mkdir sdk
mkdir boot
cd PetaLinux
repo init -u http://github.com/akira-nishiyama/petalinux-ros2-manifests -b feature-v2020.2
repo sync
source setupsdk
#edit conf/local.conf

conf/local.confを開き、下記の通りHDF設定を修正する。

HDF_EXT_ultra96v2-zynqmp = "xsa"
HDF_BASE_ultra96v2-zynqmp = "file://"
HDF_PATH_ultra96v2-zynqmp = "<work-dir-path>/xsa_dir/ultra96v2_4z/ultra96v2_4z.xsa"

bitbakeする。

MACHINE=ultra96v2-zynqmp bitbake petalinux-image-minimal-ultra96v2ros2
MACHINE=ultra96v2-zynqmp bitbake petalinux-image-minimal-ultra96v2ros2 -c do_populate_sdk

動作のためにQEMUを起動する。

cp <path-to-vitis-installation>/2020.1/data/emulation/dtbs/zynqmp/pmu_rom_qemu_sha3.elf tmp/deploy/image/tmp/deploy/images/ultra96v2-zynqmp/pmu-rom.elf
MACHINE=ultra96v2-zynqmp runqemu

起動したら以下の通り実行して動作を確認する。

root@ultra96v2-zynqmp:~# source ros_setup.sh
root@ultra96v2-zynqmp:~# (sleep 5; ros2 topic pub /chatter std_msgs/String "data: Hello world") &
root@ultra96v2-zynqmp:~# ros2 topic echo /chatter &
publisher: beginning loop
publishing #1: std_msgs.msg.String(data='Hello world')

data: Hello world
---
publishing #2: std_msgs.msg.String(data='Hello world')

data: Hello world
---
publishing #3: std_msgs.msg.String(data='Hello world')

終了するにはpoweroffを入力し、Ctrl-a, Ctrl-x。

sdkを展開する

tmp/deploy/sdk/petalinux-glibc-x86_64-petalinux-image-minimal-ultra96v2ros2-aarch64-ultra96v2-zynqmp-toolchain-2020.1.sh -d ../../sdk/

必要なデータをbootフォルダにコピーしておく。 2020.2ではVitisで絶対パス指定がうまく行かなくなっていたので、 ブートデータ作成に必要なファイルはすべてbootフォルダに保存する。

cp tmp/deploy/images/ultra96v2-zynqmp/fsbl-ultra96v2-zynqmp.elf ../../boot/
cp tmp/deploy/images/ultra96v2-zynqmp/arm-trusted-firmware.elf ../../boot/
cp tmp/deploy/images/ultra96v2-zynqmp/pmu-firmware-ultra96v2-zynqmp.elf ../../boot/
cp tmp/deploy/images/ultra96v2-zynqmp/system.dtb ../../boot/
cp tmp/deploy/images/ultra96v2-zynqmp/u-boot.elf ../../boot/
cp tmp/deploy/images/ultra96v2-zynqmp/boot.scr ../../boot/
cp tmp/deploy/images/ultra96v2-zynqmp/uEnv.txt ../../boot/
cp tmp/deploy/images/ultra96v2-zynqmp/Image ../../boot/

2020年11月29日日曜日

ultra96v2のembedded acceleration platformをvitis2020.1で作成してみた話その2

ultra96v2のembedded platformを作成した話。 VitisのVecaddを動かすまで。 前回の続き。

準備

vitisで使用するlinux_bifとqemu_args.txtとpmu_args.txt

cd <work-dir-path>
mkdir vitis_args

vitis_argsにlinux.bifとqemu_args.txtとpmu_args.txtを保存する。内容は以下の通り。 <>で囲んだファイルはvitisが補完してくれるようだけど、よく問題が出たのでbitstream以外は直接指定することにしている。

  • linux.bif
    ##work-dir-path##は環境に合わせて置き換えてください。

    /* linux */
    the_ROM_image:
    {
      [fsbl_config] a53_x64
      [bootloader] ##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/fsbl-ultra96v2-zynqmp.elf
      [destination_device=pl] <bitstream>
      [pmufw_image] ##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/pmu-firmware-ultra96v2-zynqmp.elf
      [destination_cpu=a53-0, exception_level=el-3, trustzone] ##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/arm-trusted-firmware.elf
      [load=0x100000] ##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/system.dtb
      [destination_cpu=a53-0, exception_level=el-2] ##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/u-boot.elf
    }
  • qemu_args.txt
    system.dtbは2020.1からBOOT.binで書き込むようにしている模様。
    ##work-dir-path##は環境に合わせて置き換えてください。

    -M arm-generic-fdt
    -net nic -net nic -net nic
    -serial /dev/null -serial mon:stdio
    -display none
    -device loader,file=##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/arm-trusted-firmware.elf,cpu-num=0
    -device loader,file=<u-boot.elf>
    -device loader,file=##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/system.dtb,addr=0x100000
    -drive file=##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.wic.qemu-sd,if=sd,id=sd0,format=raw,index=0
    -boot mode=3
    -global xlnx,zynqmp-boot.cpu-num=0
    -global xlnx,zynqmp-boot.use-pmufw=true
    -m 4G
  • pmu_args.txt
    ##work-dir-path##は環境に合わせて置き換えてください。

    -M microblaze-fdt
    -serial /dev/null -serial /dev/null
    -display none
    -device loader,file=##work-dir-path##/build/tmp/deploy/images/ultra96v2-zynqmp/pmu-ultra96v2-zynqmp.elf
    -device loader,addr=0xfd1a0074,data=0x1011003,data-len=4
    -device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4

Platformの作成

ここを参考にplatformを作成していく。 日本語ならこちら。 2020.1ではこのARを実行しないとEmulation-HWのビルドができない。

export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu
source <path-to-vitis-installation>/2020.1/settings64.sh
cd <work-dir-path>
mkdir vitis_pfm
cd vitis_pfm
mkdir wksp1
vitis -workspace wksp1

create platformを行い、platform名はultra96v2-platform、xsaは/xsa_dir/ultra96v2_4z/ultra96v2_4z.xsaを指定する。

linux domainの設定を以下のように行う。

Bif File: <work-dir-path>/vitis_args/linux.bif
Boot Components Directory:<work-dir-path>/boot
Linux Image Directory:<work-dir-path>/boot
Linux Rootfs:<work-dir-path>/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.ext4
Bootmode:SD
Sysroot Directory:<work-dir-path>/sdk/sysroots/aarch64-xilinx-linux
QEMU Data:<work-dir-path>/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp
QEMU Arguments:<work-dir-path>/vitis_args/qemu_args.txt
PMU QEMU Arguments:<work-dir-path>vitis_args/pmu_args.txt

platformをbuildする。方法は上記ページを参照のこと。

Platformのテスト

ここを参考にplatformのテストを行う。 日本語ならこちら

application project nameはvecaddとした。 途中、Kernel Imageが空欄となっているので、/boot/Imageを指定しておく。

Emulation-SW

まずはEmulation-SWをLaunch on EmulatorとLaunch on Hardwareで試す。 Emulation-SWを右クリックで選択し、Buildを実行する。

その後Emulation-SWを右クリックで選択し、Run->Launch On Emulatorを実行する。

Launch on Emulator 実行結果


Launch on HardwareではSDを作成する必要がある。 SDは以下の通り作成する。

cd <work-dir-path>/vitis_pfm/wksp1/vecadd/Emulation-SW/package
dd if=sd_card.img of=/dev/sdX

上記のsd_card.imgにはBOOT.binが含まれていないので、 /petalinux/build/tmp/image/ultra96v2-zynqmp/boot.binをパーティション1に追加する。

SDをultra96v2に挿入し、電源をONする。 しばらく待っているとWifiのアクセスポイントが見えて来るので、これに接続する。

Lunch Target Connectionで実機に接続できるように設定を行う。 ultra96v2のwifi APはデフォルトで192.168.2.1のIPを持っているので、以下のように設定する。 ultra96v2が起動していればTest Connectionで接続を確認できる。

Launch Target Connection


 
Target Connectionsの+ボタンから設定を追加する。


その後Emulation-HWを右クリックで選択し、Run->Launch On Hardwareを実行する。

Launch on Hardware 実行結果
省略

Emulation-HW

Launch on Emulatorでは理由は不明だが、Launch on Emulatorを実行するとQEMUのプロセスが停止したままとなる。 恐らくはVivado Simulatorからの接続待ちなのではないかと思っているけど、 どうしても使用したいわけでもないのでツールのバージョンアップに期待する。 ここでは実機との組み合わせで動かしてみる。

SDの準備はEmulation-HWのものを使用する他はEmulation-SWと同じ。 すでにEmulation-SWをLaunch on Hardwareで実行している場合にはbinary_container_1.xclbinとvecaddを差し替えるだけで良い(はず。あまり自信が無い)。 scpで/media/sd-mmcblk0p1に送り込むのが便利。Vitisが勝手にやってくれるかもしれないけど。

あと、Vivado simが動いていないように見えるのも気になる。これのやり方合ってるのだろうか?

Launch on Hardware 実行結果


Hardware

Hardwareを右クリックしてBuildする。 SDの準備はHardwareのものを使用する他はEmulation-SWと同じ。 その後Hardwareを右クリックで選択し、Run->Launch On Hardwareを実行する。

Launch on Hardware実行結果


Vitis Analyzer 

それぞれの実行結果を記載する。
Kernel RuntimeをSW実行時とHW実行時で比較するのと、 Application Timelineでボトルネックを特定して改良していく感じなのかな?
Emulation-HW(Launch on Hardware)はHardware実行に比べてApplication Timelineが得られるということだろうか。
このあたりはもう少しドキュメントの読み込みが必要そう。

Emulation-SW(Launch on Emulator)


Emulation-SW(Launch on Hardware)





Emulation-HW(Launch on Hardware)



Hardware(Launch on Hardware)







2020年11月28日土曜日

ultra96v2のembedded acceleration platformをvitis2020.1で作成してみた話その1

ultra96v2のembedded platformを作成した話。 今回はHW-ComponentとSW-Componentを作成するところまで。

準備

使用するのは以下のもの。 

  • cmake
  • make
  • repo
  • Vivado 2020.1
  • Vitis 2020.1

cmake と repoが無い場合は以下の通り入手可能。

apt install cmake
curl -k https://storage.googleapis.com/git-repo-downloads/repo > repo
chmod a+x repo
sudo mv repo /usr/local/bin/

HW-Componentの作成

ここを参考にしてブロックデザインを作成している。 日本語ならこちら。 以下の手順はすでに実施済のものを生成し、xsa_dirにxsaファイルをコピーする。

cd <work-dir-path>
source <path-to-vivado-installation>/2020.1/settings64.sh
git clone https://github.com/akira-nishiyama/vivado_cmake_helper.git
git clone https://github.com/akira-nishiyama/ultra96v2_4z.git -b v2020.1
source vivado_cmake_helper/setup.sh
mkdir xsa_dir
cd ultra96v2_4z
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=../../xsa_dir
make
make install
cd ../../

buildディレクトリ以下にvivadoのプロジェクトが作られるので、これを操作してカスタマイズも可能。

SW-Componentの作成

mkdir petalinux
mkdir sdk
mkdir boot
cd PetaLinux
repo init -u http://github.com/akira-nishiyama/petalinux-ros2-manifests -b feature-rel-v2020.1
repo sync
source setupsdk
#edit conf/local.conf

conf/local.confを開き、下記の通りHDF設定を修正する。

HDF_EXT_ultra96v2-zynqmp = "xsa"
HDF_BASE_ultra96v2-zynqmp = "file://"
HDF_PATH_ultra96v2-zynqmp = "<work-dir-path>/xsa_dir/ultra96v2_4z/ultra96v2_4z.xsa"

bitbakeする。

MACHINE=ultra96v2-zynqmp bitbake petalinux-image-minimal-ultra96v2ros2
MACHINE=ultra96v2-zynqmp bitbake petalinux-image-minimal-ultra96v2ros2 -c do_populate_sdk

動作のためにQEMUを起動する。

cp <path-to-vitis-installation>/2020.1/data/emulation/dtbs/zynqmp/pmu_rom_qemu_sha3.elf tmp/deploy/image/tmp/deploy/images/ultra96v2-zynqmp/pmu-rom.elf
MACHINE=ultra96v2-zynqmp runqemu

起動したら以下の通り実行して動作を確認する。

root@ultra96v2-zynqmp:~# source ros_setup.sh
root@ultra96v2-zynqmp:~# (sleep 5; ros2 topic pub /chatter std_msgs/String "data: Hello world") &
root@ultra96v2-zynqmp:~# ros2 topic echo /chatter &
publisher: beginning loop
publishing #1: std_msgs.msg.String(data='Hello world')

data: Hello world
---
publishing #2: std_msgs.msg.String(data='Hello world')

data: Hello world
---
publishing #3: std_msgs.msg.String(data='Hello world')

終了するにはpoweroffを入力し、Ctrl-a, Ctrl-x。

sdkを展開する

tmp/deploy/sdk/petalinux-glibc-x86_64-petalinux-image-minimal-ultra96v2ros2-aarch64-ultra96v2-zynqmp-toolchain-2020.1.sh -d ../../sdk/

必要なデータをbootフォルダにコピーしておく。

cp tmp/deploy/images/ultra96v2-zynqmp/boot.scr ../../boot/
cp tmp/deploy/images/ultra96v2-zynqmp/uEnv.txt ../../boot/
cp tmp/deploy/images/ultra96v2-zynqmp/Image ../../boot/

2020年11月20日金曜日

ultra96v2のwifiを2020.1で動かしてみた

ultra96v2のwifiを2020.1で動かした話。 パッチはここにおいておく。

事象

私の環境で、2020.1にアップデートしたデータを起動するとwifiのアクセスポイントが見えなくなる事象が確認された

原因

ultra96-ap-setupによって作成されるアクセスポイントは wpa_supplicantにwpa_ap_actual.confを渡して設定している模様。 私の環境ではwpa_ap_actual.confが空となっていた。

ap.shを順に動かしてみるとどうもsedでwpa_ap_actual.confを作成するところがコケているようなので、パッチを当てる。

対策

自分で使う分にはap.shを直接修正してもいいが、 レシピのファイルに対してパッチを当てるにはquiltというものを使うらしいので使ってみた。 使い方はここにある。 目的のソースの探し方なども書いてあるので読んでおくのがおすすめ。 インストールして使うみたい。

apt install quilt
cd <path-to-src>
quilt new fix-for-my-hw.patch
quilt add ap.sh
#fix ap.sh
quilt refresh

するとpatchesフォルダ配下にfix-for-my-hw.patchが得られるのでこれを自分のレシピへと取り込む。

更に、meta-avnetを見るとconnman使っているようなので、imageに追加した。 connmanのblacklistにp2p0を登録する設定ファイルを追加した。 加えて、shutdown時にAPの設定をoffにできるようにmeta-avnetからultra96-wpaを借りてきた。

また、起動時からネットワークを有効とするためにconnmanの設定を行った。 /var/lib/connman/settingsがあらかじめ存在していればそれに従った動作をするようなので、 ultra96-ap-setup.bbappendでsettingsを追加する。

動作

Ultra96V2-********ctxというAPが見えるのでこれに接続し、192.168.2.1にrootアクセスする。

ssh 192.168.2.1 -l root
#ultra96v2のrootに接続

2020年11月7日土曜日

meta-ultra96v2を作って、yoctoでビルドしてみたをros2対応させてみた

wifi動作させたイメージをベースにros2を動作させてみた話。

イメージの取得

以下のようにmanifestsを実行してビルドに記載の通りpetalinux-image-minimal-ultra96v2ros2をビルドすれば同じものが得られる。ここに至るまで行った設定は後述。

meta-rosを追加

meta-rosをクローンし、bblayerに追加する。petalinuxは2019.1のためthudベースであるからthudブランチを使用する。

cd <petalinux-repository-top>
source setupsdk
git clone https://github.com/ros/meta-ros ../sources/meta-ros -b thud
bitbake-layers add-layer ../sources/meta-ros/meta-ros-backports-warrior ../sources/meta-ros/meta-ros-common ../sources/meta-ros/meta-ros2 ..//sources/meta-ros/meta-ros2-dashing

ros設定の追加。 ROS_DISTRO_BASELINE_PLATFORMとROS_DISTROを指定する。 ROS_DISTRO_BASELINE_PLATFORMは選択したROS_DISTROの対応環境と合わせて選ぶものと思う。今回はros2-dashingなのでbionicを選択。他にはeloquentやfoxyも選択可能な模様。

  • build/conf/bblayer.conf

    ROS_DISTRO_BASELINE_PLATFORM ?= "ubuntu-bionic"
    ROS_DISTRO ?= "dashing"

meta-ros-backports-warriorのpythonレシピがあるとpetalinux環境のpythonとバッティングするため、pythonレシピを除外する。特定のレシピを除外するにはlocal.confにBBMASKを記載して除くことができる。

  • build/conf/local.conf

    BBMASK = "meta-ros/meta-ros-backports-warrior/recipes-devtools/python/python3_3.7.5.bb"

イメージの追加

今回使うのはros-coreだけなので、imageに追加する。

CORE_IMAGE_EXTRA_INSTALL_append = " ros-core"

ビルド

下記の通りビルドを行う。

cd <petalinux-project-path>/build
MACHINE=ultra96v2-zynqmp bitbake petalinux-image-minimal-ultra96v2ros2

実行結果

wic.qemu-sdをddで/dev/sdXに書き込んで実行する。

dd if=tmp/deploy/images/ultra96v2-zynqmp/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.wic.qemu-sd of=/dev/sdX

sshで接続できるので、ros2のpubとechoをテストする。 結果は以下。

akira@akira-Surface-Book:~$ ssh 192.168.2.1 -l root
root@ultra96v2-zynqmp:~# (sleep 5; ros2 topic pub /chatter std_msgs/String "data: Hello world") &
[1] 2219
root@ultra96v2-zynqmp:~# ros2 topic echo /chatter
publisher: beginning loop
publishing #1: std_msgs.msg.String(data='Hello world')

data: Hello world
---
publishing #2: std_msgs.msg.String(data='Hello world')

data: Hello world
---
publishing #3: std_msgs.msg.String(data='Hello world')

data: Hello world
---
publishing #4: std_msgs.msg.String(data='Hello world')

data: Hello world
---
publishing #5: std_msgs.msg.String(data='Hello world')

data: Hello world
---
publishing #6: std_msgs.msg.String(data='Hello world')

data: Hello world
---