首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UVM中的域分离

UVM中的域分离
EN

Stack Overflow用户
提问于 2019-06-28 10:28:55
回答 1查看 553关注 0票数 1

为了重置测试环境的各个代理,我尝试将它们转移到不同的域。但是,我遇到了困难:当我为一个代理设置单独的域时,序列项停止流向该代理的驱动程序。

下面是我能写的最简单的例子。如果你把这些行注释掉

代码语言:javascript
复制
    ag1.set_domain (d1);
    ag2.set_domain (d2);

然后代理的驱动程序将接收数据;如果取消注释,它们将停止。但是,如果将jump放置在fork块中,则会发生这种情况。

如果将域设置移动到测试类的主阶段,数据将消失,但不会发生jumppre_reset_phase

代码语言:javascript
复制
`include "uvm_macros.svh"
package t;
    import uvm_pkg::*;
    class seq_item extends uvm_sequence_item;
        `uvm_object_utils(seq_item)

        rand bit [31:0]            data;
        function new(string name = "apb_seq_item");
            super.new(name);
        endfunction: new
    endclass: seq_item

    class m_sequence extends uvm_sequence#(seq_item);
        `uvm_object_utils(m_sequence)

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

        task body();
            repeat(5) begin
                req = seq_item::type_id::create("ap_it");
                start_item(req);
                req.randomize();
                finish_item(req);
            end
        endtask: body
    endclass: m_sequence

    class driver extends uvm_driver#(seq_item);
        `uvm_component_utils(driver)
        function new (string name, uvm_component parent);
            super.new(name, parent);
        endfunction: new

        task main_phase(uvm_phase phase);
            fork
                super.main_phase(phase);
            join_none
            forever begin
                seq_item_port.get_next_item(req);
                `uvm_info(get_type_name(),$psprintf("Got item with data: %h",req.data),UVM_NONE);
                seq_item_port.item_done();
            end
        endtask: main_phase
    endclass: driver
    class agent extends uvm_agent;
        `uvm_component_utils(agent)
        uvm_analysis_port#(seq_item) ap;

        uvm_sequencer#(seq_item)     seqr;
        driver                       drv;

        function new(string name, uvm_component parent);
            super.new(name,parent);
        endfunction: new
        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            ap  = new(.name("apb_ap"), .parent(this));
            seqr= uvm_sequencer#(seq_item) ::type_id::create(.name("uvm_sequenver"), .parent(this) );
            drv = driver        ::type_id::create(.name("driver"), .parent(this) );
        endfunction: build_phase

        function void connect_phase(uvm_phase phase);
            super.connect_phase(phase);
            drv.seq_item_port.connect(seqr.seq_item_export);
        endfunction: connect_phase

        task pre_reset_phase(uvm_phase phase);
            fork
                super.pre_reset_phase(phase);
            join_none
            `uvm_info(get_type_name(),"jumped into pre_reset_phase",UVM_NONE);
        endtask
    endclass: agent
    class env extends uvm_env;
        `uvm_component_utils(env)

        agent ag1;
        agent ag2;
        uvm_domain d1;
        uvm_domain d2;
        function new(string name, uvm_component parent);
            super.new(name,parent);
        endfunction: new

        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            ag1 = agent::type_id::create("ag1", this);
            ag2 = agent::type_id::create("ag2", this);
            d1 = new("d1");
            d2 = new("d2");

            ag1.set_domain(d1);
            ag2.set_domain(d2);
        endfunction: build_phase
    endclass: env

    class test extends uvm_test;
        `uvm_component_utils(test)
        env e;
        m_sequence seq1;
        m_sequence seq2;

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

        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            e = env::type_id::create("env",this);
        endfunction
        task main_phase(uvm_phase phase);
            fork
                super.main_phase(phase);
            join_none
            phase.raise_objection(this);
            seq1  = m_sequence::type_id::create("se1");
            seq2  = m_sequence::type_id::create("se2");
            fork
                seq1.start(e.ag1.seqr);
                seq2.start(e.ag2.seqr);
            join
            e.d1.jump(uvm_pre_reset_phase::get());
            phase.drop_objection(this);
        endtask
    endclass: test
endpackage

module top();
    import uvm_pkg::*;
    import t::*;
    initial begin
        run_test();
    end
endmodule
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-28 14:17:37

UVM运行时阶段用于控制事情发生的顺序.如果事情是在不同的阶段完成的,那么您可以保证在后期完成的事情会发生在早期阶段的事情之前。

您的原始代码创建了两个新的阶段域,并将两个代理放入这些新域。测试平台的其余部分位于原始域中。如果您不同步域,那么您就无法保证发生在哪个顺序中。

因此,我对您的代码做了一些更改:

i)我在代理中添加了对序列的引用:

代码语言:javascript
复制
   m_sequence seq;

( ii)我已在代理人的主要阶段加入代码,以(a)提出反对及(b)展开程序。现在(a)每个序列在其域中的正确时间开始,(b)关键的是,在序列完成之前,相位不会结束。(您对阶段结束提出异议,所以现在每个main_phase都需要自己的反对。)

代码语言:javascript
复制
    task main_phase(uvm_phase phase);
      phase.raise_objection(this);
      `uvm_info(get_type_name(),"jumped into main_phase",UVM_NONE);
      seq.start(seqr);
      phase.drop_objection(this);
    endtask

我向您的set_domain方法调用添加了一个额外的参数,以便代理的子级也被放入新域中(默认情况下它们不是):

代码语言:javascript
复制
      ag1.set_domain(d1,1);
      ag2.set_domain(d2,1);

4)我已经将创建序列的代码放入测试的configure_phase中。我怀疑这是否保证了序列是在主要阶段开始之前创建的,所以它的工作更多是靠运气而不是判断。(您需要使用这样的事实,即阶段保证执行顺序,从而对此进行微调。)

代码语言:javascript
复制
    task configure_phase(uvm_phase phase);
      e.ag1.seq  = m_sequence::type_id::create("se1");
      e.ag2.seq  = m_sequence::type_id::create("se2");
    endtask

最后,为了确保在序列完成后发生相位跳变,我在执行之前添加了一个延迟:

代码语言:javascript
复制
        #1 e.d1.jump(uvm_pre_reset_phase::get());

这是个小问题。同样,考虑到您已经跳入了阶段域的世界,您可能希望使用阶段来保证这一点。

但最后..。相位跳跃是个小问题。我只建议把它作为最后的手段。难道没有一种更简单、更传统的方法来重复域1的序列吗?

代码语言:javascript
复制
`include "uvm_macros.svh"
package t;
    import uvm_pkg::*;
    class seq_item extends uvm_sequence_item;
        `uvm_object_utils(seq_item)

        rand bit [31:0]            data;
        function new(string name = "apb_seq_item");
            super.new(name);
        endfunction: new
    endclass: seq_item

    class m_sequence extends uvm_sequence#(seq_item);
        `uvm_object_utils(m_sequence)

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

        task body();
            repeat(5) begin
                req = seq_item::type_id::create("ap_it");
                start_item(req);
                req.randomize();
                finish_item(req);
            end
        endtask: body
    endclass: m_sequence

    class driver extends uvm_driver#(seq_item);
        `uvm_component_utils(driver)
        function new (string name, uvm_component parent);
            super.new(name, parent);
        endfunction: new

        task main_phase(uvm_phase phase);
            fork
                super.main_phase(phase);
            join_none
            forever begin
                seq_item_port.get_next_item(req);
                `uvm_info(get_type_name(),$psprintf("Got item with data: %h",req.data),UVM_NONE);
                seq_item_port.item_done();
            end
        endtask: main_phase
    endclass: driver
    class agent extends uvm_agent;
        `uvm_component_utils(agent)
         uvm_analysis_port#(seq_item) ap;
       m_sequence seq;

        uvm_sequencer#(seq_item)     seqr;
        driver                       drv;

        function new(string name, uvm_component parent);
            super.new(name,parent);
        endfunction: new
        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            ap  = new(.name("apb_ap"), .parent(this));
            seqr= uvm_sequencer#(seq_item) ::type_id::create(.name("uvm_sequenver"), .parent(this) );
            drv = driver        ::type_id::create(.name("driver"), .parent(this) );
        endfunction: build_phase

        function void connect_phase(uvm_phase phase);
            super.connect_phase(phase);
            drv.seq_item_port.connect(seqr.seq_item_export);
        endfunction: connect_phase

        task pre_reset_phase(uvm_phase phase);
            fork
                super.pre_reset_phase(phase);
            join_none
            `uvm_info(get_type_name(),"jumped into pre_reset_phase",UVM_NONE);
        endtask

        task main_phase(uvm_phase phase);
          phase.raise_objection(this);
          `uvm_info(get_type_name(),"jumped into main_phase",UVM_NONE);
          seq.start(seqr);
          phase.drop_objection(this);
        endtask
    endclass: agent
    class env extends uvm_env;
        `uvm_component_utils(env)

        agent ag1;
        agent ag2;
        uvm_domain d1;
        uvm_domain d2;
        function new(string name, uvm_component parent);
            super.new(name,parent);
        endfunction: new

        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            ag1 = agent::type_id::create("ag1", this);
            ag2 = agent::type_id::create("ag2", this);
            d1 = new("d1");
            d2 = new("d2");

            ag1.set_domain(d1,1);
            ag2.set_domain(d2,1);
        endfunction: build_phase
    endclass: env

    class test extends uvm_test;
        `uvm_component_utils(test)
        env e;      

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

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

        task configure_phase(uvm_phase phase);
          e.ag1.seq  = m_sequence::type_id::create("se1");
          e.ag2.seq  = m_sequence::type_id::create("se2");
        endtask

        task main_phase(uvm_phase phase);
            fork
                super.main_phase(phase);
            join_none
            phase.raise_objection(this);          
            #1 e.d1.jump(uvm_pre_reset_phase::get());
            phase.drop_objection(this);
        endtask
    endclass: test
endpackage

module top();
    import uvm_pkg::*;
    import t::*;
    initial begin
        run_test();
    end
endmodule

https://www.edaplayground.com/x/imV

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56805277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档