uvm_config_dbについて考える

はじめに

UVMを使っていると必ず出てくるuvm_config_db。

なんとなく、テストベンチでInterfaceをデータベースに登録して、クラスの中で呼び出すんだなぁと漠然と思っていました。

今回は様々な条件で使用してみて理解を深めます。

また、本サンプルコードのインクルードファイルを置き換えることで動作するようになっています。

module top;
    `include "uvm_macros.svh"
    import uvm_pkg::*;

    `include "sample.svh"  // これ。
endmodule

使い方

uvm_config_db#(<型>)::set(<UVMの階層>, <インスタンス名>, <フィールド名>, <setする値>);
uvm_config_db#(<型>)::get(<UVMの階層>, <インスタンス名>, <フィールド名>, <getしたものを入れる変数>);

体感ですが、

<uvmの階層>.<インスタンス名>.<フィールド名>

みたいな感じで値がsetされていそうです。

sample0.svh
int a, b;
initial begin
    uvm_config_db#(int)::set(null, "fuga", "val1", 1);
    uvm_config_db#(int)::set(null, "fuga", "val2", 2);

    void'(uvm_config_db#(int)::get(null, "fuga", "val1", a));
    void'(uvm_config_db#(int)::get(null, "fuga", "val2", b));

    $display("%d", a);
    $display("%d", b);
end
// 出力
// 1
// 2

null.fuga.val1に1, null.fuga.val2に2をsetして取り出しました。

sample1.svh

null.fuga.val1に2回setしてみます。

int a, b;
initial begin
    uvm_config_db#(int)::set(null, "fuga", "val1", 1);
    uvm_config_db#(int)::set(null, "fuga", "val1", 2);

    void'(uvm_config_db#(int)::get(null, "fuga", "val1", a));
    $display("%d", a);
end
// 出力
// 2

上書きされました。

sample2.svh

別な型で同じ場所にsetしてみます。

int a;
string b;
initial begin
    uvm_config_db#(int)::set(null, "fuga", "val", 1);
    uvm_config_db#(string)::set(null, "fuga", "val", "hello");

    void'(uvm_config_db#(int)::get(null, "fuga", "val", a));
    void'(uvm_config_db#(string)::get(null, "fuga", "val", b));

    $display("%d", a);
    $display("%s", b);
end
// 1
// hello

同じ場所でも、型が違うと違うところにsetされています。

sample3.svh

uvm_component環境で使用します。

class sample_test extends uvm_test;
    `uvm_component_utils(sample_test)
    int a;

    function new(string name="sample_test", uvm_component parent=null);
        super.new(name, parent);
    endfunction

    task run_phase(uvm_phase phase);
        super.run_phase(phase);

        void'(uvm_config_db#(int)::get(null, "", "hoge", a));
        $display("%d", a);
    endtask
endclass

initial begin
    uvm_config_db#(int)::set(null, "", "hoge", 1);
    run_test("sample_test");
end
// 出力
// 1

sample4.svh

getせずに直接値を渡します。

class sample_test extends uvm_test;
    int a;
    `uvm_component_utils_begin(sample_test)
        `uvm_field_int(a, UVM_ALL_ON)
    `uvm_component_utils_end

    function new(string name="sample_test", uvm_component parent=null);
        super.new(name, parent);
    endfunction

    task run_phase(uvm_phase phase);
        super.run_phase(phase);
        $display("%d", a);
    endtask
endclass

initial begin
    uvm_config_db#(int)::set(null, "", "a", 2);
    run_test("sample_test");
end
// 出力
// 2
sample5.svh

uvm_componentを階層構造にします。

class sample_env extends uvm_env;
    int a;
    `uvm_component_utils_begin(sample_env)
        `uvm_field_int(a, UVM_ALL_ON)
    `uvm_component_utils_end

    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction

    task run_phase(uvm_phase phase);
        super.run_phase(phase);
        $display("Env %d", a);
    endtask
endclass

class sample_test extends uvm_test;
    int a;
    `uvm_component_utils_begin(sample_test)
        `uvm_field_int(a, UVM_ALL_ON)
    `uvm_component_utils_end
    sample_env env;

    function new(string name="sample_test", uvm_component parent=null);
        super.new(name, parent);
    endfunction

    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        env = sample_env::type_id::create("env", this);
    endfunction

    task run_phase(uvm_phase phase);
        super.run_phase(phase);
        $display("Test %d", a);
    endtask
endclass

initial begin
    uvm_config_db#(int)::set(null, "uvm_test_top.env", "a", 3);
    uvm_config_db#(int)::set(null, "uvm_test_top", "a", 4);
    run_test("sample_test");
end

// 出力
// Test 4
// Env 3

まとめ

uvm_config_dbについて調べました。

コメント

タイトルとURLをコピーしました