FPGA開発日記

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

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

前回、RISC-V Rocket-Chip を使って、コアの基本体力である命令のレイテンシ・スループットを測定する環境作成に取り掛かった。

整数命令についてはおおよそ測定できるようになった。次は浮動小数点命令だ。四則演算など、基本的なところから手を付けて行きたい。

f:id:msyksphinz:20180306001612p:plain

測定用のベンチマークは、少し改造して以下のようになっている。あまり命令間に余計なものが入ってほしくないので、 同じ命令を連続して同じasm volatile内に並べることにしている。オペランドの数にどうやら制限がある?(asm volatileでは30個以上のオペランドを取ることはできないようだ)ので、そこは分割している。

int benchmark () {
  float register out0;
  float register out1;
  float register out2;
  float register out3;
  float register out4;
  float register out5;
  float register out6;
  float register out7;
  float register out8;
  float register out9;
  float register out10;
  float register out11;
  float register out12;
  float register out13;
  float register out14;
  float register out15;
  float register in0_0 = 13334.21358;
  float register in1_0 = 15871.94397;
  float register in2_0 = 12938.99489;
  float register in3_0 = 22206.69387;
  float register in0_1 = 2078.584430;
  float register in1_1 = 8601.0001;
  float register in2_1 = 4256.832673;
  float register in3_1 = 6706.55472;
  int i;
  for (i = 0; i < 32; i++) {
    asm volatile (
                                  "fadd.s %[w00],%[a00],%[b00]; \n"
                                  "fadd.s %[w01],%[a01],%[b01]; \n"
                                  "fadd.s %[w02],%[a02],%[b02]; \n"
                                  "fadd.s %[w03],%[a03],%[b03]; \n"
                                  "fadd.s %[w04],%[a00],%[b00]; \n"
                                  "fadd.s %[w05],%[a01],%[b01]; \n"
                                  "fadd.s %[w06],%[a02],%[b02]; \n"
                                  "fadd.s %[w07],%[a03],%[b03]; \n"
                                  "fadd.s %[w08],%[a00],%[b00]; \n"
                                  "fadd.s %[w09],%[a01],%[b01]; \n"
                                  "fadd.s %[w10],%[a02],%[b02]; \n"
                                  "fadd.s %[w11],%[a03],%[b03]; \n"
                                  "fadd.s %[w12],%[a00],%[b00]; \n"
                                  "fadd.s %[w13],%[a01],%[b01]; \n"
                                  "fadd.s %[w14],%[a02],%[b02]; \n"
                                  "fadd.s %[w15],%[a03],%[b03]; \n"
                                  : [w00] "=f"(out0), [w01] "=f"(out1), [w02] "=f"(out2), [w03] "=f"(out3),
                                        [w04] "=f"(out4), [w05] "=f"(out5), [w06] "=f"(out6), [w07] "=f"(out7),
                                        [w08] "=f"(out8), [w09] "=f"(out9), [w10] "=f"(out10), [w11] "=f"(out11),
                                        [w12] "=f"(out12), [w13] "=f"(out13), [w14] "=f"(out14), [w15] "=f"(out15)
                                  : [a00] "f" (in0_0 ), [b00] "f" (in0_1 ),
                                        [a01] "f" (in1_0 ), [b01] "f" (in1_1 ),
                                        [a02] "f" (in2_0 ), [b02] "f" (in2_1 ),
                                        [a03] "f" (in3_0 ), [b03] "f" (in3_1 )
                                  );

さらにベンチマークを取得しようとしてハマってしまったのだが、 RISC-VのFPUは実行前にCSRを操作してEnableにしなければならないらしい。 まあ、その辺はどのCPUアーキテクチャでも一緒なので別に驚くにはあたらないのだが、RISC-Vの場合はそういう情報を探そうとしてどこにも載っていないところだなあ... 結局riscv-testsのベンチマークテストのアセンブリを見ながら見様見真似した。

#define MSTATUS_FS          0x00006000

void start ()
{
  asm volatile ("csrs mstatus, %0":
                                :"r"(MSTATUS_FS & (MSTATUS_FS >> 1)));
  asm volatile ("csrwi fcsr, 0");
  asm volatile ("csrw mepc, %0"
                                : :"r"(benchmark));
  asm volatile ("mret");
}

ベンチマークを実行するのにmretをしなければならないかどうかは正直よくわからない。とりあえずこれで動いたから良しとするけど、本当はFCSRレジスタを設定するだけでアッサリ動いたりするのかなあ。

というわけでベンチマークプログラムを走らせた。まずはスループットだ。ログを確認してみよう。

C0:        730 [1] pc=[00800000ee] W[r 5=000000000000000e][1] R[r15=000000000000000f] R[r31=750f36e9750f36eb] inst=[fff7829b] addiw   t0, a5, -1
C0:        731 [1] pc=[00800000f2] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000f153] fadd.s  ft2, ft1, ft0
C0:        732 [1] pc=[00800000f6] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b571d3] fadd.s  ft3, fa0, fa1
C0:        733 [1] pc=[00800000fa] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67253] fadd.s  ft4, fa2, fa3
C0:        734 [1] pc=[00800000fe] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f772d3] fadd.s  ft5, fa4, fa5
C0:        735 [1] pc=[0080000102] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000f353] fadd.s  ft6, ft1, ft0
C0:        736 [1] pc=[0080000106] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b573d3] fadd.s  ft7, fa0, fa1
C0:        737 [1] pc=[008000010a] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67853] fadd.s  fa6, fa2, fa3
C0:        738 [1] pc=[008000010e] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f778d3] fadd.s  fa7, fa4, fa5
C0:        739 [1] pc=[0080000112] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000fe53] fadd.s  ft8, ft1, ft0
C0:        740 [1] pc=[0080000116] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b57ed3] fadd.s  ft9, fa0, fa1
C0:        741 [1] pc=[008000011a] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67f53] fadd.s  ft10, fa2, fa3
C0:        742 [1] pc=[008000011e] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f77fd3] fadd.s  ft11, fa4, fa5
C0:        743 [1] pc=[0080000122] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000f453] fadd.s  fs0, ft1, ft0
C0:        744 [1] pc=[0080000126] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b574d3] fadd.s  fs1, fa0, fa1
C0:        745 [1] pc=[008000012a] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67953] fadd.s  fs2, fa2, fa3
C0:        746 [1] pc=[008000012e] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f779d3] fadd.s  fs3, fa4, fa5
C0:        747 [1] pc=[0080000132] W[r 6=000000000000000d][1] R[r 5=000000000000000e] R[r31=750f36e9750f36eb] inst=[fff2831b] addiw   t1, t0, -1
C0:        748 [1] pc=[0080000136] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000f153] fadd.s  ft2, ft1, ft0
C0:        749 [1] pc=[008000013a] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b571d3] fadd.s  ft3, fa0, fa1
C0:        750 [1] pc=[008000013e] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67253] fadd.s  ft4, fa2, fa3
C0:        751 [1] pc=[0080000142] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f772d3] fadd.s  ft5, fa4, fa5
C0:        752 [1] pc=[0080000146] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000f353] fadd.s  ft6, ft1, ft0
C0:        753 [1] pc=[008000014a] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b573d3] fadd.s  ft7, fa0, fa1
C0:        754 [1] pc=[008000014e] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67853] fadd.s  fa6, fa2, fa3
C0:        755 [1] pc=[0080000152] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f778d3] fadd.s  fa7, fa4, fa5

1サイクル毎にfadd.s命令が発行できていることが分かる。素晴らしい。整数乗算命令は結構遅いのに...

続いて、fadd.sのレイテンシを図ってみよう。レジスタ依存関係を作ることでレイテンシを測定する。

C0:       2165 [1] pc=[00800001d4] W[r 0=000000000000000a][0] R[r13=0000000000000007] R[r29=750f36e9750f36eb] inst=[01d6ff53] fadd.s  ft10, fa3, ft9
C0:       2169 [1] pc=[00800001d8] W[r 0=0000000000000009][0] R[r14=0000000000000007] R[r30=750f36e9750f36eb] inst=[01e77fd3] fadd.s  ft11, fa4, ft10
C0:       2173 [1] pc=[00800001dc] W[r 0=0000000000000008][0] R[r15=0000000000000007] R[r31=750f36e9750f36eb] inst=[01f7f453] fadd.s  fs0, fa5, ft11
C0:       2174 [1] pc=[00800001e0] W[r11=0000000000000002][1] R[r10=0000000000000003] R[r31=750f36e9750f36eb] inst=[fff5059b] addiw   a1, a0, -1
C0:       2175 [1] pc=[00800001e4] W[r 0=0000000000000009][0] R[r11=0000000000000002] R[r12=750f36e9750f36eb] inst=[00c5f553] fadd.s  fa0, fa1, fa2
C0:       2179 [1] pc=[00800001e8] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r10=750f36e9750f36eb] inst=[00a6f053] fadd.s  ft0, fa3, fa0
C0:       2183 [1] pc=[00800001ec] W[r 0=000000000000000d][0] R[r14=0000000000000003] R[r 0=0000000000000000] inst=[000770d3] fadd.s  ft1, fa4, ft0
C0:       2187 [1] pc=[00800001f0] W[r 0=000000000000000c][0] R[r15=0000000000000003] R[r 1=750f36e9750f36eb] inst=[0017f153] fadd.s  ft2, fa5, ft1
C0:       2191 [1] pc=[00800001f4] W[r 0=0000000000000008][0] R[r11=0000000000000003] R[r 2=750f36e9750f36eb] inst=[0025f1d3] fadd.s  ft3, fa1, ft2
C0:       2195 [1] pc=[00800001f8] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r 3=750f36e9750f36eb] inst=[0036f253] fadd.s  ft4, fa3, ft3
C0:       2199 [1] pc=[00800001fc] W[r 0=000000000000000d][0] R[r14=0000000000000003] R[r 4=750f36e9750f36eb] inst=[004772d3] fadd.s  ft5, fa4, ft4
C0:       2203 [1] pc=[0080000200] W[r 0=000000000000000c][0] R[r15=0000000000000003] R[r 5=750f36e9750f36eb] inst=[0057f353] fadd.s  ft6, fa5, ft5
C0:       2207 [1] pc=[0080000204] W[r 0=0000000000000008][0] R[r11=0000000000000003] R[r 6=750f36e9750f36eb] inst=[0065f3d3] fadd.s  ft7, fa1, ft6
C0:       2211 [1] pc=[0080000208] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r 7=750f36e9750f36eb] inst=[0076f853] fadd.s  fa6, fa3, ft7
C0:       2215 [1] pc=[008000020c] W[r 0=000000000000000d][0] R[r14=0000000000000003] R[r16=750f36e9750f36eb] inst=[010778d3] fadd.s  fa7, fa4, fa6
C0:       2219 [1] pc=[0080000210] W[r 0=000000000000000c][0] R[r15=0000000000000003] R[r17=750f36e9750f36eb] inst=[0117fe53] fadd.s  ft8, fa5, fa7
C0:       2223 [1] pc=[0080000214] W[r 0=0000000000000008][0] R[r11=0000000000000003] R[r28=750f36e9750f36eb] inst=[01c5fed3] fadd.s  ft9, fa1, ft8
C0:       2227 [1] pc=[0080000218] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r29=750f36e9750f36eb] inst=[01d6ff53] fadd.s  ft10, fa3, ft9
C0:       2231 [1] pc=[008000021c] W[r 0=000000000000000d][0] R[r14=0000000000000003] R[r30=750f36e9750f36eb] inst=[01e77fd3] fadd.s  ft11, fa4, ft10
C0:       2235 [1] pc=[0080000220] W[r 0=000000000000000c][0] R[r15=0000000000000003] R[r31=750f36e9750f36eb] inst=[01f7f453] fadd.s  fs0, fa5, ft11
C0:       2236 [1] pc=[0080000224] W[r12=0000000000000001][1] R[r11=0000000000000002] R[r31=750f36e9750f36eb] inst=[fff5861b] addiw   a2, a1, -1
C0:       2237 [1] pc=[0080000228] W[r 0=0000000000000008][0] R[r11=0000000000000003] R[r12=0000000000000001] inst=[00c5f353] fadd.s  ft6, fa1, fa2
C0:       2241 [1] pc=[008000022c] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r 6=750f36e9750f36eb] inst=[0066f2d3] fadd.s  ft5, fa3, ft6
C0:       2245 [1] pc=[0080000230] W[r 0=000000000000000d][0] R[r14=0000000000000003] R[r 5=750f36e9750f36eb] inst=[00577253] fadd.s  ft4, fa4, ft5
C0:       2249 [1] pc=[0080000234] W[r 0=000000000000000c][0] R[r15=0000000000000003] R[r 4=750f36e9750f36eb] inst=[0047f1d3] fadd.s  ft3, fa5, ft4
C0:       2253 [1] pc=[0080000238] W[r 0=0000000000000008][0] R[r11=0000000000000003] R[r 3=750f36e9750f36eb] inst=[0035f153] fadd.s  ft2, fa1, ft3
C0:       2257 [1] pc=[008000023c] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r 2=750f36e9750f36eb] inst=[0026f0d3] fadd.s  ft1, fa3, ft2

1命令実行におおよそ4サイクルかかっている。つまりレイテンシ=4だ。整数乗算より速いじゃないか... ? とりあえず測定できる環境は構築できたので、次はいろんな命令で体力測定をしてみる。