前回はこちら:msyksphinz.hatenablog.com
UVMで色々コントロールできることが分かってきたので、今度はランダム検証に使うための要素について考えていきたい。 単純に考えられるのは、RISC-Vの命令をランダムに生成するランダムパタンジェネレータだ。
UVMのSequence ItemにRISC-Vの命令エンコーディングのフィールドを定義して、オペコードやレジスタのフィールドをランダムに変更すれば、ランダムな命令を生成できるはずだ。
とりあえず、UVMのSequence Itemを定義してみる。
rand bit [ 6: 0] opcode; rand bit [ 4: 0] rd; rand bit [ 2: 0] funct3; rand bit [ 4: 0] rs1; rand bit [ 4: 0] rs2; rand bit [ 6: 0] funct7; // Use utility macros to implement standard functions // like print, copy, clane, etc `uvm_object_utils_begin (inst_gen_seq_item) `uvm_field_int (opcode, UVM_DEFAULT) `uvm_field_int (rd, UVM_DEFAULT) `uvm_field_int (funct3, UVM_DEFAULT) `uvm_field_int (rs1, UVM_DEFAULT) `uvm_field_int (funct7, UVM_DEFAULT) `uvm_object_utils_end function new (string name = "inst_gen_seq_item"); super.new(name); endfunction // new endclass // inst_gen_seq_item
今回は全てのフィールドをランダムにするようにしているが、別に必要な部分は後で固定する。
ポイントだけを抜き出すと、以下のドライバが命令を生成する部分だ。 一部のフィールドを固定することによって、必ずADD命令が生成されるようにしている。
item.opcode = 'h33; // ADD item.funct3 = 'h0; // ADD item.funct7 = 'h0; // ADD `uvm_info("DRV", $sformatf("Instruction Generate : %08x DASM(%08x)", {item.funct7, item.rs2, item.rs1, item.funct3, item.rd, item.opcode}, {item.funct7, item.rs2, item.rs1, item.funct3, item.rd, item.opcode}), UVM_LOW); @ (posedge vif.clk); endtask // drive_item
これでUVMを実行した結果が以下となった。必要な部分だけを抜き出している。spike-dasm
に掛けることによって、ADD命令が生成できていることが確認できた。
$ grep Instruction xsim.log | spike-dasm
UVM_INFO ./model/inst_gen_driver.sv(34) @ 0: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 01df8ab3 add s5, t6, t4 UVM_INFO ./model/inst_gen_driver.sv(34) @ 200000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 010b81b3 add gp, s7, a6 UVM_INFO ./model/inst_gen_driver.sv(34) @ 300000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 00900133 add sp, zero, s1 UVM_INFO ./model/inst_gen_driver.sv(34) @ 400000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 01530fb3 add t6, t1, s5 UVM_INFO ./model/inst_gen_driver.sv(34) @ 500000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 019a81b3 add gp, s5, s9 UVM_INFO ./model/inst_gen_driver.sv(34) @ 600000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 002802b3 add t0, a6, sp UVM_INFO ./model/inst_gen_driver.sv(34) @ 700000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 014481b3 add gp, s1, s4 UVM_INFO ./model/inst_gen_driver.sv(34) @ 800000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 007284b3 add s1, t0, t2 UVM_INFO ./model/inst_gen_driver.sv(34) @ 900000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 01e081b3 add gp, ra, t5 UVM_INFO ./model/inst_gen_driver.sv(34) @ 1000000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 00540433 add s0, s0, t0 UVM_INFO ./model/inst_gen_driver.sv(34) @ 1100000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 002a0133 add sp, s4, sp UVM_INFO ./model/inst_gen_driver.sv(34) @ 1200000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 01708633 add a2, ra, s7 UVM_INFO ./model/inst_gen_driver.sv(34) @ 1300000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 009c0633 add a2, s8, s1 UVM_INFO ./model/inst_gen_driver.sv(34) @ 1400000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 01798d33 add s10, s3, s7 UVM_INFO ./model/inst_gen_driver.sv(34) @ 1500000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 01480d33 add s10, a6, s4 UVM_INFO ./model/inst_gen_driver.sv(34) @ 1600000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 001d8db3 add s11, s11, ra UVM_INFO ./model/inst_gen_driver.sv(34) @ 1700000: uvm_test_top.e0.a0.d0 [DRV] Instruction Generate : 01528cb3 add s9, t0, s5