AIアクセラレータ・IMAXの紹介 ~ (2) IMAXのツールチェーン及び環境構築方法

# 前回の記事
[AIアクセラレータ・IMAXの紹介 ~ (1) CGRAとIMAXについて](https://qiita.com/Prokuma/items/2b98099102a2cf59bc34)

# IMAXの開発環境構築
IMAXを利用するためには、IMAXというハードウェアを利用できるソフトウェア的インターフェースを用いずに使用することはできません。もちろん、極論「設定に必要な情報をメモリの特定番地において特定の信号を出す」にすれば動きはしますが、そのようなプログラミングをしたいと思う方はいないと思います。
IMAXでも、少なくともデータフローに集中してプログラミングができるツールチェーンが存在します。WebのフレームワークとかCUDAとかのそういう凝ったものではありませんが、とりあえずプログラミングが「できなくもない」程度のツールチェーンは存在します。
今回は、そのツールチェーンの使用方法と簡単なサンプルプログラムの作成をしみたいと思います。

# IMAXのツールチェーン
IAMXのツールチェーンはここから入手できます。
- [IMAX2-Compiler(conv-c2c)](https://github.com/yasuhiko-nakashima/IMAX2-compiler)
- [IMAX2-Preprocessor(conv-mark)](https://github.com/yasuhiko-nakashima/IMAX2-preprocessor/blob/main/conv-mark)
- [IMAX2-Simulator(csim)](https://github.com/yasuhiko-nakashima/IMAX2-simulator)

それぞれ実際IMAXで動かすためのコードを生成するコンパイラ、マークを貼ってくれるプロプロセッサ、そしてIMAXのシミュレータです。実機はこの研究室の人間でもない限り入手は困難だと思うので、ここではシミュレータを使ってやっていくことにします。

## ツールチェーンの構成
IMAX関係のツールチェーンは
- `emax6lib.c`. `emax6.h`のようなFPGA上のIMAXを動かすのに必要な型定義や関数呼び出しを定義したファイル
- どのような部分がIMAXのコードに置換されるかを決める特定様式のコメントアウトからマークを貼り付ける`conv-mark`
- 上でマークをつけられたコードにマクロを実行し、置き換える`cpp -P`
- 最終的にIMAXの操作ができるコードを生成する`conv-c2c`
があります。これらを見ていきましょう。

## conv-mark
conv-markは、設定されている部分にわかりやすいマークをつけていく作業だけを行います。conv-mark自体、Perlで作成された正規表現で定義された文字列置き換えプログラムに過ぎないので、いくつかの注意事項がありますがそれは後で解説します。
IMAXで実行させたいループの上に、IMAXで実行させたいという意思を示します。
```c
//EMAX5A begin name mapdist=0
    for () {
        for () {
            for () {
......
    }}}
//EMAX5A end
//EMAX5A drain_dirty_lmm
```
こういうふうにどこから始まってどこで終わるという処理を書く必要があります。これらが後々IMAXをインターフェース的に操作するコードと置き換わっていきます。注意事項としては、**あのコメントの先頭に何かしらの空白やTabを入れてはいけないということです。これに関しては、EMAX5Aと/の間も同様で、そう書かないとconv-markがマークをつけてくれません。**
この一連の置き換え過程が終わると、`/-EMAX5AB-/`,`/-EMAX5AE-/`,`/-EMAX5AS-/`のようなマークが各行の先頭に付きます。この部分をIMAXで実行していく、という表示です。


`mapdist=0`や`drain_dirty_lmm`の意味については追々説明していくことにします。とりあえずおまじないだと考えてください。ループの書き方にも一定の決まった記述をしなければ動きませんが、それも追々説明していきます。

実行すると次のようなコードに変換されます。
```c
#define printf(format,...)
/-EMAX5AB-/ name 0
/-EMAX5AS-/ for () {
/-EMAX5AS-/     for () {
/-EMAX5AS-/         for () {
...
/-EMAX5AS-/ }}}
#undef printf
/-EMAX5AE-/
/-EMAX5AD-/
```

## `cpp -P`によるマクロの変換
`cpp`自体、IMAXのツールチェーンではありませんが、先程変換したコードを`cpp -P`に通すことによりC言語のマクロや`#include`の中身を貼り付けます。このプロセスの次で、IMAXのコンパイラである`conv-c2c`を使います。

## conv-c2c
`conv-c2c`は、IMAX用に書いたC言語のコードの中をIMAXで実行可能な形に変換するコンパイラです。IMAXで実行する命令に変換し、それをメモリに乗せるようなC言語のコードが結果として出力されます。このようなものを「コンパイラ」と呼ぶのは普段Qiitaを読んでいる方からしたら違和感を覚えるかもしれませんが、VueやReactのコードからSPAを生成するようなものも辞書定義上立派な「コンパイラ」なので、ここでは`conv-c2c`をコンパイラとします。

## emax6.h, emax6lib.cなどのコード作成に必要なライブラリ
IMAXのコード作成に必要な関数、構造体などが定義されてあります。普通に使うC言語のファイルの上に`#include`でインクルードするだけでいいのですが、最新のコンパイラでは
```c
#include <stdio.h>
#include <stdlib.h>
#include "emax6.h"
#include "emax6lib.c"
```
のようにインクルードする前に`stdio.h`と`stdlib.h`をインクルードしないとエラーになる場合があります。これは、生成されたIMAXのコードでも当該ライブラリを使用するためですが、最新のコンパイラだとこれらの明示的なインクルードがないとエラーを出すため、`emax6.h`と`emax6lib.c`をインクルードする前に標準ライブラリのインクロードが必要になってきます。これらのコードは、コンパイラの`conv-c2c`に含まれているため、そこから取ってきてインクルードしてください。

## csim
`csim`は、IMAXの実機がない状態でIMAXのバイナリーを試せるシミュレータです。

```shell
csim binary param1 param2 .....
```

という風にすればシミュレータでプログラムを走らせることができます。 

## FPGAで試したい方
残念ながら、IMAXのVerilogファイルは公開されていません。しかし、一部のFPGAで実行可能なバイナリ等がホームページにて提供されています。もちろんそのFPGA一式は最低でもうん百万円するようなものなので、余程の高給取りなエンジニアではない限り家で試すことは不可能など思われますが、一応載せておきます。

[IMAX2 Installation Manual](http://archlab.naist.jp/proj-arm64/fpga/index.shtml)

## 共通事項
コンパイルは、`Makefile`を使えばできますが、gcc10以降では`-fcommon`オプションがないとエラーが出る場合があるので、コンパイルに失敗したら`Makefile`の`CFLAGS`に`-fcommon`を追加してください。複数の`Makefile`が存在し、`make`だけでは実行できない場合がありますが、その場合は`make -f ファイル名`でファイルを指定して`make`を走らせることができます。複数ある場合、プラットフォームによってさまざまな定義がされているので、自分の環境にあったファイルを選べばいいと思います。基本x86環境のLinux(またはWSL環境)での実行になると思うので、`Makefile-cent`を選んでおけば問題ありません。ラズパイなら`Makefile-zynq`を選んでおけばいいと思います。

あと、macOSをご使用の方、特にARMのMacユーザならDocker上のLinuxで環境構築を行うのをおすすめします。Macはgccを実行してもclangが実行されるし、gccの導入が結構面倒な方なので、Dockerがおすすめです。

# おわりに
今回は、ツールチェーンの紹介と環境構築の仕方について紹介しました。次回からは、例題を一つずつ挙げ、それらを解説しながらIMAXの機能について紹介していきたいと思います。

# 次回の記事
[AIアクセラレータ・IMAXの紹介 ~ (3) 基本的なデータの扱い方及び演算](https://qiita.com/Prokuma/items/eab7ab1fb4ce49813714)

# 参考文献
[EMAX6/ZYNQ64(IMAX2) Architecture Handbook](http://archlab.naist.jp/proj-arm64/doc/emax6/emax6j.pdf)