RISC-VのUCB実装であるRocketChipはRISC-Vのプロセッサ実装の中で最も参考になるもので、例えばSoCに組み込むとなると真っ先に導入を考えるRISC-V IPの一つだ。
RocketChipはデフォルトで64ビット命令をサポートしており、シンプルなパイプラインながら性能もソコソコ出る、と言うことを謳っている(まあそれが真実かは分からないけれども)。
RocketChipのコアだけを取り出して他のSoCに組み込みたいとき、または自分のバスにRocketChipを接続したいときに、どのようにすればよいのだろう? 適当にgithubから取得してきた環境でMakeして、とりあえずVerilatorでシミュレーションして終わるのならば可能だが、実際のインプリメンテーションとなるとRocketChipは分からないことが多い。 特に足回りの部分だ。
今回は、RocketChipの足回りの構成について、Scalaの実装部分と、出力されたVerilogの部分を見ながら比較、調査してみる。
RockeChipのサンプルデザインで構築される環境
今回は、VerilatorのVCDも分かりにくい、家にVCSなんてライセンスの必要なシミュレータなんて持っているはずもない、という環境のため、QuestaSim Starter Editionを使ってシミュレーションをする環境を構築した。
RocketChipのリポジトリをcloneしてくると、シミュレーション用のディレクトリとして、
- emulator : Verilatorを使ったシミュレーション
- vsim : VCSを使ったシミュレーション
のディレクトリが作成されるらしい。何故Questaが無いのだ!という話はあるかもしれないが、これはDPIの仕様などが微妙に異なるためと予想する。
ただし今回はDPIなんて使わずに基本的にリセット解除して、フェッチして、デコードして実行ができればよいので、無駄なものはいろいろ切り取ってシンプルな構成に変更していく。
この結果、RocketChipのデザインで生成されるRTLシミュレーション環境は、大まかに言って以下のような関係になっている。
- TestDriver
- TestHarness
- ExampleRocketTop
- 足回りの部品など
- SRAMなど
- coreplex
このCoreplexというものが実際のRocketCoreだと予想するが、確証はない。そこから先も大量のモジュールがインスタンスされているので、正直どこがコア部分なのか良く分からないのだ。
このcoreplexというモジュールは、RocketPlex_coreplexというモジュールになっている。Verilogファイルを参照してみる。Verilogファイルはrocket-chip/emulator/generated-src/freechips.rocketchip.chipDefaultcConfig.v
に格納されている。
module RocketPlex_coreplex( input clock, input reset, input io_interrupts_0_0, input io_interrupts_0_1, output io_l2in_0_a_ready, input io_l2in_0_a_valid, input [2:0] io_l2in_0_a_bits_opcode, input [2:0] io_l2in_0_a_bits_param, input [3:0] io_l2in_0_a_bits_size, input [3:0] io_l2in_0_a_bits_source, input [31:0] io_l2in_0_a_bits_address, input [7:0] io_l2in_0_a_bits_mask, ...
大きく分けて以下のバスが搭載されている。
- io_l2in : External –> coreplex (L2関係?)
- io_mmio : coreplex –> External (IOMMU関係?)
- io_mem : coreplex –> External (命令、データフェッチ関係?)
- io_debug : External –> coreplex (デバッグ関係?)
良く分からないのだけれど、これらのバスはTileLinkと呼ばれるものだろうか?生成されたVerilogの中にも、TLBufferなどというモジュールでは、
module TLBuffer_fsb( output io_in_0_a_ready, input io_in_0_a_valid, input [2:0] io_in_0_a_bits_opcode, input [2:0] io_in_0_a_bits_param, input [3:0] io_in_0_a_bits_size, input [3:0] io_in_0_a_bits_source, input [31:0] io_in_0_a_bits_address, input [7:0] io_in_0_a_bits_mask, input [63:0] io_in_0_a_bits_data, ...
という感じでこのバスプロトコルが使われている。これも含め要調査だな。