4. ベクトル要素のベクトルレジスタへの割り付け --------------------------------------------- 以下の図は、ELEN, VLENの実装と同様に、現在のSEWおよびLMULの設定に基づいてベクトルレジスタのバイトをどのようにして異なるサイズのベクトル要素にパックするかについて説明している。要素は、最下位のビットの中で最も重要度の低いバイトを持つ各ベクトルレジスタにパックされる。 Elements are packed into each vector register with the least-significant byte in the lowest-numbered bits. 以前のRISC-V Vector Proposal(< バージョン0.6)ではこのマッピングをソフトウェアから隠していたが、今回のProposalではすべての構成について具体的なマッピングについて説明している。これにより実装の柔軟性が失われるが、コンフィグレーションが変更されることによりゼロ埋めの必要性が除去される。マッピングを明示することにより、明示的なコンテキストの保存・回復コードを簡単化することができる。つまりコンフィグレーションを読み込まずにすべてのベクトルレジスタを保存するのではなく、\ ``vl``,\ ``vtype``\ を保存して、\ ``vtype``\ を便利な値にリセットする(例えば、LMUL=8, SEW=ELENとする4つのベクトルグループ)ことができる。この逆の処理を行えば、ベクトルの状態を回復させることができる。 4.1 LMUL=1のマッピング ~~~~~~~~~~~~~~~~~~~~~~ LMUL=1の場合、要素はベクトルレジスタに対して単純に最下位から最上位に向けてパッキングされる。 可読性を向上させるために、ベクトルレジスタのレイアウトはバイトサイズで右から左にバイトアドレスを増加させる形式でく述する。エレメント内のビットはリトルエンディアンの形式で記述し、ビットインデックスは右から左へと増加していく。 :: 要素のインデックは16進数で記述し、格納されている要素のうち最も下位の位置に記述している。ELEN<=128かつLMUL=1である。 VLEN=32b Byte 3 2 1 0 SEW=8b 3 2 1 0 SEW=16b 1 0 SEW=32b 0 VLEN=64b Byte 7 6 5 4 3 2 1 0 SEW=8b 7 6 5 4 3 2 1 0 SEW=16b 3 2 1 0 SEW=32b 1 0 SEW=64b 0 VLEN=128b Byte F E D C B A 9 8 7 6 5 4 3 2 1 0 SEW=8b F E D C B A 9 8 7 6 5 4 3 2 1 0 SEW=16b 7 6 5 4 3 2 1 0 SEW=32b 3 2 1 0 SEW=64b 1 0 SEW=128b 0 VLEN=256b Byte 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 SEW=8b 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 SEW=16b F E D C B A 9 8 7 6 5 4 3 2 1 0 SEW=32b 7 6 5 4 3 2 1 0 SEW=64b 3 2 1 0 SEW=128b 1 0 4.2. LMUL > 1のマッピング ~~~~~~~~~~~~~~~~~~~~~~~~~ ベクトルレジスタがグループ化されているとき、ベクトルレジスタグループの要素はベクトルレジスタでストライプして配置される。ストライプの距離はSLENビットで表現され、グループ内で1つのベクトルレジスタ内で何ビットが1つの要素としてパッキングされているかを示している。 例えば、SLEN=128のとき、ストライプのパタンは128ビットの倍数である。最初の128/SEW個の要素はグループ内で最初のベクトルレジスタのスタート位置から連続してパッキングされる。次の128/SEW要素は連続してグループ内で次のベクトルレジスタのスタート位置から連続してパッキングされる。最初のLMUL*128/SEW個の要素をパッキングすると、次のLMUL*128/SEW個の要素のグループは次の128ビットのセグメントとしてグループ内のベクトルレジスタでパッキングされる。これが続く。 :: 例1: VLEN=32b, SEW=16b, LMUL=2 Byte 3 2 1 0 v2*n 1 0 v2*n+1 3 2 例2: VLEN=64b, SEW=32b, LMUL=2 Byte 7 6 5 4 3 2 1 0 v2*n 1 0 v2*n+1 3 2 例3: VLEN=128b, SEW=32b, LMUL=2 Byte F E D C B A 9 8 7 6 5 4 3 2 1 0 v2*n 3 2 1 0 v2*n+1 7 6 5 4 例4: VLEN=256b, SEW=32b, LMUL=2 Byte 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 v2*n B A 9 8 3 2 1 0 v2*n+1 F E D C 7 6 5 4 SEW> SLENの場合、ストライピングパターンは、グループ内の次のベクトルレジスタに移動する前に、グループ内の各ベクトルレジスタに1つの要素を配置する。 したがって、LMUL=2の場合、偶数ベクトルレジスタにはベクトルの偶数要素が含まれ、奇数ベクトルレジスタにはベクトルの奇数要素が含まれます。 ほとんどの実装では、SLEN≥ELENである。 :: 例: VLEN=256b, SEW=256b, LMUL=2 Byte 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 v2*n 0 v2*n+1 1 LMUL=4では、ベクトルレジスタは以下のように要素を格納する。 :: 例1: VLEN=32b, SLEN=32b, SEW=16b, LMUL=4, Byte 3 2 1 0 v4*n 1 0 v4*n+1 3 2 v4*n+2 5 4 v4*n+3 7 6 例2: VLEN=64b, SLEN=64b, SEW=32b, LMUL=4 Byte 7 6 5 4 3 2 1 0 v4*n 1 0 v4*n+1 3 2 v4*n+2 5 4 v4*n+3 7 6 例3: VLEN=128b, SLEN=64b, SEW=32b, LMUL=4 Byte F E D C B A 9 8 7 6 5 4 3 2 1 0 v4*n 9 8 1 0 32b elements v4*n+1 B A 3 2 v4*n+2 D C 5 4 v4*n+3 F E 7 6 例4: VLEN=128b, SLEN=128b, SEW=32b, LMUL=4 Byte F E D C B A 9 8 7 6 5 4 3 2 1 0 v4*n 3 2 1 0 32b elements v4*n+1 7 6 5 4 v4*n+2 B A 9 8 v4*n+3 F E D C 例5: VLEN=256b, SLEN=128b, SEW=32b, LMUL=4 Byte 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 v4*n 13 12 11 10 3 2 1 0 v4*n+1 17 16 15 14 7 6 5 4 v4*n+2 1B 1A 19 18 B A 9 8 v4*n+3 1F 1E 1D 1C F E D C 例6: VLEN=256b, SLEN=128b, SEW=256b, LMUL=4 Byte 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 v4*n 0 v4*n+1 1 v4*n+2 2 v4*n+3 3 似たようなパタンで、LMUL=8の場合である。 :: 例: VLEN=256b, SLEN=128b, SEW=32b, LMUL=8 Byte 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 v8*n 23 22 21 20 3 2 1 0 v8*n+1 27 26 25 24 7 6 5 4 v8*n+2 2B 2A 29 28 B A 9 8 v8*n+3 2F 2E 2D 2C F E D C v8*n+4 33 32 31 30 13 12 11 10 v8*n+5 37 36 35 34 17 16 15 14 v8*n+6 3B 3A 39 38 1B 1A 19 18 v8*n+7 3F 3E 3D 3C 1F 1E 1D 1C アーキテクチャ上はさまざまなストライピングパターンが表示されるが、ストライピングパターンに関係なく同じ結果を生成するソフトウェアを作成できる。 主な制約は、ベクトルレジスタグループに保持されている値にアクセスするために使用されるLMULを変更しないことである(つまり、グループに値を書き込むために使用されるものとは異なるLMULで値を読み取らない)。 実装のストライピング長SLENは、幅が広いユニットのストライドメモリアクセスをベクターレジスタファイルの並列アクセスにコーナーターンするために必要な、幅の異なる操作のデータパス配線とバッファリングのトレードオフを最適化するように設定される。 .. 以前の明示的なコンフィグレーションデザインでは、これらのトレードオフをマイクロアーキテクチャレベルで管理し、構成ごとに最適化することができた。 4.3. Mixed-Width演算へのマッピング ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ベクトルレジスタグループ内の要素をマップするために使用されるパターンは、複数の要素幅にわたる操作をサポートするときにデータパスの配線を減らすように設計されている。 この場合の推奨されているソフトウェア戦略は、 ``vtype``\ を動的に変更して、SEW / LMULを一定に(つまりVLMAXを一定に)維持することである。 次の例は、VLEN=256b / SLEN=128bの実装における4つの異なるパッキング要素の幅(8b,16b,32b,64b)を示している。 ベクトルレジスタグループ化係数(LMUL)は、各要素が同じ数のベクトル要素(この例では32)を保持できるように相対的な要素サイズによって増加し、ストリップマイニングコードを簡素化する。 同じインデックスを持つ要素間の操作は、データパスの同じ128b部分にあるオペランドビットにのみ影響する。 :: VLEN=256b, SLEN=128b Byte 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 SEW=8b, LMUL=1, VLMAX=32 v1 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 SEW=16b, LMUL=2, VLMAX=32 v2*n 17 16 15 14 13 12 11 10 7 6 5 4 3 2 1 0 v2*n+1 1F 1E 1D 1C 1B 1A 19 18 F E D C B A 9 8 SEW=32b, LMUL=4, VLMAX=32 v4*n 13 12 11 10 3 2 1 0 v4*n+1 17 16 15 14 7 6 5 4 v4*n+2 1B 1A 19 18 B A 9 8 v4*n+3 1F 1E 1D 1C F E D C SEW=64b, LMUL=8, VLMAX=32 v8*n 11 10 1 0 v8*n+1 13 12 3 2 v8*n+2 15 14 5 4 v8*n+3 17 16 7 6 v8*n+4 19 18 9 8 v8*n+5 1B 1A B A v8*n+6 1D 1C D C v8*n+7 1F 1E F E LMULに大きな値を設定することは、論理的なベクトルレジスタ長を削減しなければならないときに、単純にベクトル長を増加させ、命令フェッチ幅を削減し、ディスパッチのオーバヘッドを削減するために役に立つ。 以下の表は、混合幅動作について、可能なSEW/LMULの動作ポイントについて示している。 :: 横軸はLMULの値を示し、各軸はSEW/MULの動作ポイントを示している。 SEW/LMUL 1 2 4 8 16 32 64 128 256 512 1024 SEW 8 8 4 2 1 16 8 4 2 1 32 8 4 2 1 64 8 4 2 1 128 8 4 2 1 256 8 4 2 1 512 8 4 2 1 1024 8 4 2 1 .. SLENが空間データパス幅よりも小さい場合、LMUL値を大きくすると、短いベクトルのデータパス使用率が低くなる。 VLEN=256b、SLEN=128b、およびLMUL=8を使用した上記の例では、実装が256b幅のベクトルデータパスを持つ純粋な空間である場合、アプリケーションベクトル長が17未満の場合、データパスの半分のみがアクティブになる。 以下の「vsetvl」命令には、必要なアプリケーションベクトル長(AVL)と要素幅の範囲に従って適切なLMULを動的に選択する機能を追加できる。 狭いマシンでは、SLENが少なくともデータパスの空間幅と同じ大きさに設定されるため、LMULを減らす必要ない。 幅の広いマシンでは、SLENを空間データパスの幅よりも小さく設定して、幅が混在する操作(例えば、width=1024、ELEN=32、SLEN=128)の配線を減らすことができる。 4.4. マスクレジスタのレイアウト ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ベクトルのマスクは、SEWとLMULの値に関係なく1つのベクトルレジスタにのみ適用される。各ベクトル操作に使用されるマスクビットは現在のSEWとLMUL設定に依存する。 ベクトルオペランドの最大エレメント長は以下になる。 :: VLMAX = LMUL * VLEN/SEW マスクは、マスクレジスタをVLEN/LVMAXフィールドで分割することにより各エレメントに割り当てられる。各マスクエレメントのサイズ\ **MLEN**\ は以下で計算できる。 :: MLEN = VLEN/VLMAX = VLEN/(LMUL * VLEN/SEW) = SEW/LMUL MLENはELEN(SEW=ELEN, LMUL=1)から1(SEW=8b, LMUL=8)までの値を取ることができ、したがって単一のベクトルレジスタは常に全体のマスクレジスタを保持することができる。 マスクビットの要素\ *i*\ はマスクレジスタのビット\ ``[MLEN*i+(MLEN-1):MLEN*i]``\ である。比較命令によりマスクの要素に書き込みが行われた場合、マスクの要素の再開ビットに比較結果が書き込まれ、上位ビットはゼロが設定される。現在のベクトル長の長さよりも先のマスク要素は変更されない。現在のベクトル長その値がマスクとして読みだされた場合、マスク要素の最下位ビットのみがコントロールマスクとして使用され、上位のビットは無視される。現在のベクトル長を超えるマスク要素はゼロとなる。 パターンは、一定のSEW/LMUL値の場合、有効なプレディケートビットがマスクベクトルレジスタの同じビットに配置されるため、幅の異なる要素を含むループでのマスキングの使用が簡単になる。 :: VLEN=32b Byte 3 2 1 0 LMUL=1,SEW=8b 3 2 1 0 Element [24][16][08][00] Mask bit position in decimal LMUL=2,SEW=16b 1 0 [08] [00] 3 2 [24] [16] LMUL=4,SEW=32b 0 [00] 1 [08] 2 [16] 3 [24] :: LMUL=2,SEW=8b 3 2 1 0 [12][08][04][00] 7 6 5 4 [28][24][20][16] LMUL=8,SEW=32b 0 [00] 1 [04] 2 [08] 3 [12] 4 [16] 5 [20] 6 [24] 7 [28] LMUL=8,SEW=8b 3 2 1 0 [03][02][01][00] 7 6 5 4 [07][06][05][04] B A 9 8 [11][10][09][08] F E D C [15][14][13][12] 13 12 11 10 [19][18][17][16] 17 16 15 14 [23][22][21][20] 1B 1A 19 18 [27][26][25][24] 1F 1E 1D 1C [31][30][29][28] :: VLEN=256b, SLEN=128b Byte 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 SEW=8b, LMUL=1, VLMAX=32 v1 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0 [248] ... [128] ...[96] ...[64] ...[32] ... [0] Mask bit positions in decimal SEW=16b, LMUL=2, VLMAX=32 v2*n 17 16 15 14 13 12 11 10 7 6 5 4 3 2 1 0 [184] ... [128] ... [32] ... [0] v2*n+1 1F 1E 1D 1C 1B 1A 19 18 F E D C B A 9 8 [248] ... [196] ... [96] ... [64] SEW=32b, LMUL=4, VLMAX=32 v4*n 13 12 11 10 3 2 1 0 [152] ... [128] [24] ... [0] v4*n+1 17 16 15 14 7 6 5 4 [184] ... [160] [56] ... [32] v4*n+2 1B 1A 19 18 B A 9 8 [116] ... [192] [88] ... [64] v4*n+3 1F 1E 1D 1C F E D C [248] ... [224] [120] ... [96] SEW=64b, LMUL=8, VLMAX=32 v8*n 11 10 1 0 [136] [128] [8] [0] v8*n+1 13 12 3 2 [152] [144] [24] [16] v8*n+2 15 14 5 4 [168] [160] [40] [32] v8*n+3 17 16 7 6 [184] [176] [56] [48] v8*n+4 19 18 9 8 [200] [192] [72] [64] v8*n+5 1B 1A B A [216] [208] [88] [80] v8*n+6 1D 1C D C [232] [224] [104] [96] v8*n+7 1F 1E F E [248] [240] [120] [112]