RISC-Vの実装

RISC-Vを使うにはいろんな手段があります。ASICチップが乗っているボードを買ってくることもできますし、FPGAにデザインを焼いて動作させることもできます。特にFPGAを使う場合は、自分で簡単にカスタマイズすることもできますので独自のRISC-V環境を作ることもできます。

今回は、実際にRISC-Vを使う場合にどのような手段があるのか、特にオープンソースで公開されているものを中心に、RISC-Vプロセッサの実装について見ていきます。

入手できる評価ボード

まだ数は多くありませんが、RISC-Vチップが乗っている評価ボードもすでに製品化されています。有名なものを2つ挙げると、HiFive1という小型のArduinoインタフェースとの互換性のあるボードと、HiFive UnleashedというマルチコアのRISC-Vボード環境です。どちらも、米国のベンチャー企業であるSiFive社が開発・販売しています。

図

これらのボードに搭載されているデザインは、どちらもSiFive社が開発し、GitHub上に公開されているものがベースになっています。HiFive1はシングルコア・HiFive Unleashedは4コア+1コアで構成されています。

オープンソースのRISC-Vデザイン

オープンソースで公開されているRISC-Vプロセッサはどうでしょうか?実は、RISC-Vの実装についてはRISC-V Foundationがまとまった情報を公開しています。

RISC V Cores and SoCs

代表的なものについて見ていきます。

Rocket Core

Rocketは、UCB(カリフォルニア大学バークレイ校)およびSiFive社が開発しているRISC-V実装です(https://github.com/freechipsproject/rocket-chip)。RocketはCPUコアの部分を示しており、L1キャッシュやバスなどを含めてRocket Chipという環境を作ることが出来ます。

Rocketの実装はシンプルです。標準的な5ステージのパイプラインですが、マシンモードやスーパバイザモードなどの各種実行モードをサポートし、64ビット演算、FPU演算なども搭載しています。RISC-V ISAの仕様はほぼすべて実装してあるため、まずは手軽にRISC-Vを動かしてみたいというときはRocketから試してみるのがおすすめです。また、上記のHiFive1やHiFive UnleashedボードもこのRocketコアをベースにしています。

BSDライセンスですので、自由に改造して配布することも可能です。

Rocketコアは手軽なデザインですが、ハードウェア開発の経験がある技術者にとっては、Verilogで記述していないというところが難点になる可能性があります。Rocketはほぼすべての実装部分が、ChiselというScalaをベースにしたDSL(Design Specific Language)で記述されています。なので、Rocketの実装について中身を見るときは、一緒にChisel(しいてはScala)も勉強する必要があるでしょう。

これはコアだけでなく、TileLinkなどのバス実装もChiselで記述されているため必須と言えるでしょう。

図図. Rocketのパイプライン(図は"A 45nm 1.3GHz 16.7 Double-Precision GFLOPS/W RISC-V Processor with Vector Accelerators“ より抜粋抜粋)

Rocketを搭載したSoC環境 Rocket-Chip

RocketはCPUコアの部分だけですが、RocketをCPUコアとしてキャッシュメモリやバスなどを追加してSoC環境を構築することができます。これはRocket-Chipと呼ばれています。FPGAでRISC-Vチップを動作させるためには、このRocket-Chip環境を使用します。

図図. Rocket-Chipの環境。Rocketコアの周りにキャッシュ・アクセラレータインタフェース(RoCC)をつないでTileを構成し、さらにL2を接続してDRAMや外部インタフェースと接続できる(図は https://www2.eecs.berkeley.edu/Pubs/TechRpts/2016/EECS-2016-17.pdf より抜粋)

BOOM

上記のRocketコアはシンプルなパイプライン構成ですが、より高性能で高い動作周波数を狙った実装もあります。これがBOOM(Berkeley Out-of Order Machine)です。BOOMはアウトオブオーダ実行で複数命令を同時にデコード、発行する能力を持っており、Rocketよりも高い性能を発揮することができます。BOOMにはv1とv2があり、v2はv1に比べてより高い周波数で動作するように改良されています。

図図. BOOMプロセッサのパイプライン構成(上側がBOOM v1, 下側がBOOM v2)

こちらもすべてのデザインがGitHub上で公開されています

riscv-boom
boom-template

BOOMの特徴は、現代のアウトオブオーダプロセッサが性能向上のために取り入れている数々の最新の機能を実装してあるということです。例えば分岐予測、オートプリフェッチなどが実装してあり、ベンチマークスコアもRocket Chipのものよりも高くなっています。

一方で、BOOMもRocketと同様に、VerilogではなくChiselで実装してあります。生成されたVerilogを見ても解析するのかなり困難で、Chiselについてしっかりと勉強しないと改造するのはかなり難しいです。

その他のRISC-V実装について

本章ではUCBおよびSiFiveで開発したRISC-V実装を紹介しましたが、それ以外にも研究・開発用に様々なRISC-Vデザインが開発されています。それらの情報をまとめて調査したい場合には、最初に紹介したRISC-VデザインのまとめられたWikiが参考になります。みなさんも、自分が使いたい用途のRISC-Vデザインを探してみてください。

RISC V Cores and SoCs

図

Rocket-Chipを動かしてみよう

後半では、前半で紹介したRocketコアを実際に動かしてみようと思います。ただ、今回はFPGAではなくRTLシミュレーションにてRocketコアを動かします。

Rocket-Chipのリポジトリは、以下のコマンドで取得してきます。Rocket-Chipにはメインのリポジトリ以外にサブリポジトリも含まれており、これらをすべて取得するとかなりの量になるので注意です(ただしリポジトリの大半はGNUツールチェインですので、すでにRISC-V向けツールチェインをダウンロードしてビルドしている方は不要です)。

riscv-gnu-toolchainをすでにダウンロードしてビルドしている方向け

					  git clone https://github.com/freechipsproject/rocket-chip.git
					  cd rocket-chip
					  git submodule update --init --recursive chisel3 firrtl hardfloat torture
					

riscv-gnu-toolchainをダウンロードしていない方向け

					  git clone https://github.com/freechipsproject/rocket-chip.git
					  cd rocket-chip
					  git submodulp update --init --recursive
					

Rocket-ChipのビルドとVerilogファイル生成

前述したように、Rocket-ChipはChiselというScalaをベースにしたDSLを使っているため、そのままではシミュレーションができません。そこで、まずはChiselからVerilogにデザインを変換します。変換後にRTLシミュレータを立ち上げるのですが、Rocket-ChipではSynopsys社のVCSか、Verilatorをサポートしています。どのRTLシミュレータを使用するかで作業するリポジトリが変わります。

  • VCSを使用する場合 cd vsim
  • Verilatorを使用する場合 cd emulator
  • 以下でChiselからVerilogファイルが生成されます。以下では、生成するRocket-Chipとしてはデフォルトの構成を使用しています。

    					make CONFIG=DefaultConfig
    					

    しばらく時間がかかります。手元の環境では、Verilogファイルを生成するまでに約10分程度かかりました。

    生成が完了したら、Verilogファイルを見てみましょう。generated-src/freechips.rocketchip.system.DefaultConfig.vにVerilogファイルが生成されています。中身を見てみましたが、とても人間の読めるレベルのVerilogではありません(配線名なども機械的な名前に変換されており、かなりデバッグが大変そうです...)。やはり、自分でRocket-Chipを改造するとなると、Chiselを触るのが近道なようです。

    提供されているベンチマークプログラムを動かしてみました。以下は4並列でベンチマークプログラムを動かしています。それぞれのベンチマークの実行結果及びCPUのトレースファイルは、`output/`ディレクトリに格納されているので、確認してみましょう。

    					make run
    					

    カスタムプログラムをコンパイルしてシミュレーションする

    つぎに自分のオリジナルプログラムをコンパイルして、シミュレーションしてみましょう。ここでは、オリジナルプログラムと言ってもRocket-Chipのリポジトリで公開されているサンプルプログラムを使用しています。

    helloworld.c

    					  #include <stdio.h>
      
    					  int main()
    					  {
    					    char text[] = "Vafgehpgvba frgf jnag gb or serr!";
      
    					    int i = 0;
    					    while (text[i]) {
    					          char lower = text[i] | 32;
    					          if (lower >= 'a' && lower <= 'm')
    					            text[i] += 13;
    					          else if (lower > 'm' && lower <= 'z')
    					            text[i] -= 13;
    					          i++;
    					    }
      
    					    printf("%s\n", text);
      
    					    return 0;
    					  }
    					

    コンパイルするためには、riscv-tools/riscv-testsリポジトリに含まれているcrt.Ssyscalls.c、さらにリンカスクリプトであるtest.ldを使用します。

    					riscv64-unknown-elf-gcc -mcmodel=medany -O2 -fno-builtin-printf -nostartfiles helloworld.c crt.S syscalls.c -Ttest.ld -o helloworld
    					

    生成したバイナリを先ほどのシミュレーションディレクトリ`output/`において、シミュレーションを実行してみましょう。

    					cd output
    					ln -s ${サンプルプログラムをコンパイルしたディレクトリ}/helloworld
    					cd ..
    					make CONFIG=DefaultConfig output/helloworld.out
    					./emulator-freechips.rocketchip.system-DefaultConfig +max-cycles=100000000 +verbose output/helloworld 3>&1 1>&2 2>&3 | /home/msyksphinz/riscv64/bin/spike-dasm  > output/helloworld.out && [ $PIPESTATUS -eq 0 ]
    					Instruction sets want to be free!
    					

    最後に表示されたInstruction sets want to be free!が出力です。プログラムが正しく動いたことが確認できました。

    いかがでしたでしょうか。このように、RISC-VはISAだけでなく、すぐに動かすことができる実装がたくさん公開されています。皆さんもぜひ触ってみてください。