FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Vivado Simulatorを使ってUVMに入門する (24. UVMを使ってランダムパタンジェネレータを作りたい)

前回はこちら:msyksphinz.hatenablog.com

前回、ランダム命令を生成するための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;

  constraint inst_opcode_c { soft opcode inside {'h33}; }
  constraint inst_funct3_c { soft funct3 inside {'h0}; }
  constraint inst_funct7_c { soft funct7 inside {'h0}; }

全部constraintを使って記述することで、なんとなくカッコよくなった気がする。 生成結果も問題ないように見える。

UVM_INFO ./model/inst_gen_driver.sv(34) @ 200000: uvm_test_top.e0.a0.d0 [DRV] Inst : 017381b3 add     gp, t2, s7
UVM_INFO ./model/inst_gen_driver.sv(34) @ 300000: uvm_test_top.e0.a0.d0 [DRV] Inst : 00068133 add     sp, a3, zero
UVM_INFO ./model/inst_gen_driver.sv(34) @ 400000: uvm_test_top.e0.a0.d0 [DRV] Inst : 00660fb3 add     t6, a2, t1
UVM_INFO ./model/inst_gen_driver.sv(34) @ 500000: uvm_test_top.e0.a0.d0 [DRV] Inst : 015901b3 add     gp, s2, s5
UVM_INFO ./model/inst_gen_driver.sv(34) @ 600000: uvm_test_top.e0.a0.d0 [DRV] Inst : 010d02b3 add     t0, s10, a6
UVM_INFO ./model/inst_gen_driver.sv(34) @ 700000: uvm_test_top.e0.a0.d0 [DRV] Inst : 009401b3 add     gp, s0, s1
UVM_INFO ./model/inst_gen_driver.sv(34) @ 800000: uvm_test_top.e0.a0.d0 [DRV] Inst : 005904b3 add     s1, s2, t0
UVM_INFO ./model/inst_gen_driver.sv(34) @ 900000: uvm_test_top.e0.a0.d0 [DRV] Inst : 001701b3 add     gp, a4, ra
UVM_INFO ./model/inst_gen_driver.sv(34) @ 1000000: uvm_test_top.e0.a0.d0 [DRV] Inst : 00848433 add     s0, s1, s0
UVM_INFO ./model/inst_gen_driver.sv(34) @ 1100000: uvm_test_top.e0.a0.d0 [DRV] Inst : 01440133 add     sp, s0, s4
UVM_INFO ./model/inst_gen_driver.sv(34) @ 1200000: uvm_test_top.e0.a0.d0 [DRV] Inst : 00158633 add     a2, a1, ra
UVM_INFO ./model/inst_gen_driver.sv(34) @ 1300000: uvm_test_top.e0.a0.d0 [DRV] Inst : 018c8633 add     a2, s9, s8
UVM_INFO ./model/inst_gen_driver.sv(34) @ 1400000: uvm_test_top.e0.a0.d0 [DRV] Inst : 01308d33 add     s10, ra, s3
UVM_INFO ./model/inst_gen_driver.sv(34) @ 1500000: uvm_test_top.e0.a0.d0 [DRV] Inst : 01030d33 add     s10, t1, a6
UVM_INFO ./model/inst_gen_driver.sv(34) @ 1600000: uvm_test_top.e0.a0.d0 [DRV] Inst : 01b38db3 add     s11, t2, s11
UVM_INFO ./model/inst_gen_driver.sv(34) @ 1700000: uvm_test_top.e0.a0.d0 [DRV] Inst : 00518cb3 add     s9, gp, t0

しかし、これでもやっぱり違う気がする。この制約はSequence Itemに与えられるものじゃなくて、testに対して与えられるものでは? というわけで、今度はSequence Itemではなくtestの方に制約を追加してみる。

この時、testにおいてuvm sequenceではなくuvm sequenceに対して制約を適用させたいため、UVM sequenceにおいてitemをメンバ変数にし、test側から直接触れるようにする。

  virtual task run_phase (uvm_phase phase);
    inst_gen_gen_item_seq seq = inst_gen_gen_item_seq::type_id::create ("seq");
    phase.raise_objection(this);
    apply_reset();

    seq.item.randomize() with {
      opcode inside {'h33};
      funct3 inside {'h0};
      funct7 inside {'h0};
    };

    seq.start(e0.a0.s0);
    phase.drop_objection(this);
  endtask // run_phase

しかしこれでもなんかまだ制約が正しく効いていない感じだ。もうちょっと調査する。