FPGA開発日記

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

SiFiveの新RISC-VコアIP(E51, E31 Coreplex IP)

RISC-V 6th Workshop にて、SiFiveが新RISC-VコアIPであるE51を発表した。これまで発表されていたE31 Coreplex-IPは32ビット版だが、E51は64bitだ。

www.eetimes.com

SiFiveはそれ以外にも、E51の有償サポートを発表している。足回りのIPにより値段が若干変わるが、有償サポートは1年のライセンスで$600となっている。

dev.sifive.com

E31とE51はほとんど構成が変わらず、コアの内容だけが32bitから64bitとなっている。どちらもLinuxをサポートしていないが、Exxシリーズではなく、UxxシリーズではすでにLinuxをサポートしている。

f:id:msyksphinz:20170510223409p:plain

また、E31もE51も、リクエストすればRTLをダウンロードできるようになっている。

dev.sifive.com

今回発表されたE51、また既存のE31の特徴をまとめると、

  • RISC-V ISA準拠
    • E31 : RV32IMACサポート
    • E51 : RV64IMACサポート
  • マイクロアーキテクチャ
    • 整数乗算、除算ハードウェアをサポート
    • アトミック演算をサポート
    • Complexモードをサポート
    • マシンモード、ユーザモードを持つ
    • インオーダ 5-6ステージパイプライン
  • メモリ
    • 16kB, 2-way 命令キャッシュ
    • 最大64kBのデータキャッシュ
  • 割り込み
    • ローカル割り込み
    • プラットフォームレベル割り込み
    • Coreplexローカル割り込み
  • 8領域のメモリプロテクション
  • 性能
    • E31 : 1.61 DMIPS/MHz, 2.73 Coremark/MHz
    • E51 : 1.80 DMIPS/Mhz, 2.76 Coremark/MHz

コンパイルオプションを変えてCoremarkベンチマークを改善する

自作RISC-Vプロセッサは16バイト単位で命令をフェッチしてくる。つまり分岐などで新しい場所に命令フェッチを発生した時も、16バイトアラインで命令をフェッチする。

このとき、分岐先や関数の先頭が16バイトに乗っていると効率的だ。16バイトアラインの乗っていないとその分命令フェッチラインを損していることになる。

このとき、分岐先の命令のバイトアラインを調整するために、RISC-VのGCCには以下のコンパイルオプションが乗っている。

-falign-functions=16 -falign-jumps=16 -falign-labels=16 -falign-loops=16

これらにより、ジャンプ先の命令が16バイトアラインに制限される。

例えば、分岐先を調整するために以下のようにわざとnopが挿入される。

80001050:       0088de93                srli    t4,a7,0x8
80001054:       01de6f33                or      t5,t3,t4
80001058:       01e59023                sh      t5,0(a1)
8000105c:       00259583                lh      a1,2(a1)
80001060:       40b50533                sub     a0,a0,a1
80001064:       00008067                ret
80001068:       00000013                nop   // この2つのnopにより、次の関数の場所が調整される。
8000106c:       00000013                nop   // この2つのnopにより、次の関数の場所が調整される。

80001070 <core_list_mergesort.constprop.2>:
80001070:       00100f93                li      t6,1
80001074:       000f8393                mv      t2,t6
80001078:       26050c63                beqz    a0,800012f0 <core_list_mergesort.constprop.2+0x280>
8000107c:       00000013                nop
80001080:       00000f13                li      t5,0
80001084:       00000693                li      a3,0
80001088:       00000293                li      t0,0
8000108c:       00000013                nop
80001090:       00052783                lw      a5,0(a0)

この調整を行って、昨日と同様にCoremarkの性能を測定した。

Inst Bufferサイズ サイクル数 比率 サイクル数 比率
通常Coremark アライン調整Coremark
2 406395 1.00 360167 0.89
4 371580 0.91 340276 0.84
8 403437 0.99 366379 0.90
16 476439 1.17 429816 1.06

やはり、命令バッファが4の場合に最大の効果が得られた。命令の位置を調整しただけで、かなりの効果だ。

f:id:msyksphinz:20170509232542p:plain

命令バッファのサイズによる性能変化の調査

自作RISC-VプロセッサでCoremarkベンチマークを計測しているが、命令フェッチをどれだけ投機的に実行するかによって性能がずいぶん変わってきた。

投機フェッチは、命令バッファが空いている限り実行しているが、あまりフェッチを出しすぎると、パイプラインフラッシュによるフェッチ破棄を行った場合のペナルティが大きくなる。

命令キャッシュミスが発生しており外部に命令フェッチを出している場合、その命令フェッチを破棄することはできないので、フェッチが戻ってくるまで待機することになる。このペナルティが、以外と影響してくる。

f:id:msyksphinz:20170509221651p:plain

そこで、命令バッファのサイズを変えて、どの大きさにするのが一番性能が出るのかを調査した。

Inst Bufferサイズ サイクル数 比率
2 406395 1.00
4 371580 0.91
8 403437 0.99
16 476439 1.17

やはりバッファのサイズを大きくすればよいわけではないらしい。かと言って、小さすぎると今度は投機フェッチが出せなさ過ぎている。

今回の実装は、命令バッファのサイズを4にしておくのがよさそうだ。今回の実装では1リクエストで128ビットをフェッチしてくるので、最大で128x4=512bit=16命令文を保持できる計算となる。

自作RISC-VプロセッサにRASを実装する

自作RISC-VプロセッサにRAS(Return Address Stack)を実装して性能を調査した。

RASの実装をここしばらくやっていたのだが、意外と難しいということが分かった。

Return命令の判定をどこで行うか

RAS以外の分岐予測、アドレスを使って分岐予測を行う方式の分岐予測は、フェッチアドレスを見て予測し、次のフェッチアドレスを決める。 この方式の場合はIFU(命令フェッチユニット)から出力されるアドレスを見ればよいのだが、RASの場合はReturn命令を検出しなければならないので、 フェッチ後のデータを見て予測しなければならない。したがって、予測がアドレスを基にする予測よりも少し遅れることになった。

f:id:msyksphinz:20170509003802p:plain

よって、アドレスを使う分岐予測BHTなどと比較して少しペナルティが発生することになった。これについては、まあそんなものだということで割り切らなければならない。

Return予測の失敗条件

RAS予測の失敗条件というのはいろいろあって、思いついたのは、

  • Return Registerが書き換えられていて、予測したは良いが実際のアドレスが異なっていた。
  • ジャンプの深さが深すぎて、昔のジャンプ記録が破棄されてしまった(今回の実装では最大深さ4のJump And Link命令しかサポートしていない)。

などがありうる。したがって、RASは無条件分岐命令だけれども、本当に正しいアドレスに分岐予測できたのか判定する必要がある。

比較命令などで実施する分岐命令は、現在のプログラムカウンタの場所からの相対位置でジャンプ先が決まるので、分岐する場合のアドレスは必ず決まっている。 しかしレジスタ相対ジャンプの場合は、「分岐するorしない」以外にも「その分岐アドレスは本当に正しいか」を判定しなければならないという問題がある。

これらをチェックし、もし分岐予測したジャンプアドレスが、実際の戻りアドレスと異なっている場合にもパイプラインフラッシュを発生される機構を導入した。

性能測定

RASの実装有り無しで、性能を比較した。使用したのはCoremarkだ。

サイクル数 比率
RAS無し 393771 1.00
RAS有り 371580 0.94

約5%の性能向上となった。と言っても5%かあ。。。もっと向上するかと思ってたのになあ。。

もう一つ、IPC推移を取ってみた。X軸が命令数、Y軸は1000命令単位でのIPCをプロットしている。

f:id:msyksphinz:20170509010525p:plain

全体的に少しだけ向上しているが、そこまで目立ったものじゃないなあ。実装がまずいのかもしれない。

「Zedroid - Android (5.0 and later) on Zedboard」をやってみる(7. Linuxブート途中で失敗)

前回のLinuxが立ち上がらない原因を調べていたのだが、どうやらBOOT.binを作成するとき、U-bootのファイルはu-bootではなく、u-boot.elfに改名しておかなければならない気がする。

f:id:msyksphinz:20170506112911p:plain

生成されるBOOT.binのファイルサイズも違うので、ファイル名が違うだけではない気がする。良く分からない。

とりあえずこれでBOOT.binを作成してビルドすると、U-bootが起動するようになった。

f:id:msyksphinz:20170506113127p:plain

しかしここから先、カーネルパニックを起こしてしまい終了。。。これは何だろう?解析する必要があるなあ。なかなか先は長い。

f:id:msyksphinz:20170506113206p:plain

「Zedroid - Android (5.0 and later) on Zedboard」をやってみる(6. SDカードへの書き直し)

前回SDカードを使ってブートしてみたが、動作しなかった。

いろいろ解析を続けていたのだが、まずZedBoardのプログラム書き込み終了の青色LEDが点灯していなかった。

そこでデザインなどの再ビルドと再度SDカードに書き込みを行い、再度SDカードから起動すると青色LEDが点灯するようになった。

だがまだGUIも出ないし、何もコンソールに出力されない。 よく考えてみると、何かしら出てこないといけないはずだと思うのだが、、、解析を続けていきたいと思う。

「Zedroid - Android (5.0 and later) on Zedboard」をやってみる(5. SDカードへの書き込み・ブート失敗)

ここまででAndroidをブートさせるためのファイル群ができたので、SDカードに書き込んでブートの試行をしてみよう。

参考にしている資料は以下。

www.slideshare.net

SDカードには4つのパーティションを作らなければならないらしい。

  • 1st primary: VFAT(FAT32) over 1GB with boot flag
  • 2nd primary: ext4 over 1GB
  • 3rd primary: ext4 over 500MB
  • 4th primary: Linux Swap over 500MB

ちなみに、3rdは500MBでは足りなかったので、1-4までのパーティションはそれぞれ1GBずつ確保した。 パーティション確保にはfdiskを用いる。

まず、1st Primaryのパーティションには、

  • Zedboard用のハードウェアバイナリ [Xilinx SDK dir]/BOOT.bin
  • カーネルファイル [kernel dir]/arch/arm/boot/uImage
  • バイスツリー [kernel dir]/arch/arm/boot/dts/devicetree.dtb
  • アンドロイドファイルシステム [Android dir]/uramdisk.image.gz

を格納する。

2nd Primaryのパーティションには、Androidのsystemファイル群を格納する。Androidのファイル群はAndroidディレクトリのout/target/product/zedboard/system.imgを使えばよいと思う。ddで格納する。

sudo dd if=system.img of=/dev/sdb3

3rd Primaryのパーティションには、Androidのユーザデータファイル群を格納する。これにはAndroidディレクトリのout/target/product/zedboard/userdata.imgを使えばよいと思う。ddで格納する。

sudo dd if=userdata.img of=/dev/sdb3

これでZedboardのジャンパピンを調整してブートしてみたが、うまく動作しなかった。 どこを間違えたかなあ。。。解析必要。

関連記事

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com