欢迎来到皮皮网网首页

【rebase 丢失源码】【阅读tomcat源码】【sklearn 源码阅读】uvmseqencer源码

来源:php添加商品源码 时间:2024-11-23 15:42:58

1.第六章 UVM中的sequence
2.第三章 UVM基础
3.UVM验证总结(四)-sequence机制(进阶)
4.systemverilog速记--$cast
5.sequence和sequencer的区别
6.UVM学习笔记(三)

uvmseqencer源码

第六章 UVM中的sequence

        (1)通过 uvm_do_pri 和 uvm_do_pri_with 改变所产生的transaction的优先级:

                    "my_case0.sv"

                    class sequence0 extends uvm_sequence #(my_transaction);

                        ...

                        virtual task body();

                            `uvm_do_pri(m_trans, )

                             or

                            `uvm_do_pri_with(m_trans, , { m_trans.pload.size < ;})

                    第二个参数是优先级,这个数必须是一个大于等于-1的整数,数字越大,优先级越高。

        (2)sequencer的仲裁算法:

                    SEQ_ARB_FIFO(默认仲裁算法,遵循先入先出,不考虑优先级)

                    SEQ_ARB_WEIGHTED(加权的仲裁)

                    SEQ_ARB_RANDOM(完全随机选择)

                    SEQ_ARB_STRICT_FIFO(严格按照优先级,当有多个同一优先级的sequence时,按照先入先出的顺序选择)

                    SEQ_ARB_STRICT_RANDOM(严格按照优先级,当有多个同一优先级的sequence时,随即从最高优先级中选择)

                    SEQ_ARB_USER (用户自定义的仲裁算法)

                若想要优先级起作用,应该设置仲裁算法为SEQ_ARB_STRICT或者SEQ_ARB_STRICT_RANDOM:

                    env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);

                    fork

                        seq0.start(env.i_agt_sqr);

                        seq1.start(env.i_agt_sqr);

                    join

        (3)lock 操作

                 grab 操作(比lock优先级更高,放入sequencer仲裁队列的最前面)

                 is_relevent() 函数(1说明此sequence有效,否则无效)

                 wait_for_relevent() 函数

        (1)uvm_do系列

        (2)uvm_create 与 uvm_send

        (3)uvm_rand_send,与uvm_send类似,唯一区别是它会对transaction进行随机化

                        m_trans = new("m_trans");

                        `uvm_rand_send(m_trans);

        (4)`uvm_do系列宏其实是将下述动作封装在了一个宏中:

                        tr = new("tr");

                        start_item(tr);

                        assert(tr.randomize() with { tr.pload.size() == ;});

                        finish_item(tr);

        (5)pre_do (task), mid_do (function), post_do (function)

        (1)嵌套的sequence:在一个sequence的body中,除了可以使用uvm_do宏产生transaction外,该可以启动其他的sequence,直接在新的sequence的body中调用定义好的sequence。

        (2)uvm_do, uvm_send, uvm_rand_send, uvm_create宏,其第一个参数除了可以是transaction的指针外,还可以是sequence的指针。start_item & finish_item,这两个任务的参数必须是transaction的指针。

        (3)sequence与transaction都可以调用randomize进行随机话,都可以由rand修饰符的成员变量。在sequence中定义的rand类型变量以向产生的transaction传递约束时,变量的名字一定要与transaction中相应字段的名字不同。

        (4)`uvm_declare_p_sequencer(my_sequencer) == (my_sequencer p_sequencer);这个过程在pre_body()之前就完成了,因此在sequence中可以直接使用成员变量p_sequencer来访问sequencer中的成员变量。

        (1)实现sequence之间同步最好的方式就是使用virtual sequence。virtual sequence不发送transaction,它只是控制其他的sequence,起统一调度的作用。为了使用virtual sequence,一般需要一个virtual sequencer,其里面包含指向其他真实sequencer的指针。

        (2)一般来说。只在最顶层的virtual sequence中控制objection。

        (1)在sequence中获取参数

                    sequence的路径:uvm_test_top.env.i_agt.sqr.case0_sequence

                    【uvm_config_db#(int)::set(this, "env.i_agt.sqr.*", "count", 9);】

                    因为sequence在实例化时名字一般是不固定的,而且有时时未知的(比如使用default_sequence启动的sequence的名字就是未知的),所i使用通配符。

                    uvm_config_db#(int)::get(null, get_full_name(), "count", count));

                    在get函数原型中,第一个参数必须是component,而sequence不是一个component,所以这里不能使用this指针,只能使用null或uvm_root::get()。

        (2)在sequence中设置参数

                    uvm_config_db#(bit)::set(uvm_root::get(), "uvm_test_top.env0.scb", "cmp_en", 0);

                    uvm_config_db#(bit)::set(uvm_root::get(), "uvm_test_top.v_sqr.*", "first_start", 0);

        (3)一个sequence是在task phase中运行的,当其设置一个参数的时候,起事件往往是不固定的。针对这种不固定的设置参数的方式,UVM提供了wait_modified任务。当它检测当第三个参数的值被更新过后,它就返回,否则一直等待在那里:

                    uvm_config_db#(bit)::wait_modified(this, "", "cmp_en");

        (1)在driver中,

                        rsp = new("rsp");   

                        rsp.set_id_info(req);

                        seq_item_port.put_response(rsp);

                        seq_item_port.item_done();

                or

                        rsp = new("rsp");     

                        rsp.set_id_info(req);

                        seq_item_port.item_done(rsp);

                 在sequence中,

                        virtual task body();

                               ...

                               get_response(rsp);

        (1)随机选择sequence

                class simple_seq_library extends uvm_sequence_library #(my_transaction);

                    function new(string name = "simple_seq_library");

                        supre.new(name);

                        init_sequence_library();

                    endfunction

                    `uvm_object_utils(simple_seq_library)

                    `uvm_sequence_library_utils(simple_seq_library);

                endclass

                一个sequence在定义时使用宏uvm_add_to_seq_lib(seq0, simple_seq_library)来将其加入某个sequence library中。一个sequence可以加入多个sequence library中。

        (2)控制选择算法

                typedef enum { UVM_SEQ_LIB_RAND, UVM_SEQ_LIB_RANDC, UVM_SEQ_LIB_ITEM, UVM_SEQ_LIB_USER} uvm_sequence_lib_mode;

                UVM_SEQ_LIB_RAND:完全随机。

                UVM_SEQ_LIB_RANDC:将加入其中的sequence随机排一个顺序,然后按照此顺序执行,可以保证每个sequence执行一遍。配置方式:

                           uvm_config_db#(uvm_sequence_lib_mode)::set(this, "env.i_agt.sqr.main_phase", "default_sequence.selection_mode", UVM_SEQ_LIB_RANDC);

                UVM_SEQ_LIB_ITEM:sequence library并不执行其sequence队列中的sequence,而是自己产生transaction。

                UVM_SEQ_LIB_USER:用户自定义选择的算法。此时需要用户重载select_sequence参数:

                            virtual function int unsigned select_sequence(int unsigned max);

                               ...

                            endfunction

        (3)控制执行次数

                            min_random_count, max_random_count

        (4)UVM提供了一个类uvm_sequence_library_cfg来对sequence library进行配置:

                            uvm_sequence_library_cfg    cfg;

                            super.build_phase(phase);

                            cfg = new("cfg", UVM_SEQ_LIB_RANDC, 5, );

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

                            uvm_config_db#(uvm_sequence_library_cfg)::set(this. "env.i_agt.sqr.main_phase", "default_sequence.config", cfg);

                or

                            simple_seq_library     seq_lib;

                            super.build_phase(phase);

                            seq_lib = new("seq_lib");

                            seq_lib.selection_mode = UVM_SEQ_LIB_RANDC;

                            seq_lib.min_random_count = ;

                            seq_lib.max_random_count = ;

                            uvm_config_db#(uvm_sequence_base)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", seq_lib);

第三章 UVM基础

        uvm_object是UVM中最基本的类。

        uvm_component有两大特性uvm_object所没有的:(1)通过在new的时候指定parent参数来形成一种属性的组织结构;(2)有phase的自动执行特点。

        只有基于uvm_component派生的类才可能成为UVM树的结点。

        除了driver, monitor, agent, model, scoreboard, env, test之外的几乎所有的类,本质上都是uvm_object,如sequence, sequence_item, transaction, config等。

        uvm_sequence_item :所有transaction要从uvm_sequence_iem派生。 uvm_sequence_item是从uvm_transaction派生而来的,它相比uvm_transaction添加了很多实用的成员变量和函数/任务。

        uvm_sequence :所有sequence要从uvm_sequence派生,sequence就是sequence_item的组合。

        config :所有的config一般直接从uvm_object派生,其主要功能就是规范验证平台的行为方式。config是把所有参数放在一个object中,然后通过config_db的方式设置给所有需要这些参数的component。

        uvm_reg_item :派生自uvm_sequence_item,用于register model中。

        uvm_reg_map, uvm_mem, uvm_reg_field, uvm_reg, uvm_reg_file, uvm_reg_block 等与寄存器相关的众多的类都是派生自uvm_object,它们都是用于register model。

        uvm_phase :派生自uvm_object,主要作用为控制uvm_component的行为方式,使得uvm_component平滑地在各个不同的phase之间依次运转。

        uvm_driver :所有的driver都要派生自uvm_driver。driver的主要功能就是向sequencer索要sequence_item(transaction),并且将sequence_item里的信息驱动到DUT的端口上,这相当于 完成了从transaction级别到DUT能接受的端口级别信息的转换 。与uvm_component相比,uvm_driver多了如下几个成员变量:

                    uvm_seq_item_pull_port    #(REQ, RSP)    seq_item_port;

                    uvm_seq_item_pull_port    #(REQ, RSP)    seq_item_prod_if;

                    uvm_analysis_port    #(RSP)    rsp_port;

                    REQ    req;

                    RSP    rsp;

        uvm_monitor :所有的monitor都要派生自uvm_monitor。monitor从DUT的pin上接收数据,并且把接收到的数据转换成transaction级别的sequence_item,再把转换后的数据发送给scoreboard,供其比较。与uvm_component相比,uvm_monitor几乎没有做任何扩充。

        uvm_sequencer :所有的sequencer都要派生自uvm_sequencer。sequencer的功能就是组织管理sequence,当driver要求数据时,它就把sequence生成的sequence_item转发个driver。与uvm_component相比,uvm_sequencer做了相当多的扩展。

        uvm_scoreboard :一般的scoreboard都要派生自uvm_scoreboard。uvm_scoreboard几乎没有在uvm_component的基础上做扩展。

        reference model :直接派生自uvm_component。

        uvm_agent :所有agent派生自uvm_agent。它把driver和monitor封装在一起。与uvm_component相比,uvm_agent的最大改动在于引进了一个变量is_active。

        uvm_env :所有的env都要派生自uvm_env。env将验证平台上用到的固定不变的component都封装在一起。uvm_env没有在uvm_component的基础上做过多扩展。

        uvm_test :所有的测试用例都要派生自uvm_test或其派生类,不同的测试用例之间差异很大。uvm_env没有在uvm_component的基础上做任何扩展。

        在UVM中与uvm_object相关的factory宏有如下几个:

                    uvm_object_utils :用于把一个直接或间接派生自uvm_object的类注册到factory中。

                    uvm_object_param_utils :用于把一个直接或间接派生自uvm_object的参数化的类注册到factory中。

                    uvm_object_utils_begin :当需要使用field_automation机制时,需要使用此宏。

                    uvm_object_param_utils_begin

                    uvm_object_utils_end :与uvm_object_*_begin成对出现,facotry注册的结束标志。

        在UVM中与uvm_component相关的factory宏有如下几个:

                    uvm_component_utils

                    uvm_component_param_utils

                    uvm_component_utils_begin :在component中使用field_automation机制,可以自动地使用config_db来得到某些变量的值。

                    uvm_component_param_utils_begin

                    uvm_component_utils_end

        uvm_component无法使用 clone 函数,但是可以使用 copy 函数。 (clone = new + copy)

        位于同一个父结点下的不同component,在实例化时不能使用相同的名字。

        UVM中真正的树根是一个称为uvm_top的东西。uvm_top是一个全局变量,它时uvm_root的一个实例(而且也是唯一一个实例),而uvm_root派生自uvm_component,uvm_top的parent是null。

        如果一个component在实例化时,其parent被设置为null,那么这个component的parent将会被系统设置为uvm_root的实例uvm_top。还可以使用如下方式得到它的指针:

                    uvm_root top;

                    top = uvm_root::get();

       

        UVM提供了一系列的接口函数用于访问UVM树中的结点:

                    get_parent()

                    get_child(string name) :name表示此child的实例在实例化时指定的名字。

                    uvm_component array[$]

                     get_children(array)

                    get_num_children()

        `define uvm_field_**_**(ARG, FLAG)

        copy 函数:

                    B.copy(A):把实例A复制到B实例中,B必须已经使用new函数分配好了内存空间。

        compare 函数:

                    A.compare(B) or B.compare(A)。

        pack_bytes 函数:

                    用于将所有字段打包成byte流。

        unpack_bytes 函数:

                    用于将一个byte流逐一恢复到某个类的实例中。

        pack 函数:

                    用于将所有的字段打包成bit流。

        unpack 函 数:

                    用于将一个bit流逐一恢复到某个类的实例中。

        pack_ints 函数

        unpack_ints 函数

        print 函数

        clone 函数

        UVM的标志位本身是一个bit的数字:

        在打印信息之前,UVM会比较要显示信息的冗余度级别与默认的冗余度阈值。如果小于等于阈值,就会显示。默认的冗余度阈值时UVM_MEDIUM,所有低于等于UVM_MEDIUM的信息都会被打印出来。

        get_report_verbosity_level 函数:得到某个component的冗余度阈值。

        set_report_verbosity_level 函数:设置某个特定的component的默认冗余度阈值。由于需要牵扯到层次引用,所以需要在connect_phase及之后的phase才可以调用这个函数。如果不牵扯到任何层次引用,就可以在之前调用。

        set_report_verbosity_level_hier 函数:设置某个component及其以下所有的component的冗余度阈值。

        set_report_id_verbosity 函数:根据不同的uvm_info宏的id来设置冗余度阈值。

        set_report_id_verbosity_hier 函数

        UVM支持在命令行中设置冗余度阈值:

                    <sim command> +UVM_VERBOSITY=UVM_HIGH

                    <sim command> +UVM_VERBOSITY=HIGH        

                    将整个验证平台的冗余度阈值设置为UVM_HIGH。

        set_report_severity_override(UVM_WARNING, UVM_ERROR);

        set_report_severity_id_override(UVM_WARNING, "my_driver", UVM_ERROR);

        命令行中实现:

                    <sim command> +uvm_set_severity=<comp>,<id>,<current severity>,<new severity>

        set_report_max_quit_count(number);

        set_report_severity_action(UVM_WARNING, UVM_DISPLAY | UVM_COUNT):把UVM_WARNING加入计数目标。

        set_report_severity_action_hier(UVM_WARNING, UVM_DISPLAY | UVM_COUNT);

        set_report_severity_action(UVM_ERROR, UVM_DISPLAY):把UVM_ERROR从统计计数目标中移除。

        set_report_id_action("my_drv", UVM_DISPLAY | UVM_COUNT):对某个特定的ID进行计数。把ID为my_drv的所有信息加入到计数中,UVM_INFO, UVM_WARNING, UVM_ERROR, UVM_FATAL。

        set_report_severity_id_action(UVM_WARNING, "my_driver", UVM_DISPLAY | UVM_COUNT);

        ......

        命令行中设置技术目标:

                    <sim command> +uvm_set_action=<comp>,<id>,<severity>,<action>

       

        当程序执行到断点处时,停止仿真,进入交互模式,从而进行调试。

        "base_test.sv"

        virtual function void connect_phase(uvm_phase phase);

            env.i_agt.drv.set_report_severity_action(UVM_WARNING, UVM_DISPLAY | UVM_STOP);

        ...

        当env.i_agt.drv中出现UVM_WARNIN时,立即停止仿真,进入交互模式。

        命令行中设置UVM断电:

                    <sim command> +uvm_set_action="uvm_test_top.env.i_agt_drv,my_driver,UVM_WARNING,UVM_DISPLAY | UVM_STOP"

        变量名与其实例化时传递的名字不一致的情况应该尽量避免。

        config_db机制用于在UVM验证平台间传递参数,set函数和get函数通常成对出现。

        在某些情况下,可以省略get语句:

        (1)必须使用uvm_component_utils宏注册;(2)变量必须使用uvm_field宏注册;(3)在调用set函数的时候,set函数的第三个参数必须要与get函数中的变量名字相一致。

        UVM规定层次越高,它的优先级越高。越靠近根结点uvm_top,其层次越高,set函数的优先级也越高。

        寄信人的层次相同时,比较寄信的时间。

        在调用set函数时其第一个参数应该尽量使用this。在无法使用this指针的情况下(如在top_tb中),使用null或者uvm_root::get()。

        非直线的设置,如在scoreboard中对driver的某些变量使用config_db机制进行设置:

                    uvm_config_db#(int)::set(this.m_parent, "i_agt.drv", "pre_num", );

                    or

                    uvm_config_db#(int)::set(uvm_root::get(), "uvm_test_top.env.i_agt.drv", "pre_num", );

        非直线的获取,如在reference model中获取其他component设置给my_driver的参数的值:

                    void'(uvm_config_db#(int)::get(this.m_parent, "i_agt.drv", "pre_num", drv_pre_num));

                    or

                    void'(uvm_config_db#(int)::get(uvm_root::get(), "uvm_test_top.env.i_agt.drv", "pre_num", drv_pre_num));

        不推荐使用通配符。

        如果set函数的第二个参数设置错误,不会给出错误信息。

        check_config_usage()函数可以显示出截止到此函数调用时有哪些参数是被设置过但是却没有被获取过,此函数一般在connect_phase被调用。

        print_config(1):参数1表示递归的查询,参数0只显示当前component的信息。

        print_config会遍历整个验证平台的所有节点,找出哪些被设置过的信息对于它们是可见的。

        命令行参数:

                    <sim command> +UVM_CONFIG_DB_TRACE

UVM验证总结(四)-sequence机制(进阶)

       在前文的UVM验证总结(四)-sequence机制(基础篇)中,我们详细讨论了sequencer和sequence组件,包括启动方式、objection机制、virtual sequence的运用以及p_sequencer的使用。此部分将进一步补充sequence机制的rebase 丢失源码关键内容:

       1. Sequence的仲裁机制

       在多sequence并发情况下,sequence如何同步和发送case至关重要。uvm提供了多种仲裁方法:

       1.1 优先级仲裁:通过调整uvm_do和uvm_do_with宏的优先级,数值越大,优先级越高。可以设置仲裁算法为SEQ_ARB_STRICT_FIFO或SEQ_ARB_STRICT_RANDOM来利用优先级。

       1.2 lock或grab:lock和grab控制sequencer的独占使用权,grap优先级更高,但不会打断正在执行的sequence。

       1.3 is_relevant和wait_for_relevant:is_relevant决定sequence是阅读tomcat源码否有效,配合wait_for_relevant实现更复杂的同步逻辑。

       1.4 virtual sequence和virtual sequencer:用于复杂同步,避免全局变量过多,简化了多agent间sequence的有序执行。

       2. Sequence相关宏及其实现

       包括start()方法的应用,以及start_item()和finish_item()用于item挂载。发送transaction的宏如uvm_do_on, uvm_do_on_pri, uvm_do_on_with等提供了灵活的发送选项。

       3. Sequence、sequencer、driver之间的通信

       sequence通过ID信息标识item来源,确保item发送的准确性。

       4. config_db在sequence中的使用

       sequence中可以通过get_full_name获取组件路径,用于动态获取或设置config_db中的参数。

       5. Response机制

       sequence机制提供response机制,sklearn 源码阅读driver通过get_response获取sequence的反馈,set_id_info确保response与正确sequence关联。

systemverilog速记--$cast

       在实际工作中,$cast函数的使用相对较少,主要在构建环境时传输transaction时会涉及。特别是在UVM的p_sequencer中,$cast函数被隐藏在宏中。初次接触$cast时,可能会感觉有些混淆,但随着对SystemVerilog(SV)的理解加深,其真正意图也逐渐清晰。

       $cast函数的作用可以通俗地解释为:将指向基类的指针转换成指向派生类的指针。想象一下,有一个三维生物称为基类parent,caffe 源码 卷积它复制并降低了自己到一个较低的维度,产生了派生类child。尽管基类parent没有内容,但派生类child却承载着丰富的属性和方法。基类parent对派生类child的属性和方法垂涎三尺,于是它通过高级二向箔$cast,将基类句柄base_tr转化为可以使用child的属性和方法的形式。这个过程就像是将基类的句柄base_tr降维并夺取了child的句柄child2,使得base_tr能以child2的名义与派生类的属性和方法进行交互。

       在UVM的p_sequencer中,$cast的使用颇为典型。当case_sequence绑定到start_sequencer时,m_sequencer作为基类的句柄指向了start_sequencer。由于m_sequencer更靠近uvm_void,vip精品源码因此无法直接使用start_sequencer的属性和方法。此时,需要使用高级二向箔$cast来将start_sequencer的句柄p_sequencer进行降维和夺舍,使其能够伪装成start_sequencer的类型。这样一来,case_sequence就可以自由访问start_sequencer的属性和方法了。

       理解$cast的能力在特定情况下十分关键,尤其是在构建新环境或需要向不同类型的句柄传递参数时。这时,可以创建一个空类,并让需要传递的类从该基类派生。在函数中声明这些类的句柄,并根据tag进行$cast。虽然掌握$cast的使用并不总是有直接的业务价值,但在面试中理解它可以帮助展示你对语言特性的熟悉程度。

       举个例子,假设要编写一个收集transaction的函数,并且需要根据传入的transaction类型进行相应的处理。可以使用如下结构:

       typedef class my_transaction extends uvm_sequence_item ;

       typedef class your_transaction extends uvm_sequence_item ;

       typedef class her_transaction extends uvm_sequence_item ;

       function void collect_q(uvm_seq_item pass_in) ;

       my_transaction m_t ;

       your_transaction y_t ;

       her_transaction h_t ;

       if($cast(m_t,pass_in)) begin

       display("[collect_q] get the transaction type:my_transaction");

       ...

       end

       if($cast(y_t,pass_in)) begin

       display("[collect_q] get the transaction type:your_transaction");

       ...

       end

       if($cast(h_t,pass_in)) begin

       display("[collect_q] get the transaction type:her_transaction");

       ...

       end

       endfunction

       在这个例子中,$cast的作用是将传入的句柄pass_in转化为对应类的实例,从而使得函数能够根据传入的transaction类型进行相应的处理。

       $cast的本质是让父类的句柄能够获取子类对象的所有内容,而virtual函数的本质则在于让父类的句柄能够调用子类的方法。理解这些概念有助于更灵活地使用SystemVerilog语言,尤其在构建复杂的系统验证环境时。

sequence和sequencer的区别

       sequence和sequencer是uvm(虚拟测试平台)中的两个重要概念。它们的主要区别在于仲裁机制和使用方式不同。

       sequence是一个uvm_object,它代表了一个交易或者一组交易,具有一定的生命周期。在使用sequence时,需要在仲裁队列中进行排队等待执行。如果有多个sequence占用同一个序列号,那么它们将按照仲裁机制进行轮询,先被执行的序列将被取消,直到有一个序列释放了序列号。

       而sequencer是一个uvm_component,它代表了一个序列器,可以同时执行多个序列。sequencer具有专门的仲裁线程和仲裁队列,它可以在任何时候接受新的序列并执行它们。在使用sequencer时,不需要在仲裁队列中排队等待执行,而是立即开始执行下一个序列。

       另外,sequencer和sequence的另一个区别在于is_revelant函数和wait_for_relevant任务。在使用sequence时,当一个序列的is_revelant函数返回1时,说明这个序列有效并参加仲裁,可以被序列器接受并执行。而在使用sequencer时,当它接受到一个新的序列时,会查看这个序列的is_revelant函数的返回结果,如果返回1,说明这个序列有效并参加仲裁,可以被立即执行。在执行完所有有效的序列后,sequencer会调用处于无效状态的序列的wait_for_relevant任务。

       总之,sequence和sequencer在功能和使用方式上有很大的区别,需要根据具体的应用场景选择合适的概念。

UVM学习笔记(三)

       前言

       笔记内容对应张强所著的《UVM实战》。该书对UVM使用进行了比较详尽的介绍,并在前言中提供了书籍对应源码的下载网址,是一本带有实操性的书籍,对新手比较友好,推荐阅读。

       第2章一个简单的UVM验证平台2.4 UVM的终极大作: sequence

       2.4.1 在验证平台中加入sequencer

       sequence机制作用:用于产生激励。其分为两部分,一是sequence,二是sequencer。

       在定义driver时指明此driver要驱动的transaction的类型,这样定义的好处是可以直接使用uvm_driver中的某些预先定义好的成员变量,如uvm_driver中有成员变量req,它的类型就是传递给uvm_driver的参数。由此带来的变化如下:(不需要定义中间变量tr了)

       2.4.2 sequence机制

       三者关系:

       每一个sequence都有一个body任务,当一个sequence启动之后,会自动执行body中的代码。body中uvm_do这个宏的作用如下:

       如果不使用uvm_do宏,也可以直接使用start_item与finish_item的方式产生transaction。

       sequencer负责协调sequence和driver的请求

       get_next_item和try_next_item的比较

       2.4.3 default_sequence的使用

       引入default_sequence的原因:

       如何使用default_sequence:

       使用default_sequence时如何提起和撤销objection?

       2.5 建造测试用例2.5.1 加入base_test

       对my_env进一步封装,添加一些公司个性化内容,举例如下:

       2.5.2 UVM中测试用例的启动

       通过传递参数变量值启动的原因:

       如何使用:

       参考资料

       UVM实战(卷一) 张强 编著 机械工业出版社