当前位置:   article > 正文

UVM之sequence机制_uvm sequence机制

uvm sequence机制

sequence不是component,但是sequencer是component。sequence是sequencer中的一个成员。

定义:
控制和产生一系列的事务,并将事务发送给driver的一套机制。(一系列动作的集合)

例子:
driver向sequencer发送事务请求,sequencer再向其关联的sequence发送请求,sequence接收到请求之后,立即将已经生成好的事务发送出去。发送出去的事务通过sequencer之后再转发给请求事务的对象。请求该事务的对象处理完事务之后,发送处理完事务的响应,再以sequencer为中介,转发到sequence。接着sequence将产生下一个事务,等待下一次事务请求。
优点:
将事务的产生和驱动分离,提高组件可重用性,事务的产生更为灵活。

控制原理:
1、sequencer查看平台组件是否配置了default_sequence,是则到第2步,否则跳转到第六步。
2、创建default_sequence对象,到第三步。
3、设置该sequence的starting_phase,到第四步。
4、随机化该sequence
5、调用该sequence的start()方法,在该sequence中启动sequence方法。

6、平台的其他组件是否手动例化sequence并调用它的start()方法,是则执行sequence,否则该phase中没有sequence执行。

sequence的执行:start()执行body()方法
1、产生items,并将items放进对应的sequencer中(存放于FIFO中)。
2、等待driver返回完成标志
3、判断是否执行完毕,是则推出执行,否则回到1。
uvm_do*宏
在这里插入图片描述

在这里插入图片描述

driver的执行:
1、请求事务(seq_item_port.get_next_item())
2、等待获取事务
3、处理事务
4、完成事务后给出标志(seq_item_port.item_done()),回到1。

此处借用一张图来说明整个过程
在这里插入图片描述
手动启动sequence
在这里插入图片描述
上述代码中注释掉部分为默认启动方式。

sequence获取响应
在这里插入图片描述

driver发送响应
在这里插入图片描述

小结:
两种方法产生items
两种方法启动sequence
获取响应

Advance_sequence

1、sequence library
A sequence
包含了一组在其内部注册了的sequence类型
可通过对其进行配置,创建并执行一系列的sequence/sequence item

向sequence library永久注册sequence。

class da3_sequence extends my_sequence;
	// 向sequence library永久注册sequence。
    `uvm_object_utils(da3_sequence)
    `uvm_add_to_seq_lib(da3_sequence, my_sequence_lib)

    int item_num = 10;

    function new(string name = "da3_sequence");
        super.new(name);
    endfunction

    function void pre_randomize();
        uvm_config_db#(int)::get(m_sequencer, "", "item_num", item_num);
    endfunction

    virtual task body();
        my_transaction tr;
        if(starting_phase != null)
            starting_phase.raise_objection(this);

        repeat(item_num) begin
            //`uvm_do(req);
            tr = my_transaction::type_id::create("tr");
            start_item(tr);
            tr.randomize() with { tr.da == 3; };
            finish_item(tr);

            get_response(rsp);
            `uvm_info("SEQ", {"\n", "Sequence get the response:\n", rsp.sprint()}, UVM_MEDIUM)

        end
	   
        #100;
    	if(starting_phase != null)
            starting_phase.drop_objection(this);
    endtask

endclass

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

在顶层中配置

class my_test extends uvm_test;

    `uvm_component_utils(my_test)

    my_env m_env;
    env_config m_env_cfg;

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

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        m_env = my_env::type_id::create("m_env", this);

        uvm_config_db#(uvm_object_wrapper)::set(this, "*.m_seqr.run_phase","default_sequence", my_sequence_lib::get_type());

        uvm_config_db#(int)::set(this, "*.m_seqr", "item_num", 20);

        m_env_cfg.is_coverage = 1;
        m_env_cfg.is_check    = 1;
        m_env_cfg.m_agent_cfg.is_active  = UVM_ACTIVE;
        m_env_cfg.m_agent_cfg.pad_cycles = 5;

        if(!uvm_config_db#(virtual dut_interface)::get(this, "", "top_if", m_env_cfg.m_agent_cfg.m_vif)) begin
            `uvm_fatal("CONFIG_ERROR", "test can not get the interface !!!")
        end

        uvm_config_db#(env_config)::set(this, "m_env", "env_cfg", m_env_cfg);

    endfunction

    virtual function void start_of_simulation_phase(uvm_phase phase);
        super.start_of_simulation_phase(phase);
        uvm_top.print_topology(uvm_default_tree_printer);
    endfunction
    // 手动启动sequence
    /*
    virtual task run_phase(uvm_phase phase);
        my_sequence m_seq;
        m_seq = my_sequence::type_id::create("m_seq");
        phase.raise_objection(this);
            m_seq.start(m_env.m_agent.m_seqr);
        phase.drop_objection(this);
    endtask
    */
endclass

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

启动十次sequence library
在这里插入图片描述

31 class case0_sequence extends uvm_sequence #(my_transaction);37 virtual task body();
38 crc_seq cseq;
39 long_seq lseq;42 repeat (10) begin
43 cseq = new("cseq");
44 cseq.start(m_sequencer);
45 lseq = new("lseq");
46 lseq.start(m_sequencer);
47 end
…
51 endtask
…
54 endclass
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在上面代码中,m_sequencer是case0_sequence在启动后所使用的sequencer的指针。但通常来说并不用这么麻烦,可以使用uvm_do宏来完成这些事

31 class case0_sequence extends uvm_sequence #(my_transaction);38 virtual task body();
39 crc_seq cseq;
40 long_seq lseq;43 repeat (10) begin
44 `uvm_do(cseq)
45 `uvm_do(lseq)
46 end
…
50 endtask
…
53 endclass
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

仿真结束控制
在这里插入图片描述

在这里插入图片描述
未加控制部分代码,默认仿真结束时间99290000ps。
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/938542
推荐阅读
相关标签
  

闽ICP备14008679号