RISC-Vのベクトル命令には、浮動小数点におけるWideningとNarrowingというものがある。
Wideningは、浮動小数点の演算実行時に、データ型を拡張して計算するものであり、一方でNarrowingは、データ型を縮小して計算する。 例えば、SEW=32(FP32)ならば、演算実行前(あるいは実行後)にデータ幅をFP64に拡張させてから実行する。 一方で、NarrowingはSEW=64ならば、演算実行前(あるいは実行後)にデータ幅をFP32に縮小する。
# Double-width result, two single-width sources: 2*SEW = SEW op SEW vwop.vv vd, vs2, vs1, vm # integer vector-vector vd[i] = vs2[i] op vs1[i] vwop.vx vd, vs2, rs1, vm # integer vector-scalar vd[i] = vs2[i] op x[rs1] # Double-width result, first source double-width, second source single-width: 2*SEW = 2*SEW op SEW vwop.wv vd, vs2, vs1, vm # integer vector-vector vd[i] = vs2[i] op vs1[i] vwop.wx vd, vs2, rs1, vm # integer vector-scalar vd[i] = vs2[i] op x[rs1]
つまり、入力するオペランドのサイズと出力するオペランドのサイズが違うため、レジスタのサイズに合わせてパイプラインの制御を調整する必要がある。結構面倒くさい。
// vfwadd.vv vd, vs2, vs1 VI_VFP_VV_LOOP_WIDE ({ vd = f32_add(vs2, vs1); }, { vd = f64_add(vs2, vs1); })
// vfwadd.wv vd, vs2, vs1 VI_VFP_WV_LOOP_WIDE ({ vd = f32_add(vs2, vs1); }, { vd = f64_add(vs2, vs1); })
つまり、LMUL=xで実行開始しても、レジスタの書き込みはLMUL=2xのつもりで書きこまなければならない。VLEN=512, DLEN=128の場合、パイプラインイメージとしては以下のようになるか? 命令の発行は、1サイクルずつ空けながら、2回レジスタに書き込む余裕を持たせる必要がありそうだ。
1オペランドだけLMUL=2xのつもりでレジスタを読まなければならないのも、同じようなパイプラインの制御で行けるかな。