FPGA開発日記

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

Rocket-ChipとBOOMの環境の違いは何なのか?(1)

f:id:msyksphinz:20171130012507p:plain

UCB(University of California Berkeley)の実装したRISC-Vコアとしては代表的なものが2つあり、1つのリポジトリでブランチが切られている。

github.com

  • Rocket-Chip : masterブランチ
  • BOOM-v1 : boom2ブランチ
  • BOOM-v1 : boom-v1ブランチ

しかしどうもRocket-Chipのシミュレーションを試行していると、Rocket-ChipとBOOMで、異なるriscv-toolsを使わなければならない気がしている。

boom2ブランチでのriscv-toolsサブモジュールでのツールチェインをビルドし、それをRISCV=/home/msyksphinz/riscv64_boom/としてインストールしている。 一方masterブランチでのriscv-toolsサブモジュールでのツールチェインは、RISCV=/home/msyksphinz/riscv64/としてインストールしている。

そして、Rocket-Chipを実行するときはRISCV=/home/msyksphinz/riscv64/, BOOMを実行するときはRISCV=/home/msyksphinz/riscv64_boomを使うなど切り替えるようにして実行している。 この違いは何なのだろう?

例えば、RISCV=/home/msyksphinz/riscv/(Rocket-Chip用にビルドしたツールチェイン)にパスを通してBOOMをシミュレーションすると、なぜか無限ループに陥ってしまう。

  • Rocket-Chip用のriscv-toolsにパスを通した場合のシミュレーションログ
C0:         24 [0] pc=[0000001000] W[r 0=0000000000001000][0] R[r 0=3ef5069c0fbbdc7f] R[r 0=664f9c28ef95a723] inst=[0000006f] j       pc + 0x0
C0:         25 [0] pc=[0000001000] W[r 0=0000000000001000][0] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[0000006f] j       pc + 0x0
C0:         26 [0] pc=[0000001000] W[r 0=0000000000001000][0] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[0000006f] j       pc + 0x0
C0:         27 [0] pc=[0000001000] W[r 0=0000000000001000][0] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[0000006f] j       pc + 0x0
C0:         28 [1] pc=[0000001000] W[r 0=0000000000001004][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[0000006f] j       pc + 0x0
C0:         29 [1] pc=[0000001000] W[r 0=0000000000001004][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[0000006f] j       pc + 0x0
C0:         30 [1] pc=[0000001000] W[r 0=0000000000001004][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[0000006f] j       pc + 0x0
C0:         31 [1] pc=[0000001000] W[r 0=0000000000001004][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[0000006f] j       pc + 0x0
C0:         32 [1] pc=[0000001000] W[r 0=0000000000001004][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[0000006f] j       pc + 0x0
  • BOOM用のriscv-toolsにパスを通した場合のシミュレーションログ
C0:      17348 [1] pc=[0080000144] W[r29=00000000000007ff][1] R[r 0=0000000000000000] R[r31=0000000000000003] inst=[7ff00e93] li      t4, 2047
C0:      17349 [1] pc=[0080000148] W[r28=0000000000000008][1] R[r 0=0000000000000000] R[r 8=0000000000000003] inst=[00800e13] li      t3, 8
C0:      17350 [1] pc=[008000014c] W[r 0=0000000000000000][0] R[r 3=00000000000007ff] R[r29=00000000000007ff] inst=[21d19263] bne     gp, t4, pc + 516
C0:      17351 [1] pc=[0080000150] W[r 1=ffffffff80000000][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[800000b7] lui     ra, 0x80000
C0:      17352 [1] pc=[0080000154] W[r 1=000000007fffffff][1] R[r 1=ffffffff80000000] R[r31=0000000000000003] inst=[fff0809b] addiw   ra, ra, -1
C0:      17353 [1] pc=[0080000158] W[r 3=000000007fffffff][1] R[r 1=000000007fffffff] R[r 0=0000000000000000] inst=[00008193] mv      gp, ra
C0:      17354 [1] pc=[008000015c] W[r29=ffffffff80000000][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[80000eb7] lui     t4, 0x80000
C0:      17355 [1] pc=[0080000160] W[r29=000000007fffffff][1] R[r29=ffffffff80000000] R[r31=0000000000000003] inst=[fffe8e9b] addiw   t4, t4, -1
C0:      17356 [1] pc=[0080000164] W[r28=0000000000000009][1] R[r 0=0000000000000000] R[r 9=0000000000000003] inst=[00900e13] li      t3, 9
C0:      17357 [1] pc=[0080000168] W[r 0=0000000000000000][0] R[r 3=000000007fffffff] R[r29=000000007fffffff] inst=[1fd19463] bne     gp, t4, pc + 488
C0:      17358 [1] pc=[008000016c] W[r 1=ffffffff80000000][1] R[r 0=0000000000000000] R[r 0=0000000000000000] inst=[800000b7] lui     ra, 0x80000
C0:      17359 [1] pc=[0080000170] W[r 1=000000007fffffff][1] R[r 1=ffffffff80000000] R[r31=0000000000000003] inst=[fff0809b] addiw   ra, ra, -1
C0:      17360 [1] pc=[0080000174] W[r 3=00000000800007fe][1] R[r 1=000000007fffffff] R[r31=0000000000000003] inst=[7ff08193] addi    gp, ra, 2047

module switch riscv/riscv64 を設定してBOOMを実行する。

RISCV=/home/msyksphinz/riscv64/ make && make output/rv64ui-p-addi.out で実行する。

C0:          0 [0] pc=[0000001000] W[r 0=0000000000000000][0] R[r23=260bcc317122ae33] R[r31=10b4a6fd8b9b6017] inst=[e3fbf3fb] custom3.rd.rs1.rs2 (args unknown)
C0:          1 [0] pc=[0000001000] W[r 0=0000000000000000][0] R[r23=260bcc317122ae33] R[r31=10b4a6fd8b9b6017] inst=[e3fbf3fb] custom3.rd.rs1.rs2 (args unknown)
C0:          2 [0] pc=[0000001000] W[r 0=0000000000000000][0] R[r23=260bcc317122ae33] R[r31=10b4a6fd8b9b6017] inst=[e3fbf3fb] custom3.rd.rs1.rs2 (args unknown)
C0:          3 [0] pc=[0000001000] W[r 0=0000000000000000][0] R[r23=260bcc317122ae33] R[r31=10b4a6fd8b9b6017] inst=[e3fbf3fb] custom3.rd.rs1.rs2 (args unknown)
C0:          4 [0] pc=[0000001000] W[r 0=0000000000000000][0] R[r23=260bcc317122ae33] R[r31=10b4a6fd8b9b6017] inst=[e3fbf3fb] custom3.rd.rs1.rs2 (args unknown)
emulator-Top-DefaultConfig: ../fesvr/dtm.cc:556: void dtm_t::producer_thread(): Assertion `get_field(hartinfo, DMI_HARTINFO_NSCRATCH) > 0' failed.

fesvr(RISC-V Front-End Server)の実装の違いが原因っぽい。

Rocket-Chipが立ち上がる仕組み

本ブログでも何度か開設したが、Rocket-Chipの立ち上がりは、TsetHarness内に含まれるSimDTM.vにより管理されている。

emulator/generated_src/freechips.rocketchip.system.DefaultConfig.v

module TestHarness(
  input   clock,
  input   reset,
  output  io_success
);
  wire  ExampleRocketSystem_clock;
...
  SimDTM SimDTM (
    .exit(SimDTM_exit),
    .debug_req_ready(SimDTM_debug_req_ready),
    .debug_req_valid(SimDTM_debug_req_valid),
...

SimDTMはvsrc/SimDTM.vで定義されており、これは内部でC++で記述されているdtm_tで記述されている。 vsrc/SimDTM.v

module SimDTM(
  input clk,
  input reset,

  output        debug_req_valid,
...
    else
    begin
      __exit = debug_tick(
        __debug_req_valid,
        __debug_req_ready,
        __debug_req_bits_addr,
        __debug_req_bits_op,
        __debug_req_bits_data,

csrc/SimDTM.cc

extern "C" int debug_tick
(
  unsigned char* debug_req_valid,
  unsigned char  debug_req_ready,
  int*           debug_req_bits_addr,
  int*           debug_req_bits_op,
...

この時の、スタートアップの方法に違いがあるようだ。 - Rocket-Chipの場合 csrc/dtm.cc

void dtm_t::reset()
{
  for (int hartsel = 0; hartsel < num_harts; hartsel ++ ){
    select_hart(hartsel);
    // this command also does a halt and resume
    fence_i();
    // after this command, the hart will run from _start.
    write_csr(0x7b1, get_entry_point());
  }
  // In theory any hart can handle the memory accesses,
  // this will enforce that hart 0 handles them.
  select_hart(0);
  read(DMI_DMSTATUS);
}
...
void dtm_t::fence_i()
{
  halt(current_hart);

  const uint32_t prog[] = {
    FENCE_I,
    EBREAK
  };

  //TODO: Use the transfer = 0.
  uint32_t command = AC_ACCESS_REGISTER_POSTEXEC |
    AC_ACCESS_REGISTER_TRANSFER |
    AC_ACCESS_REGISTER_WRITE |
    AC_AR_SIZE(xlen) |
    AC_AR_REGNO(X0);

  RUN_AC_OR_DIE(command, prog, sizeof(prog)/sizeof(*prog), 0, 0);

  resume(current_hart);

}
  • BOOMの場合 csrc/dtm.cc
void dtm_t::reset()
{
  fence_i();
  // set pc and un-halt
  write_csr(0x7b1, 0x80000000U);
  clear_csr(0x7b0, 8);
}
...
void dtm_t::fence_i()
{
  const uint32_t prog[] = {
    FENCE_I,
    JUMP(rom_ret(), ram_base() + 4)
  };

  run_program(prog, sizeof(prog)/sizeof(*prog), 0);
}

デバッグレジスタの0x7b1版というのは、DebugPCのこと。Rocket-Chipの場合は、ELFファイルのエントリポイントを直接入れるが、BOOMは律儀に0x8000_0000からブートするという仕組みになっているようだ。

f:id:msyksphinz:20171130005556p:plain ※ riscv-debug-spec-0.13より抜粋。

一方で0x7b0は、Debug Control Statusレジスタなのだが、clear_csr(0x7b0, 8);の8って何だろうなあ。4bit目をクリアしても意味ない気が。。。

f:id:msyksphinz:20171130010602p:plain ※ riscv-debug-spec-0.13より抜粋。

まあとりあえず、このあたりのスタートアップで使用するFront-End Serverの違いにより、いろいろと処理が異なってくるということか。