Western DigitalからオリジナルのRISC-VコアSweRVがリリースされ、テストベンチが存在しないのでしばらく放置していたのだが、リビジョンが上がってテストベンチが公開された。
https://github.com/westerndigitalcorporation/swerv_eh1
しかし、ソースコードは公開されておらず、hexファイルしか存在してない!これではどのようにして動いているのか解析できない。
./testbench/hex/data.hex ./testbench/hex/program.hex
テストベンチの実行方法は以下だ。単純にhexをロードして動作させている。実行化完了すると"HELLO WORLD"と表示される。
make -f $RV_ROOT/tools/Makefile verilator-run
... cp /home/msyksphinz/work/riscv/swerv_eh1/testbench/hex/*.hex . ./obj_dir/Vtb_top Start of sim HELLO WORLD End of sim
手動で逆アセンブリしても良いのだが、唯一の解析手段としてトレースデータ(trace_port.csv
)が出力されている。これを見てみることにする。
少し読みにくいので、文字列を揃えて読みやすくする。
diff --git a/testbench/tb_top.sv b/testbench/tb_top.sv index a6dff4d..e5da3d1 100644 --- a/testbench/tb_top.sv +++ b/testbench/tb_top.sv @@ -131,8 +131,28 @@ module tb_top ( input logic core_clk, input logic reset_l); $write("%c", i_ahb_lsu.WriteData[7:0]); end - always @(posedge core_clk) - $fwrite(tp,"%b,%h,%h,%0h,%0h,3,%b,%h,%h,%b\n", rvtop.trace_rv_i_valid_ip, rvtop.trace_rv_i_address_ip[63:32], rvtop.trace_rv_i_address_ip[31:0], rvtop.trace_rv_i_insn_ip[63:32], rvtop.trace_rv_i_insn_ip[31:0],rvtop.trace_rv_i_exception_ip,rvtop.trace_rv_i_ecause_ip,rvtop.trace_rv_i_tval_ip,rvtop.trace_rv_i_interrupt_ip); + always @(posedge core_clk) begin + $fwrite(tp,"%03b,0x%08x_%08x,0x%08x_%08x,3,%03b,%01x,%08x,%03b ", + rvtop.trace_rv_i_valid_ip, + rvtop.trace_rv_i_address_ip[63:32], + rvtop.trace_rv_i_address_ip[31: 0], + rvtop.trace_rv_i_insn_ip[63:32], + rvtop.trace_rv_i_insn_ip[31: 0], + rvtop.trace_rv_i_exception_ip, + rvtop.trace_rv_i_ecause_ip, + rvtop.trace_rv_i_tval_ip, + rvtop.trace_rv_i_interrupt_ip); + end // always @ (posedge core_clk) initial begin
ついでに、DASMも追加して逆アセンブルを表示できるようにする。
+ if (|rvtop.trace_rv_i_valid_ip[1:0]) begin + $fwrite (tp, "// "); + if (rvtop.trace_rv_i_valid_ip[1]) begin + $fwrite(tp, " | DASM(%08x)", rvtop.trace_rv_i_insn_ip[63:32]); + end + if (rvtop.trace_rv_i_valid_ip[0]) begin + $fwrite(tp, " | DASM(%08x)", rvtop.trace_rv_i_insn_ip[31: 0]); + end + end // else: !if(|rvtop.trace_rv_i_valid_ip[1:0]) + $fwrite (tp, "\n"); + end // always @ (posedge core_clk)
trace_port.csv
を見てみる。さらに、先頭の3ビットが"000"のものはバブルなので除去すると以下のようになる。
$ grep -v ^000 trace_port.csv
001,0x00000000_00000000,0x00000000_b0219173,3,000,00,00000000,000 // | DASM(b0219173) 001,0x00000000_00000004,0x00000000_ee0002b7,3,000,00,00000000,000 // | DASM(ee0002b7) 001,0x00000000_00000008,0x00000000_0002e293,3,000,00,00000000,000 // | DASM(0002e293) 001,0x00000000_0000000c,0x00000000_30529173,3,000,00,00000000,000 // | DASM(30529173) 001,0x00000000_00000010,0x00000000_5d555337,3,000,00,00000000,000 // | DASM(5d555337) 001,0x00000000_00000014,0x00000000_55536313,3,000,00,00000000,000 // | DASM(55536313) 001,0x00000000_00000018,0x00000000_7c0310f3,3,000,00,00000000,000 // | DASM(7c0310f3) 001,0x00000000_0000001c,0x00000000_000002b7,3,000,00,00000000,000 // | DASM(000002b7) 001,0x00000000_00000020,0x00000000_0002e293,3,000,00,00000000,000 // | DASM(0002e293) 001,0x00000000_00000024,0x00000000_7f829173,3,000,00,00000000,000 // | DASM(7f829173) 001,0x00000000_00000028,0x00000000_000002b7,3,000,00,00000000,000 // | DASM(000002b7) 001,0x00000000_0000002c,0x00000000_0002e293,3,000,00,00000000,000 // | DASM(0002e293) 001,0x00000000_00000030,0x00000000_7f929173,3,000,00,00000000,000 // | DASM(7f929173) 011,0x00000038_00000034,0xf0040537_00000013,3,000,00,00000000,000 // | DASM(f0040537) | DASM(00000013) 011,0x00000040_0000003c,0x00100013_00056513,3,000,00,00000000,000 // | DASM(00100013) | DASM(00056513) 011,0x00000048_00000044,0x04806493_000004b7,3,000,00,00000000,000 // | DASM(04806493) | DASM(000004b7) 001,0x00000048_0000004c,0x04806493_00108093,3,000,00,00000000,000 // | DASM(00108093) 011,0x00000054_00000050,0xd05805b7_00108093,3,000,00,00000000,000 // | DASM(d05805b7) | DASM(00108093) 011,0x0000005c_00000058,0x000004b7_0005e593,3,000,00,00000000,000 // | DASM(000004b7) | DASM(0005e593) 011,0x00000064_00000060,0x0095a023_0484e493,3,000,00,00000000,000 // | DASM(0095a023) | DASM(0484e493) 001,0x00000064_00000068,0x0095a023_000004b7,3,000,00,00000000,000 // | DASM(000004b7) 011,0x00000070_0000006c,0x0095a023_0454e493,3,000,00,00000000,000 // | DASM(0095a023) | DASM(0454e493) 011,0x00000078_00000074,0x00748493_00000013,3,000,00,00000000,000 // | DASM(00748493) | DASM(00000013) 001,0x00000078_0000007c,0x00748493_00000013,3,000,00,00000000,000 // | DASM(00000013) 011,0x00000084_00000080,0x00000013_0095a023,3,000,00,00000000,000 // | DASM(00000013) | DASM(0095a023) 011,0x0000008c_00000088,0x00000013_0095a023,3,000,00,00000000,000 // | DASM(00000013) | DASM(0095a023) 011,0x00000094_00000090,0x00348493_00000013,3,000,00,00000000,000 // | DASM(00348493) | DASM(00000013)
さらに逆アセンブリを追加する。
grep -v ^000 trace_port.csv | spike-dasm
001,0x00000000_00000000,0x00000000_b0219173,3,000,00,00000000,000 // | csrrw sp, minstret, gp 001,0x00000000_00000004,0x00000000_ee0002b7,3,000,00,00000000,000 // | lui t0, 0xee000 001,0x00000000_00000008,0x00000000_0002e293,3,000,00,00000000,000 // | ori t0, t0, 0 001,0x00000000_0000000c,0x00000000_30529173,3,000,00,00000000,000 // | csrrw sp, mtvec, t0 001,0x00000000_00000010,0x00000000_5d555337,3,000,00,00000000,000 // | lui t1, 0x5d555 001,0x00000000_00000014,0x00000000_55536313,3,000,00,00000000,000 // | ori t1, t1, 1365 001,0x00000000_00000018,0x00000000_7c0310f3,3,000,00,00000000,000 // | csrrw ra, unknown_7c0, t1 001,0x00000000_0000001c,0x00000000_000002b7,3,000,00,00000000,000 // | lui t0, 0x0 001,0x00000000_00000020,0x00000000_0002e293,3,000,00,00000000,000 // | ori t0, t0, 0 001,0x00000000_00000024,0x00000000_7f829173,3,000,00,00000000,000 // | csrrw sp, unknown_7f8, t0 001,0x00000000_00000028,0x00000000_000002b7,3,000,00,00000000,000 // | lui t0, 0x0 001,0x00000000_0000002c,0x00000000_0002e293,3,000,00,00000000,000 // | ori t0, t0, 0 001,0x00000000_00000030,0x00000000_7f929173,3,000,00,00000000,000 // | csrrw sp, unknown_7f9, t0 011,0x00000038_00000034,0xf0040537_00000013,3,000,00,00000000,000 // | lui a0, 0xf0040 | nop 011,0x00000040_0000003c,0x00100013_00056513,3,000,00,00000000,000 // | li zero, 1 | ori a0, a0, 0 011,0x00000048_00000044,0x04806493_000004b7,3,000,00,00000000,000 // | ori s1, zero, 72 | lui s1, 0x0 001,0x00000048_0000004c,0x04806493_00108093,3,000,00,00000000,000 // | addi ra, ra, 1 011,0x00000054_00000050,0xd05805b7_00108093,3,000,00,00000000,000 // | lui a1, 0xd0580 | addi ra, ra, 1 011,0x0000005c_00000058,0x000004b7_0005e593,3,000,00,00000000,000 // | lui s1, 0x0 | ori a1, a1, 0 011,0x00000064_00000060,0x0095a023_0484e493,3,000,00,00000000,000 // | sw s1, 0(a1) | ori s1, s1, 72 001,0x00000064_00000068,0x0095a023_000004b7,3,000,00,00000000,000 // | lui s1, 0x0 011,0x00000070_0000006c,0x0095a023_0454e493,3,000,00,00000000,000 // | sw s1, 0(a1) | ori s1, s1, 69 011,0x00000078_00000074,0x00748493_00000013,3,000,00,00000000,000 // | addi s1, s1, 7 | nop 001,0x00000078_0000007c,0x00748493_00000013,3,000,00,00000000,000 // | nop 011,0x00000084_00000080,0x00000013_0095a023,3,000,00,00000000,000 // | nop | sw s1, 0(a1) 011,0x0000008c_00000088,0x00000013_0095a023,3,000,00,00000000,000 // | nop | sw s1, 0(a1)
- アドレス
0xd058_0000
に文字データを書き込む。 - H(79) → E(69) → L(69+7) → L(76) → O(79) → " "(32) → W(32+55) → O(79) → R(83) → L(76) → D(68)
という、非常にストレートで無理やり文字列を出力するプログラムだった。少し笑える。