FPGA開発日記

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

自作CPUにベクトル命令を追加する実装検討 (20. LMUL>1への対応実装)

ベクトル命令における、LMUL>1の対応というのは結構難易度の高い問題だ。

今回はその解決方法として、LMULの値がVSETVL命令で変更されると、例外を出して物理レジスタの構成を整列し直す方式を考えたい。

ここでは、Spikeの実装のみを示すが、同様にハードウェア側も実装を変更する。

まず、現在のLMULとVSETVL命令で設定されたLMULが異なると、例外を発生させる。

require_vector_novtype(false, false);
float old_vflmul = P.VU.vflmul;
WRITE_RD(P.VU.set_vl(insn.rd(), insn.rs1(), RS1, insn.v_zimm11()));
if (old_vflmul != P.VU.vflmul) {
  throw trap_lmul_change();
}

例外が設定されると、PCを更新して特別な例外ルーティングに移動するようにする。

  if (t.cause() == CAUSE_LMUL_CHANGE) {
    fprintf(log_file, "detect lmul change\n");
    state.pc = 0x2000;
    return;
  }

例外ルーティンの入っている領域はSpikeのモジュール接続を使用し、メモリを接続する。ここには、ベクトルレジスタをすべてストアして、ロードし直すルーティンが含まれている。

class lmul_change_rom_t : public abstract_device_t {
  FILE *lmul_change_log_fp;
  char ram[0x1000];
 public:
  lmul_change_rom_t(std::string name);
  bool load(reg_t addr, size_t len, uint8_t* bytes);
  bool store(reg_t addr, size_t len, const uint8_t* bytes);
 private:
  uint8_t DATA[1024] =
  {
#include "lmul_exc_rom.txt"
  };
};
    .section    .text
    csrrw   sp, sscratch, sp
    la      sp, temp_data
    sd      x10, 0(sp)
    sd      x11, 8(sp)
    la      x10, vector_stack_data
    csrr    x11, vlenb
    vs1r.v v0 , (x10); add   x10, x10, x11
    vs1r.v v1 , (x10); add   x10, x10, x11
    vs1r.v v2 , (x10); add   x10, x10, x11
    vs1r.v v3 , (x10); add   x10, x10, x11
    vs1r.v v4 , (x10); add   x10, x10, x11
...
    vs1r.v v30, (x10); add   x10, x10, x11
    vs1r.v v31, (x10); add   x10, x10, x11

    la      x10, vector_stack_data
    vl1r.v v0 , (x10); add   x10, x10, x11
    vl1r.v v1 , (x10); add   x10, x10, x11
    vl1r.v v30, (x10); add   x10, x10, x11
    vl1r.v v31, (x10); add   x10, x10, x11

    ld      x10, 0(sp)
    ld      x11, 8(sp)
    csrrw   sp, sscratch, sp

まだ物理レジスタのソーティングの機能を持たせてはいないが、ISS側ではとりあえずちゃんと動いてはいるようだ。次はハードウェア側の調整だ。