美文网首页UVM实战(张强)
第二章 一个简单的UVM验证平台

第二章 一个简单的UVM验证平台

作者: Shankssss | 来源:发表于2020-03-07 22:06 被阅读0次

    2.1 验证平台的组成

    2.2 只有driver的验证平台

    2.2.1 最简单的验证平台

    class my_driver extends uvm_driver;

        function new(string name = "my_driver", uvm_component parent = null);

            super.new(name, parent);

        endfunction

        extern virtual task main_phase(uvm_phase phase)

    endclass

    task my driver::main_phase(uvm_phase phase);

        ......

            `uvm_info("my_driver", "data is drived", UVM_LOW)

        ......

    endtask

    uvm_driver是一个派生字uvm_component的类,每一个派生自uvm_component或其派生类的类在其new函数种要指明两个参数:name 和 parent。

    uvm_info宏有三个参数,第一个参数是字符串,把打印的信息归类,第二个参数是具体要打印的信息,第三个参数是冗余级别(UVM_LOW, UVM_MEDIUM, UVM_HIGH)。

    get_full_name() 获取路径索引。

    2.2.1 加入factory机制

    "my_driver.sv"

    class my_driver extends uvm_driver;

        `uvm_component_utils(my_driver)

        ......

    endclass

    "top_tb.sv"

    module top_tb;

    initial begin

        run_test("my_driver");

    end

    endmodule

    `uvm_component_utils(my_driver) 其功能之一是将my_driver登记在UVM内部的一张表中,这张表是factory功能实现的基础。

    一个run_test语句会创建一个my_driver的实例,并会自动调用my_driver的main_phase。只有在类的定义时声明了`uvm_component_utils(my_driver)才能使用这个功能。所有派生自uvm_component及其派生类的类都应该使用宏注册。

    2.2.3 加入objection机制

    task my_driver::main_phase(uvm_phase phase);

        phase.raise_objection(this);

        ......

        phase.drop_objection(this);

    endtask

    raise_objection语句必须在main_phase种第一个消耗仿真时间的语句之前,如$display语句可以放在raise_objection之前。

    2.2.4 加入virtual interface

    "top_tb.sv"

    module top_tb;

    initial begin

        run_test("my_driver");

    end

    initial begin

        uvm_config_db#(virtual my_if)::set(null, "uvm_test_top", "vif", input);

    end

    endmodule

    "my_driver.sv"

    virtual function void build_phase(uvm_phase phase);

        ......

        if(!uvm_config_db#(virtual my_if)::get(this, " ", "vif", vif)

        ......

    endfunction

    UVM通过run_test语句实例化了一个脱离了top_tb层次结构的实例,建立了一个新的层次结构。

    对于这种脱离了top_tb层次结构,同时又期望在top_tb中对其进行某些操作的实例,UVM引进了config_db机制。

    在build_phase中主要通过config_db的 set 和 get 操作来传递一些数据,以及实例化成员变量等。build_phase是一个函数phase,不消耗仿真时间,总是在仿真时间为0时执行,而main_phase是一个任务phase。

    config_db的 set 和 get 函数都有四个参数,这两个函数的第三个参数必须完全一致。set函数的第四个参数表示要将哪个interface通过config_db传递给my_driver,get函数的第四个参数表示把得到的interface传递给哪个my_driver的成员变量。set函数的第二个参数表示的是路径索引,无论传递给run_test的参数是什么,创建的实例的名字都为uvm_test_top,因为set操作的目标是my_driver,所以set函数的第二个参数就是uvm_test_top。

    2.3 为验证平台加入各个组件

    2.3.1 加入transaction

    验证平台的组件之间,信息的传递是基于transaction的。

    class my_transaction extends uvm_sequence_item;

        rand bit [47:0] dmac;

        ......

        constraint ...{}

        function bit [31:0] calc_crc();

            return 32'h0;

        endfunction

        `uvm_object_utils(my_transaction)

        function new(...);

        ......

    endclass

    在UVM中,所有transaction都要从uvm_sequence_item派生。

    my_transaction有生命周期,这种类都是派生自uvm_object或者uvm_object的派生类,uvm_sequence_item的祖先就是uvm_object,UVM中具有这种特征的类都要使用uvm_object_utils宏来实现。

    2.3.2 加入env

    run_test只能实例化一个实例。引入一个容器类,在这个容器类中实例化driver, monitor, reference model 和 scoreboard等,在调用run_test时,传递参数是这个容器类,uvm_env。

    class my_env extends uvm_env;

        my_driver drv;

        ......

        virtual function void build_phase(uvm_phase phase);

            super.build_phase(phase);

            drv = my_driver::type_id::create("drv", this);

        endfunction

        `uvm_component_utils(my_env)

    endclass

    factory机制注册过的类的实例化: type_name::type_id::create()。

    2.3.3 加入monitor

    class my_monitor extends uvm_monitor;

        virtual my_if vif;

        `uvm_component_utils(my_monitor)

        function new(...)

        ......

        virtual function void build_phase(uvm_phase phase);

        ......

    endclass

    2.3.4 封装成agent

    driver和monitor二者处理的是同一种协议,agent将driver和monitor封装在一起,不同agent代表了不同的协议。

    class my_agent extends uvm_agent;

        my_driver     drv;

        my_monitor  mon;

        ......

        `uvm_component_utils(my_agent)

    endclass

    function void my_agent::build_phase(uvm_phase phase);

        super.build_phase(phase);

        if(is.active == UVM_ACTIVE)    begin

            drv = my_driver::type_id::create("drv", this);

        end

        mon = my_monitor::type_id::create("mon", this);

    endfunction

    function void my_agent::connect_phase(uvm_phase phase);

        super.connect_phase(phase);

    endfunction

    is_avtive 是uvm_agent的一个成员变量:

        uvm_active_passive_enum is_active = UVM_ACTIVE;

        typedef enum bit {UVM_PASSIVE=0, UVM_ACTIVE=1} uvm_active_passive_enum;

    2.3.5 加入reference model

    class my_model extends uvm_component;

        uvm_blocking_get_port     #(my_transaction)     port;

        uvm_analysis_port    #(my_transaction)    ap;

    在UVM中,通常使用TLM(Transaction Level Modeling)实现compone之间transaction级别的通信。

    数据的一种发送方式:uvm_analysis_port

    数据的一种接收方式:uvm_blocking_get_port

    my_monitor在main_phase收集完一个transaction,将其写入ap中:

                task my_monitor::main_phase(uvm_phase phase);

                    ......

                    ap.write(tr);

    my_env中使用fifo将 ap 和 port 端口联系在一起:

                uvm_tlm_analysis_fifo    #(my_transaction)    agt_mdl_fifo;

                ......

                agt_mdl_fifo = new("agt_mdl_fifo", this);

    my_env在connect_phase中将fifo分别与my_monitor中的analysis_port和my_model中的blocking_get_port相连:

                function void my_env::connect_phase(uvm_phase phase);

                    super.connect_phase(phase);

                    i_agt.ap.connect(agt_mdl_fifo.analysis_export);

                    mdl.port.connect(agt_mdl_fifo.blocking_get_export);

                endfunction

    my_agent在connect_phase中:ap = mon.ap。

    2.3.6 加入scoreboard

    class my_scoreboard extends uvm_scoreboard;

    2.3.7 加入field_automation机制

    class my_transaction extends uvm_sequence_item;

        rand bit[47:0] dmac;

        rand byte       pload[];

        ......

        `uvm_object_utils_begin(my_transaction)

            `uvm_field_int(dmac, UVM_ALL_ON)

            `uvm_field_array_int(pload, UVM_ALL_ON)

        `uvm_object_utils_end

    endclass

    使用uvm_object_utils_begin和uvm_object_utils_end来实现my_factory的factory注册,在这两个宏中间,使用uvm_field宏注册所有字段,就可以直接调用copy, compare, print等函数。

    data_size = tr.pack_bytes(data_q)/8

                pack_bytes将 tr 中的所有字段变成byte流放入data_q中,字段按照uvm_field系列宏书写的顺序排列。

    data_size = tr.unpack_bytes(data_array)/8

                unpack_bytes将data_q中的byte流转换成 tr 中的各个字段,其输入参数必须是一个动态数组。

    2.4 UVM的终极大作:Sequence

    2.4.1 在验证平台中加入sequencer

    在规范化的UVM验证平台中,driver只负责驱动transaction,而不负责产生transaction。

    class my_sequencer extends uvm_sequencer #(my_transaction);

        function new(string name, uvm_component parent);

            super.new(name, parent);

        endfunction

        `uvm_component_utils(my_sequencer)

    endclass

    class my_driver extends uvm_driver #(my_transaction);

    2.4.2 sequence机制

    class my_sequence extends uvm_sequence #(my_transaction);

        my_transaction m_trans;

        function new(string name = "my_sequence");

            super.new(name);

        endfunction

        virtual task body();

            repeat (10) begin

                `uvm_do(m_trans)

            end

            #1000;

        endtask

        `uvm_object_utils(my_sequence)

    endclass

    当一个sequence启动之后,会自动执行body中的代码。

    `uvm_do: (1)创建一个my_transaction的实例m_trans; (2)将其随机化; (3)最终将其送给sequencer。

    uvm_driver中有成员变量seq_item_port,uvm_sequencer中有成员变量seq_item_export,这两者之间可以建立一个通道,通道中传递transaction。在my_agent中,使用connect函数将两者联系在一起:

    drv.seq_item_port.connect(sqr.seq_item_export);

    2.4.3 default_sequence的使用

    "my_env.sv"

    virtual function void build_phase(uvm_phase phase);

        super.build_phase(phase);

        ......

        uvm_config_db#(uvm_object_wrapper)::set(this, "i_agt.sqr.main_phase", "default_sequence", my_sequence::type_id::get());

    2.5 建造测试用例

    2.5.1 加入base_test

    class base_test extends uvm_test;

        my_env    env;

        function new(...)

        extern virtual function void build_phase(uvm_phase phase);

        extern virtual function void report_phase(uvm_phase phase);

        `uvm_component_utils(base_test)

    endclass

    2.5.2 UVM中测试用例的启动

    class case0_sequence extends uvm_sequence #(my_transaction);

    ......

    endclass

    class my_case0 extends base_test

        ......

        uvm_config_db#(uvm_object_wrapper)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", case0_sequence::type_id::get());

    class case1_sequence extends uvm_sequence #(my_transaction);

    ......

    endclass

    class my_case1 extends base_test

    ......

    endclass

                    

    相关文章

      网友评论

        本文标题:第二章 一个简单的UVM验证平台

        本文链接:https://www.haomeiwen.com/subject/qrrkdhtx.html