FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages

Rocket-Chip で命令レイテンシ・スループットを測定する環境の構築 (1. 整数命令系)

前回の記事で、Rocket-Chip で任意のプログラムを実行できるような環境が構築できた。 これでRocket-Chipの体力測定ができそうだ。

まずは各命令のレイテンシ・スループットを測定するのがよさそうだ。 命令の実行レイテンシやスループットは、一般的には、同じ命令を何度も繰り返して実行して測定する。

f:id:msyksphinz:20180306001612p:plain

以下のプログラムは、出力レジスタの依存関係が存在しないので、命令依存関係がなく、スループットが測定できる。

  • program/benchmark/inst_add/inst_add.c
...
  for (i = 0; i < 32; i++) {
    asm volatile ("add        %0,%1,%2"
                                  :"=r"(out0)
                                  :"r"(in0_0),"r"(in0_1)
                                  :
                                  );
    asm volatile ("add        %0,%1,%2"
                                  :"=r"(out1)
                                  :"r"(in1_0),"r"(in1_1)
                                  :
                                  );
    asm volatile ("add        %0,%1,%2"
                                  :"=r"(out2)
                                  :"r"(in2_0),"r"(in2_1)
                                  :
                                  );
    asm volatile ("add        %0,%1,%2"
                                  :"=r"(out3)
                                  :"r"(in3_0),"r"(in3_1)
                                  :
                                  );
    asm volatile ("add        %0,%1,%2"
...

一方で以下のプログラムは、出力レジスタを次の命令レジスタで使うので、1命令に必要なレイテンシを測定できる。

RISC-V add 命令のスループット

330 - 337がサイクル数。1サイクル毎に実行されていることが分かる。IPC=1.0だ。

C0:        330 [1] pc=[00800000a8] W[r25=00000000cb5f139c][1] R[r 9=000000004f7a652e] R[r 8=000000007be4ae6e] inst=[00848cb3] add     s9, s1, s0
C0:        331 [1] pc=[00800000ac] W[r24=0000000063bb12ae][1] R[r 7=000000005e9aaa1d] R[r 5=0000000005206891] inst=[00538c33] add     s8, t2, t0
C0:        332 [1] pc=[00800000b0] W[r23=000000014ad97382][1] R[r31=000000004d1f56e1] R[r17=00000000fdba1ca1] inst=[011f8bb3] add     s7, t6, a7
C0:        333 [1] pc=[00800000b4] W[r22=00000000ac561dbb][1] R[r16=00000000845cb9cb] R[r30=0000000027f963f0] inst=[01e80b33] add     s6, a6, t5
C0:        334 [1] pc=[00800000b8] W[r21=0000000146687fa8][1] R[r10=0000000083f85a2f] R[r11=00000000c2702579] inst=[00b50ab3] add     s5, a0, a1
C0:        335 [1] pc=[00800000bc] W[r20=000000007b5a2ebe][1] R[r29=0000000046081d0a] R[r28=00000000355211b4] inst=[01ce8a33] add     s4, t4, t3
C0:        336 [1] pc=[00800000c0] W[r19=0000000155d5e712][1] R[r12=00000000fd6878f7] R[r 6=00000000586d6e1b] inst=[006609b3] add     s3, a2, t1
C0:        337 [1] pc=[00800000c4] W[r18=000000014d25a196][1] R[r13=00000000b059fbf5] R[r14=000000009ccba5a1] inst=[00e68933] add     s2, a3, a4

RISC-V add 命令レイテンシ

326 - 333 がサイクル数。1サイクル毎にこちらも実行されていることが分かる。レイテンシも1.0だ。スループットとレイテンシがどちらも1.0なので少し面白くない。

C0:        326 [1] pc=[008000005c] W[r17=00000000cb5f139c][1] R[r 9=000000004f7a652e] R[r 8=000000007be4ae6e] inst=[008488b3] add     a7, s1, s0
C0:        327 [1] pc=[0080000060] W[r16=0000000129f9bdb9][1] R[r 7=000000005e9aaa1d] R[r17=00000000cb5f139c] inst=[01138833] add     a6, t2, a7
C0:        328 [1] pc=[0080000064] W[r10=000000017719149a][1] R[r 5=000000004d1f56e1] R[r16=0000000129f9bdb9] inst=[01028533] add     a0, t0, a6
C0:        329 [1] pc=[0080000068] W[r11=00000001fb75ce65][1] R[r30=00000000845cb9cb] R[r10=000000017719149a] inst=[00af05b3] add     a1, t5, a0
C0:        330 [1] pc=[008000006c] W[r12=000000027f6e2894][1] R[r29=0000000083f85a2f] R[r11=00000001fb75ce65] inst=[00be8633] add     a2, t4, a1
C0:        331 [1] pc=[0080000070] W[r13=00000002c576459e][1] R[r31=0000000046081d0a] R[r12=000000027f6e2894] inst=[00cf86b3] add     a3, t6, a2
C0:        332 [1] pc=[0080000074] W[r14=00000003c2debe95][1] R[r28=00000000fd6878f7] R[r13=00000002c576459e] inst=[00de0733] add     a4, t3, a3
C0:        333 [1] pc=[0080000078] W[r18=000000047338ba8a][1] R[r 6=00000000b059fbf5] R[r14=00000003c2debe95] inst=[00e30933] add     s2, t1, a4

もう少しいろんな命令を実行してみよう。FPUとか面白そうだ。

2018/03/07追記。整数乗算命令についても実験してみた。発行レートは7サイクルに1回... IPC=0.142だって!? そんなことあるかなあ。パイプライン化されていないのかも。

C0:       1481 [1] pc=[008000008e] W[r 0=00000000cb5f139c][1] R[r17=000000004f7a652e] R[r16=000000007be4ae6e] inst=[03088b33] mul     s6, a7, a6
C0:       1488 [1] pc=[0080000092] W[r 0=0000000063bb12ae][1] R[r10=000000005e9aaa1d] R[r11=0000000005206891] inst=[02b50bb3] mul     s7, a0, a1
C0:       1495 [1] pc=[0080000096] W[r 0=000000014ad97382][1] R[r12=000000004d1f56e1] R[r14=00000000fdba1ca1] inst=[02e60c33] mul     s8, a2, a4
C0:       1502 [1] pc=[008000009a] W[r 0=00000000ac561dbb][1] R[r15=00000000845cb9cb] R[r13=0000000027f963f0] inst=[02d78cb3] mul     s9, a5, a3
C0:       1503 [1] pc=[008000009e] W[r 6=0000000000000014][1] R[r 6=0000000000000015] R[r31=0000000027f963f3] inst=[0000337d] addiw   t1, t1, -1
C0:       1504 [1] pc=[00800000a0] W[r 0=0000000000000000][0] R[r 6=0000000000000014] R[r 0=0000000000000000] inst=[fa031fe3] bnez    t1, pc - 66
C0:       1509 [1] pc=[008000005e] W[r 0=00000000cb5f139c][1] R[r17=000000004f7a652e] R[r16=000000007be4ae6e] inst=[030884b3] mul     s1, a7, a6
C0:       1516 [1] pc=[0080000062] W[r 0=0000000063bb12ae][1] R[r10=000000005e9aaa1d] R[r11=0000000005206891] inst=[02b50433] mul     s0, a0, a1
C0:       1523 [1] pc=[0080000066] W[r 0=000000014ad97382][1] R[r12=000000004d1f56e1] R[r14=00000000fdba1ca1] inst=[02e603b3] mul     t2, a2, a4
C0:       1530 [1] pc=[008000006a] W[r 0=00000000ac561dbb][1] R[r15=00000000845cb9cb] R[r13=0000000027f963f0] inst=[02d782b3] mul     t0, a5, a3
C0:       1537 [1] pc=[008000006e] W[r 0=00000000cb5f139c][1] R[r17=000000004f7a652e] R[r16=000000007be4ae6e] inst=[03088fb3] mul     t6, a7, a6
C0:       1544 [1] pc=[0080000072] W[r 0=0000000063bb12ae][1] R[r10=000000005e9aaa1d] R[r11=0000000005206891] inst=[02b50f33] mul     t5, a0, a1
C0:       1551 [1] pc=[0080000076] W[r 0=000000014ad97382][1] R[r12=000000004d1f56e1] R[r14=00000000fdba1ca1] inst=[02e60eb3] mul     t4, a2, a4
C0:       1558 [1] pc=[008000007a] W[r 0=00000000ac561dbb][1] R[r15=00000000845cb9cb] R[r13=0000000027f963f0] inst=[02d78e33] mul     t3, a5, a3
C0:       1565 [1] pc=[008000007e] W[r 0=00000000cb5f139c][1] R[r17=000000004f7a652e] R[r16=000000007be4ae6e] inst=[03088933] mul     s2, a7, a6
C0:       1572 [1] pc=[0080000082] W[r 0=0000000063bb12ae][1] R[r10=000000005e9aaa1d] R[r11=0000000005206891] inst=[02b509b3] mul     s3, a0, a1
C0:       1579 [1] pc=[0080000086] W[r 0=000000014ad97382][1] R[r12=000000004d1f56e1] R[r14=00000000fdba1ca1] inst=[02e60a33] mul     s4, a2, a4
C0:       1586 [1] pc=[008000008a] W[r 0=00000000ac561dbb][1] R[r15=00000000845cb9cb] R[r13=0000000027f963f0] inst=[02d78ab3] mul     s5, a5, a3
C0:       1593 [1] pc=[008000008e] W[r 0=00000000cb5f139c][1] R[r17=000000004f7a652e] R[r16=000000007be4ae6e] inst=[03088b33] mul     s6, a7, a6
C0:       1600 [1] pc=[0080000092] W[r 0=0000000063bb12ae][1] R[r10=000000005e9aaa1d] R[r11=0000000005206891] inst=[02b50bb3] mul     s7, a0, a1
C0:       1607 [1] pc=[0080000096] W[r 0=000000014ad97382][1] R[r12=000000004d1f56e1] R[r14=00000000fdba1ca1] inst=[02e60c33] mul     s8, a2, a4

2018/03/10 追記。タイムアウトまで実行するのは時間がかかりすぎるのでベンチマークが終了するとシミュレーションも終了するようにする。

計測後に以下のコードを実行するようにする。 これにより、デバッグ領域にメモリアクセスが入り、これを検知するとRTLシミュレーションを終了する。

void finish () __attribute__((section(".text")));

void run_bench ()
{benchmark (); benchmark(); finish(); }
void finish ()
{
  asm volatile ("csrr    s0, mhartid");
  asm volatile ("sw      s0, 264(zero)");
  asm volatile ("csrr    s0, dscratch");
  asm volatile ("dret");
}
  • tp_freechips_rocketchip.sv
  always_ff @ (posedge clock) begin
    if (tb.duv.ExampleRocketSystem.debug_1.auto_dmInner_dmInner_tl_in_a_valid &&
        tb.duv.ExampleRocketSystem.debug_1.auto_dmInner_dmInner_tl_in_a_ready &&
        tb.duv.ExampleRocketSystem.debug_1.auto_dmInner_dmInner_tl_in_a_bits_address == 32'h108) begin
      $fwrite (32'h80000002,"ExapmleRocketSystem Debug Asserted. Finished.\n");
      $finish;
    end
  end