Rocket-Chip / BOOMのTLBを調査している。Page Table Walkerの動作の詳細を見ていく。
Page Table Walkerのインタフェース
Page Table Walkerのインタフェースは以下のようになっている。
リクエスト側
リクエスト側は複数のマスタが接続されており、これらはいったんArbiterを経由してどのリクエストを受け付けるかを決定している。
// リクエスト:複数のリクエストを受け付ける val requestor = Vec(n, new TLBPTWIO).flip
リクエストの入力側
リクエスト信号が接続されている。
Valid / Ready
信号:Handshakeを行うためのValid / Ready信号bits.addr
: リクエスト側の仮想アドレス。ただし27ビットしか定義されていないので、RV64におけるVPNのみを転送しているものと思われる。
リクエストの応答側
リクエストに対する応答が接続されている。
Valid
信号:レスポンスのためのValid信号- PTEの信号:Page Table Entryの信号が渡されるようになっている。
output [53:0] io_requestor_0_resp_bits_pte_ppn output io_requestor_0_resp_bits_pte_d output io_requestor_0_resp_bits_pte_a output io_requestor_0_resp_bits_pte_g output io_requestor_0_resp_bits_pte_u output io_requestor_0_resp_bits_pte_x output io_requestor_0_resp_bits_pte_w output io_requestor_0_resp_bits_pte_r output io_requestor_0_resp_bits_pte_v
I/Oメモリアクセスポート
外部メモリアクセスのためのポートとなっている。
// メモリアクセスインタフェース val mem = new HellaCacheIO
input io_mem_req_ready output io_mem_req_valid output [39:0] io_mem_req_bits_addr output io_mem_s1_kill input io_mem_s2_nack input io_mem_resp_valid input [63:0] io_mem_resp_bits_data input io_mem_s2_xcpt_ae_ld
io_mem_s1_kill
とio_mem_s2_kill
の出力ポートについては使用用途が不明なのだが、これはすでに出したリクエストを殺すことができるようなポートなのだろうか?
io_mem_s2_xcpt_ae_ld
入力ポートは、メモリアクセスのビットとは別にアクセスエラーを検出するためのポートなのだろうか。
コアの設定情報ポート
dpath
信号はコアからの情報を含んでいる。
sfence
に関する情報status
に関する情報(mstatus
の情報など)PMP
に関する情報
PMPの情報などに至っては、コアの設定情報からのポートからリクエストポートに直結されているのが、何か意味はあるのだろうか。
riscv-tests
のRTLシミュレーション波形を見ながらTLBの動作を追いかける
riscv-tests/isa/rv64ui-v-add
のChipyardでのRTLでのシミュレーション波形を見ながら、TLBの動作を追いかけていこうと思う。
$ ./simulator-chipyard-MediumBoomConfig-debug --vcd=rv64ui-v-add.medium.vcd \ --verbose ~/riscv64/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-v-add 2>&1 | tee rv64ui-v-add.log
途中からSRET
にてユーザモードに切り替わるのだが、これでTLBが動き始める。0x2AC8にジャンプしようとするのだが、当然TLBにヒットしないのでPage Table Walkが始まる。VPNが渡されるのでまずは下位12ビットを除いた2が渡される。SATPの設定から0x8000_4000へのリクエストが入るのだが、ここには何も書かれていないので0x000が返される。これによりPTE.Valid=0のPTEが返されるので例外が発生してさらにスーパバイザ―モードに移ることになる。
レスポンスには、PTE.V=0なので例外が発生する。