19. 要素分割拡張命令 (‘Zvediv’) ------------------------------- EDIV拡張は現在では“V”基本命令には取り込まれない予定である。現在の仕様から大幅に変更となる可能性がある。 要素分割拡張は、各ベクトルの要素をさらに小さなサブベクトルとして取り扱うための拡張である。この拡張により、よりビット幅の小さなデータの取り扱いや、複数のビット幅が混在した算術演算や、小さなベクトルのループ外領域のベクトル化、行列の演算などに使用できる。既存の命令の挙動の変更に加え、EDIV > 1の際にはいくつかの新しい命令を定義する。 要素分割拡張では、\ ``vtype``\ レジスタに\ ``vediv[1:0]``\ という2ビットのフィールドを追加する。 +----------+------------+--------------------------------------------+ | ビット | 名前 | 説明 | +==========+============+============================================+ | XLEN-1 | vill | このビットが設定され | | | | ると、不正な設定が行われたことを意味する。 | +----------+------------+--------------------------------------------+ | XLEN-2:7 | | 予約 | +----------+------------+--------------------------------------------+ | 6:5 | vediv[1:0] | EDIV拡張のために使用される。 | +----------+------------+--------------------------------------------+ | 4:2 | vsew[2:0] | Standard element width (SEW) の設定 | +----------+------------+--------------------------------------------+ | 1:0 | vlmul[1:0] | Vector register group multiplier (LMUL) | | | | の設定 | +----------+------------+--------------------------------------------+ ``vediv``\ フィールドはEDIVがSEWビットの要素をどのように分割するかについて設定する。ベクトルレジスタグループはサブベクトルのベクトル列として考える。 =========== = = =============================== vediv [1:0] Division EDIV =========== = = =============================== 0 0 1 分割しない。ベースISA 0 1 2 2つの等幅のサブ要素に分割する。 1 0 4 4つの等幅のサブ要素に分割する。 1 1 8 8つの等幅のサブ要素に分割する。 =========== = = =============================== +------+------+-------+-------+------+-------+-------+-------+ | SEW | EDIV | サブ | 整 | | 浮動 | | | | | | 要素 | 数ア | | 小数 | | | | | | | キュ | | 点加 | | | | | | | ムレ | | 算・ | | | | | | | ータ | | ドッ | | | | | | | | | トア | | | | | | | | | キュ | | | | | | | | | ムレ | | | | | | | | | ータ | | | +======+======+=======+=======+======+=======+=======+=======+ | | | | sum | dot | FL | FL | FLE | | | | | | | EN=32 | EN=64 | N=128 | +------+------+-------+-------+------+-------+-------+-------+ | 8b | 2 | 4b | 8b | 8b | - | - | - | +------+------+-------+-------+------+-------+-------+-------+ | 8b | 4 | 2b | 8b | 8b | - | - | - | +------+------+-------+-------+------+-------+-------+-------+ | 8b | 8 | 1b | 8b | 8b | - | - | - | +------+------+-------+-------+------+-------+-------+-------+ | 16b | 2 | 8b | 16b | 16b | - | - | - | +------+------+-------+-------+------+-------+-------+-------+ | 16b | 4 | 4b | 8b | 16b | - | - | - | +------+------+-------+-------+------+-------+-------+-------+ | 16b | 8 | 2b | 8b | 8b | - | - | - | +------+------+-------+-------+------+-------+-------+-------+ | 32b | 2 | 16b | 32b | 32b | 32b | 32b | 32b | +------+------+-------+-------+------+-------+-------+-------+ | 32b | 4 | 8b | 16b | 32b | - | - | - | +------+------+-------+-------+------+-------+-------+-------+ | 32b | 8 | 4b | 8b | 16b | - | - | - | +------+------+-------+-------+------+-------+-------+-------+ | 64b | 2 | 32b | 64b | 64b | 32b | 64b | 64b | +------+------+-------+-------+------+-------+-------+-------+ | 64b | 4 | 16b | 32b | 64b | 32b | 32b | 32b | +------+------+-------+-------+------+-------+-------+-------+ | 64b | 8 | 8b | 16b | 32b | - | - | - | +------+------+-------+-------+------+-------+-------+-------+ | 128b | 2 | 64b | 128b | 128b | 32b | 64b | 128b | +------+------+-------+-------+------+-------+-------+-------+ | 128b | 4 | 32b | 64b | 128b | 32b | 64b | 64b | +------+------+-------+-------+------+-------+-------+-------+ | 128b | 8 | 16b | 32b | 64b | 32b | 32b | 32b | +------+------+-------+-------+------+-------+-------+-------+ | 256b | 2 | 128b | 256b | 256b | 32b | 64b | 128b | +------+------+-------+-------+------+-------+-------+-------+ | 256b | 4 | 64b | 128b | 256b | 32b | 64b | 128b | +------+------+-------+-------+------+-------+-------+-------+ | 256b | 8 | 32b | 64b | 128b | 32b | 64b | 64b | +------+------+-------+-------+------+-------+-------+-------+ 各実装では、SELENと呼ばれるサブ要素の最小サイズを定義することができる。この値は最大で8ビットでなければならない。 SLENは実装に依存するパラメータであるが、8よりも小さな値は更なる拡張として定義される可能性がある。 19.1. EDIVの変更に影響しない命令群 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ベクトル開始レジスタ\ ``vstart``\ と例外通知については、これまでと同様に動作する。 ベクトル長\ ``vl``\ 制御レジスタおよびベクトルマスクについては、これまで通り要素レベルで動作する。 ベクトルマスクはこれまで通り要素レベルで動作し、従ってサブ要素に対して個々にマスクをすることはできない。 SEWは、8ビット以上のサブ要素のエレメントごとのマスキングを有効にするために動的に変更できる。 ベクトルロードストア・AMO命令はEDIVに影響せず、要素全体に対してデータの移動を行う。 ベクトルマスク論理演算についてはEDIVの設定に影響せず、ベクトル要素全体に対してマスクの適用を行う。 マスク付きPopulation Count(``vpopc``)、ビット先頭探索に関連する命令(``vfirst``, ``vmsbf``, ``vmsif``, ``vmsof``)、iota(``viota``)、要素インデックス(``vid``)命令についても、EDIVの設定に影響しない。 ベクトルインデックスビット挿入・抽出命令および整数・浮動小数点スカラ移動命令についてもEDIVに影響しない。 ベクトルスライドアップ・スライドダウン命令についても、EDIVの設定に影響しない。 ベクトル圧縮命令も、EDIVの設定に影響しない。 19.2. EDIVの設定に影響する命令 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19.2.1. EDIV下での通常のベクトル算術演算命令 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 多くのベクトル算術演算命令は、個々のサブ要素の中で独立して演算を実行する。したがって有効なSEWビット幅はSEW/EDIVであり、有効なベクトル長は\ ``vl`` \* EDIVである。例えば、32ビット要素のベクトル加算命令を\ ``vl``\ =5, EDIV=4で実行すると、8ビットのベクトル加算命令をベクトル長20で実行するのと同じである。 :: vsetvli t0, a0, e32,m1,d4 # 32ビットベクトル要素、バイト単位のサブ要素に分割 vadd.vv v1,v2,v3 # 4*vl 8ビットの加算に変更。 vsll.vx v1,v2,x1 # 4*vl 8ビットのシフトに変更。 19.2.2. EDIV>1下でのキャリー付きベクトル加算、ボロー付きベクトル減算 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ For EDIV > 1, ``vadc``, ``vmadc``, ``vsbc``, ``vmsbc`` are reserved. EDIV > 1において、 ``vadc``, ``vmadc``, ``vsbc``, ``vmsbc`` 命令は予約されている。 19.2.3. EDIV下でのベクトルリダクション命令 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ベクトルビット単一幅整数リダクション加算命令はEDIV>1下では予約されている。他のビット単一幅ベクトルリダクション命令およびビット幅拡張整数リダクション加算命令はベクトル内のすべての要素について独立して動作し、各サブ要素の値をリダクションし、エレメント幅での結果を計算する。 スカラー入力は、第2オペランドの最下位ビットから取得される。ビット数は有意な結果ビットの数に等しい(つまり、加算およびドットリダクションの場合、ビット数は上記の表で与えられる。 非加算、非ドットリダクションの場合は、要素のサイズと同じである)。 :: # 4つのサブ要素を加算し、16ビットの結果を得る。 vsetvli t0, a0, e32,d4 # 32ビット用要素が4つに分割されている。 vwredsum.vs v1, v2, v3 # v1[i][15:0] = v2[i][31:24] + v2[i][23:16] # + v2[i][15:8] + v2[i][7:0] + v3[i][15:0] # サブ要素の中で最大要素を探索する。 vredmax.vs v5, v6, v7 # v5[i][7:0] = max(v6[i][31:24], v6[i][23:16], # v6[i][15:8], v6[i][7:0], v7[i][7:0]) 整数のサブ要素を使用した非加算のリダクション命令はmax(8, SEW/EDIV)ビットの計算結果を出力し、必要であればSEWビットまで符号拡張またはゼロ拡張を行う。 整数のサブ要素を使用したビット幅拡張のリダクション加算命令は、max(8, min(SEW, 2*SEW/EDIV))ビットの計算結果を出力し、必要であればSEWビットまで符号拡張またはゼロ拡張を行う。 単一ビット幅の浮動小数点リダクション命令はSEW/EDIVビットの計算結果を出力する。 ビット幅拡張を行う浮動小数点リダクション加算命令はmin(2*SEW/EDIV, FLEN)ビットの計算結果を出力し、必要であればNaN Boxingを行う。 19.2.4. EDIV下でのベクトルレジスタギャザー命令 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ EDIVが非ゼロの場合のベクトルレジスタギャザー命令は、要素内のサブ要素でのギャザー操作のみを行う。ソースとインデックスの値は要素内の操作に限定される。インデックスの値 ≥ EDIV の結果のサブ要素には、ゼロが書き込まれる。 :: | | | SEW = 32b, EDIV=4 7 6 5 4 3 2 1 0 bytes d e a d b e e f v1 0 1 9 2 0 2 3 2 v2 vrgather.vv v3, v1, v2 d a 0 e f e b e v3 vrgather.vi v4, v1, 1 a a a a e e e e v4 .. スカラ値および即値を利用したベクトルレジスタギャザー命令はベクトル要素の中のサブ要素を“splat”するために使用できる。 レジスタギャザー命令は、単一要素ビット幅において高速な実装を提供することができる。 19.3. ベクトル整数ドットプロダクト命令 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 整数ドットプロダクトリダクション命令\ ``vdot.vv``\ はベクトル要素内で、ソースのサブ要素を乗算し、書き込み先のレジスタにベクトル要素を累積加算する。ここで、アセンブラの文法では\ ``.vv``\ サフィックスを使用しているのは入力がどちらともベクトル要素であるためである。 サブ要素の整数ドットリダクション命令は、max(8, min(SEW, 4*SEW/EDIV))ビット幅の計算結果を出力し、必要であればSEWビットまで符号拡張またはゼロ拡張を行う。 :: # 符号なし整数ドットプロダクト命令 vdotu.vv vd, vs2, vs1, vm # ベクトル ー ベクトル # 符号付整数ドットプロダクト命令 vdot.vv vd, vs2, vs1, vm # ベクトル ー ベクトル # ドットプロダクト, SEW=32, EDIV=1 vdot.vv vd, vs2, vs1, vm # vd[i][31:0] += vs2[i][31:0] * vs1[i][31:0] # ドットプロダクト, SEW=32, EDIV=2 vdot.vv vd, vs2, vs1, vm # vd[i][31:0] += vs2[i][31:16] * vs1[i][31:16] + vs2[i][15:0] * vs1[i][15:0] # ドットプロダクト, SEW=32, EDIV=4 vdot.vv vd, vs2, vs1, vm # vd[i][31:0] += vs2[i][31:24] * vs1[i][31:24] + vs2[i][23:16] * vs1[i][23:16] + vs2[i][15:8] * vs1[i][15:8] + vs2[i][7:0] * vs1[i][7:0] 19.4. ベクトル浮動小数点ドットプロダクト命令 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 浮動小数点のドットプロダクト命令\ ``vfdot.vv``\ はベクトル要素内において乗算を行い、その結果を書き込みベクトルレジスタに累積加算する。ここで、アセンブラの文法では\ ``.vv``\ サフィックスを使用しているのは入力がどちらともベクトル要素であるためである。 :: # 符号付きdot-product vfdot.vv vd, vs2, vs1, vm # ベクトル ー ベクトル # ドットプロダクト. SEW=32, EDIV=2 vfdot.v vd, vs2, vs1, vm # vd[i][31:0] += vs2[i][31:16] * vs1[i][31:16] + vs2[i][15:0] * vs1[i][15:0] # 2つの半精度の浮動小数点を32ビットにパッキングする。 vsetvli t0, a0, e32,m1,d2 # 32ビット要素を2つの16ビットに分割したサブ要素として取り扱う。 vfdot.vv v1, v2, v3 # v1[i][31:0] += v2[i][31:16]*v3[i][31:16] + v2[i][16:0]*v3[i][16:0] # 2つの半精度の浮動小数点を32ビットにパッキングする。 vsetvli t0, a0, e32,m1,d2 # 32ビット要素を2つの16ビットに分割したサブ要素として取り扱う。 vfdot.vv v1, v2, v3 # v1[i][31:0] += v2[i][31:16]*v3[i][31:16] + v2[i][16:0]*v3[i][16:0] # 4つの半精度の浮動小数点を64ビットにパッキングする。 vsetvli t0, a0, e64,m1,d4 # 64ビット要素を4つの16ビットに分割したサブ要素として取り扱う。 vfdot.vv v1, v2, v3 # v1[i][31:0] += v2[i][31:16]*v3[i][31:16] + v2[i][16:0]*v3[i][16:0] + # v2[i][63:48]*v3[i][63:48] + v2[i][47:32]*v3[i][47:32]; # v1[i][63:32] = ~0 (NaN boxing)