RISC-Vの実装であるHummingBirdを調査していくことにした。
Verilator用のビルドを追加したい試行。VerilatorはRISC-VのRocket-Chipなどで間接的に使用したことはあるし、gtkwaveで生成した波形をデバッグしたことはあるけど、自分でテストベンチを書いた事は無いので四苦八苦している。なるほど、ChiselのIOTesterと同じノリで書いていけばいいのか、ということが分かってきた。
あとは、VerilatorはテストベンチはC++で記述するという仕様上、通常のテストベンチをそのまま使ってはいけないということに気がついた。
Verilatorは遅延演算子(#10
みたいなやつ)をサポートしていないので、テストベンチをそのまま食わせると一瞬でテストが終了してなにも実行されない。
#1000000; // こういうテストベンチの記述はVerilatorではすべて無視されて、一瞬で終了する。 $finish
というか昔Verilatorの特徴をまとめていたのだった。自分で書いていて忘れていた。
頑張ってC++のテストコードを書いている。これらを合わせてコンパイルを通らせるようにした。テストベンチは最低限の機能を残して削っている。これは後でブランチで公開する。
#include "Vtb_top.h" #include "verilated.h" #include "verilated_vcd_c.h" static uint64_t trace_count = 0; double sc_time_stamp() { return trace_count; } int main(int argc, char **argv, char **env) { Verilated::commandArgs(argc, argv); Vtb_top* top = new Vtb_top; Verilated::traceEverOn(true); VerilatedVcdC* tfp = new VerilatedVcdC; vluint64_t sim_time = 100000; top->trace(tfp, 99); // Trace 99 levels of hierarchy tfp->open("simx.vcd"); top->clk = 0; top->lfextclk = 0; top->rst_n = 0; while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) { if (trace_count >= 10) { top->rst_n = 1; } if ((trace_count % 5) == 0) { top->clk = !top->clk; } if ((trace_count % 15) == 0) { top->lfextclk = !top->lfextclk; } trace_count ++; top->eval(); tfp->dump(trace_count); if ((trace_count % 1000) == 0) { printf ("Count = %d\n", trace_count); } } tfp->close(); delete top; exit(0); }
とりあえず波形は出るようになってきたが、まだフェッチが出ているかどうか怪しいなあ?
っていうか$readmemh
は効いているのだろうか?
次は波形を見ながらHummingBirdのデバッグをしてみる。