FPGA開発日記

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

Freechips Project Rocket-Core と SiFive Freedom E300 Everywhere Rocket-Core のブートシーケンス

RISC-Vの実装であるRocket-Chipは、RISC-Vの最新使用に追従しているため最初に見るべきデザインとしてはよくできているが、

  • Chiselで記述されており(初心者には)可読性が低い。
  • 外部のSoCプラットフォームについて情報がない

ことから、なかなかオリジナルのSoCをくみ上げるためのデザインとしてポーティングしにくい。

とはいえ、TileLinkは単なるバスのはずだし、クロックとリセットさえ突っ込めばとりあえずフェッチリクエストが上がってくるはずだ。 そのあたりを解析して、Rocket-Chipを利用したオリジナルSoCプラットフォーム構築のための情報収集を行っていこう。

f:id:msyksphinz:20180211025506p:plain
図. とりあえず実現したいRISC-V SoCブロック。まずはQSPIを取り除いて、だれでもアクセスできるTestRAMを接続したい。

SiFive の Freedom SoCとFreechips ProjectのRocket Chipのブート時の挙動を解析しているのだが、どうも理解できないところが多い。

FreeChips ProjectのRocket Coreが生成しているログ

FreeChips ProjectがRocket CoreのVerilog記述だけを抜き出して、TestBenchを被せてRTLシミュレーションを実行してみた。 最初の20命令を抜き出して、どのような命令を実行しているのかをチェックする。

C0:         42 [1] pc=[0000000800] W[r 0=0000000000000804][1] R[r 0=0000000000000000] R[r12=d72473afd72473af] inst=[00c0006f] j       pc + 0xc
C0:         44 [1] pc=[000000080c] W[r 0=0000000000000004][0] R[r 0=0000000000000000] R[r31=d72473afd72473af] inst=[0ff0000f] fence
C0:         45 [1] pc=[0000000810] W[r 0=515059a2515059a2][1] R[r 8=9178322291783222] R[r18=d72473afd72473af] inst=[7b241073] csrw    dscratch, s0
C0:         50 [1] pc=[0000000814] W[r 8=0000000000000000][1] R[r 0=0000000000000000] R[r20=d72473afd72473af] inst=[f1402473] csrr    s0, mhartid
C0:         68 [1] pc=[0000000818] W[r 0=0000000000000100][0] R[r 0=0000000000000000] R[r 8=0000000000000000] inst=[10802023] sw      s0, 256(zero)
C0:         79 [1] pc=[000000081c] W[r 0=0000000000000400][1] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu     s0, 1024(s0)
C0:         86 [0] pc=[000000081c] W[r 8=0000000000000000][1] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu     s0, 1024(s0)
C0:         89 [1] pc=[0000000820] W[r 8=0000000000000000][1] R[r 8=0000000000000000] R[r 1=0000000000000003] inst=[00147413] andi    s0, s0, 1
C0:         90 [1] pc=[0000000824] W[r 0=0000000000000000][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[02041063] bnez    s0, pc + 32
C0:         94 [1] pc=[0000000828] W[r 8=0000000000000000][1] R[r 0=0000000000000000] R[r20=0000000000000003] inst=[f1402473] csrr    s0, mhartid
C0:         97 [1] pc=[000000082c] W[r 0=0000000000000400][1] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu     s0, 1024(s0)
C0:        104 [0] pc=[000000082c] W[r 8=0000000000000000][1] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu     s0, 1024(s0)
C0:        107 [1] pc=[0000000830] W[r 8=0000000000000000][1] R[r 8=0000000000000000] R[r 2=0000000000000003] inst=[00247413] andi    s0, s0, 2
C0:        108 [1] pc=[0000000834] W[r 0=0000000000000000][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[fc0418e3] bnez    s0, pc - 48
C0:        112 [1] pc=[0000000838] W[r 0=000000000000083c][1] R[r31=0000000000000003] R[r29=0000000000000003] inst=[fddff06f] j       pc - 0x24
C0:        114 [1] pc=[0000000814] W[r 8=0000000000000000][1] R[r 0=0000000000000000] R[r20=0000000000000003] inst=[f1402473] csrr    s0, mhartid
C0:        117 [1] pc=[0000000818] W[r 0=0000000000000100][0] R[r 0=0000000000000000] R[r 8=0000000000000000] inst=[10802023] sw      s0, 256(zero)
C0:        128 [1] pc=[000000081c] W[r 0=0000000000000400][1] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu     s0, 1024(s0)
C0:        135 [0] pc=[000000081c] W[r 8=0000000000000000][1] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu     s0, 1024(s0)
C0:        138 [1] pc=[0000000820] W[r 8=0000000000000000][1] R[r 8=0000000000000000] R[r 1=0000000000000003] inst=[00147413] andi    s0, s0, 1

Freedom E300 Everywhere の Rocket Coreが生成しているログ

一方で、Freedom E300 Everywhere の Verilog記述だけを抜き出して、TestBenchを被せてRTLシミュレーションを実行してみた。 最初の命令群を抜き出して、どのような命令を実行しているのかチェックする。

C0:         31 [1] pc=[00010000] W[r10=00000000][1] R[r 0=00000000] R[r20=e4a715cb] inst=[f1402573] csrr    a0, mhartid
C0:         34 [1] pc=[00010004] W[r10=20000000][1] R[r 0=00000000] R[r 0=00000000] inst=[20000537] lui     a0, 0x20000
C0:        260 [1] pc=[00010008] W[r 0=20000020][1] R[r10=20000000] R[r 0=00000000] inst=[02052283] lw      t0, 32(a0)
C0:        261 [1] pc=[0001000c] W[r 0=00000000][1] R[r 0=00000000] R[r 0=00000000] inst=[00000013] nop
C0:        262 [1] pc=[00010010] W[r 0=00000000][1] R[r 0=00000000] R[r 0=00000000] inst=[00000013] nop
C0:        263 [1] pc=[00010014] W[r 0=00000000][1] R[r 0=00000000] R[r 0=00000000] inst=[00000013] nop
C0:        264 [1] pc=[00010018] W[r 0=00000000][1] R[r 0=00000000] R[r 0=00000000] inst=[00000013] nop
C0:        265 [1] pc=[0001001c] W[r 0=00000000][1] R[r 0=00000000] R[r 0=00000000] inst=[00000013] nop
C0:        266 [1] pc=[00010020] W[r 0=00000000][1] R[r 0=00000000] R[r 0=00000000] inst=[00000013] nop
C0:        267 [1] pc=[00010024] W[r 0=00000000][1] R[r 0=00000000] R[r 0=00000000] inst=[00000013] nop
C0:        268 [0] pc=[00010028] W[r 5=00c6cf01][1] R[r 0=00000000] R[r 0=00000000] inst=[00000013] nop
C0:        273 [1] pc=[00010028] W[r 0=00000000][1] R[r 0=00000000] R[r 0=00000000] inst=[00000013] nop
C0:        274 [1] pc=[0001002c] W[r 5=deadc000][1] R[r27=20000003] R[r10=e4a715cb] inst=[deadc2b7] lui     t0, 0xdeadc
C0:        275 [1] pc=[00010030] W[r 5=deadbeef][1] R[r 5=deadc000] R[r15=e4a715cb] inst=[eef28293] addi    t0, t0, -273
C0:        276 [1] pc=[00010034] W[r 0=20000000][0] R[r10=20000000] R[r 5=deadbeef] inst=[00552023] sw      t0, 0(a0)
C0:        287 [1] pc=[00010038] W[r 0=20000004][0] R[r10=20000000] R[r 5=deadbeef] inst=[00552223] sw      t0, 4(a0)
C0:        298 [1] pc=[0001003c] W[r 0=20000008][0] R[r10=20000000] R[r 5=deadbeef] inst=[00552423] sw      t0, 8(a0)
C0:        319 [1] pc=[00010040] W[r11=00010040][1] R[r 0=00000000] R[r 0=00000000] inst=[00000597] auipc   a1, 0x0
C0:        320 [1] pc=[00010044] W[r11=00010050][1] R[r11=00010040] R[r16=deadbeef] inst=[01058593] addi    a1, a1, 16
C0:        321 [1] pc=[00010048] W[r 5=40000000][1] R[r 0=00000000] R[r 0=00000000] inst=[400002b7] lui     t0, 0x40000
C0:        322 [1] pc=[0001004c] W[r 0=00010050][1] R[r 5=40000000] R[r 0=00000000] inst=[00028067] jr      t0

根本的に異なるのは、ブートアドレスが

  • Freechips Project Rocket-Core : PC=0x00000800 (デバッグモジュール)
  • SiFive Freedom E300 Everywhere : PC=0x00010000 (BootROM)

となっており、同じコアを使っているのになぜかスタートアドレスが異なるという事態になっている。

そもそも、何故このような違いが発生するのだろうか?

Freechips Project Rocket-Core のリセット後の挙動

Freechips Project の Rocket Coreは、リセット直後にTileLinkからフェッチが入っており、 0x10040 という不思議なアドレスからフェッチが入っている。

f:id:msyksphinz:20180217224105p:plain
図. Freechips Project Rocket Coreの最初のブートの様子。0x10040という不思議なアドレスからBootROMへの命令フェッチが入っている。

何故だろうと解析をしていったのだが、これはどうもBootROMのhangアドレスによって決められているようだ。やはり、最初にBootROMへのフェッチが入っているのは間違いなさそう。

/** Size, location and contents of the boot rom. */
case class BootROMParams(
  address: BigInt = 0x10000,
  size: Int = 0x10000,
  hang: BigInt = 0x10040,
  contentFileName: String)
case object BootROMParams extends Field[BootROMParams]
0000000000010040 <_hang>:
   10040:       f1402573                csrr    a0,mhartid
   10044:       00000597                auipc   a1,0x0
   10048:       03c58593                addi    a1,a1,60 # 10080 <_dtb>
   1004c:       10500073                wfi
   10050:       bff5                    j       1004c <_hang+0xc>

f:id:msyksphinz:20180217230714p:plain

ここで、WFI(Wait for Interrupt) が実行され、Interrupt待ちの状態になっているが、Coreに対してio_interrupts_debug信号が既にAssertになっている。 これにより、直ぐにDebug割り込みが入り、0x0000_0800にジャンプしているという訳だ。

一方で、SiFive Freedom E300 EverywhereではデフォルトでDebug InterruptがAssertされていない。これにより、デバッグコードにはジャンプしない。

f:id:msyksphinz:20180217230846p:plain