趣味でRISC-VのCPUコアを設計しているのだが、デバッグおよび性能検証を行うためのパタンが必要になる。 様々なアプリケーションを使って検証すれば良いのだが、網羅的かどうかも分からない。また、基本的な命令セットの性能検証も行う必要がありそうだ。
そういう意味では、定義した命令毎に性能検証を行う必要がありそうだ。このためには、あらかじめ定義したISSの命令テーブルを使ってテストパタンを自動生成できるかもしれない。
命令発行幅を確認するためのテストパタンを自動生成する方式の検討
$arch_table[ 0] = Array['lui d[11:7],h[31:12]', 'XXXXX', 'XX', 'XXXXX', 'XXXXX', 'XXX', 'XXXXX', '0110111', Array['OP'] , 'ALU', Array['RD_R3', 'OP_S $arch_table[ 1] = Array['auipc d[11:7],h[31:12]', 'XXXXX', 'XX', 'XXXXX', 'XXXXX', 'XXX', 'XXXXX', '0010111', Array['OP'] , 'ALU', Array['R1_PC', 'RD_R3', 'OP_S $arch_table[ 2] = Array['jal d[11:7],uj[31:12]', 'XXXXX', 'XX', 'XXXXX', 'XXXXX', 'XXX', 'XXXXX', '1101111', Array['OP'] , 'BRU', Array['RD_R3', $arch_table[ 3] = Array['jalr d[11:7],d[19:15],h[11:0]', 'XXXXX', 'XX', 'XXXXX', 'XXXXX', '000', 'XXXXX', '1100111', Array['OP'] , 'BRU', Array['RD_R3', 'R1_R1' $arch_table[ 4] = Array['beq d[19:15],d[24:20],sb[31:25]', 'XXXXX', 'XX', 'XXXXX', 'XXXXX', '000', 'XXXXX', '1100011', Array['OP', 'F3'] , 'BRU', Array['R1_R1', 'R2_R2', 'OP_S $arch_table[ 5] = Array['bne d[19:15],d[24:20],sb[31:25]', 'XXXXX', 'XX', 'XXXXX', 'XXXXX', '001', 'XXXXX', '1100011', Array['OP', 'F3'] , 'BRU', Array['R1_R1', 'R2_R2', 'OP_S```
命令テーブルは上記のように定義されている。ここで、auipc d[11:7],h[31:12]
のd[11:7]
はレジスタの定義を示している。
この部分をアセンブリ言語に変換して、該当命令を生成させれば良い。
自動生成するのは以下のような構造をしたC言語のプログラムだ。
for (i = 0; i < 32; i++) { ターゲット命令 ターゲット命令 ターゲット命令 ターゲット命令 ターゲット命令 ターゲット命令 ターゲット命令 }
volatile asm の使用
欲しい命令を生成するためには、Cプログラム中にvolatile asm
を挿入すれば良い。
asm volatile ("add t0,t1,t2")
ここでレジスタを直接指定すると、間違ってレジスタを書き潰してしまうかもしれない。 そこで、asm volatileの拡張表現を使用しよう。
int32_t out0; int32_t in0_0 = 308; int32_t in0_1 = 928; asm volatile ("add %0,%1,%2" :"=r"(out0) :"r"(in0_0),"r"(in0_1) :
asm volatile
の構文は以下のようになる。
asm volatile ("命令ニーモニック" : 書き込みが発生するレジスタ : 読み込みが発生するレジスタ : 暗黙的に書き込みレジスタ(フラグなど)
書き込みが発生するレジスタは、"=r"(out0)
として記述している。rは汎用レジスタであることを示し、out0はそれに該当する変数である。
また、読み込みが発生するレジスタは"r"(in0_0),"r"(in0_1)
として記述している。in0_0
とin0_1
はそれに該当する変数である。
生成されたC言語プログラム
以下のような実装を行った。
例えば、add
命令は以下のようになる。
int main () { int32_t out0; int32_t in0_0 = 308; int32_t in0_1 = 928; int32_t out1; int32_t in1_0 = 156; int32_t in1_1 = 494; int32_t out2; int32_t in2_0 = 21; ... 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" :"=r"(out4) :"r"(in4_0),"r"(in4_1) : ); asm volatile ("add %0,%1,%2" :"=r"(out5) :"r"(in5_0),"r"(in5_1) : ); asm volatile ("add %0,%1,%2" :"=r"(out6) :"r"(in6_0),"r"(in6_1) : ); asm volatile ("add %0,%1,%2" :"=r"(out7) :"r"(in7_0),"r"(in7_1) : ); } ...
add命令を8個並べた。コンパイル後は以下のようになった。-O3
を使っているので、アンローリングされている。
310: 1d400713 li a4,468 314: 03c00793 li a5,60 318: 00740933 add s2,s0,t2 31c: 01f28933 add s2,t0,t6 320: 01df0933 add s2,t5,t4 324: 006e0933 add s2,t3,t1 328: 01088933 add s2,a7,a6 32c: 00b50933 add s2,a0,a1 330: 00d60933 add s2,a2,a3 334: 00f70933 add s2,a4,a5 338: 00740933 add s2,s0,t2 33c: 01f28933 add s2,t0,t6 340: 01df0933 add s2,t5,t4 344: 006e0933 add s2,t3,t1 348: 01088933 add s2,a7,a6 34c: 00b50933 add s2,a0,a1 350: 00d60933 add s2,a2,a3 354: 00f70933 add s2,a4,a5 358: 00740933 add s2,s0,t2 35c: 01f28933 add s2,t0,t6 360: 01df0933 add s2,t5,t4 364: 006e0933 add s2,t3,t1 368: 01088933 add s2,a7,a6 36c: 00b50933 add s2,a0,a1 370: 00d60933 add s2,a2,a3 374: 00f70933 add s2,a4,a5 378: 00740cb3 add s9,s0,t2 37c: 01f28c33 add s8,t0,t6 380: 01df0bb3 add s7,t5,t4 384: 006e0b33 add s6,t3,t1 388: 01088ab3 add s5,a7,a6 38c: 00b50a33 add s4,a0,a1 390: 00d609b3 add s3,a2,a3 394: 00f70933 add s2,a4,a5 398: ffc48493 addi s1,s1,-4 39c: f6049ee3 bnez s1,318 <main+0x70>
これを開発中のRISC-VのCPU実装で実行すると、パイプラインは以下のようになった。一応、想定通りの性能が得られている。
| || | | | || | | | ||(Cm36,D32)[PC=000002a8] R 2<=000043c8 : ADDI r 2,r 2,0xfd0 ( 3) 36| | | ||(Cm37,D--)[PC=000002ac] : SW r 8,0x02c,r 2 37| | | ||(Cm38,D--)[PC=000002b0] : SW r 9,0x028,r 2 38| | | ||(Cm39,D--)[PC=000002b4] : SW r18,0x024,r 2 39| | | ||(Cm40,D--)[PC=000002b8] : SW r19,0x020,r 2 40| | | ||(Cm41,D--)[PC=000002bc] : SW r20,0x01c,r 2 41| | | ||(Cm42,D--)[PC=000002c0] : SW r21,0x018,r 2 42| | | ||(Cm43,D--)[PC=000002c4] : SW r22,0x014,r 2 43| | b47| ||(Cm44,D--)[PC=000002c8] : SW r23,0x010,r 2 44| | b49| ||(Cm45,D--)[PC=000002cc] : SW r24,0x00c,r 2 45| | b51| ||(Cm46,D--)[PC=000002d0] : SW r25,0x008,r 2 46|(Cm47,D35)[PC=000002d4] R 9<=00000020 : ADDI r 9,r 0,0x020 (10) 47|(Cm48,D36)[PC=000002d8] R 8<=00000317 : ADDI r b53| ||(Cm50,D38)[PC=000002e0] R 5<=00000279 : ADDI r 5,r 0,0x279 ( 6) 50|(Cm51,D39)[PC=000002e4] R31<=000001b1 : ADDI r31,r 0,0x1b1 (34) 51|(Cm52,D40)[PC=000002e8] R30<=00000377 : ADDI r3 b55| ||(Cm53,D41)[PC=000002ec] R29<=000002b9 : ADDI r29,r 0,0x2b9 (30) 53|(Cm54,D42)[PC=000002f0] R28<=0000038a : ADDI r28,r 0,0x38a (29) 54| b57| ||(Cm55,D43)[PC=000002f4] R 6<=0000032f : ADDI r 6,r 0,0x32f ( 7) 55|(Cm56,D44)[PC=000002f8] R17<=00000161 : ADDI r17,r 0,0x161 (18) 56| b59| ||(Cm57,D45)[PC=000002fc] R16<=0000017d : ADDI r16,r 0,0x17d (17) 57|(Cm58,D46)[PC=00000300] R10<=00000159 : ADDI r10,r 0,0x159 (11) 58| b61| ||(Cm59,D47)[PC=00000304] R11<=00000165 : ADDI r11,r 0,0x165 (12) 59|(Cm60,D48)[PC=00000308] R12<=0000023d : ADDI r12,r 0,0x23d (13) 60| b63| ||(Cm61,D49)[PC=0000030c] R13<=00000207 : ADDI r13,r 0,0x207 (14) 61|(Cm62,D50)[PC=00000310] R14<=000002bc : ADDI r14,r 0,0x2bc (15) 62| b 1| ||(Cm63,D51)[PC=00000314] R15<=000000a7 : ADDI r15,r 0,0x0a7 (16) 63|(Cm 0,D52)[PC=00000318] R18<=0000060a : ADD r18,r 8,r 7 (19) 64| b 3| ||(Cm 1,D53)[PC=0000031c] R18<=0000042a : ADD r18,r 5,r31 (52) 65|(Cm 2,D54)[PC=00000320] R18<=00000630 : ADD r18,r30,r29 (53) 66| b 5| ||(Cm 3,D55)[PC=00000324] R18<=000006b9 : ADD r18,r28,r 6 (54) 67|(Cm 4,D56)[PC=00000328] R18<=000002de : ADD r18,r17,r16 (55) 68| b 7| ||(Cm 5,D57)[PC=0000032c] R18<=000002be : ADD r18,r10,r11 (56) 69|(Cm 6,D58)[PC=00000330] R18<=00000444 : ADD r18,r12,r13 (57) 70| b 9| ||(Cm 7,D59)[PC=00000334] R18<=00000363 : ADD r18,r14,r15 (58) 71|(Cm 8,D60)[PC=00000338] R18<=0000060a : ADD r18,r 8,r 7 (59) 72| b11| ||(Cm 9,D61)[PC=0000033c] R18<=0000042a : ADD r18,r 5,r31 (60) 73|(Cm10,D62)[PC=00000340] R18<=00000630 : ADD r18,r30,r29 (61) 74| b13| ||(Cm11,D 9)[PC=00000344] R18<=000006b9 : ADD r18,r28,r 6 (62) 75|(Cm12,D 0)[PC=00000348] R18<=000002de : ADD r18,r17,r16 ( 9) 76| b15| ||(Cm13,D 4)[PC=0000034c] R18<=000002be : ADD r18,r10,r11 ( 0) 77|(Cm14,D 3)[PC=00000350] R18<=00000444 : ADD r18,r12,r13 ( 4) 78| b17| ||(Cm15,D10)[PC=00000354] R18<=00000363 : ADD r18,r14,r15 ( 3) 79|(Cm16,D33)[PC=00000358] R18<=0000060a : ADD r18,r 8,r 7 (10) 80| b19| ||(Cm17,D 8)[PC=0000035c] R18<=0000042a : ADD r18,r 5,r31 (33) 81|(Cm18,D 6)[PC=00000360] R18<=00000630 : ADD r18,r30,r29 ( 8) 82| b21| ||(Cm19,D34)[PC=00000364] R18<=000006b9 : ADD r18,r28,r 6 ( 6) 83|(Cm20,D31)[PC=00000368] R18<=000002de : ADD r18,r17,r16 (34) 84| b23| ||(Cm21,D30)[PC=0000036c] R18<=000002be : ADD r18,r10,r11 (31) 85|(Cm22,D29)[PC=00000370] R18<=00000444 : ADD r18,r12,r13 (30) 86| b25| ||(Cm23,D 7)[PC=00000374] R18<=00000363 : ADD r18,r14,r15 (29) 87|(Cm24,D18)[PC=00000378] R25<=0000060a : ADD r25,r 8,r 7 (26) 88| b27| ||(Cm25,D17)[PC=0000037c] R24<=0000042a : ADD r24,r 5,r31 (25) 89|(Cm26,D11)[PC=00000380] R23<=00000630 : ADD r23,r30,r29 (24) 90| b29| ||(Cm27,D12)[PC=00000384] R22<=000006b9 : ADD r22,r28,r 6 (23) 91|(Cm28,D13)[PC=00000388] R21<=000002de : ADD r21,r17,r16 (22) 92| b31| ||(Cm29,D14)[PC=0000038c] R20<=000002be : ADD r20,r10,r11 (21) 93|(Cm30,D15)[PC=00000390] R19<=00000444 : ADD r19,r12,r13 (20) 94| | ||(Cm31,D16)[PC=00000394] R18<=00000363 : ADD r18,r14,r15 ( 7) 95|(Cm32,D19)[PC=00000398] R 9<=0000001c : ADDI r 9,r 9,0xffc (35) 96| | ||(Cm33,D--)[PC=0000039c] : BNE r 9,r 0,0x7b 97| | | || | | -- FLUSH --------------- FLUSH --------------- FLUSH --------------- FLUSH --------------- FLUSH --------------- FLUSH --------------- FLUSH --------------- FLUSH --------------- FLUSH --------------- FLUSH --------------- FLU | || | | | || | | | || | |