FPGA開発日記

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

7th RISC-V Workshop の Vector Extension Proposal 概要

RISC-V 7th Workshopでは、Vector Extensionの説明がなされている。

https://content.riscv.org/wp-content/uploads/2017/12/Wed-1330-RISCVRogerEspasaVEXT-v4.pdf

f:id:msyksphinz:20171222012224p:plain

資料を読みながらまとめてみる。追記の可能性あり。


RISC-V Vector Extensionの特徴としては、

  • なるべくコンパクトにすること。
  • ベクトルレジスタの処理にマスクを加え、任意の要素のみ演算が適用されるようにする。
  • スカラー、ベクトル、行列の形式などをサポートする(ただし行列形式はオプションであり、ベースの仕様には追加されない)。
  • 型を混在させることが出来る。
  • (自称)これまでのベクトル命令の中で最高の出来である。

ベクトルレジスタ

ベクトルレジスタはV0からV31までの32本が定義されている。

  • 各ベクトルレジスタには"Type"とよばれるレジスタが付与される。これは16bit長のベクトルレジスタである。
  • 各ベクトルレジスタには"Type"が付けられ、ベクトルレジスタ毎に異なる"Type"を設定することが出来る。
  • "Type"はvdcfgレジスタにより設定することが出来る。16bit×32本で512bitあるのだが、これをどのように設定することが出来るのかは詳細が語られていない。
  • おそらくvdcfgレジスタが複数作られ、csrrw命令により設定されていくものと思われる。

ベクトル算術演算の実行

  • 実装されているベクトルレジスタの長さはMVLで定義する。一方で実行中の演算が適用されるベクトルの要素の長さはVLで定義する。
  • MVLの長さは全てのベクトルレジスタにおいて同一である。
  • ベクトルレジスタの長さと、演算のレイテンシは別物として考える。vadd命令を実行した場合その命令を1サイクルで実行する必要はない。何サイクル化に分けて実行して構わない。

f:id:msyksphinz:20171221011520p:plain

  • 4サイクルで実行する場合

f:id:msyksphinz:20171221011615p:plain

  • 2サイクルで実行する場合

f:id:msyksphinz:20171221011634p:plain

マスク付きの実行

ベクトル命令は、マスクを使ってエレメント毎に演算の有効無効を指定できる。例えば、vadd v5, v3, v4, v1.tとする場合、以下のようにv1.tで指定されるレジスタの値に依存してマスクがかけられる。

f:id:msyksphinz:20171221012156p:plain

メモリアクセス

ロード命令・ストライド付きロード命令

ロード命令は非常にシンプルなロード命令。Unalignedも許可するが、非常に低速なことが前提。

ストライド付きロード命令は、いわゆるGather命令。RISC-Vの仕様であるGather命令はさらにえげつない。 f:id:msyksphinz:20171221013344p:plain

Gather命令

Gather命令は、各ベクトルエレメントで、ロードするメモリアドレスのオフセットを自由に設定できる。 結構実装が大変になる気がするが。。。

f:id:msyksphinz:20171221014131p:plain

ベクトルレジスタの型、型変換

  • 異なる"Type"が設定されたレジスタ同士の演算でも、ある程度ルールの中ならば演算を適用させることが出来る。
vcvt v1(F32) --> v0(F16)
vcvt v1(u8) --> v0(F32)
vcvct v1(F32) --> v0(I32)

この場合のベクトルレジスタのサイズが非常にややこしいことになる。 各ベクトルレジスタは異なる型を持つことが出来るが、MVL(ベクトルレジスタ当たりのエレメントの数)は常に同一である。 したがって、以下のようなことが出来るようになる。

  • プログラムコードが2つのF16ベクトルレジスタおよび2つのF32ベクトルレジスタを必要としている場合、
    • F16(=2byte)×2 + F32(=4byte)×2 = 12byteが必要となる。

このとき、ベクトルレジスタのハードウェアとしては  4\text{byte}\times 4\text{element}\times 32\text{本}=512\text{byte} 保持しているとすると、 \text{MVL}=512\text{byte} / (12\text{byte} + 4\text{byte(使用しないレジスタ)}) = 32となり、1ベクトルレジスタ当たり32エレメントを持つことが出来るようになる。

これをどのようにベクトルレジスタに当てはめるかは実装に任されている。例えば、以下のような構成が可能となる。

上位の 4\text{byte}\times 4\text{element}\times 4\text{本}\times 2\text{レジスタ}(=128\text{byte}) をF16のベクトルレジスタとして使い、 次の4\text{byte}\times 4\text{element}\times 8\text{本}\times 2\text{レジスタ}(=256\text{byte}) をF32のベクトルレジスタとして使う。

f:id:msyksphinz:20171222012123p:plain

以上のように、ベクトルレジスタのハードウェアを実際のアーキテクチャ的などのレジスタに割り当てるかは非常に柔軟に持つことが出来るようになる。 その分、かなり制限を加えないと実装が大変そうだが... (検証も大変そうだ)。

と思ったら、命令コード表には入っていた。師匠に指摘していただきました。ありがとうございます。

f:id:msyksphinz:20171226010836p:plain