Ubuntu Weekly Recipe

第505回 オープン規格の新しい命令セットアーキテクチャRISC-V入門 ツールチェインを用意する

この記事を読むのに必要な時間:およそ 9 分

RISC-Vの拡張性

RISC-Vの「標準拡張(Standard Extention)⁠とはモダンなCPUであれば備えておいたほうが良い便利な命令集です。

RISC-Vは組み込みからハイパフォーマンスコンピューティングに至るまで,できるだけ広い範囲のプロセッサを構築できるよう作られています。特定の分野では便利な命令でも,別の分野では不要であるケースも多々あるため,必要最低限な整数演算やjump/load/storeのみを必須の機能とし,それ以外は「標準拡張」としてオプション扱いとしています。⁠標準拡張」はRISC-Vとして標準化されているため,将来的にその命令が別の機能に割り当てられることはありません。これとは別にベンダーごとに「非標準拡張(non-Standard Extention)⁠を作ることも可能です。

基本整数命令と標準拡張は,各ソフトウェアやチップでサポートしているかどうかを判別しやすいように,それぞれ機能ごとに「フラグ」が設定されています。

I: 基本整数命令
E: レジスタの数を減らしたIのサブセット
M: 整数の乗算除算命令
A: アトミック命令
F: 単精度の浮動小数点演算命令
D: 倍精度の浮動小数点演算命令
Q: 四倍精度の浮動小数点演算命令
L: 十進の浮動小数点演算命令(未定義)
C: 圧縮命令
B: ビット演算命令(未定義)
J: JavaのようなDynamic Translation用命令(未定義)
T: トランザクショナルメモリー用命令(未定義)
P: Packed-SIMD命令
V: ベクタ命令
N: ユーザーレベル割り込み

IMAFDQC以外は「策定中」というステートです。今後大きく変更される可能性があります。

たとえば「RV32I」であれば,レジスタのサイズが32bitで基本整数命令のみをサポートしていることがわかりますし,⁠RV64IMAFD」であれば64bitアーキテクチャの一般的なPC用のCPUを構築できる程度には機能が揃っていることがわかります。ちなみに「IMAFD」「G」と省略することも可能です。つまり「RV64IMAFD=RV64G」です。また「I」からレジスタの数を半減させた「E」というフラグも存在します。

今回作ったツールチェインは,⁠RV64IMAFDC」です。gccのconfigureオプションを見るとrv64imafdcが指定されていることがわかります。

$ riscv64-unknown-elf-gcc -v
Using built-in specs.
COLLECT_GCC=riscv64-unknown-elf-gcc
COLLECT_LTO_WRAPPER=/home/ubuntu/riscv/libexec/gcc/riscv64-unknown-elf/7.2.0/lto-wrapper
Target: riscv64-unknown-elf
Configured with:
 /home/ubuntu/riscv-tools/riscv-gnu-toolchain/build/../riscv-gcc/configure
 --target=riscv64-unknown-elf --prefix=/home/ubuntu/riscv --disable-shared
 --disable-threads --enable-languages=c,c++ --with-system-zlib --enable-tls
 --with-newlib --with-sysroot=/home/ubuntu/riscv/riscv64-unknown-elf
 --with-native-system-header-dir=/include --disable-libmudflap
 --disable-libssp --disable-libquadmath --disable-libgomp --disable-nls
 --src=../../riscv-gcc --enable-checking=yes --disable-multilib
 --with-abi=lp64d
 --with-arch=rv64imafdc
 'CFLAGS_FOR_TARGET=-Os  -mcmodel=medlow'
Thread model: single
gcc version 7.2.0 (GCC)

「C」フラグが付いているので,16bit幅の命令(RVC命令)も使えることがわかります。

命令長は「最下位ビットの1が連続する数」で判定されます(1.2 Instruction Length Encoding)⁠最下位2ビットが「11」ではない場合,16bit長の命令です。最下位2ビットが「11」で,なおかつ最下位5ビットのうち上位3ビットが「111」ではない場合,32bitの命令長になります。さらに32bitよりも長い命令に拡張できるようにも作られています。

前述の2つのaddiを比べてみましょう。

16bit幅の加算命令(s0 = sp + 16):
   0x00000000000101a0 <+6>:     00 08           addi    s0,sp,16
32bit幅の加算命令(a0 = a5 - 40):
   0x00000000000101a4 <+10>:    13 85 87 fd     addi    a0,a5,-40 # 0x11fd8

RISC-Vの標準ではリトルエンディアンなので,命令部分のバイト列・ビット列は次のとおりです。

  • 16bitのaddi:0x0800 = 0000 1000 0000 0000
  • 32bitのaddi:0xfd878513 = 1111 1101 1000 0111 1000 0101 0001 0011

太字で表示している最下位2ビットを比べてみると,16bit版は「00」に32bit版は「11」になっていることがわかりますね。

さらにISA仕様書を見れば他のビットの意味も確認できます。たとえば「Table 12.5: Instruction listing for RVC, Quadrant 1.」「Table 19.3: RISC-V control and status register (CSR) address map.」には関連命令の一覧表が掲載されています。

16bitのaddi:0x0800
             FNC          [RD]OP
  C.ADDI4SPN 0000 1000 0000 0000
                ^ ^^^^ ^^^
                Non-Zero IMM[5:4|9:6|2|3]
    OP  = 00
    FNC = 000
    RD  = 000
    IMM = 0000010000 = 0x10

OP/FNCからこの命令が「C.ADDI4SPN」だということがわかります。この命令はスタックポインタ(spレジスタ)にIMMの値を足して,RDで指定されたレジスタに保存する命令です。

IMMは「nzuimm」と書かれていますので,符号拡張しない即値となります。つまり命令に含まれていない上位ビットは0で埋められます。また下位2ビットも0で埋めます。結果的にIMMの値は「0x10 = 16」です。

RDは「000」となっています。これは「Table 12.2: Registers specified by the three-bit rs1⁠, rs2⁠, and rd’ fields of the CIW, CL, CS, and CB formats.」からs0レジスタであることがわかります。

まとめるとdisassembleした結果どおり「s0 = sp + 16」になりましたね。

32bit版のaddiも同様にパースできます。

32bitのaddi:0xfd878513
        [IMM         ] [RS1  ]FNC [RD  ][OP    ]
  ADDI  1111 1101 1000 0111  1000 0101 0001 0011
    OP  = 0010011
    FNC = 000
    RD  = 01010 = 10
    RS1 = 01111 = 15
    IMM = 1111 1101 1000 => 1111 1111 1101 1000 = -0x28 = -40

ADDI命令は符号拡張したIMMをRS1で指定されたレジスタに足して,RDで指定されたレジスタに保存する命令です。

IMMは下位12ビットしか記録されていないので32ビット値(RV32の場合)や64ビット値(RV64の場合)に拡張するには,最上位ビットをそのまま左に埋めることになります(符号拡張)⁠今回最上位ビットは1なので,2の補数表現からこれが「-40」であることがわかります。

「Table 20.1: Assembler mnemonics for RISC-V integer and floating-point registers.」を参考にRDはa0レジスタ(x10レジスタ)⁠RS1はa5レジスタ(x15レジスタ)であることがわかります。こちらもdisassembleした結果どおり「a0 = a5 - 40」となりました。

2018年はRISC-Vで遊ぼう

いろいろなところで言われているように半導体プロセスの進化は限界に近づきつつあります。特に微細化による恩恵は,開発コスト的にも消費電力的にもこれまでのようには汎用プロセッサの性能に寄与することはないでしょう。そのような状況で,より高性能な計算能力を提供する方法の一つとして考えられているのが,⁠ドメイン固有アーキテクチャ(Domain Specific Architecture)⁠です。汎用プロセッサとしての性能があげられなかったとしても,特定の用途に限定してチューニングすればまだ改良の余地があるだろうということです。

グラフィックの用途に限定してGPUが進化してきたように,最近では深層学習用のTPUやブロックチェーン用のCatapultと言った専用コアが注目を浴びていますし,Pixel Visual Core/Neural Engineのように「Neural Processing Unit」が搭載されたスマートフォンも登場しています。

いわゆる専用プロセッサは開発コストが大きくなりがちです。いろいろな「コプロセッサ」がCPU/SoCに統合されていったことからもわかるでしょう。それなりに量産できるのであれば多少コストが増えてもなんとかなるのでしょうが,そもそも「特定用途」という縛りがある以上,そこまで数が必要になるわけでもありません。開発コストを抑えるために既存のIPコアを流用するとなると,今度はライセンスフィーなどの形で量産コストが増えることになります。

商用アーキテクチャの場合,開発している企業が別の企業に買収されて,ライセンス形態等が変わってしまうという可能性もあります。特にここ数年は半導体企業の大型買収にともなう再編が進んでいました。2016年にARMがソフトバンクに買収されたニュースを覚えている方もいることでしょう。ある程度落ち着いてきたとは言うものの,昨年11月末にはMarvellがCaviumを買収していますし,QualcommによるNXPの買収は結局2018年までずれ込むことになりました。そのQualcomm自身もBroadcom(=旧Broadcomを買収した旧Avago)から敵対的買収をかけられています。もうなにがなんだか。

RISC-Vの場合は,原則としてライセンスフィーは発生しませんし,基本的な情報はすべて公開されているのでカスタマイズも比較的容易です。特定の企業に依存していないため,ある日突然別の企業に買収されて,ビジネスを考え直す必要が出てくることもほぼありません。

このようにオープン規格であるということは,参入障壁や将来のリスクを低減し,よりイノベーションを起こしやすくなる可能性を秘めているのです。もちろん良いことばかりではなく,広く様々なユーザーに使われなければオープンである強みは出てこないですし,強いマネタイズの手段がない故に研究開発への投資はどうしても制限されてしまうリスクも持っています。幸い,現時点ではRISC-Vは広い注目を集めています。昨年末に日本で開催されたRISC-V Day 2017 Tokyoも大盛況でした。

2018年の新たな目標として,他の商用アーキテクチャとは別の解としてRISC-Vが流行ることを期待しつつ,注目されているうちに様々な可能性を見出してみるのはいかがでしょうか。

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member株式会社 創夢所属。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。

コメント

コメントの記入