FPGA開発日記

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

RISC-Vの特権命令まとめ

f:id:msyksphinz:20160605215109p:plain

この記事は ハードウェア開発、CPUアーキテクチャ Advent Calendar 2016 - Qiita の5日目の記事です。

Advent-Calendarを埋めてくれるかた、今からでも募集中です!是非参加してください! 僕一人では、クオリティのある記事を続けられそうにありません。。。(弱音)

1. RISC-Vにはどのような特権命令があるのか

最初に、「特権命令」とは何かについて簡単にまとめておこう。

例えば、演算やメモリアクセスに使うような通常の命令と違って、CPUのステータスを変更したり、オペレーティングシステムを動作させるための命令などが含まれる。このような命令のことを特権命令と呼ぶ。 また、特権命令が操作する、CPUの各種情報を格納するためのシステムレジスタの仕様も含まれることが多い。これらをまとめて、「Privileged Architecture」などと言ったりするけど、日本語では何と言うのか良く分からない。

RISC-Vの特権命令の情報はどこにあるの

以下をサイトを参考にする。今ダウンロードすると、いつの間にか仕様書が1.9.1にアップデートされていることに気がついた。前まで1.9だったのに!

Draft Privileged ISA Specification v1.9.1 - RISC-V Foundation

Changelogを見ていると、デバッグ命令あたりの情報も加わっているのか、、見逃していた。

2. RISC-Vのプロセッサ実行モード

RISC-Vには、仕様として以下の実行モードが存在する。上はユーザモードから、下はマシンモードまで。基本的にはユーザモードでは殆どのシステムレジスタにアクセス出来ないが、マシンモードでは全てのシステムレジスタへのアクセスが許される。

f:id:msyksphinz:20161202002918p:plain

ちなみに、3. Hypervisor-Modeについては、仕様書にすらまだ詳細が書かれていない。まだ決まっていないらしい。。。そうすると、通常のRTL実装とか、チップとして上がってくるRISC-Vのプロセッサは、「Machine-Mode」「Supervisor-Mode」「User-Mode」から構成されるという訳だ。

f:id:msyksphinz:20161202011208p:plain

なるほどなあ。

3. RISC-Vのシステムレジスタ(CSRレジスタ)と制御命令

システムレジスタを1つずつ解説していくのは無理なので、おおよそ重要なところをピックアップしていこう。

mstatus, hstatus, sstatus, ustatusレジスタ

レジスタ群の中でおそらく最も重要なのは、*statusレジスタとよばれる、現在のシステムの状態を格納しているレジスタだ。接頭語の「m,h,s,u」はそれぞれどの実行モード中に利用するかを指定する。

ここでは、mstatusレジスタのビットフィールドを見てみる。

f:id:msyksphinz:20161202011722p:plain

0ビット目から3ビット目までは、Interrupt Enableビットで、各実行モードにおける例外許可を示すビットだ。使い方としては、基本的に現在の実行モードxの時には、xIE=1として利用する。下位の実行モードのIEビットはもちろんDisableだし、上位の実行モードのIEビットは1にすることができる。

次の4ビット目から7ビット目は、割り込みのネストを許可するために、一つ前の割り込み許可ビットを保持している。具体的には、Trapが発生する目のInterrupt Enableビットの状態を保持している。

また、VMビットはアドレス変換のモードを示すビットだ。RISC-Vにはいくつかのアドレス変換モードがある。詳細は、私の過去のブログも参考にして欲しい。

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

その他にも、メモリプロテクションのためのMPRVビット、FSビットは浮動小数レジスタの状態を示し、XSビットはユーザモードの拡張のためのビットだ。

4. システムレジスタのアクセスに必要な特権命令

では、上記のシステムレジスタにどのようにしてアクセスするのだろうか?RISC-Vのシステムレジスタには、下記の表のように、一意のアドレスが付加されている。CSR Addressと書かれている12ビットの部分だ。このアドレスを利用してシステムレジスタにアクセスすることになる。

f:id:msyksphinz:20161203005824p:plain

RISC-Vアーキテクチャではシステムレジスタは各実行モードによりまとめられており、もちろん各モードでアクセスできるシステムレジスタは異なっている。実際にアクセスするのは、"CSRxx"命令と呼ばれる命令だ。 概念としては、MIPSのmtc0命令や、mfc0命令に似ている。汎用レジスタとシステムレジスタの移動を行う命令なのだが、CSR命令はこのデータを「移動」ではなく「交換」するところがMIPS系の命令と異なる。

RISC-Vでは、以下のシツテムレジスタにアクセスする命令が用意されている。

f:id:msyksphinz:20161203010311p:plain

  • CSRRW命令 CSRRW rd,csr,rs1 で記述されるこの命令は、csrで表現される12ビットアドレスで示されるCSRレジスタと、汎用レジスタの交換を示す。本命令が実行されると、CSRレジスタの値がrdレジスタにロードされ、rs1の値がCSRレジスタに書き込まれる。この操作がアトミックに行われるというのが本命令の利点で、もしrd=x0(ゼロレジスタ)ならば、rdレジスタへのCSRの値読み込みは行われず、rs1の値がCSRレジスタに書き込まれるだけである。

  • CSRRWI命令 CSRRWI rd,csr,imm は、rs1の変わりに5ビットの即値が指定できる命令だ。CSRRW命令ではrs1の値がCSRに書き込まれるが、本命令はimmの値がCSRに書き込まれる。下位5ビットしか効果が無いのでいまいち付きどころが分からないが、まあそういう命令だそうな。

  • CSRRS命令、CSRRSI命令 CSRRS rd,csr,rs1, CSRRSI rd,csr,immで表現されるこの命令は、CSRの元の値がrdに読み込まれ、CSRレジスタのrs1レジスタの各ビットで1が立っている部分が強制的に1に設定される。rs1レジスタの各ビットで0であるビットに相当するCSRレジスタビットは影響を受けない。CSRRSIについても、rs1の値が即値になっているだけで同様である。

  • CSRRC命令、CSRRCI命令 CSRRC rd,csr,rs1, CSRRCI rd,csr,immで表現されるこの命令は、CSRの元の値がrdに読み込まれ、CSRレジスタのRs1レジスタの各ビットで1が立っている部分が強制的にクリアされる。rs1レジスタの各ビットで0であるビットに相当するCSRレジスタビットは影響を受けない。CSRRCIについても、rs1の値が即値になっているだけで同様である。

余談。CSRRW命令はアウトオブオーダのプロセッサにおいてどうやって実装するのか?

CSRアドレスが付加されているとは言え、12Bビット存在する。これをリネームマップを利用して変換するのは現実的に不可能だ。だとすると、CSRへの書き込みについて、リネームマップで変換してアウトオブオーダで処理するという機構は無いだろう。

とすると、CSR命令の場合のみアウトオブオーダ発行を止め、インオーダで一つずつ実行するという方式が現実的ではなかろうかと思う。例えば、同一CSRレジスタに連続して書き込む命令であれば、

CSRRW x1,mstatus,x3   // x1<--mstatus, mstatus<--x3
CSRRW x4,mstatus,x5   // x4<--mstatus, mstatus<--x5

mstatusにはレジスタ書き込みが発生するが、汎用レジスタであるならばリネーミングにより、1命令目と2命令目で別々の物理レジスタマッピングされる。しかしCSRレジスタはリネーミングが出来ないので、この部分だけインオーダだ実装する必要があるだろう。 つまり、1命令目のmstatusの書き込みが完了するまで、2命令目のmstatusの更新命令はストールさせるという方法になる。

Rocketとか、BOOMとかはどのようにして実装しているんだろうな?

5. トラップリターン命令

v.1.7までの仕様

v.1.7までのPrivileged Instructions では、以下の命令が定義されていた。

f:id:msyksphinz:20161204015513p:plain

mrts命令は、現在の実行モードから前の実行モードに遷移する命令だ。

  • MRTS : マシンモードからスーパバイザモードへの帰還命令
  • MRTH : マシンモードからハイパーバイザモードへの帰還命令

v.1.9からの仕様

f:id:msyksphinz:20161204020151p:plain

MRET 命令は常に提供される、それ以外の命令はそのプロセッサがどのアーキテクチャまでをサポートしているかに依存する。

6. まとめ

これらのシステム特権命令は、上記にも伸べたように仕様のアップデートの度に命令が増えたり消えたりする。細かいチェックが必要だが、大体の命令は一般的な命令と同様なので、知っている人がすぐに理解出来ると思う。

ただし、まだ仕様として固まっていないので、例えばLinuxなどのシステムを動かすときは、RTLの実装とコンパイラがどのバージョンに対応しているかの確認をしっかりしておく必要がある。