FPGA開発日記

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

Chiselを使ってCPUを作ろう(11. 例外やシステムコールでのCSRの取り扱いなど)

Chiselを使って、非常にシンプルなCPUを作ってみるプロジェクト。テストパタンを動かすためには、CSRレジスタを扱えければならないのと、Ecallなどの例外を扱う命令が実行できなければならない。

Ecallは、例外を発生させ例外コードをmcauseに書き込み、mtvecに格納されているPC位置までジャンプする。 mcauseへの書き込みと、mtvecの読み込みとPC更新ができればよいわけだ。

f:id:msyksphinz:20181123005953p:plain

CSRへの書き込みを実行するのは以下のコードとなる。

  when(io.ecall_inst) {
    reg_mcause := Causes.UserEcall.U
  } .elsewhen (decoded_addr(CsrAddr.mcause)) {
    reg_mcause := wdata & ((BigInt(1) << (63)) + 31).U /* only implement 5 LSBs and MSB */
  }

Ecall命令を実行すると、mtvecの値に従ってPCを変更し、mcauseに値を設定する。

  if_inst_addr := MuxCase (0.U, Array (
    (if_inst_en & dec_jalr_en) -> dec_reg_op0.asUInt,
    (if_inst_en & dec_jal_en)  -> (dec_inst_addr + dec_imm_j),
    (if_inst_en & dec_br_en)   -> (dec_inst_addr + dec_imm_b_sext),
    (if_inst_en & dec_mret_en) -> u_csrfile.io.mepc,
    (if_inst_en & dec_ecall_en)-> u_csrfile.io.mtvec,
    (if_inst_en & io.inst_bus.ack) -> (if_inst_addr + 4.U)
  ))

これで、Ecallでジャンプして、CSRを制御できるようになった。