Vengineerの妄想(準備期間)

人生は短いけど、長いです。人生を楽しみましょう!

Google の RISCV-DV

@Vengineerの戯言 : Twitter
SystemVerilogの世界へようこそすべては、SystemC v0.9公開から始まった 

Google の RISCV-DVのソースコードを眺めてみました。

github.com

あたしは、Design 眺めるより、Verification 眺める方が好きなので。。。

こちら。test ディレクトリにある。

パッケージ ( 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)