FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Vivado HLSで開発したIPをZynq ZedBoardでIPとして利用したい(1)

f:id:msyksphinz:20160601001536p:plain

これまで、Zynq ZedBoardを利用して、Vivadoで作成したカスタムIPをインテグレートする方法について調査してきた。 この場合、IPは自分でVerilogを記述しAXIに接続した。これはこれで十分有益だ。 しかしせっかくVivado HLSがあるので、C言語で回路を記述し、それをHDLに変換した上でVivado IPとしてまとめ、Zynq ZedBoardのPL階層に接続して利用できるようにしたい。

ここでは、折角なのでC言語の行列乗算器を記述し、それをHWに変換、ARMから制御できるようにしたい。このための調査と試行をしよう。

f:id:msyksphinz:20160903163636p:plain

Vivado HLSを使ってC言語で行列演算関数を実装する

まずはVivado HLSを立ち上げるところから備忘録として取っていく。

プロジェクト名はmatrix_hlsとした。まずは[New Project]でプロジェクトを作成しよう。

f:id:msyksphinz:20160903163741p:plain

最初に追加するソースコード類は、ここでは特に指定しない。

f:id:msyksphinz:20160903163829p:plainf:id:msyksphinz:20160903163830p:plain

実装ボードとしては、Zynq ZedBoardを指定する。

f:id:msyksphinz:20160903163942p:plainf:id:msyksphinz:20160903163944p:plainf:id:msyksphinz:20160903163945p:plain

これでプロジェクトとしては作成完了となる。

ここでは、matrix_hls.cppとして以下のような関数を記述した。ごく普通の行列積を計算する関数だ。

void matrix_mul (const float matrix_a[8][8], const float matrix_b[8][8], float matrix_c[8][8])
{
  for (int j = 0; j < 8; j++) {
    for (int i = 0; i < 8; i++) {
      matrix_c[j][i] = 0;
      for (int k = 0; k < 8; k++) {
        matrix_c[j][i] += matrix_a[j][k] * matrix_b[k][i];
      }
    }
  }
  return;
}

これをプロジェクトに追加する。

f:id:msyksphinz:20160903164134p:plainf:id:msyksphinz:20160903164136p:plain

さらに、本関数をテストするためのテストプログラムを作成した。このテストプログラムは、CoSimulationによりC言語でのプログラムでも、RTLに変換後のプログラムでも使えるように工夫してある。 入力としては8×8の行列を2つ用意しており、データ型はfloatとした。この場合の結果の行列積のデータも保持しておき、一致すればPASS、一致しなければFAILとする。

#ifdef C_SIMULATION
#include <stdio.h>
#endif // C_SIMULATION

#include "./matrix_hls.h"

int main ()
{
  const float matrix_a[8][8] = {{2.00861, 4.96191, 0.03365, 8.49076, 2.05199, 2.35618, 6.64845, 2.48825},
                          {8.24828, 3.79825, 0.71616, 5.02615, 2.37722, 1.70809, 3.09136, 7.97736},
                          {0.81262, 4.22766, 6.10453, 1.67064, 1.95103, 7.01496, 0.92316, 4.52642},
                          {6.44442, 2.59385, 1.32141, 1.64139, 7.25922, 1.16130, 0.29613, 1.15290},
                          {8.40171, 4.97169, 3.97962, 2.65527, 6.64343, 4.18250, 9.66444, 8.76806},
                          {6.02191, 0.71815, 2.29678, 5.76173, 4.72776, 9.79415, 6.47138, 7.49650},
                          {2.11535, 5.73055, 6.17571, 5.24272, 5.13695, 8.90108, 6.35120, 1.16608},
                          {7.40435, 0.45430, 8.73240, 6.09247, 4.89821, 4.02948, 2.66578, 4.80374}};

  const float matrix_b[8][8] = {{6.31683, 7.40894, 4.11552, 5.11706, 3.89267, 2.53873, 0.89988, 3.21347},
                          {9.67123, 4.80318, 0.46820, 2.54917, 8.17656, 7.38784, 0.98314, 4.25930},
                          {1.61677, 5.34579, 5.74210, 7.85177, 1.93416, 3.57129, 9.49534, 8.32125},
                          {5.20353, 1.78412, 9.06261, 6.23715, 5.52162, 4.11266, 2.34838, 4.09494},
                          {8.49776, 9.95641, 1.99669, 5.11842, 1.71897, 0.96354, 3.33916, 9.04869},
                          {8.19442, 6.65203, 6.72998, 4.58975, 0.77722, 1.05325, 2.65544, 0.80571},
                          {6.91818, 5.26098, 8.58867, 7.27429, 4.99427, 2.20705, 0.79829, 0.85794},
                          {3.72035, 8.24444, 8.54816, 8.66889, 2.99164, 9.01359, 4.28659, 0.49119}};
  float matrix_c[8][8];


  const float mul_answer[8][8] = {{196.909332, 145.638458, 186.056839, 167.399612, 141.344727, 118.357239, 56.026924,  90.030434},
                                  {201.411331, 209.213669, 196.371002, 200.510941, 137.020523, 155.046509, 78.897285,  98.682167},
                                  {161.872070, 170.204514, 153.244339, 161.424118, 85.720619,  114.073273, 112.057991, 104.578331},
                                  {154.012604, 161.261200, 84.908005,  114.835960, 76.222694,  66.256241,  57.253033,  116.916557},
                                  {311.613464, 329.238220, 283.188660, 302.985901, 184.883301, 194.360352, 135.061783, 168.245651},
                                  {271.772003, 278.695862, 285.540314, 267.828125, 136.055466, 149.216202, 120.559464, 125.021599},
                                  {270.917847, 238.948105, 229.040268, 230.078293, 146.940125, 130.176163, 129.347855, 163.740082},
                                  {207.943314, 243.793289, 236.898621, 250.211197, 122.303810, 136.542236, 154.109879, 175.557037}};

  matrix_mul (matrix_a, matrix_b, matrix_c);
  for (int j = 0; j < 8; j++) {
    for (int i = 0; i < 8; i++) {
      if (matrix_c[j][i] != matrix_c[j][i]) {
#ifdef C_SIMULATION
        printf ("matrix_result[%d][%d](%f) != matrix_answer[%d][%d](%f). compare failed\n",
                j, i, matrix_c[j][i], j, i, mul_answer[j][i]);
#endif // C_SIMULATION
        return -1;
      }
    }
  }

#ifdef C_SIMULATION
  printf ("Matrix verification SUCCEEDED\n");
#endif // C_SIMULATION

  return 0;
}

また、defineとして、C_SIMULATION を用意した。これはC言語モードのシミュレーションでのみ利用する。すなわち、C simulation時のオプションでのみ-DC_SIMULATIONをあてておけば、RTL Simulationの時にでもこのソースコードを活用できる訳だ。

f:id:msyksphinz:20160903164507p:plain

メニューの[Project]→[Project Settings]として、プロジェクトの設定を開く。ここから[Simulation]タブを開き、matrix_hls.cppの項目で[Edit CFLAGS]をクリックする。

f:id:msyksphinz:20160903164730p:plain

ダイアログに、-DC_SIMULATIONを設定する。

f:id:msyksphinz:20160903164810p:plain

Vivado HLSを使ってC言語で行列演算関数をテストする

まずはC言語での実行だ。ツールバーから[Run C Simulation]をクリックし実行する。ダイアログが出てきたがそのままOKを押した。

f:id:msyksphinz:20160903164930p:plain

C言語での実行なので、特に問題無く終了となる。正常に動作していることが確認できた。コンソールにMatrix verification SUCCEEDEDと表示されているのが確認できた。

f:id:msyksphinz:20160903165043p:plain

次は、RTLへのコンパイルと、C/RTL Cosimulationへと移ろう。