日常记录(74)其它

约束重载

  • 约束的定义:constraint name{},如果是想分布的,用dist就可以。
  • 约束的重载是把类继承一下,被继承了然后覆盖约束,用子类完成功能调用。
module taa ();
    class con_base;
        rand int a;
        rand int b;
        constraint a_b{
            a dist{0:=4, 1:= 1};
            b dist{0:=2, 1:= 2};
        }

        function void print();
            $display("a is %d, b is %d", a, b);
        endfunction: print
    endclass

    class con_custom extends con_base;
        constraint a_b{
            a ==1;
            b ==2;
        }
        function void print();
            super.print();
        endfunction: print

    endclass: con_custom

    initial begin
        con_base cons_inst = new();
        con_custom cust_inst = new();
        cust_inst.randomize();
        cust_inst.print();
        cust_inst.randomize();
        cust_inst.print();
        cust_inst.randomize();
        cust_inst.print();
        cust_inst.randomize();
        cust_inst.print();
        cust_inst.randomize();
        cust_inst.print();
    end
endmodule

输出结果:

a is           1, b is           2
a is           1, b is           2
a is           1, b is           2
a is           1, b is           2
a is           1, b is           2

工厂类的重载

  • set_type_override等的方法,是继承父类实现子类,然后重载最终以父类形式调用了子类。约束本身也可以被重载(soft)
  • 一般的uvm方法是有virtual的,但是没有就一定要加,都加也更保险一些,否则无法完成重载。
  • set_type_override等的方法,需要在实例化以前被调用,才能实现重载功能,否则uvm_top.print_topology();看不到效果,虽然print_override_info可以看到效果。
module tbb ();
    import uvm_pkg::*;
    class source extends uvm_component;
        `uvm_component_utils(source)
        function new(string name="source", uvm_component parent);
            super.new(name, parent);
        endfunction: new

        virtual function void print();
            `uvm_info("SOURCE", $sformatf("source print"), UVM_LOW)
        endfunction: print
    endclass: source

    class target extends source;
        `uvm_component_utils(target)
        function new(string name="target", uvm_component parent);
            super.new(name, parent);
        endfunction: new

        function void print();
            `uvm_info("TARGET", $sformatf("target print"), UVM_LOW)
        endfunction: print
    endclass: target

    class my_test extends uvm_test;
        `uvm_component_utils(my_test)
        source s;
        target t;

        function new(string name="my_test", uvm_component parent);
            super.new(name, parent);
        endfunction: new

        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            set_type_override_by_type(source::get_type(), target::get_type());
            s = source::type_id::create("s", this);
            t = target::type_id::create("t", this);

            uvm_top.print_topology();
            print_override_info("source");
        endfunction: build_phase

        function void start_of_simulation_phase(uvm_phase phase);
            super.start_of_simulation_phase(phase);
            s.print();
            t.print();
        endfunction:start_of_simulation_phase

        task run_phase(uvm_phase phase);
            s.print();
            t.print();
        endtask: run_phase
    endclass: my_test

    initial begin
        run_test("my_test");
    end
endmodule

输出结果:

UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO /home/synopsys/vcs-mx/O-2018.09-1/etc/uvm-1.2/base/uvm_root.svh(589) @ 0: reporter [UVMTOP] UVM testbench topology:
----------------------------------
Name          Type     Size  Value
----------------------------------
uvm_test_top  my_test  -     @335 
  s           target   -     @348 
  t           target   -     @357 
----------------------------------

UVM_INFO /home/synopsys/vcs-mx/O-2018.09-1/etc/uvm-1.2/base/uvm_factory.svh(1786) @ 0: reporter [UVM/FACTORY/DUMP] 
#### Factory Override Information (*)

Given a request for an object of type 'source' with an instance
path of 'uvm_test_top' the factory encountered

the following relevant overrides. An 'x' next to a match indicates a
match that was ignored.

Original Type  Instance Path  Override Type
  -------------  -------------  -------------
  source       
  *              target         <type override>
Result:

  The factory will produce an object of type 'target'

(*) Types with no associated type name will be printed as <unknown>

####


UVM_INFO tbb.sv(22) @ 0: uvm_test_top.s [TARGET] target print
UVM_INFO tbb.sv(22) @ 0: uvm_test_top.t [TARGET] target print
UVM_INFO tbb.sv(22) @ 0: uvm_test_top.s [TARGET] target print
UVM_INFO tbb.sv(22) @ 0: uvm_test_top.t [TARGET] target print
UVM_INFO /home/synopsys/vcs-mx/O-2018.09-1/etc/uvm-1.2/base/uvm_report_server.svh(894) @ 0: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

** Report counts by severity
UVM_INFO :    8
UVM_WARNING :    0
UVM_ERROR :    0
UVM_FATAL :    0
** Report counts by id
[RNTST]     1
[TARGET]     4
[UVM/FACTORY/DUMP]     1
[UVM/RELNOTES]     1
[UVMTOP]     1

$finish called from file "/home/synopsys/vcs-mx/O-2018.09-1/etc/uvm-1.2/base/uvm_root.svh", line 527.
$finish at simulation time                    0

uvm的create_object_by_name

在定义该class以后,编译的阶段(程序还没开始运行,没有发生任何调用),my_driver对应的get函数就被调用了,由于刚调用的时候,me还是空的,就进入到分支中,创建了me。这个me只是一个registry类的实例,里面有一个指针inst和一个名称Tname。该类被放置到global_tab中。使用的时候,取出来工厂类的inst的部分,然后给它new出来,得到了对象。
因此:在uvm的实现中,任何component既然注册,意思就是创建了一个工厂类的实例,但是里面的class类型T,虽然被指定,但是没有实例,是在运行时调用对应的方法实现的实例。
uvm的factory机制:

class registry#(type T=uvm_object, string Tname="");
	T inst;
	string name = Tname;
endclass

class my_driver
	typedef registry#(my_driver, "my_driver") this_type;
	local static this_type me = get();
	static function this_type get();
		if(me == null) begin
			me = new();
			global_tab[me.name] = me;
		end
		return me;
	enfunction
endclass

function uvm_component create_component_by_name(string name)
	registry#(uvm_object, "") me_ptr;
	me_ptr = global_tab[name];
	me_ptr.inst = new("uvm_test_top", null);
	return me_ptr.inst;
endfunction

定义和使用:

function uvm_object uvm_factory::create_object_by_name (string
	requested_type_name,
	string parent_inst_path="",
	string name="");

一般只使用第一个参数:

my_transaction tr;
void'($cast(tr, factory.create_object_by_name("my_transaction")));

回调函数

我这个只能在uvm1.1上用
开发者

  • 定义A(回调类),定义A_pool(回调池)、定义组件如my_comp(调用回调的组件)。
  • 其中的A包括了回调函数,A_pool中有组件和回调类,组件中注册了回调类,然后使用uvm_do_callback宏,完成回调功能。
    使用者
  • 从回调类A中继承,定义子类,实现方法即可。使用者在使用组件的时候,顺便实例化回调的子类,加入到池子中(带入组件和回调类),就可以完成回调的实现。
module tcc ();
    import uvm_pkg::*;
    typedef struct {
        string a;
        int b;
    } my_trans;

    typedef class my_comp;
    class A extends uvm_callback;
        `uvm_object_utils(A);
        virtual task pre_trans(my_comp comp, ref my_trans tr);
        endtask
    endclass: A
	typedef uvm_callbacks#(my_comp, A) A_pool;

    class my_comp extends uvm_component;
        `uvm_component_utils(my_comp)
        `uvm_register_cb(my_comp, A)
        function new(string name="my_comp", uvm_component parent);
            super.new(name, parent);
        endfunction: new

        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
        endfunction: build_phase

        task run_phase(uvm_phase phase);
            my_trans tr= '{"hahaha", 345};
            repeat (3) begin
                `uvm_do_callbacks(my_comp, A, pre_trans(this, tr));
                `uvm_info("COMP_TR", $sformatf("%s, %d", tr.a, tr.b), UVM_LOW)
            end
        endtask: run_phase
    endclass: my_comp

//-------------------------------------------------------------------------------

    class my_callback extends A;
        `uvm_object_utils(my_callback)
        task pre_trans(my_comp comp, ref my_trans tr);
            tr.a = "123";
            tr.b = 12;
            `uvm_info("CB", $sformatf("callback is here."), UVM_LOW)
        endtask: pre_trans
    endclass: my_callback

    class my_test extends uvm_test;
        `uvm_component_utils(my_test)
        my_callback my_cb;
        my_comp comp;

        function new(string name="my_test", uvm_component parent);
            super.new(name, parent);
        endfunction: new

        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            my_cb = my_callback::type_id::create("my_cb");
            comp = my_comp::type_id::create("comp", this);
            A_pool::add(comp, my_cb);
        endfunction: build_phase

    endclass: my_test

    initial begin
        run_test("my_test");
    end
endmodule

输出结果:

UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO tcc.sv(44) @ 0: reporter [CB] callback is here.
UVM_INFO tcc.sv(31) @ 0: uvm_test_top.comp [COMP_TR] 123,          12
UVM_INFO tcc.sv(44) @ 0: reporter [CB] callback is here.
UVM_INFO tcc.sv(31) @ 0: uvm_test_top.comp [COMP_TR] 123,          12
UVM_INFO tcc.sv(44) @ 0: reporter [CB] callback is here.
UVM_INFO tcc.sv(31) @ 0: uvm_test_top.comp [COMP_TR] 123,          12

--- UVM Report Summary ---

** Report counts by severity
UVM_INFO :    7
UVM_WARNING :    0
UVM_ERROR :    0
UVM_FATAL :    0
** Report counts by id
[CB]     3
[COMP_TR]     3
[RNTST]     1
$finish called from file "/home/synopsys/vcs-mx/O-2018.09-1/etc/uvm-1.1/base/uvm_root.svh", line 439.
$finish at simulation time                    0
posted @ 2022-03-10 21:09  大浪淘沙、  阅读(144)  评论(0)    收藏  举报