FPGA開発日記

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

RISC-VのRoCC アクセラレータ付きRocket-Chip構成をFPGA向けに合成する (2. LinuxのビルドとFPGAでのブート)

RISC-VのRocket Chipで、FPGAにインプリメンテーションをするためにはいくつかの方法があるが、その中でfpga-zynqリポジトリ(https://github.com/ucb-bar/fpga-zynq)を使って、FPGARISC-Vを焼いてみている。

その中で、やはりRoCC(Rocket Custom Coprocessor)を使った実験をいろいろ行っているため、RoCCのアクセラレータ付きでのRocket Chip構成をFPGAにビルドしてみたい。 そのため、前回は、RoccZynqConfigという構成を新たに作成して、FPGAのビルドを行ってみた。前回までで、とりあえずVivadoでのビルドは完了した。 次はLinuxをブートするための各種ファイルの生成とビルドだ。

RISC-Vの動作するLinuxは、既に生成済みのものが提供されている。詳細は、fpga-zynqリポジトリのREADME.md (https://github.com/ucb-bar/fpga-zynq) を参考にしてほしいが、

“2) Pushing Your Rocket Modifications to the FPGA"で、Vivadoのプロジェクトを作成する。 "3) Building Everything from Scratch"で、各種必要なFSBLや、Linuxのビルドを行う。

最終的に、以下のようなファイル構成が完成する。これをSDカードにコピーして、ZedBoardからブートさせるということだ。

SD_ROOT/
|-> boot.bin
|-> devicetree.dtb
|-> uImage
|-> uramdisk.image.gz

ちなみに、"3) Building Everything from Scratch"を一つ一つステップを踏んでいかなくても、make CONFIG=RoccZynqConfig で一気に実行できるみたい?良く分からない。

ファイル群をSDカードにコピーして、ブートしてみたのだが、以下のようなメッセージが出てどうやらARM上のLinuxがブートしない。

f:id:msyksphinz:20170915004714p:plain

とりあえずなんだか分からないので、ほかに方法はあったはずだといろいろ調べ、以下のウェブサイトを見つけた。

Xilinx Wiki - U-boot

ここに書いてある、以下のコマンドシーケンスを実行するとLinuxがブートされる。

fatload mmc 0 0x3000000 uImage
fatload mmc 0 0x2A00000 devicetree.dtb
fatload mmc 0 0x2000000 uramdisk.image.gz
bootm 0x3000000 0x2000000 0x2A00000

f:id:msyksphinz:20170915004859p:plain

そこで、fpga-zynqの説明にあるように、RISC-Vプロセッサをフロントエンドから制御してみようと思ったのだが、どうも上手く行かない。 つまり、サンプルプログラムを実行させても、固まって応答が無くなってしまうのだ。

./fesvr-zynq pk hello
(応答なし)

./fesvr-zynq bbl
(応答なし)

おかしいので、構成を元に戻して (CONFIG=ZynqConfigで再合成)、再びFPGAボードに書き込んで同じようにテストをすると正しく動作した。何が違うんだろうなあ。。 これは継続して調査が必要だ。

f:id:msyksphinz:20170915005204p:plain

RoCC アクセラレータ付きの構成をFPGA向けに合成する(1. 構成の追加とFPGA合成)

RISC-VのRocket Chipを使う構成で、FPGAインプリメントするためのパッケージとしては以下の2つがあるだろう。

それぞれに特徴があるだろう。Freedomのリポジトリを利用すると、Arty, VC707 がメインになるがSiFiveのデバッグツールなどを利用することができる。 一方で、UCBのfpga-zynqでは、ZedBoard, Zybo, ZC706などのボードのための構成が用意されている。

今回は、より一般的な構成(になっていそうな)fpga-zynqリポジトリを使って、RoCCのアクセラレータを搭載したRISC-VのFPGAデザインを作るためにはどうしたらよいのか調査した。

RISC-VのRocket Chipには様々なコンフィギュレーションが存在し、その中に、RoCC(Rocket Custom Coprocessor)にアクセラレータを接続した構成が存在する。 今回私がRoCCの試行に使用しているのもその構成の一つだ。RoccExampleConfigという構成でRocket Chipをコンパイルすれば、アクセラレータ付きのデザインがコンパイルされVerilogが生成される。

fpga-zynqのREADME.mdには、make rocket CONFIG=MyFPGAConfig などと例が載っており、自分の必要なRocket Chipの構成してFPGAを作成することができる。

デフォルトでは、コンフィグレーションはZynqConfigとなっている。これは、リポジトリ内の、common/Makefragから分かる。

  • common/Makefrag
CONFIG ?= ZynqConfig

それ以外に、いくつか構成が存在する。良く知られたところではDefaultConfigなどがRocket Chipのシミュレーションなどに使用される。 これらのコンフィグレーションはどこで定義されているかというと、common/src/main/scala/Configs.scala を参照すれば分かる。

...
class ZynqConfig extends Config(new WithZynqAdapter ++ new DefaultFPGAConfig)
class ZynqSmallConfig extends Config(new WithSmallCores ++ new ZynqConfig)
...

つまりZynqConfigというのは、DefaultFPGAConfigというものと、WithZynqAdapterというコンフィグレーションから構成されている。ではこのDefaultFPGAConfigとは何なのかというと、rocket-chip/src/main/scala/rocketchip/Configs.scalaに定義されてある。

  • rocket-chip/src/main/scala/rocketchip/Configs.scala
class DefaultFPGAConfig extends Config(new FPGAConfig ++ new BaseConfig)

ベースのコンフィグレーションに対して、FPGAConfigというものを付け加えたものがDefaultFPGAConfigというものになるらしい。同様に、RoccExampleConfigはどのようになっているのかというと、

  • rocket-chip/src/main/scala/rocketchip/Configs.scala
class RoccExampleConfig extends Config(new WithRoccExample ++ new BaseConfig)

と定義されており、ベースのコンフィグレーションに対して、RoCCのアクセラレータを付加したものになっている。 では、これにFPGAConfigを付け加えてFPGA向けのRoCCアクセラレータ付きのコンフィグレーションとして定義できるだろうか。 以下を付け加えた。

  • rocket-chip/src/main/scala/rocketchip/Configs.scala
diff --git a/src/main/scala/rocketchip/Configs.scala b/src/main/scala/rocketchip/Configs.scala
index e253bfb..a7b93f0 100644
--- a/src/main/scala/rocketchip/Configs.scala
+++ b/src/main/scala/rocketchip/Configs.scala
@@ -146,6 +146,8 @@ class DualChannelDualBankL2Config extends Config(

 class RoccExampleConfig extends Config(new WithRoccExample ++ new BaseConfig)

+class RoccFPGAConfig extends Config(new FPGAConfig ++ new WithRoccExample ++ new BaseConfig)
+
 class WithEdgeDataBits(dataBits: Int) extends Config(
   (pname, site, here) => pname match {
     case EdgeDataBits => dataBits

RoccFPGAConfigを作成した。これをさらにfpga-zynq側のリポジトリFPGA合成用の構成として定義する。 ここでは新たにRoccZynqConfigを作成した。

diff --git a/common/src/main/scala/Configs.scala b/common/src/main/scala/Configs.scala
index 7ae2c38..bf52376 100644
--- a/common/src/main/scala/Configs.scala
+++ b/common/src/main/scala/Configs.scala
@@ -41,6 +41,8 @@ class WithSmallCores extends Config(
 class ZynqConfig extends Config(new WithZynqAdapter ++ new DefaultFPGAConfig)
 class ZynqSmallConfig extends Config(new WithSmallCores ++ new ZynqConfig)

+class RoccZynqConfig extends Config(new WithZynqAdapter ++ new RoccFPGAConfig)
+
 class WithIntegrationTest extends Config(
   (pname, site, here) => pname match {
     case BuildSerialDriver =>

これでFPGA用のVerilogファイルを生成してみよう。以下で実行可能だ。

make rocket CONFIG=RoccZynqConfig
make project
make vivado

これでVivadoのGUIが立ち上がり、合成が可能となる。Verilogファイルを確認し、RoCCアクセラレータが含まれていること、一応合成を試行し、FPGAのbitファイルが生成されることを確認した。

f:id:msyksphinz:20170914020118p:plain

f:id:msyksphinz:20170914020622p:plain

"An Introduction to RISC-V Architecture for Embedded Developers" 聴講

世の中ではAppleが新しい製品を発表するらしくそっちで徹夜している人はたくさんいるだろうが、私はRISC-VのWebinarを聴講するために徹夜してました。

zoom.us

f:id:msyksphinz:20170913022110p:plain

内容としてはRISC-Vの基本的なISAの基礎から始まる初心者向け。

f:id:msyksphinz:20170913024016p:plain

なお、このウェブセミナーは三回構成らしい。

f:id:msyksphinz:20170913031448p:plain

RISC-Vの命令セットカードをお勧めしていた。これは最新版。

http://www.cl.cam.ac.uk/teaching/1617/ECAD+Arch/files/docs/RISCVGreenCardv8-20151013.pdf

うーん、今回は基礎的過ぎてあまり面白くなかった。

追記:今回のセミナーの資料。

zoom.us

  • Presentation Slides

https://cdn2.hubspot.net/hubfs/3020607/SiFive%20-%20RISCV%20101%20(1).pdf?t=1508188715906

  • Q & A

https://cdn2.hubspot.net/hubfs/3020607/WEBINAR%201%20Q&A.pdf?t=1508188715906

RISC-V向けHiFive1ボードのフラッシュメモリアクセス性能評価

f:id:msyksphinz:20170821013230p:plain

RISC-V評価ボードのHiFive1は、オンチップのメモリが少なく、L1Dキャッシュが16KBしかない。それ以外のデータにアクセスするためには、外部のフラッシュメモリを利用する必要がある。

これにより、ほとんどすべてのデータはあらかじめフラッシュメモリに格納することになるが、この時のフラッシュメモリのアクセス性能が問題だ。 実際問題、MNISTは画像データとパラメータをフラッシュメモリに配置したことにより、ずいぶんとメモリアクセスに時間がかかり、性能が落ちてしまっている。

一応、HiFive1のフラッシュメモリアクセスにどの程度のレイテンシが必要なのか、定量的なデータを取っておきたい。

メモリのアクセスレイテンシとスループットを計測するためのプログラム

HiFive1のフラッシュメモリにアクセスするためのプログラムを用意した。あらかじめフラッシュメモリにMNISTの画像データを格納しておき、これを取得しに行く。

1回のアクセスに必要なサイクル数がレイテンシ、単位時間毎に何回のメモリアクセスが実行できるかを測定するのがスループットとなる。

github.com

レイテンシ測定

以下のようなプログラムを作成して、1回あたりのアクセスサイクルを測定した。 メモリアクセスする前後のサイクルカウントを取得して、引き算する。

  for (int i = 0; i < 28*28; i++){
    rdmcycle(&before_cycle);
    rdminstret(&before_instret);

    volatile char result = p_data[i];
    
    rdmcycle(&after_cycle);
    rdminstret(&after_instret);

    if ((i % 100) == 0) {
      printf ("Start:%ld, Stop:%ld, Cycle=%ld\n",
              (uint32_t)(before_cycle),
              (uint32_t)after_cycle,
              (uint32_t)(after_cycle - before_cycle));
    }
  }

結果、

となった。予想はしていたが、やはり大きい。ちなみに、L1Dキャッシュに配置したデータの場合でも15cycle程度だったので、やはりフラッシュメモリは非常に遅い。

スループット測定

スループットは、データの塊を一気に読み込んで、それで消費したサイクル数を、データ数で除算する。 これにより、単位時間あたりにアクセスできるデータ数が計算でき、それがスループットとなる。

以下のようなプログラムを作成して、スループットを測定した。

  rdmcycle(&before_cycle);
  rdminstret(&before_instret);
  for (int i = 0; i < 28*28*10; i++){
    volatile int result = p_data[i];
  }
  rdmcycle(&after_cycle);
  rdminstret(&after_instret);
  printf ("Start:%ld, Stop:%ld, Cycle=%ld\n",
          (uint32_t)(before_cycle),
          (uint32_t)after_cycle,
          (uint32_t)(after_cycle - before_cycle));

動作周波数は、実際のところ260MHz程度で動作しているらしい。28x28x10個のデータ(1データあたり4バイト)にアクセスするのに1220472サイクルかかっている。

core freq at 259450470Hz

従って、スループットは、

\text{Throughput} = \dfrac{28\times 28\times 10\times 4(\text{byte})}{1220472(\text{cycle}) / 259450470(\text{Hz})} = 6.75\text{MByte/s}

となる。やはり、あんまり速くないなあ。RISC-Vチップがもっと世の中に普及するためには、ボードレベルで、メモリ周りの強化をまずは行ってほしい。

f:id:msyksphinz:20170913010839p:plain

Windowsで動作するRISC-Vプログラム開発環境"Freedom Studio"

RISC-Vチップで動作するプログラムを開発する場合、いくつか方法が存在する。

  • Arduino IDEを使って開発する
  • Freedom-E-SDK を使って開発する

これらの方法はどちらとも、本ブログを通じで紹介してきた。Arduino IDEは他のArduinoプラットフォームとの親和性が良く、Arduinoチップとして楽しむならば十分な環境だ。 Freedom-E-SDKはコンソールを使ってプログラムのコンパイルやアップロードを行う環境で、初心者にはややハードルが高いが、柔軟なプログラムを開発することができる。 Freedom-E-SDKでもデバッグはできるみたいだが、あまり調査していないしちょっとハードルが高い。 もう少し初心者向けのツールとして、EclipseをベースとしたGUIツールとして、SiFiveから"Freedom Studio"というものが公開されている。 これの使い心地はどうだろう。

www.sifive.com

www.sifive.com

注: このキャプチャ画面は試行中に取得したもので、指定したツールチェインのパスは間違っている。下記の設定項目を確認してください。

f:id:msyksphinz:20170911012523p:plain

Freedom StudioのダウンロードはSiFiveのホームページから誰でもダウンロードすることができる。 実際、マニュアルだけ読めば、ほかの資料を一切当たらなくても、HiFive1で簡単なプログラムを動作させることができた。 Windowsで開発できるというのはとても便利だ。

少し注意点なのは、Freedom StudioにRISC-VのWindowsGCCやOpenOCD、ツールチェインの場所を教えてやらなければならない。 この設定を最初に間違えていて、エラーの原因が分からずに苦労した。

Freedom Studioの画面から、[Window]→[Preferences]をクリックして、[MCU]の項目を設定していく。

  • Global Build Tool Path : $(Freedom Studioのパッケージ場所)\FreedomStudio\build-tools\bin
  • Global OpenOCD Path : $(Freedom Studioのパッケージ場所)\FreedomStudio\SiFive\riscv-openocd-20170612-x86_64-w64-mingw32\bin
  • Global RISC-V Toolchain Path : $(Freedom Studioのパッケージ場所)\FreedomStudio\SiFive\riscv64-unknown-elf-gcc-20170612-x86_64-w64-mingw32\bin

を指定する。さらに、HiFive1をWindows上でデバッグするためには、Windowsにドライバをインストールする必要がある。 $(Freedom Studioのパッケージ場所)\FreedomStudio\SiFive\Miscに格納されている、対応しているボードのドライバを指定する。

f:id:msyksphinz:20170911021230p:plain

予めパッケージに含まれているサンプルプログラムをFreedom Studioにインポートし、その中でdemo_gpioを動作させた。ビルドを実行し、「Debug Run」を実行するとデバッグモードに移行する。 Tera Termからシリアルコンソールを観測すると、無事にコンソールが表示された。

このFreedom Studio、何がうれしいって、Windows上で動作するGCCが含まれていることだ。 これまでRISC-VのツールチェインはLinuxMacOSあたりでしか動作していなかったようだが、Windows用のビルドツールチェインが用意されていることは大きい。

これからは、HiFive1のアプリケーション開発はWindowsでやろうかな。

CARRV(Computer Architecture Research with RISC-V)の事前プログラム

f:id:msyksphinz:20170628010131p:plain

msyksphinz.hatenablog.com

RISC-Vに特化したワークショップ、IEEE MICROとの連携で開催されるCARRV(Computer Architecture Research with RISC-V)の事前プログラムが公開されています。

開催は2017/10/14、ボストン

carrv.github.io

分かってはいますけど、やはりRISC-Vを実装してみた、系が多いですね。RISC-Vを使用して、何か新しい評価用の環境を作り上げました、とかなら面白そう。

発表内容が公開されるまで、とりあえず遠目に見てみようと思う。 出来れば(ネタがあれば)、Workshopでも発表してみたいですね。

最大8コアのRISC-V Rocket-ChipがAmazon F1インスタンスで動く (FireSim)

本日アナウンスがあって知った。Amazonが提供するインスタンスF1で動作するRISC-V マルチコアNoCがリリースされたらしい。

f:id:msyksphinz:20170909012120p:plain

fires.im

名前は"FireSim"。AmazonだからFireなのかな?

構成としては2種類用意されている。Amazon F1にも2種類あるが、

  • f1.2xlarge : シングルコアのRocket-Chip
  • f1.16xlarge : 8コアのRocket-Chip

となっている。さらにオペレーティングシステムとしてLinuxも動作させることができるらしい。これは面白いな。

FireSimのTwitterGithubはこちら。

github.com

twitter.com

FireSimをF1インスタンスで起動させるためには、Amazon Marketplaceを利用するのが便利そうだ。

AWS Marketplace: FireSim Demo v1.0

予めビルドされたRISC-Vプロセッサをインスタンスして、1コアもしくは8コアのRISC-Vを立ち上げることができる。 Linuxを起動して、SSHでログインすることも可能らしい。

ま、F1インスタンスは高いので、興味はあるけどちょっと手は出せないかな。


ちなみに余談だが、F1インスタンスは、帯に短し襷に長しではないかと思っている。 別にAmazonAWSを使ってFPGAを使うことがユーザにとっての目的ではなくて、例えばASICをテープアウトする前の検証であるとか、話題のディープラーニング向けに行列演算器をたくさん作ってインスタンスするとか、こういうことを考えると、f1.16xlargeでも物足りない。

わざわざ大きなFPGAを買わなくても安上りなのは便利だが、外部信号などの制御は難しそうだし、手元に置くことができないというデメリットは何だかんだで大きいとおもう。

もうちょっと大きなインスタンスに期待ですね。