@Vengineerの戯言 : Twitter
SystemVerilogの世界へようこそ、すべては、SystemC v0.9公開から始まった
Google の RISCV-DVのソースコードを眺めてみました。
あたしは、Design 眺めるより、Verification 眺める方が好きなので。。。
パッケージ ( riscv_instr_test_pkg.sv ) は、こちら。
package riscv_instr_test_pkg;
import uvm_pkg::*;
import riscv_instr_pkg::*;
`include "riscv_instr_base_test.sv"
`include "riscv_instr_test_lib.sv"
`include "riscv_instr_cov_test.sv"
endpackage
baseのテストになるものが、risc_instr_base_test.sv
- virtual function void build_phase(uvm_phase phase);
- function void report_phase(uvm_phase phase);
- virtual function void apply_directed_instr();
- task run_phase(uvm_phase phase);
- virtual function void randomize_cfg();
が定義されているが、apply_directed_instr は空。apply_directed_instr は、run_phase の中で呼ばれる。
task run_phase(uvm_phase phase);
int fd;
for(int i = 0; i < cfg.num_of_tests; i++) begin
string test_name;
randomize_cfg();
riscv_instr::create_instr_list(cfg);
asm_gen = riscv_asm_program_gen::type_id::create("asm_gen", , `gfn);
asm_gen.cfg = cfg;
asm_gen.get_directed_instr_stream();
test_name = $sformatf("%0s_%0d.S", asm_file_name, i+start_idx);
apply_directed_instr();
`uvm_info(`gfn, "All directed instruction is applied", UVM_LOW)
asm_gen.gen_program();
asm_gen.gen_test_file(test_name);
end
endtask
ダイレクト検証したいときは、test で apply_directed_instr を定義すればいい。
riscv_instr_test_lib.sv の riscv_rand_instr_test とか。
virtual function void apply_directed_instr();
// Mix below directed instructino streams with the random instructions
asm_gen.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 4);
asm_gen.add_directed_instr_stream("riscv_loop_instr", 3);
asm_gen.add_directed_instr_stream("riscv_jal_instr", 4);
asm_gen.add_directed_instr_stream("riscv_hazard_instr_stream", 4);
asm_gen.add_directed_instr_stream("riscv_load_store_hazard_instr_stream", 4);
asm_gen.add_directed_instr_stream("riscv_multi_page_load_store_instr_stream", 4);
asm_gen.add_directed_instr_stream("riscv_mem_region_stress_test", 4);
endfunction
制約付きランダム生成をする場合は、randomize_cfg 内で色々定義すればいい。
たとえば、riscv_instr_test_lib.sv の riscv_rand_instr_test では、次のようなことを行っている。
virtual function void randomize_cfg();
cfg.instr_cnt = 10000;
cfg.num_of_sub_program = 5;
`DV_CHECK_RANDOMIZE_FATAL(cfg)
`uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s",
cfg.sprint()), UVM_LOW)
endfunction
インストラクションの数は、cfg.instr_cnt で設定。
トップテストベンチは、こちら。
module riscv_instr_gen_tb_top;
import uvm_pkg::*;
import riscv_instr_test_pkg::*;
initial begin
run_test();
end
endmodule
UVM の run_test を呼んでいるだけ。
このファイルは、files.f で使われている。
// HEADERS
+incdir+${RISCV_DV_ROOT}/src
+incdir+${RISCV_DV_ROOT}/test
// SOURCES
${RISCV_DV_ROOT}/src/riscv_signature_pkg.sv
${RISCV_DV_ROOT}/src/riscv_instr_pkg.sv
${RISCV_DV_ROOT}/test/riscv_instr_test_pkg.sv
${RISCV_DV_ROOT}/test/riscv_instr_gen_tb_top.sv
このファイル (files.f) は、 ここ(simulator.yaml)で使われている。
simulator.yaml では、
vcs (Synopsys)
ius (Cadence)
questa (Mentor)
dsim
qrun
riviera (Aldec)