自作RISC-V CPUコアの方は、いくつかのコンフィグレーションにおいてDhrystoneを完走させることができるくらいになってきた。
パイプライントレースのログ生成を実装する。基本としては各モジュールのパイプラインステージ毎にDPI-Cを通じてC++側に情報を取り出し、C++側でログファイルに出力するという形態にする。
// Kanata import "DPI-C" function void log_stage ( input longint id, input string stage ); always_ff @ (negedge i_clk, negedge i_reset_n) begin if (i_reset_n) begin if (w_ex0_issue.valid) begin log_stage (w_ex0_issue.kanata_id, "EX0"); end if (r_ex1_issue.valid) begin log_stage (r_ex1_issue.kanata_id, "EX1"); end if (r_ex2_issue.valid) begin log_stage (r_ex2_issue.kanata_id, "EX2"); end if (r_ex3_issue.valid) begin log_stage (r_ex3_issue.kanata_id, "EX3"); end end end
log_stage()
という関数では、kanata_id
(シミュレーション内で一意となるID)とともに現在どのステージにいるのかを指定する。
log_stage()
内では、過去に同じ命令で別のステージにいた場合は、E
命令を出してステージを終了しないといけないので、そのためのE
命令の生成を行う。
void log_stage (long long id, const char *stage) { decltype(stage_map)::iterator it = stage_map.find(id); if (it != stage_map.end()) { fprintf (kanata_fp, "E\t%lld\t0\t%s\n", id, it->second); stage_map.erase (id); } fprintf (kanata_fp, "S\t%lld\t0\t%s\n", id, stage); char *stage_str = (char *)malloc(sizeof(strlen(stage))+1); strcpy(stage_str, stage); stage_map.insert (std::make_pair(id, stage_str)); }
これにより、以下のようなトレースファイルが生成されるようになった。
I 72735 72735 0 L 72735 0 800028e8:lbu a5, 0(a0) S 72735 0 Di I 72736 72736 0 L 72736 0 800028ec:addi a1, a1, 1 S 72736 0 Di I 72737 72737 0 L 72737 0 800028ee:addi a0, a0, 1 S 72737 0 Di I 72738 72738 0 L 72738 0 800028f0:lbu a4, -1(a1) S 72738 0 Di I 72739 72739 0 L 72739 0 800028f4:beqz a5, pc + 14 S 72739 0 Di E 72732 0 Di S 72732 0 Rn E 72733 0 Di S 72733 0 Rn E 72734 0 Di S 72734 0 Rn E 72730 0 Rn S 72730 0 EX0 E 72728 0 EX1 S 72728 0 EX2 E 72711 0 Rn S 72711 0 EX0 E 72709 0 EX0 S 72709 0 EX1 E 72702 0 EX1 S 72702 0 EX2 E 72695 0 EX2 S 72695 0 EX3 E 72723 0 Rn S 72723 0 EX0 E 72712 0 EX0 S 72712 0 EX1 E 72718 0 EX1 S 72718 0 EX2 E 72714 0 EX2 S 72714 0 EX3 C 1 I 72740 72740 0 L 72740 0 800028f6:beq a5, a4, pc - 14 S 72740 0 Di E 72735 0 Di S 72735 0 Rn E 72736 0 Di
これをKonataパイプラインビューアで表示すると以下のようになる。
こうみると、例えば0x8020はなんでしばらくの間実行パイプラインに入れていないんだ?となるよね。この辺も解析していきたい。