FC2カウンター FPGAの部屋 Vitis HLS
fc2ブログ

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

FPGAの部屋

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

DFX をやってみよう13(Blink1 と Blink05)

DFX をやってみよう12(DMA_square_root8 の実行)”の続き。

前回は、DMA_pow2 IP の代わりに DMA_square_root8 IP のフル・ビット・ファイルの動作を確認してから、パーシャル・ビット・ファイルをコンフィグレーションして動作を確認したが、パーシャル・ビット・ファイルをコンフィグレーションをしても動作しなかった。今回は、気を取り直して、ソフトウェアを使用しないハードウェアだけをDFX するために Blink1 と Blink05 を作成する。

Blink1 は 1 秒間隔の点滅を 100 回繰り返す回路で、 Blink05 は 0.5 秒間隔の点滅を 200 回繰り返す回路にする。どちらも Vitis HLS 2021.1 で作成する。どちらも動作周波数は ZYBO Z7-20 のクロックの CLK125 を使用するため 125 MHz とした。

Blink1 からソースコードを示す。

// Blink1.cpp
// 2021/07/28 by marsee
//

#include <ap_int.h>

#define PS_CLK_FREQ 125000000 // Hz
#define HALF_PS_CLK_FREQ (PS_CLK_FREQ/2) // Hz

int Blink1(volatile ap_uint<1> &out){
#pragma HLS INTERFACE mode=ap_ctrl_none port=return
#pragma HLS INTERFACE mode=ap_none port=out register
    for(int i=0; i<100; i++){
        for(int j=0; j<HALF_PS_CLK_FREQ; j++){
#pragma HLS PIPELINE II=1 rewind
            out = 1;
            ap_wait();
        }
        for(int j=0; j<HALF_PS_CLK_FREQ; j++){
#pragma HLS PIPELINE II=1 rewind
            out = 0;
            ap_wait();
        }
    }
    return(0);
}


Blink05 のソースコードを示す。

// Blink05.cpp
// 2021/07/28 by marsee
//

#include <ap_int.h>

#define PS_CLK_FREQ 125000000 // Hz
#define HALF_PS_CLK_FREQ (PS_CLK_FREQ/2) // Hz
#define QUARTER_PS_CLK_FREQ (PS_CLK_FREQ/4) // Hz

int Blink05(volatile ap_uint<1> &out){
#pragma HLS INTERFACE mode=ap_ctrl_none port=return
#pragma HLS INTERFACE mode=ap_none port=out register
    for(int i=0; i<200; i++){
        for(int j=0; j<QUARTER_PS_CLK_FREQ; j++){
#pragma HLS PIPELINE II=1 rewind
            out = 1;
            ap_wait();
        }
        for(int j=0; j<QUARTER_PS_CLK_FREQ; j++){
#pragma HLS PIPELINE II=1 rewind
            out = 0;
            ap_wait();
        }
    }
    return(0);
}


Blink1_211 プロジェクトを示す。
DFX_116_210729.png

Blink05_211 プロジェクトを示す。
DFX_118_210729.png

Blink1 の C コードの合成結果を示す。
1 秒ごとに点滅するはずだ。
DFX_117_210729.png

Blink05 の C コードの合成結果を示す。
0.5 秒ごとに点滅するはずだ。
DFX_119_210729.png

Blink1 と Blink05 両方共 Export RTL を行った。

Blink1 と Blink05 両方共インプリメンテーションを行った。結果を示す。
Blink1
DFX_120_210729.png

Blink05
DFX_121_210729.png
  1. 2021年07月29日 04:58 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

DFX をやってみよう4(DMA_square_root8 IP の作成2)

DFX をやってみよう3(DMA_square_root8 IP の作成1)”の続き。

前回は、8 ビットの整数の平方根を計算する DMA_square_root8 を作成するということで、ソースコードとテストベンチ・コードを貼って、Vitis HLS 2021.1 で DMA_square_root8 プロジェクトを作成した。
今回は、その C シミュレーション、 C コードの合成、 C/RTL 協調シミュレーション、Export RTL、 インプリメンテーションを行っていこう。

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

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

レイテンシは 35 クロックだった。
リソース使用量は BRAM が 4 個、 DSP が 0 個、 FF が 1001 個、LUT が 1584 個だった。
DMA_pow2 は BRAM 4 個、DSP 3 個、FF 968 個、LUT 1029 個だった。リソース使用量がほぼ同じと言える。

C/RTL 協調シミュレーションを行った。
レイテンシは 44 クロックだった。
DMA_square_root8_211_6_210719.png

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

波形を拡大した。
DMA_square_root8_211_7_210719.png

バースト転送しているのが分かる。

Export RTL を行った。

IMPLEMENTATION で Run Implementation を Place & Route 付きで行った。
結果を示す。
DMA_square_root8_211_8_210719.png
DMA_square_root8_211_9_210719.png
  1. 2021年07月20日 04:15 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

DFX をやってみよう3(DMA_square_root8 IP の作成1)

DFX をやってみよう2(DMA_pow2 IP の作成)”の続き。

前回は、DMA_pow2 IP を Vitis HLS 2021.1 で作成した。今回は、8 ビットの整数の平方根を計算する DMA_square_root8 を作成してみよう。
元ネタは、”square root を Vivado HLS で実装する3”だ。

まずは、ソースコードを貼っておく。

// DMA_square_root8.cpp
// 2021/07/01 by marsee
//

#include <stdint.h>

int DMA_square_root8(volatile int32_t *data, volatile int32_t *result){
#pragma HLS INTERFACE mode=s_axilite port=return
#pragma HLS INTERFACE mode=m_axi depth=10 port=result offset=slave
#pragma HLS INTERFACE mode=m_axi depth=10 port=data offset=slave
    int32_t temp, data_temp;
    int32_t square;

    for(int j=0; j<10; j++){
#pragma HLS PIPELINE II=1
        temp = 0;
        data_temp = data[j];
        for(int i=7; i>=0; --i){
            temp += (1 << i);
            square = temp * temp;

            if(square > data_temp){
                temp -= (1 << i);
            }
        }
        result[j] = temp;
    }

    return(0);
}


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

// DMA_square_root8_tb.cpp
// 2021/07/01 by marsee

#include <stdio.h>
#include <stdint.h>

int DMA_square_root8(volatile int32_t *data, volatile int32_t *result);

int main(){
    int data[10] = {8, 10, 12, 14, 16, 18, 20, 22, 24, 26};
    int result[10];

    DMA_square_root8(data, result);

    for(int i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d \n", i, data[i], i, result[i]);
    }
    return(0);
}


Vitis HLS 2021.1 で作成した DMA_square_root8 プロジェクトを作成した。
DMA_square_root8_211_1_210719.png
  1. 2021年07月19日 20:54 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

DFX をやってみよう2(DMA_pow2 IP の作成)

DFX をやってみよう2(チュートリアル例の説明)”の続き。

DFX をやってみよう2(チュートリアル例の説明)”に書いたように、”Vitis HLS 2021.1 を使ってみる(DMA_pow2)”の IP の入出力ポートを少々変更する。

ソースコード DMA_pow2.cpp を示す。

// DMA_pow2.cpp
// 2021/07/18 by marsee
//

#include <stdint.h>

int DMA_pow2(volatile int32_t *data, volatile int32_t *result){
#pragma HLS INTERFACE s_axilite port=result
#pragma HLS INTERFACE s_axilite port=data
#pragma HLS INTERFACE m_axi depth=10 port=result offset=slave
#pragma HLS INTERFACE m_axi depth=10 port=data offset=slave
#pragma HLS INTERFACE mode=s_axilite port=return

    for (int i=0; i<10; i++){
        int temp = data[i];
        result[i] = temp * temp;
    }

    return(0);
}


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

// DMA_pow2_tb.cpp
// 2021/07/ by marsee
//

#include <iostream>

int DMA_pow2(volatile int32_t *data, volatile int32_t *result);

int main(){
    int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int 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.1 の DMA_pow2 プロジェクトを示す。
DMA_pow2_211_1_210718.png

なお、Zynq なので、Solution メニューの Solution Settings... で表示された Soluiton Settings (solution1) ダイアログで、 config_interface -> m_axi_addr64 のチェックボックスのチェックを外して、アドレスを 32 ビットにした。

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

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

C/RTL 協調シミュレーションを行った。
レイテンシは 35 クロックだった。
DMA_pow2_211_5_210718.png

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

拡大した。
きちんとバーストしているのが分かる。
DMA_pow2_211_7_210718.png

Export RTL を行った。
Run Implementation を Place & Route 付きで行った。
結果を示す。
大丈夫そうだ。
DMA_pow2_211_8_210718.png
DMA_pow2_211_9_210718.png
  1. 2021年07月18日 12:07 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

hls4ml を Vitis HLS 2021.1 でやってみる

hls4ml はVivado HLS を使用して機械学習をハードウェア化するフレームワークだ。以前、FPGAの部屋でもやってみたが、ロボットカーの曲がる方向を示すニューラルネットワークを構築しようとして、large runtime and excessive memory usage エラーで止まっていた。(”hls4mlをやってみた7(自分で学習したネットワークをhls4mlでハードウェア化2)”参照)これを Vitis HLS 2021.1 でやり直してみようと思う。
現在の hls4ml は fastmachinelearning/hls4ml にあるようだ。
hls4ml-tutorial もある。Docker での構築もできるようだ。

さて、すでに keras_curve_cnn2_line_VitisH が作ってあったので、 Vitis HLS 2021.1 で 開いた。hls4ml_1_210630.png

重みやソースコード、テストベンチ・ファイルは firmware ディレクトリにある。
hls4ml_5_210630.png

このプロジェクトは Ultra96V2 ボード用だった。
hls4ml_3_210630.png

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

C コードの合成を行ったが、エラーになってしまった。
hls4ml_4_210630.png

エラー内容を示す。

ERROR: [XFORM 203-103] Array 'mult.V.1' (/home/masaaki/DNN/hls4ml/nnet_utils/nnet_dense.h:56): partitioned elements number (15600) has exeeded the threshold (1024), which may cause long run-time.
ERROR: [HLS 200-1715] Encountered problem during source synthesis
ERROR: [HLS 200-70] Pre-synthesis failed.



このエラーは Vivado HLS の時の”” ARRAY_PARTITION COMPLETE has exceeded the threshold (1024)”の解決策”でやったはず。。。。

Vitis HLS 2021.1 の Solution メニューから Solution Settings... を選択して、 Solution Settings (solution1) を開いたが、 maximum_size の項目がなかった。。。 orz
hls4ml_6_210630.png

エラーの回避方法は無いのだろうか?
  1. 2021年06月30日 05:05 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

”(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る”を Vitis HLS 2021.1 でやってみる

”(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る”を Vitis HLS 2020.2 でやってみる”で”large runtime and excessive memory usage”でうまく行かなかった”(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る”を Vitis HLS 2021.1 で、もう一度やってみよう。

元ネタは、以下の記事だ。
(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る1(学習編)
(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る2(ソースコード)
(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る3(Vivado HLS)
(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る4(チューンナップ1)
(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る5(チューンナップ2)

Vitis HLS 2021.1 で all_deploy_afnet4mnist2_211 プロジェクトを作成した。
プロジェクトに入れているソースコードは”(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る4(チューンナップ1)”の普通の MNIST の 784 入力をプロジェクトに入れている。
all_deploy_afnet4mnist2_211_1_210628.jpg

Part は Ultra96V2 用に xczu3eg-sbva484-1-e に設定した。
all_deploy_afnet4mnist2_211_2_210628.jpg

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

(目標)Vivado HLSで1クロック毎に結果を出力できるNNを作る3(Vivado HLS)”の結果と同じだった。

C コードの合成を行った。
C Synthesis ダイアログがデフォルトで OK ボタンをクリックした。
all_deploy_afnet4mnist2_211_4_210628.jpg

何と合成が終了した。
凄いぞ Vitis HLS 2021.1 。。。
結果を示す。
all_deploy_afnet4mnist2_211_5_210628.jpg

レイテンシは 842 クロックだった。
DSP は 803 個、 FF は 146850 個、LUT は 177705 個使用している。リソース使用量が多すぎると思うが、ともかくコンパイルできたのは嬉しい。。。

変換された Verilog HDL のファイルを示す。
all_deploy_afnet4mnist2_211_8_210628.png

Function Call Graph を示す。
all_deploy_afnet4mnist2_211_6_210628.png

次に NUM_ITERATIONS を 100 から 2 に変更して、C/RTL 協調シミュレーションを行う。
all_deploy_afnet4mnist2_211_7_210628.png

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

Avg Latency は 848 クロック、 Max Latency は 858 クロック、 Min Latency は 838 クロックだった。

Export RTL を行って成功した。
IP 化できた。
all_deploy_afnet4mnist2_211_10_210628.png

Run Implementation を行った。
現在、進行中。
  1. 2021年06月29日 04:40 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0

Vitis HLS 2021.1 を使ってみる(DMA_pow2)

Vitis HLS 2021.1 が出たので、使ってみることにした。
題材は DMA_pow2 で、入力を 2 乗して出力する AXI4 Master 入出力の IP だ。
なお、今回は訳あって、Windows 10 の Vitis HLS 2021.1 を使用している。

Vitis HLS 2021.1 の DMA_pow2 プロジェクトを示す。
左下の Window が新しくなって、Flow Navigator になったようだ。
Vitis_HLS_211_1_210626.png

ソース・ファイルの DMA_pow2n.cpp を示す。

// DMA_pow2.cpp
// 2018/05/08 by marsee
//

int DMA_pow2(volatile int *in, volatile int *out){
#pragma HLS INTERFACE s_axilite port=out
#pragma HLS INTERFACE s_axilite port=in
#pragma HLS INTERFACE m_axi depth=10 port=out offset=slave
#pragma HLS INTERFACE m_axi depth=10 port=in offset=slave
#pragma HLS INTERFACE mode=s_axilite port=return

    for (int i=0; i<10; i++){
        int temp = in[i];
        out[i] = temp * temp;
    }

    return(0);
}


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

// DMA_pow2_tb.cpp
// 2018/05/08 by marsee
//

#include <iostream>

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

int main(){
    int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int 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;
    }
}


Solution メニューから Synthesis を選択する。
プロジェクトの Part は xc7z010clg400-1 にした。ZYBO Z7-10 に使用する。
Vitis_HLS_211_2_210626.png

ZYBO Z7-10 に使用するので、General の config_interface の m_axi_addr64 のチェックは外した。つまり AXI4 Master のアドレスは 32 ビットとした。
Vitis_HLS_211_3_210626.png

C シミュレーションを行う。
Flow Navigator の Run CSimulation をクリックしても、C シミュレーションが走る。
Vitis_HLS_211_4_210626.png

C シミュレーションの結果を示す。この辺りは前のバージョンと変わらない。
Vitis_HLS_211_5_210626.png

Flow Navigator で C SYNTHESIS の Run C Synthesis をクリックする。
C コードの合成時にもダイアログが表示されるようになった。
Vitis_HLS_211_6_210626.png

C コードの合成が終了した。
Vitis_HLS_211_7_210626.png

C コードの合成結果を示す。
Performance & Resource Estimates の VITIS_LOOP_12_1 を見ると、PIPELINE 指示子が書いてないのに、Interval が 1 になっていて、パイプラインされているのが分かる。
Vitis_HLS_211_8_210626.png
Vitis_HLS_211_9_210626.png

Open Function Call Graph → Synthesis を選択する。
Vitis_HLS_211_10_210626.png

Function Call Graph が表示された。
簡単なコードなので、良く分からない?もっと複雑なコードをやってみた方が良さそうだ。
Vitis_HLS_211_11_210626.png

C/RTL協調シミュレーションを行った。
C/RTL Co-simulation Dialog で Dump Trace を all に変更した。このダイアログは 2020.2 から変更点が無さそう?
Vitis_HLS_211_12_210626.png

C/RTL協調シミュレーションの結果を示す。
レイテンシは 35 クロックだった。
Vitis_HLS_211_13_210626.png

Open Function Call Graph → Cosimulation を見た。
こちらも複雑なモデルで見た方が良さそうだ。
Vitis_HLS_211_14_210626.png

Export RTL を行った。
Export RTL のダイアログを示す。そのまま OK ボタンをクリックした。
Vitis_HLS_211_15_210626.png

Export RTL が終了した。
Vitis_HLS_211_16_210626.png

次に Flow Navigator から Run Implementation をクリックする。
Run Implementation ダイアログが表示された。
RTL Synthesis のラジオボタンがクリックされていた。
Vitis_HLS_211_17_210626.png

RTL Synthesis, Place & Route ラジオボタンに変更して、OKボタンをクリックした。
Vitis_HLS_211_18_210626.png

結果を示す。
Vitis_HLS_211_19_210626.png
Vitis_HLS_211_20_210626.png

solution1 -> impl の export.zip に IP が圧縮されている。
Vitis_HLS_211_21_210626.png
  1. 2021年06月26日 13:12 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0
»