FPGA開発日記

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

NEONとRISC-V VectorのSoAとAoSのデータ並び変換命令について

もちろん、NEONSIMD命令でRVVはVector命令群なので目的も細かな仕様も異なるわけだけれども、命令の挙動として似ているものを対比してみる。

developer.arm.com

  • Unit-Stride Load 命令 RVV命令の場合はVLE.V 命令などがある。VLE8.V / VLE16.V / VLE32.V / VLE64.V など。 NEONにおいては、LD1命令がそれに該当する。

複数のベクトルレジスタに書く場合は、RVVの場合はLMUL>2に設定することで可能になる(ただしレジスタの指定できるアドレスは半分になる)。

VSETVLI m2
VLE32.V v8, (x10)   # v8とv9に32ビット単位でのデータをロードする
VSETVLI m4
VLE16.V v4, (x10)   # v4-v7に16ビット単位でのデータをロードする

NEONでは、LD1命令のオペランドを複数指定することで複数のレジスタにデータをロードすることができるようになる。

LD1 { V0.16B, V1.16B }, [x0]   # v0とv1に16ビット単位でのデータロードを行う

あまり関係ないが、連続的なデータをロードするので、32ビット単位とか16ビット単位などの条件はあまり命令の挙動に関係がないのだが、アドレスミスアラインの条件として使用する程度である。

  • Segment命令 RVVにはSegment Load/Store命令というものが定義されている。
VLSEG3E32.V v8, (x10)  # v8, v9, v10に対して縦方向に値をロードする

NEONの場合は以下の記述で同様なことが可能になる。

LD3 { V0.16B, V1.16B, V2.16B }, [x0]

これはST3でも同様のことが可能だ。同様にLD2/LD3/LD4が定義されており、これは VLSEG2E<EEW>.V / VLSEG3E<EEW>.V / VLSEG4E<EEW>.V で定義されている。

インターリーブ無しで1つのベクトルレジスタに値を格納する命令 LD1 Vx, [Rx] VSET LMUL=1; VLE.V Vx, (Rx)
インターリーブ無しで2つのベクトルレジスタに値を格納する命令 LD1 {Vx, Vy} [Rx] VSET LMUL=2; VLE.V Vx, (Rx)
インターリーブ無しで3つのベクトルレジスタに値を格納する命令 LD1 {Vx, Vy, Vz} [Rx]
インターリーブ無しで4つのベクトルレジスタに値を格納する命令 LD1 {Vx, Vy, Vz, Vw} [Rx] VSET LMUL=4; VLE.V Vx, (Rx)
インターリーブ無しで8つのベクトルレジスタに値を格納する命令 VSET LMUL=8; VLE.V Vx, (Rx)
2要素をインタリーブしながら2つのベクトルレジスタに値を格納する命令 LD2 {Vx, Vy} [Rx] VLSEG2E.V Vx, (Rx)
3要素をインタリーブしながら3つのベクトルレジスタに値を格納する命令 LD3 {Vx, Vy, Vz} [Rx] VLSEG3E.V Vx, (Rx)
4要素をインタリーブしながら4つのベクトルレジスタに値を格納する命令 LD4 {Vx, Vy, Vz, Vw} [Rx] VLSEG4E.V Vx, (Rx)
5要素をインタリーブしながら5つのベクトルレジスタに値を格納する命令 VLSEG5E.V Vx, (Rx)
6要素をインタリーブしながら6つのベクトルレジスタに値を格納する命令 VLSEG6E.V Vx, (Rx)
7要素をインタリーブしながら7つのベクトルレジスタに値を格納する命令 VLSEG7E.V Vx, (Rx)