FPGA開発日記

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

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

RISC-Vベクトル拡張仕様書の読み直し。次は整数比較命令など。


11.5. ベクトル論理命令

# 論理命令
vand.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vand.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vand.vi vd, vs2, imm, vm   # ベクトル-即値

vor.vv vd, vs2, vs1, vm    # ベクトル-ベクトル
vor.vx vd, vs2, rs1, vm    # ベクトル-スカラ
vor.vi vd, vs2, imm, vm    # ベクトル-即値

vxor.vv vd, vs2, vs1, vm    # ベクトル-ベクトル
vxor.vx vd, vs2, rs1, vm    # ベクトル-スカラ
vxor.vi vd, vs2, imm, vm    # ベクトル-即値

Note: 即値が-1の場合、スカラ即値形式の vxor 命令は、ビットごとのNOT演算を行います。 これは、アセンブラの疑似命令 vnot.v として提供することができます。

11.6. ベクトル単一幅ビットシフト命令

左への論理シフト、右への論理(ゼロ拡張)および算術(符号拡張)シフトを含む、完全なベクトルシフト命令が用意されています。 シフトするデータは、 vs2 で指定されたベクトルレジスタグループにあり、シフト量はベクトルレジスタグループ vs1 、スカラ整数レジスター rs1 、または即値となります。 ベクトルまたはスカラのシフト量の値の下位lg2(SEW)ビットが使用され、シフト量の即値はゼロ拡張されます。

# ビットシフト操作
vsll.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vsll.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vsll.vi vd, vs2, uimm, vm   # ベクトル-即値

vsrl.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vsrl.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vsrl.vi vd, vs2, uimm, vm   # ベクトル-即値

vsra.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vsra.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vsra.vi vd, vs2, uimm, vm   # ベクトル-即値

11.7. ベクトルサイズ幅縮退整数右シフト命令

サイズ幅縮退の右シフトは、広いオペランドからより小さいフィールドを取り出すもので、ゼロ拡張(srl)と符号拡張(sra)の両方の形式があります。 シフト量は、ベクトル、スカラの x レジスタ、または5ビットの即値から得られます。 ベクトルまたはスカラのシフト量の下位lg2(2*SEW)ビットが使用されます(例えば、SEW=64ビットからSEW=32ビットへの狭帯域化の場合は下位6ビット)。 即値形式は、シフト量の即値オペランドをゼロ拡張します。

 # Narrowing shift right logical, SEW = (2*SEW) >> SEW
 # ビット幅縮退論理右シフト命令, SEW = (2*SEW) >> SEW
 vnsrl.wv vd, vs2, vs1, vm   # vector-vector
 vnsrl.wx vd, vs2, rs1, vm   # vector-scalar
 vnsrl.wi vd, vs2, uimm, vm   # vector-immediate

 # Narrowing shift right arithmetic, SEW = (2*SEW) >> SEW
 # ビット幅縮退算術右シフト命令, SEW = (2*SEW) >> SEW
 vnsra.wv vd, vs2, vs1, vm   # vector-vector
 vnsra.wx vd, vs2, rs1, vm   # vector-scalar
 vnsra.wi vd, vs2, uimm, vm   # vector-immediate

Note: 書き込みレジスタがソースの1/4の幅である、n4 バリアントのサポートを追加すると便利です。

Note: 整数値は、x0のスカラオペランドを持つ幅縮退の整数シフト命令を使って、幅を半分にすることができます。 アセンブリ疑似命令 vncvt.x.x.w vd,vs,vm = vnsrl.wx vd,vs,x0,vm を定義することができます。

11.8. ベクトル整数比較命令

以下の整数比較命令は、比較の結果が真であれば書き込みマスクレジスタの要素に1を、そうでなければ0を書き込みます。 書き込みマスクベクトルは常に単一のベクトルレジスタに保持され,その要素のレイアウトはセクション マスクレジスタのレイアウト で説明されています。 書き込みマスクレジスタは、ソースベクタのマスクレジスタ(v0)と同じものでも構いません。

# Set if equal
vmseq.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmseq.vx vd, vs2, rs1, vm  # ベクトル-スカラ
vmseq.vi vd, vs2, imm, vm  # ベクトル-即値

# Set if not equal
vmsne.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmsne.vx vd, vs2, rs1, vm  # ベクトル-スカラ
vmsne.vi vd, vs2, imm, vm  # ベクトル-即値

# Set if less than, unsigned
vmsltu.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmsltu.vx vd, vs2, rs1, vm  # ベクトル-スカラ

# Set if less than, signed
vmslt.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmslt.vx vd, vs2, rs1, vm  # ベクトル-スカラ

# Set if less than or equal, unsigned
vmsleu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vmsleu.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vmsleu.vi vd, vs2, imm, vm   # ベクトル-即値

# Set if less than or equal, signed
vmsle.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmsle.vx vd, vs2, rs1, vm  # ベクトル-スカラ
vmsle.vi vd, vs2, imm, vm  # ベクトル-即値

# Set if greater than, unsigned
vmsgtu.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vmsgtu.vi vd, vs2, imm, vm   # ベクトル-即値

# Set if greater than, signed
vmsgt.vx vd, vs2, rs1, vm    # ベクトル-スカラ
vmsgt.vi vd, vs2, imm, vm    # ベクトル-即値

# 以下の2命令は直接提供されない
# Set if greater than or equal, unsigned
# vmsgeu.vx vd, vs2, rs1, vm    # ベクトル-スカラ
# Set if greater than or equal, signed
# vmsge.vx vd, vs2, rs1, vm    # ベクトル-スカラ

以下の表は全ての比較操作がどのようにネイティブマシンコードに実装されるのかを示しています。

比較            アセンブラマッピング          アセンブラ疑似命令

va < vb         vmslt{u}.vv vd, va, vb, vm
va <= vb        vmsle{u}.vv vd, va, vb, vm
va > vb         vmslt{u}.vv vd, vb, va, vm    vmsgt{u}.vv vd, va, vb, vm
va >= vb        vmsle{u}.vv vd, vb, va, vm    vmsge{u}.vv vd, va, vb, vm

va < x          vmslt{u}.vx vd, va, x, vm
va <= x         vmsle{u}.vx vd, va, x, vm
va > x          vmsgt{u}.vx vd, va, x, vm
va >= x         see below

va < i          vmsle{u}.vi vd, va, i-1, vm    vmslt{u}.vi vd, va, i, vm
va <= i         vmsle{u}.vi vd, va, i, vm
va > i          vmsgt{u}.vi vd, va, i, vm
va >= i         vmsgt{u}.vi vd, va, i-1, vm    vmsge{u}.vi vd, va, i, vm

va, vb ベクトルレジスタグループ
x      スカラ整数レジスタ
i      即値

Note: vmslt{u}.vi の即時形は、即時値を1減らして vmsle{u}.vi のバリエーションを代わりに使用できるので、提供されません。 vmsle.vi の範囲は -16 から 15 で、その結果、実効的な vmslt.vi の範囲は -15 から 16 となります。 vmsleu.vi の範囲は0から15で、実効的な vmsltu.vi の範囲は1から16になります (注意: 即値0の vmsltu.vi は常に偽なので役に立ちません)。 5ビットのベクトル即値は常に符号拡張されているので、vmsleu.vi は 2SEW-16 から 2SEW-1 の範囲の符号なし即値もサポートしており、 2SEW-15 から 2SEW の範囲の符号なし即値に対する vmsltu.vi の比較が可能です。 即値 2SEW の vlsltu.vi は常に真なので、有用ではないことに注意してください。

同様に、vmsge{u}.vi は提供されず、即値を1だけデクリメントした vmsgt{u}.vi を使用して比較を実装します。 その結果、実効的な vmsge.vi の範囲は-15~16、実効的な vmsgeu.vi の範囲は1~16となります(なお、即値が0の vmsgeu.vi は常に真なので役に立ちません)。

Note: レジスタスカラと即値の vmsgt 形式は、追加のマスク論理命令を使用せずに、 1つの比較命令でマスク値の正しい極性を提供できるようにするために提供されています。 エンコーディング空間を減らすために、vmsge{u}.vx 形式は直接提供されていないので、va ≥ x の場合は特別な処理が必要です。

Note: vmsge{u}.vx は、使用されていない OPIVI の変形である vmslt{u} の下で、非直交的な方法でエンコードされる可能性があります。 しかし、OPIVIでスカラーの x レジスタを使用する命令はこれらだけです。 別の方法として、さらに2つのfunct6エンコーディングを使用することもできますが、 これらは同じ8つのfunct6エンコーディングのグループの他のものとは異なるオペランドフォーマット(マスクレジスタへの書き込み)になります。 現在のPoRでは,これらの命令を省略し、必要に応じて以下のように合成しています。

vmsge{u}.vx の演算は、 x の表現がアンダーフローしないことがわかっている場合、 x の値を1だけ減らして vmsgt{u}.vx 命令を使用することで合成できます。

`vmsge{u}.vx` 命令を合成するための命令列

va >= x,  x > minimum

   addi t0, x, -1; vmsgt{u}.vx vd, va, t0, vm

通常は上記の順序が最も効率的な実装になりますが、 x の範囲が不明な場合にはアセンブラの疑似命令を提供することができます。

マスク無し va >= x

  疑似命令: vmsge{u}.vx vd, va, x
  展開: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd

マスク付き va >= x, vd != v0

  疑似命令: vmsge{u}.vx vd, va, x, v0.t
  展開: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0

マスク付き va >= x, vd == v0

  疑似命令: vmsge{u}.vx vd, va, x, v0.t, vt
  展開: vmslt{u}.vx vt, va, x;  vmandnot.mm vd, vd, vt

マスク付き va >= x, any vd

  疑似命令: vmsge{u}.vx vd, va, x, v0.t, vt
  展開: vmslt{u}.vx vt, va, x;  vmandnot.mm vt, v0, vt;  vmandnot.mm vd, vd, v0;  vmor.mm vd, vt, vd

  疑似命令中のvt引数は一時ベクトルレジスタの意味であり、
  vdとは異なり破壊される問題ないレジスタでなければならない

マスク付きundisturbedポリシによって複数の比較をANDする例を以下に示します。

    # (a < b) && (b < c) をマスク付きundisturbedによって2命令で実現する
    vmslt.vv    v0, va, vb        # 全ての要素に書き込みを行う
    vmslt.vv    v0, vb, vc, v0.t  # マスクの設定された場所のみ書き込みを行う

比較はマスクレジスタを書き込むため、常に末尾agnosticポリシで動作します。