FPGA開発日記

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

RISC-V SpikeシミュレータでC/C++のprintfを実現する仕組み (10. 自作RISC-VシミュレータでBBLとvmlinuxを起動する)

UCBが開発しているRISC-VのシミュレータSpikeや、Rocket-ChipのRTLデザインは通常はシステムコールを持っていない。 つまり、当然ながらC言語printf("Hello World\n");などと書いても動作しないのだが、そこはコンパイラとフロントエンドサーバfesvr、pk(Proxy Kernel)によって肩代わりすることでこれらのシステムコールを実現している。

RISC-VのシミュレータであるSpikeでは、これらのシステムコールとUARTによるコンソールを実現しており、これを移植して自作RISC-Vシミュレータで動作させると、Linuxのブートができるはずだ。 やってみよう。

f:id:msyksphinz:20180803003601p:plain

RISC-Vの外にあるホストインタフェースに、システムコールのポートと、コンソールのポートを追加した。

どちらのポートを使うかは、THOSTインタフェースに入力されるデバイス番号で識別するようにする。

以下のような感じでデバイスを追加できる

class RiscvDeviceList_t
{
 private:
  std::vector<RiscvDevice_t*> m_devices;
...
  void RegisterDevice (RiscvDevice_t* dev) {
    m_devices.push_back(dev);
  }

  void HandleCommand (UDWord_t cmd) {
    m_devices[device(cmd)]->HandleCommand(cmd);
  }

システムコールを処理するインタフェースと、BCD(コンソールインタフェース)を追加した。

RiscvPeThread::RiscvPeThread (FILE *dbgfp,
                              RiscvBitMode_t bit_mode,
                              PrivMode maxpriv,
                              bool en_stop_host,
...
  m_device_list = new RiscvDeviceList_t();
  RiscvSyscall_t *riscv_syscall = new RiscvSyscall_t(this);
  m_device_list->RegisterDevice(riscv_syscall);  // Device List = 0

  RiscvTerm_t *riscv_term = new RiscvTerm_t ();
  m_device_list->RegisterDevice(riscv_term);     // Device List = 1
...

RISC-VのBBLとvmlinuxを作成し、シミュレータで実行した。 ここまでで、どうにか最初のスプラッシュ画面と、vmlinuxの最初の方までは動作するようになってきた。

ただし、途中で止まってしまうので解析しなければ...

f:id:msyksphinz:20180803004230g:plain
f:id:msyksphinz:20180803004425p:plain