2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

vitis HLSを使ってみた

Last updated at Posted at 2025-01-02

はじめに

vitis HLSを使ってみました。
ネット上に情報はあるんですが、現在のツール(2024.1)ではなくて、微妙に違いがあったり、自分で試してみないと分らない事も多いので、試行錯誤してみました。
この過程をメモしておきます。

環境

  • Vitis 2024.1(windows 11 64bit版)

参考になりそうな公式ドキュメント

Vitis 統合ソフトウェア プラットフォームの資料: エンベデッド ソフトウェア開発 (UG1400)

Vitis 高位合成ユーザー ガイド (UG1399)

作成するもの

ARMプロセッサーに接続されたLEDを制御するモジュールを作成します。
モジュールに0,1,2,3の値を入力すると、それに応じてLEDが点灯するようにします。

Vitis HLSでの作業

Vitis HLSを起動します。ツールの使い方の詳細は、公式ドキュメントを参照してください。

flow_targetの設定

flow_targetには、Vivado IP フローとVitis カーネル フローがあります。
VivadoでIPを使う方法はわかってるので、今回は、経験のあるVivado IPフローで開発してみます。
Vitis カーネル フローの方が、HLSの開発に専念できそうなので、HLSに慣れてきたら、今後試す事にします。

vitisのHSLの設定で、flow_targetを、vivadoにします。

image.png

output.formatを、ip_catalogにします。(デフォルトでこの設定になっているのかもしれませんが、私は、試行錯誤していたので、この設定になっていなくて、設定する必要がありました。)

image.png

プログラムの作成

Sourcesにled.cppを追加します。
組み合わせ回路を記述してみます。
入力に与えられた値に応じて、LEDを点灯させるモジュールを作成してみます。
出力のLEDの状態は、axiのインターフェースでは取得しないので、ap_noneを指定します。

led.cpp
#include <ap_int.h>

void led(ap_uint<4> *in_data, ap_uint<4> *out) {
#pragma HLS TOP name=led
#pragma HLS INTERFACE s_axilite port=in_data
#pragma HLS INTERFACE ap_none port=out

    switch(*in_data){
        case 0:
            *out=0x1;
            break;
        case 1:
            *out=0x2;
            break;
        case 2:
            *out=0x4;
            break;
        case 3:
            *out=0x8;
            break;
        default:
            *out=0x0;
            break;
    }
}

テストベンチも作成してみます。

led_tb.cpp
#include <ap_int.h>

void led(ap_uint<4> *in_data, ap_uint<4> *out);

int main()
{
    ap_uint<4> a, b;
    const int test_case = 4;
    int pass = 0;
    int fail = 0;

    a = 0;
    b = 0;

    for (int i = 0; i < test_case; i++) {
    	led(&a, &b);
    	if (1<<a == b) {
    		pass++;
    	} else {
    		fail++;
    	}
    	a++;
    }

    std::cout << "test_case:" <<  test_case << " pass:" << pass << " fail:" << fail << std::endl;

    if (test_case == pass) {
    	std::cout << "PASS" << std::endl;
    	return 0;
    } else {
    	std::cout << "FAIL" << std::endl;
    	return -1;
    }
}

VitisのフローのC SIMULATION SYNTHESIS C/RTL CO-SIMULATION PACKAGEを順に実行します。
全て成功すればOKです。
これで、IPが作成されました。
意外と簡単にできました。

vivadoでIPを組み込む

Vitis HLSで作成したIPが保存されているフォルダをviadoのプロジェクトに追加します。

image.png

ブロックデザインに追加します。

image.png

AXI Interconnectは、自動配線を実行した時に自動的に追加されます。

※ZinqプロセッサーにAXIインターフェースのマスターを有効にしておかないと、配線ができません。プロセッサーの次の設定を行っておく必要があります。

image.png

vitisでアプリ作成

vitisでアプリを作成します。
Standaloneのアプリを作って、動作させてみます。

デバイスにアクセスする関数が用意されていています。
X{モジュール名}Set{パラメータ名}のような関数を呼び出すと、パラメータに値がセットされます。
今回は、in_dataに整数値を設定するとそれに応じたLEDが点灯する事になります。
0,1,2,3の値を繰り返し設定するプログラムにしてみます。

main.cpp
#include "xparameters.h"
#include "xled.h"
#include "xil_printf.h" // UART出力用

// #define XPAR_LED_0_BASEADDR 0x40000000

int main() {
    // 1. デバイスインスタンス
    XLed ledDevice;
    int i,j;

    // 2. デバイスの初期化
    int status = XLed_Initialize(&ledDevice, XPAR_LED_0_BASEADDR);
    if (status != XST_SUCCESS) {
        xil_printf("Error: XLed_Initialize failed with status %d\n", status);
        return XST_FAILURE; // 初期化に失敗
    }

    xil_printf("start");
    while(1){

    for(i=0;i<4;i++){
        XLed_Set_in_data(&ledDevice, i);
        for(j=0;j<10000000;j++){
            ;
        }
    }
    }

    return 0;
}

実行結果

想定通りにLEDが点灯しました。

おわりに

  • Vitis HLSを使って、AXI4によるIOを行うモジュールを作成してみました
  • AXIインターフェースを使ったモジュールはVivadoで作るより楽
  • C言語での記述を論理合成する道筋を理解できました
  • vitis,vivado,vitisとツールを行き来する必要があって、少し面倒

今後の課題

Vitis カーネル フローも試してみたい

2
1
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?