CPU開発をしていると、自分の設計したCPUが正しく動作しているかを検証する必要が必ず生じる。 プログラムを流して動作させているときに、そのプログラムが正しく動作したかを確かめるためには、いくつかの方法がある。 一つ目はプログラム自体に検証能力を持たせる方法(セルフチェックパタン)、もう一つはISS(命令セットシミュレータ)と比較する方法(ステップバイステップ)である。
セルフチェックパタン
セルフチェックパタンは、その名の通りパタン自身にプログラムの正常動作判定が含まれる。
total = 0; for (int i = 1; i <= 10; i++) { total += i; } if (total == 55) { Pass (); } else { Fail (); }
これ、CPUが正しく動作することが分かっていれば間違い無くPass()
なのだが、なにせ自作CPU、ちゃんと動作しているか分かったものではないため、ちゃんとプログラムが所望の場所を通ったか、このようなチェックポイントを設けて動作を確認する。
もちろん、この機構が正しく動作しない場合もある。例えばCPUが正しく演算出来ていなくても、たまたま最後に55という値になっていれば、このパタンは正常動作してしまう。 このため、もう一つのステップバイステップを用いてより詳細な検証を行う。
ステップバイステップ
ステップバイステップでは、プログラムの動作記録を自作CPUとISSの両方で取り、その一致を命令単位で確認する。
確認するポイントとしては、汎用レジスタの内容、メモリの内容などが一般的だ。
例えばCPUが以下のようなログを生成するとして、
1185000000 53 [0000334c] 00012223 : SW r 0,0x00 : 1185000000 54 [00003350] da0ff0ef : JAL r 1,0xda0ff (40,35) : R 1<=00003354 1445000000 55 [000028f0] 00100793 : ADDI r15,r 0,0x001 (43,16) : R15<=00000001 1445000000 56 [000028f4] 00f50023 : SB r15,0x00 : 1445000000 57 [000028f8] 00008067 : JALR r 0,r 1,0x067 : 1905000000 58 [00003354] 00100513 : ADDI r10,r 0,0x001 (44,39) : R10<=00000001 1905000000 59 [00003358] b7cff0ef : JAL r 1,0xb7cff (45,40) : R 1<=0000335c 2235000000 60 [000026d4] 00500793 : ADDI r15,r 0,0x005 (46,43) : R15<=00000005 2245000000 61 [000026d8] 04a7e263 : BLTU r15,r10,0x02 : 2255000000 62 [000026dc] 000047b7 : LUI r15,0x00004 (47,46) : R15<=00004000 2265000000 63 [000026e0] f6478793 : ADDI r15,r15,0xf64 (48,47) : R15<=00003f64 2265000000 64 [000026e4] 00251513 : SLLI r10,r10,0x02 (49,44) : R10<=00000004 2285000000 65 [000026e8] 00f50533 : ADD r10,r10,r15 (50,49) : R10<=00003f68 2435000000 66 [000026ec] 00052783 : LW r15,0x000 (51,48) : R15<=000026fc 2445000000 67 [000026f0] 00078067 : JALR r 0,r15,0x067 : 2645000000 68 [000026fc] 7e81a503 : LW r10,0x7e8 (52,50) : R10<=00002704 2645000000 69 [00002700] 00008067 : JALR r 0,r 1,0x067 : 3135000000 70 [0000335c] 00a11623 : SH r10,0x00 : 3175000000 71 [00003360] 00200513 : ADDI r10,r 0,0x002 (53,52) : R10<=00000002
ISSが以下のようなログを出したとする。
53:M:MBar:[0000334c][P0000334c] 00012223 : sw r00,0x004(r02) r02=>0000bf78 r00=>00000000 (0000bf7c)<=00000000 54:M:MBar:[00003350][P00003350] da0ff0ef : jal r01,0xda0ff r01<=00003354 pc<=000028f0 55:M:MBar:[000028f0][P000028f0] 00100793 : addi r15,r00,0x001 r00=>00000000 r15<=00000001 56:M:MBar:[000028f4][P000028f4] 00f50023 : sb r15,0x000(r10) r10=>0000bfc6 r15=>00000001 (0000bfc6)<=00000001 57:M:MBar:[000028f8][P000028f8] 00008067 : jalr r00,r01,0x067 r01=>00003354 pc<=00003354 58:M:MBar:[00003354][P00003354] 00100513 : addi r10,r00,0x001 r00=>00000000 r10<=00000001 59:M:MBar:[00003358][P00003358] b7cff0ef : jal r01,0xb7cff r01<=0000335c pc<=000026d4 60:M:MBar:[000026d4][P000026d4] 00500793 : addi r15,r00,0x005 r00=>00000000 r15<=00000005 61:M:MBar:[000026d8][P000026d8] 04a7e263 : bltu r15,r10,0x02 r15=>00000005 r10=>00000001 62:M:MBar:[000026dc][P000026dc] 000047b7 : lui r15,0x00004 r15<=00004000 63:M:MBar:[000026e0][P000026e0] f6478793 : addi r15,r15,0xf64 r15=>00004000 r15<=00003f64 64:M:MBar:[000026e4][P000026e4] 00251513 : slli r10,r10,0x02 r10=>00000001 r10<=00000004 65:M:MBar:[000026e8][P000026e8] 00f50533 : add r10,r10,r15 r10=>00000004 r15=>00003f64 r10<=00003f68 66:M:MBar:[000026ec][P000026ec] 00052783 : lw r15,0x000(r10) r10=>00003f68 (00003f68)=>000026fc r15<=000026fc 67:M:MBar:[000026f0][P000026f0] 00078067 : jalr r00,r15,0x067 r15=>000026fc pc<=000026fc 68:M:MBar:[000026fc][P000026fc] 7e81a503 : lw r10,0x7e8(r03) r03=>00008010 (000087f8)=>00000000 r10<=00000000 69:M:MBar:[00002700][P00002700] 00008067 : jalr r00,r01,0x067 r01=>0000335c pc<=0000335c 70:M:MBar:[0000335c][P0000335c] 00a11623 : sh r10,0x00c(r02) r02=>0000bf78 r10=>00000000 (0000bf84)<=736e0000 71:M:MBar:[00003360][P00003360] 00200513 : addi r10,r00,0x002 r00=>00000000 r10<=00000002
スクリプトを使ってこの2つのログが一致しているかを確認するのはとてもたやすい話だ。 さああなたは上記のログでどこが不一致か分かるかな?(まだバグあり笑)