FPGA開発日記

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

RISC-Vベクトル拡張を使ったサンプルプログラムの確認 (その他のサンプルプログラムについて)

RISC-Vのベクトル拡張について、いくつかのサンプルプログラムを用いて使い方を見ていく。 memcpystrlenについて見たので、これ以外のサンプルについて確認する。

まずはsaxpyこれは単純に2つの配列のうち、一つの配列に対して定数を掛け合わしてもう一つの配列の値を足し込んでいくもの。

void
saxpy(size_t n, const float a, const float *x, float *y)
{
  size_t i;
  for (i=0; i<n; i++)
    y[i] = a * x[i] + y[i];
}

riscv-v-spec/saxpy.s at master · riscv/riscv-v-spec · GitHub

これをベクトルで実装したものが以下。LMUL=8となっているので、v0からv7までに最初の配列、v8からv15までに次の配列をロードし、vfmacc.vfで一気に乗算加算しているところがポイント。 そして最後にvse32v8からv15までに格納されている値を一気にストアする。

saxpy:
    vsetvli a4, a0, e32, m8, ta, ma
    vle32.v v0, (a1)
    sub a0, a0, a4
    slli a4, a4, 2
    add a1, a1, a4
    vle32.v v8, (a2)
    vfmacc.vf v8, fa0, v0
    vse32.v v8, (a2)
    add a2, a2, a4
    bnez a0, saxpy
    ret

次にstrcpyの実装。memcpyとは異なり、文字列がコピー対象となっているからか、定数メモリ領域が指定されていることを前提として安全のためにvle8ff.vを使用して実装してある。それ以外はstrlen()とよく似ている。

github.com

strcpy:
      mv a2, a0             # Copy dst
      li t0, -1             # Infinite AVL
loop:
    vsetvli x0, t0, e8, m8, ta, ma  # Max length vectors of bytes
    vle8ff.v v8, (a1)        # Get src bytes
      csrr t1, vl           # Get number of bytes fetched
    vmseq.vi v1, v8, 0      # Flag zero bytes
    vfirst.m a3, v1         # Zero found?
      add a1, a1, t1        # Bump pointer
    vmsif.m v0, v1          # Set mask up to and including zero byte.
    vse8.v v8, (a2), v0.t    # Write out bytes
      add a2, a2, t1        # Bump pointer
      bltz a3, loop         # Zero byte not found, so loop

      ret