RISC-Vの実装であるRocket-Chipは、RISC-Vの最新使用に追従しているため最初に見るべきデザインとしてはよくできているが、
- Chiselで記述されており(初心者には)可読性が低い。
- 外部のSoCプラットフォームについて情報がない
ことから、なかなかオリジナルのSoCをくみ上げるためのデザインとしてポーティングしにくい。
とはいえ、TileLinkは単なるバスのはずだし、クロックとリセットさえ突っ込めばとりあえずフェッチリクエストが上がってくるはずだ。 そのあたりを解析して、Rocket-Chipを利用したオリジナルSoCプラットフォーム構築のための情報収集を行っていこう。
関連記事
- SiFiveのFreedom E300 Platformを単体でカスタマイズできるようにする (1. 全体構造からブートROMへのリクエストまでの仕組み)
- SiFiveのFreedom E300 Platformを単体でカスタマイズできるようにする (2. バスのマップと新しいモジュールの追加)
- SiFiveのFreedom E300 Platformを単体でカスタマイズできるようにする (3. SRAMモジュールを作成して接続、テストパタンで動作を確認する)
- SiFiveのFreedom E300 Platformを単体でカスタマイズできるようにする (4. TileLinkの解析とコンフィグレーション設定)
Freedmo-SoC の「Instruction & Data Cache」の領域に向けてメモリのフェッチを発行する
前回紹介したとおり、Freedom SoC E300 Platform のメモリマップには "Instruction & Data RAM" という項目があるため、ここにメモリアクセスを発行すると外部からデータをフェッチしてキャッシュに配置してくれるのだろう、と思い、 0x8000_0000に向けてメモリ読み込み (実際には0x8000_0000に向けてプログラムをジャンプさせる)コードを書いてシミュレーションしてみたが、途中でフェッチが止まってしまいうまく動かなかった。
そこでダンプデータを使ってアクセスの行方を探っていたのだが、
- ICache からメモリフェッチが Rocket CoreのIFに向けて発行される (0x8000_0000)
- Rocket CoreのIFからRocketTileに向けてリクエストが発行される (0x8000_0000)
- Peripheral-Busを通じて、RocketTileの逆方向のバスを通じてリクエストがRocket-Coreに戻ってくる。
- DCache/ICache にリクエストが入って消えた。
というわけで、"Instruction & Data RAM"という場所にアクセスしても意味がないらしい。
というか、Freedom E300のマニュアル的には、外部からこれらのキャッシュにアクセスするためのメモリアドレスであって、Rocket-Coreがメモリアクセスを行うためには、0x8000_0000ではなくて、普通にE31 Coreplex のメモリマップの場所を使わなければならない。
つまり、Coreplex E31のマニュアルにのっとると、システムバスとかペリフェラルバスからのアクセスを発生させるためには、0x2000_0000 もしくは 0x4000_0000 へアクセスを行わなければならない。
で、0x2000_0000にアクセスするとPeripheral-Bus なのでとりあえず外部に出るのだが、そこにはFreedom E300 PlatformではQSPIにつながっており、QSPIのプロトコルに変換されて外に出ていくわけだ。
実現したいことは、Freedom E300 Platformに適当にSRAMを接続してそこから命令とデータをフェッチできる環境を作りたい。 とりあえず、QSPIを取り除いて、そこにROMでもRAMでも接続してみたい。
Freedom E300 Platformの改造
Scalaについてはよくわからないのだが、QSPIの接続されている0x2000_0000のアドレスマップに張り付いているモジュールを取り除き、MaskROMを0x2000_0000に接続する。 なぜRAMではなくROMなのかというと、その場で接続できるRAMモジュールが見当たらなかったためだ(笑)。
diff --git a/src/main/scala/everywhere/e300artydevkit/Config.scala b/src/main/scala/everywhere/e300artydevkit/Config.scala index a85d1e6..3dd9f90 100644 --- a/src/main/scala/everywhere/e300artydevkit/Config.scala +++ b/src/main/scala/everywhere/e300artydevkit/Config.scala @@ -35,11 +35,11 @@ class E300DevKitPeripherals extends Config((site, here, up) => { case PeripherySPIKey => List( SPIParams(csWidth = 4, rAddress = 0x10024000, sampleDelay = 3), SPIParams(csWidth = 1, rAddress = 0x10034000, sampleDelay = 3)) - case PeripherySPIFlashKey => List( - SPIFlashParams( - fAddress = 0x20000000, - rAddress = 0x10014000, - sampleDelay = 3)) + // case PeripherySPIFlashKey => List( + // SPIFlashParams( + // fAddress = 0x20000000, + // rAddress = 0x10014000, + // sampleDelay = 3)) case PeripheryUARTKey => List( UARTParams(address = 0x10013000), UARTParams(address = 0x10023000)) @@ -48,7 +48,9 @@ class E300DevKitPeripherals extends Config((site, here, up) => { case PeripheryMockAONKey => MockAONParams(address = 0x10000000) case PeripheryMaskROMKey => List( - MaskROMParams(address = 0x10000, name = "BootROM")) + MaskROMParams(address = 0x10000, name = "BootROM"), + MaskROMParams(address = 0x20000000, name = "TestROM") + ) }) // Freedom E300 Arty Dev Kit Peripherals diff --git a/src/main/scala/everywhere/e300artydevkit/FPGAChip.scala b/src/main/scala/everywhere/e300artydevkit/FPGAChip.scala index e0b0634..ea3edb8 100644 --- a/src/main/scala/everywhere/e300artydevkit/FPGAChip.scala +++ b/src/main/scala/everywhere/e300artydevkit/FPGAChip.scala @@ -44,13 +44,13 @@ class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtySh // SPI flash IOBUFs //--------------------------------------------------------------------- - IOBUF(qspi_sck, dut.io.pins.qspi.sck) - IOBUF(qspi_cs, dut.io.pins.qspi.cs(0)) - - IOBUF(qspi_dq(0), dut.io.pins.qspi.dq(0)) - IOBUF(qspi_dq(1), dut.io.pins.qspi.dq(1)) - IOBUF(qspi_dq(2), dut.io.pins.qspi.dq(2)) - IOBUF(qspi_dq(3), dut.io.pins.qspi.dq(3)) + // IOBUF(qspi_sck, dut.io.pins.qspi.sck) + // IOBUF(qspi_cs, dut.io.pins.qspi.cs(0)) + // + // IOBUF(qspi_dq(0), dut.io.pins.qspi.dq(0)) + // IOBUF(qspi_dq(1), dut.io.pins.qspi.dq(1)) + // IOBUF(qspi_dq(2), dut.io.pins.qspi.dq(2)) + // IOBUF(qspi_dq(3), dut.io.pins.qspi.dq(3)) //--------------------------------------------------------------------- // JTAG IOBUFs diff --git a/src/main/scala/everywhere/e300artydevkit/Platform.scala b/src/main/scala/everywhere/e300artydevkit/Platform.scala index be1789a..289f97e 100644 --- a/src/main/scala/everywhere/e300artydevkit/Platform.scala +++ b/src/main/scala/everywhere/e300artydevkit/Platform.scala @@ -39,7 +39,7 @@ class E300ArtyDevKitPlatformIO(implicit val p: Parameters) extends Bundle { val pins = new Bundle { val jtag = new JTAGPins(() => PinGen(), false) val gpio = new GPIOPins(() => PinGen(), p(PeripheryGPIOKey)(0)) - val qspi = new SPIPins(() => PinGen(), p(PeripherySPIFlashKey)(0)) + /* val qspi = new SPIPins(() => PinGen(), p(PeripherySPIFlashKey)(0)) */ val aon = new MockAONWrapperPins() } val jtag_reset = Bool(INPUT) @@ -159,8 +159,8 @@ class E300ArtyDevKitPlatform(implicit val p: Parameters) extends Module { // Result of Pin Mux GPIOPinsFromPort(io.pins.gpio, sys.gpio(0)) - // Dedicated SPI Pads - SPIPinsFromPort(io.pins.qspi, sys.qspi(0), clock = sys.clock, reset = sys.reset, syncStages = 3) + // // Dedicated SPI Pads + // SPIPinsFromPort(io.pins.qspi, sys.qspi(0), clock = sys.clock, reset = sys.reset, syncStages = 3) // JTAG Debug Interface val sjtag = sys.debug.systemjtag.get diff --git a/src/main/scala/everywhere/e300artydevkit/System.scala b/src/main/scala/everywhere/e300artydevkit/System.scala index c3fbd96..8ef51e9 100644 --- a/src/main/scala/everywhere/e300artydevkit/System.scala +++ b/src/main/scala/everywhere/e300artydevkit/System.scala @@ -26,7 +26,7 @@ class E300ArtyDevKitSystem(implicit p: Parameters) extends RocketCoreplex with HasPeripheryDebug with HasPeripheryMockAON with HasPeripheryUART - with HasPeripherySPIFlash + /* with HasPeripherySPIFlash */ with HasPeripherySPI with HasPeripheryGPIO with HasPeripheryPWM @@ -40,7 +40,7 @@ class E300ArtyDevKitSystemModule[+L <: E300ArtyDevKitSystem](_outer: L) with HasPeripheryUARTModuleImp with HasPeripherySPIModuleImp with HasPeripheryGPIOModuleImp - with HasPeripherySPIFlashModuleImp + /* with HasPeripherySPIFlashModuleImp */ with HasPeripheryMockAONModuleImp with HasPeripheryPWMModuleImp with HasPeripheryI2CModuleImp {
これで再生成を行う。
make -f Makefile.e300artydevkit clean && make -f Makefile.e300artydevkit verilog make -f Makefile.e300artydevkit romgen
これで、MaskROMが2種類作られる。ただし、とりあえず初期値は1つしか指定できないようだ。
make -f Makefile.e300artydevkit romgen make -C /home/msyksphinz/work/freedom/bootrom/xip romgen make[1]: ディレクトリ '/home/msyksphinz/work/freedom/bootrom/xip' に入ります /home/msyksphinz/work/freedom/rocket-chip/scripts/vlsi_rom_gen /home/msyksphinz/work/freedom/builds/e300artydevkit/sifive.freedom.everywhere.e300artydevkit.E300ArtyDevKitConfig.rom.conf /home/msyksphinz/work/freedom/builds/e300artydevkit/xip.hex > /home/msyksphinz/work/freedom/builds/e300artydevkit/rom.v /home/msyksphinz/work/freedom/rocket-chip/scripts/vlsi_rom_gen:131: UserWarning: vlsi_rom_gen detected multiple ROMs. ROM contents will be duplicated. warnings.warn('vlsi_rom_gen detected multiple ROMs. ROM contents will be duplicated.') ...
このVerilogファイルを使って再度RTLシミュレーションを行ってみた。 まだROMの状態ではあるが、TestROMに対して正常なメモリアクセスを発行させることができたようだ。 次は、テスト用のRAMを作って、接続作業を行ってみる。