FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages/

SiFiveのFreedom E300 Platformを単体でカスタマイズできるようにする (1. 全体構造からブートROMへのリクエストまでの仕組み)

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

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

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

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

Freedom SoCはRocket-Coreを含むRISC-VのSoCプラットフォームだが、主にコアとなるTile部分と、外部のペリフェラル部分から構成されている。

f:id:msyksphinz:20180209234009p:plain

Freedom E300 システムのソースファイル全体像

Freedom E300システムは、Rocket-Chipと、外部のSoC部に分かれて構成されている。

freedom
src/main/
└── scala
    ├── everywhere
    │   └── e300artydevkit
    └── unleashed
        └── u500vc707devkit
rocket-chip/src/
└── main
    └── scala
        ├── amba
        │   ├── ahb
        │   ├── apb
        │   └── axi4
        ├── config
        ├── coreplex
        ├── devices
        │   ├── debug
        │   └── tilelink
        ├── diplomacy
        ├── groundtest
        ├── interrupts
        ├── jtag
        ├── regmapper
        ├── rocket
        ├── system
        ├── tile
        ├── tilelink
        ├── unittest
        └── util

Freedom E300 Platform のメモリマップ

Freedom E300 Platform は、以下のメモリマップを持っている。 このなかで、最初の0x0000_0000から0x0FFF_FFFFまでは、E3 Coreplex Manualを参照すること、と書いてある通り、こちらに掲載しているのはあくまでもSoCのメモリマップだ。 さらにSoC内部のCoreplex IPについては、E3 Coreplex Manualを参照する必要がある。

f:id:msyksphinz:20180209230017p:plain

f:id:msyksphinz:20180209230427p:plain

といっても、実際にはリセット後にBootROMに命令フェッチが入っており、そちらからジャンプする仕組みなっている。 BootROMには、以下のプログラムがコンパイルされて格納されている。

  .section .text.init
  .option norvc
  .globl _start
_start:
  csrr a0, mhartid
  la a1, dtb
  li t0, XIP_TARGET_ADDR
  jr t0

  .section .rodata
dtb:
  .incbin DEVICE_TREE

XIP_TARGET_ADDRは、以下のコンパイルコマンドで決定されている。

$(elf): xip.S $(dtb)
    $(CC) $(CFLAGS) -DXIP_TARGET_ADDR=0x20400000 -DDEVICE_TREE='"$(dtb)"' $(LFLAGS) -o $@ $<

TARGET_ADDRを見てわかるとおり、まずは0x2040_0000に配置されているQSPIへ命令をフェッチするようになっている。 つまりBootROMのターゲットアドレスを書き換えれば、所望の場所からプログラムをロードしてフェッチできそうな気がしている。

最初にブートするMaskROMは、System.scalaでmaskROMとして定義されている。

  • freedom/src/main/scala/everywhere/e300artydevkit/System.scala
class E300ArtyDevKitSystemModule[+L <: E300ArtyDevKitSystem](_outer: L)
  extends RocketCoreplexModule(_outer)
    with HasPeripheryDebugModuleImp
    with HasPeripheryUARTModuleImp
...
  • freedom/rocket-chip/src/main/scala/devices/tilelink/MaskROM.scala
trait HasPeripheryMaskROMSlave extends HasPeripheryBus {
  val maskROMParams = p(PeripheryMaskROMKey)
  val maskROMs = maskROMParams map { params =>
    val maskROM = LazyModule(new TLMaskROM(params))
    maskROM.node := pbus.toFixedWidthSingleBeatSlave(maskROM.beatBytes)
    maskROM
  }
}

RTLシミュレーション

一応E300 Freedom SoCのVerilogファイルだけ抜き出して適当にテストベンチをつなげ、ClockとResetをつなげてシミュレーションをしてみると、 とりあえずMaskROMへのフェッチが発生しているところまでは確認できる。

BootROMから、QSPIの領域(0x2040_0000)へジャンプしているため、そこからQSPIへのアクセスに移っているようだ。これをDRAMの領域に差し替えて、外部のRAMから命令をフェッチできるようにしてみよう。

f:id:msyksphinz:20180209235015p:plain

関連記事