FPGA開発日記

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

自作CPUにベクトル命令を追加する実装検討 (39. Fixed-Pointベクトル命令セットについて考える)

RISC-VのRVVにはFixed-Point命令セットが含まれており、完全にRVV1.0を名乗るためにはこれらもサポートしなければならない。

12. Vector Fixed-Point Arithmetic Instructions
12.1. Vector Single-Width Saturating Add and Subtract
12.2. Vector Single-Width Averaging Add and Subtract
12.3. Vector Single-Width Fractional Multiply with Rounding and Saturation
12.4. Vector Single-Width Scaling Shift Instructions
12.5. Vector Narrowing Fixed-Point Clip Instructions

Saturating Add and Subtractは、その名の通り加算・減算をした後オーバフローしたときに、最大値または最小値に張り付ける必要がある。

# Saturating adds of unsigned integers. 
vsaddu.vv vd, vs2, vs1, vm   # Vector-vector 
vsaddu.vx vd, vs2, rs1, vm   # vector-scalar 
vsaddu.vi vd, vs2, imm, vm   # vector-immediate 
# Saturating adds of signed integers. 
vsadd.vv vd, vs2, vs1, vm   # Vector-vector 
vsadd.vx vd, vs2, rs1, vm   # vector-scalar 
vsadd.vi vd, vs2, imm, vm   # vector-immediate 
# Saturating subtract of unsigned integers. 
vssubu.vv vd, vs2, vs1, vm   # Vector-vector 
vssubu.vx vd, vs2, rs1, vm   # vector-scalar 
# Saturating subtract of signed integers. 
vssub.vv vd, vs2, vs1, vm   # Vector-vector 
vssub.vx vd, vs2, rs1, vm   # vector-scalar

Averaging Add and Subtractは、演算結果を1ビットシフトしたうえで、vxrmに基づいて値を丸める。

# Averaging add 
# Averaging adds of unsigned integers. 
vaaddu.vv vd, vs2, vs1, vm   # roundoff_unsigned(vs2[i] + vs1[i], 1) 
vaaddu.vx vd, vs2, rs1, vm   # roundoff_unsigned(vs2[i] + x[rs1], 1) 
# Averaging adds of signed integers. 
vaadd.vv vd, vs2, vs1, vm   # roundoff_signed(vs2[i] + vs1[i], 1) 
vaadd.vx vd, vs2, rs1, vm   # roundoff_signed(vs2[i] + x[rs1], 1) 
# Averaging subtract 
# Averaging subtract of unsigned integers. 
vasubu.vv vd, vs2, vs1, vm   # roundoff_unsigned(vs2[i] - vs1[i], 1) 
vasubu.vx vd, vs2, rs1, vm   # roundoff_unsigned(vs2[i] - x[rs1], 1) 
# Averaging subtract of signed integers. 
vasub.vv vd, vs2, vs1, vm   # roundoff_signed(vs2[i] - vs1[i], 1) 
vasub.vx vd, vs2, rs1, vm   # roundoff_signed(vs2[i] - x[rs1], 1)

Fractional Multiply with Rounding and Saturationは、SEW同士の値を乗算して2SEWの積を作り、SEW-1ビットをシフトしたうえでvxrmに基づいて丸める。

# Signed saturating and rounding fractional multiply 
# See vxrm  description for rounding calculation 
vsmul.vv vd, vs2, vs1, vm  # vd[i] = clip(roundoff_signed(vs2[i]*vs1[i], SEW-1)) 
vsmul.vx vd, vs2, rs1, vm  # vd[i] = clip(roundoff_signed(vs2[i]*x[rs1], SEW-1))

Scaling Shift Instructions命令は、入力オペランドを右にシフトしたうえで丸めを行う。

 # Scaling shift right logical 
 vssrl.vv vd, vs2, vs1, vm   # vd[i] = roundoff_unsigned(vs2[i], vs1[i]) 
 vssrl.vx vd, vs2, rs1, vm   # vd[i] = roundoff_unsigned(vs2[i], x[rs1]) 
 vssrl.vi vd, vs2, uimm, vm  # vd[i] = roundoff_unsigned(vs2[i], uimm) 
 # Scaling shift right arithmetic 
 vssra.vv vd, vs2, vs1, vm   # vd[i] = roundoff_signed(vs2[i],vs1[i]) 
 vssra.vx vd, vs2, rs1, vm   # vd[i] = roundoff_signed(vs2[i], x[rs1]) 
 vssra.vi vd, vs2, uimm, vm  # vd[i] = roundoff_signed(vs2[i], uimm)

Narrowing Fixed-Point Clip Instructions は、SEW2の入力データに対してClipingを行い、SEWのサイズに縮退させたうえでレジスタに書き込む。これだけSEW2の対処が必要なため、ちょっと面倒だ。

# Narrowing unsigned clip 
#                                SEW                            2*SEW   SEW 
 vnclipu.wv vd, vs2, vs1, vm  # vd[i] = clip(roundoff_unsigned(vs2[i], vs1[i])) 
 vnclipu.wx vd, vs2, rs1, vm  # vd[i] = clip(roundoff_unsigned(vs2[i], x[rs1])) 
 vnclipu.wi vd, vs2, uimm, vm # vd[i] = clip(roundoff_unsigned(vs2[i], uimm)) 
# Narrowing signed clip 
 vnclip.wv vd, vs2, vs1, vm   # vd[i] = clip(roundoff_signed(vs2[i], vs1[i])) 
 vnclip.wx vd, vs2, rs1, vm   # vd[i] = clip(roundoff_signed(vs2[i], x[rs1])) 
 vnclip.wi vd, vs2, uimm, vm  # vd[i] = clip(roundoff_signed(vs2[i], uimm))