FPGA開発日記

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

RISC-Vベクトル拡張仕様書 v1.0 を読み直す (18. 整数算術演算命令2)

RISC-Vベクトル拡張仕様書の読み直し。算術演算命令、乗除算命令など、その他特殊な命令など。

github.com

github.com


11.9. ベクトル整数最大/最小命令

符号付き整数/符号なし整数の最大・最小値計算命令がサポートされている。

# 符号なし最小値
vminu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vminu.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 符号付き最小値
vmin.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vmin.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 符号なし最大値
vmaxu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vmaxu.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 符号付き最大値
vmax.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vmax.vx vd, vs2, rs1, vm   # ベクトル-スカラ

11.10. ベクトル単一幅整数乗算命令

単一幅の乗算命令は、SEWビット*SEWビットの乗算を行い、SEWビット幅の結果を返す。 mulh 版では、積の上位ワードを出力レジスタに書き込みます。

# 符号付き乗算、積の下位ビットを返す
vmul.vv vd, vs2, vs1, vm   # Vector-vector
vmul.vx vd, vs2, rs1, vm   # vector-scalar

# 符号付き乗算、積の上位ビットを返す
vmulh.vv vd, vs2, vs1, vm   # Vector-vector
vmulh.vx vd, vs2, rs1, vm   # vector-scalar

# 符号なし乗算、積の上位ビットを返す
vmulhu.vv vd, vs2, vs1, vm   # Vector-vector
vmulhu.vx vd, vs2, rs1, vm   # vector-scalar

# vs2を符号付き、vs1を符号なしとした乗算、積の上位ビットを返す
vmulhsu.vv vd, vs2, vs1, vm   # Vector-vector
vmulhsu.vx vd, vs2, rs1, vm   # vector-scalar

Note: 符号なしベクトル * 符号付きスカラ積の上位半分を返す vmulhus オペコードはありません。

Note: 現在の vmulh* オペコードは、単純な小数乗算を行いますが、結果をスケーリングしたり、丸めたり、飽和させたりするオプションはありません。 拡張機能としては、vmulh, vmulhu, vmulhsu のバリエーションが考えられ、積の下半分を破棄する際に vxrm 丸めモードを使用します。 これらのケースではオーバーフローの可能性はありません。

11.11. ベクトル整数除算命令

除算・剰余命令は、RISC-V標準のスカラ整数乗除算と同等で、極端な入力に対しても同じ結果が得られます。

    # 符号なし除算
    vdivu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
    vdivu.vx vd, vs2, rs1, vm   # ベクトル-スカラ

    # 符号付除算
    vdiv.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
    vdiv.vx vd, vs2, rs1, vm   # ベクトル-スカラ

    # 符号なし剰余
    vremu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
    vremu.vx vd, vs2, rs1, vm   # ベクトル-スカラ

    # 符号付剰余
    vrem.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
    vrem.vx vd, vs2, rs1, vm   # ベクトル-スカラ

Note: 整数の除算と余剰を含めるかどうかは、意見が分かれました。 標準的な命令がない場合、ソフトウェアは演算を実行するために何らかのアルゴリズムを選択しなければならず、 マイクロアーキテクチャによってはパフォーマンスが低下する可能性があるというのが賛成の理由です。 注:"ベクトルによるスカラ除算"を実行する命令はありません。

11.12. ベクトル幅拡張乗算命令

幅拡張整数乗算命令は、SEWビットSEWビット乗算から完全な2SEWビット積を返します。

# 幅拡張符号付き整数乗算
vwmul.vv  vd, vs2, vs1, vm # vector-vector
vwmul.vx  vd, vs2, rs1, vm # vector-scalar

# 幅拡張符号なし整数乗算
vwmulu.vv vd, vs2, vs1, vm # vector-vector
vwmulu.vx vd, vs2, rs1, vm # vector-scalar

# 幅拡張符号付き・符号なし整数乗算
vwmulsu.vv vd, vs2, vs1, vm # vector-vector
vwmulsu.vx vd, vs2, rs1, vm # vector-scalar

11.13. ベクトル単一幅整数乗算加算命令

整数の乗算加算命令は破壊的で、加算値や最小値を上書きするもの(vmacc、vnmsac)と、 最初の乗算値を上書きするもの(vmadd、vnmsub)の2種類が用意されています。

積の下位ビットの半分が第3オペランドに加算または減算されます。

Note: sac は「アキュムレータからの減算(subtract from accumulator)」と読むことを意図しています。 オペコードは、(残念ながら直感に反する)浮動小数点の fnmsub 命令の定義に合わせて vnmsac となっています。 オペコードは vnmsub と似ています。

# 整数乗算加算命令、加算項上書き
vmacc.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vmacc.vx vd, rs1, vs2, vm    # vd[i] = +(x[rs1] * vs2[i]) + vd[i]

# 整数乗算減算命令、減算項上書き
vnmsac.vv vd, vs1, vs2, vm    # vd[i] = -(vs1[i] * vs2[i]) + vd[i]
vnmsac.vx vd, rs1, vs2, vm    # vd[i] = -(x[rs1] * vs2[i]) + vd[i]

# 整数乗算加算命令、乗算項上書き
vmadd.vv vd, vs1, vs2, vm    # vd[i] = (vs1[i] * vd[i]) + vs2[i]
vmadd.vx vd, rs1, vs2, vm    # vd[i] = (x[rs1] * vd[i]) + vs2[i]

# 整数乗算減算命令、乗算項上書き
vnmsub.vv vd, vs1, vs2, vm    # vd[i] = -(vs1[i] * vd[i]) + vs2[i]
vnmsub.vx vd, rs1, vs2, vm    # vd[i] = -(x[rs1] * vd[i]) + vs2[i]

11.14. ベクトル幅拡張整数乗算加算命令

幅拡張整数乗算・加算命令は、SEWビットSEWビットの乗算から2SEWビットの値に2SEWビットの乗算を加算し、 2SEWビットの結果を生成します。 符号付きおよび符号なしの乗算オペランドのすべての組み合わせがサポートされています。

# 幅拡張符号なし整数乗算加算命令、加算項上書き
vwmaccu.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vwmaccu.vx vd, rs1, vs2, vm    # vd[i] = +(x[rs1] * vs2[i]) + vd[i]

# 幅拡張符号付き整数乗算加算命令、加算項上書き
vwmacc.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vwmacc.vx vd, rs1, vs2, vm    # vd[i] = +(x[rs1] * vs2[i]) + vd[i]

# 幅拡張符号なし整数乗算加算命令、加算項上書き
vwmaccsu.vv vd, vs1, vs2, vm  # vd[i] = +(signed(vs1[i]) * unsigned(vs2[i])) + vd[i]
vwmaccsu.vx vd, rs1, vs2, vm  # vd[i] = +(signed(x[rs1]) * unsigned(vs2[i])) + vd[i]

# Widening unsigned-signed-integer multiply-add, overwrite addend
# 幅拡張符号なし・符号付き整数乗算加算命令、加算項上書き
vwmaccus.vx vd, rs1, vs2, vm  # vd[i] = +(unsigned(x[rs1]) * signed(vs2[i])) + vd[i]

11.15. ベクトル整数マージ命令

ベクトル整数マージ命令は、2つのソースオペランドをマスクに基づいて結合します。 通常の算術命令とは異なり、マージはすべてのボディ要素(すなわち、 vstart から vl の現在のベクトル長までの要素の集合)に対して動作します。

vmerge命令は、マスクされた命令(vm=0)としてエンコードされます。 この命令は、次のように2つのソースを組み合わせます。 マスク値がゼロの要素では、第1オペランドがデスティネーション要素にコピーされ、そうでない場合は第2オペランドがデスティネーション要素にコピーされます。 第1オペランドは常に vs2 で指定されるベクトルレジスタ群です。 第2オペランドは、 vs1 で指定されるベクトルレジスタ群、 rs1 で指定されるスカラ x レジスタ、または5ビットの符号拡張即値です。

vmerge.vvm vd, vs2, vs1, v0  # vd[i] = v0.mask[i] ? vs1[i] : vs2[i]
vmerge.vxm vd, vs2, rs1, v0  # vd[i] = v0.mask[i] ? x[rs1] : vs2[i]
vmerge.vim vd, vs2, imm, v0  # vd[i] = v0.mask[i] ? imm    : vs2[i]

11.16. ベクトル整数移動命令

ベクトル整数移動命令は、ソース・オペランドをベクトル・レジスタ・グループにコピーします。 vmv.v.v はベクトルレジスタ群をコピーしますが、 vmv.v.x と vmv.v.i はスカラレジスタまたは即値をコピー先のベクトルレジスタ群のすべてのアクティブな要素に 転送します。 これらの命令は、マスクされていない命令(vm=1)としてエンコードされます。 第1オペランド指定子(vs2)には、 v0 が含まれていなければならず、 vs2 に含まれるその他のベクトルレジスタ番号は 予約されています 。

vmv.v.v vd, vs1 # vd[i] = vs1[i]
vmv.v.x vd, rs1 # vd[i] = x[rs1]
vmv.v.i vd, imm # vd[i] = imm

Note: マスク値は、シーケンス vmv.v.i vd, 0; vmerge.vim vd, vd, 1, v0 を使って、SEW幅の要素に広げることができます。 ベクトル整数移動命令は、ベクトルマージ命令とエンコーディングが同じですが、 vm=1 、 vs2=v0 となっています。

ボディ要素を変更しない vmv.v.vd, vd という形式は、そのレジスタが次に SEW と等しい EEW で使用されることを示すヒントとして使用されます。

Note: EEWに従ってデータを内部的に再編成する実装では、 SEWに従って内部表現をシャッフルすることができます。 データを内部的に再編成しない実装では,この命令を動的に省略し、NOP として扱うことができます。