有没有办法将uvm_tlm_analysis_fifo连接到uvm_driver?

时间:2019-07-16 09:25:48

标签: system-verilog fifo uvm

我需要将模块输出连接到受uvm_driver控制的输入上。 我是这样看的。

                  -----       ---------------------
                 | MON |---->|uvm_tlm_analysis_fifo|
                  -----       ---------------------
                    ^                    |
                    |                    |
 -------------      |      -------       |
|             |---------->| slave |      v
|     DUT     |            -------    --------
|             |<---------------------| master |
 -------------                        --------

我尝试了以下方法。

typedef class seq_item extends uvm_sequence_item;
typedef class driver extends uvm_driver(seq_item);

class agent extends uvm_agent;
    `uvm_component_utils(agent)
    uvm_analysis_port#(seq_item) ap;
    uvm_tlm_analysis_fifo#(seq_item) fifo;
    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("ap", this);
        fifo= new("fifo",this); 
        drv = driver::type_id::create("driver", this);
    endfunction: build_phase

    function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        ap.connect(fifo.analysis_export);
        drv.seq_item_port.connect(fifo.get_peek_export);
    endfunction: connect_phase

    task main_phase(uvm_phase phase);
        seq_item trans;
        phase.raise_objection(this);
        repeat(5) begin
            trans = seq_item::type_id::create("inTrans");
            assert(trans.randomize());
            ap.write(trans);
        end
        phase.drop_objection(this);
    endtask
endclass: agent

这里是最小的,可重复的示例。

`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 = "seq_item");
            super.new(name);
        endfunction: new
    endclass: seq_item

    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 test extends uvm_test;
        `uvm_component_utils(test)
        uvm_analysis_port#(seq_item) ap;
        uvm_tlm_analysis_fifo#(seq_item) fifo;

        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));
            fifo= new("fifo",this); 
            drv = driver        ::type_id::create(.name("driver"), .parent(this) );
        endfunction: build_phase

        function void connect_phase(uvm_phase phase);
            super.connect_phase(phase);
            ap.connect(fifo.analysis_export);
            drv.seq_item_port.connect(fifo.get_peek_export);
        endfunction: connect_phase

        task main_phase(uvm_phase phase);
            seq_item trans;
            phase.raise_objection(this);
            repeat(5) begin
                trans = seq_item::type_id::create("inTrans");
                assert(trans.randomize());
                ap.write(trans);
            end
            phase.drop_objection(this);
        endtask
    endclass: test
endpackage

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

它会产生以下错误。

 ** Error: (vsim-7065) 5.sv(51): Illegal assignment to class mtiUvm.uvm_pkg::uvm_port_base #(class mtiUvm.uvm_pkg::uvm_sqr_if_base #(class work.t::seq_item, class work.t::seq_item)) from class mtiUvm.uvm_pkg::uvm_get_peek_imp #(class work.t::seq_item, class mtiUvm.uvm_pkg::uvm_tlm_fifo_base #(class work.t::seq_item))
#    Time: 0 ns  Iteration: 0  Region: /t File: 5.sv
# ** Error: (vsim-8754) 5.sv(51): Actual input arg. of type 'class mtiUvm.uvm_pkg::uvm_get_peek_imp #(class work.t::seq_item, class mtiUvm.uvm_pkg::uvm_tlm_fifo_base #(class work.t::seq_item))' for formal 'provider' of 'connect' is not compatible with the formal's type 'class mtiUvm.uvm_pkg::uvm_port_base #(class mtiUvm.uvm_pkg::uvm_sqr_if_base #(class work.t::seq_item, class work.t::seq_item))'.

据我所知,我无法将fifo连接到主人的seq_item_port。有没有办法实施这种方案?如果驱动程序真的可以从音序器中获取项目,如何将音序器中的项目手动写入seq_item_port

2 个答案:

答案 0 :(得分:1)

您需要一个uvm_sequencerseq_item_export才能连接到驱动程序的seq_item_port。您没有一个。

如果要使用fifo路径,则需要在驱动程序类中创建并连接通用端口。

这是vcs生成的消息:

Error-[ICTTFC] Incompatible complex type usage
Incompatible complex type usage in task or function call.
The following expression is incompatible with the formal parameter of the 
function. The type of the actual is 'class uvm_pkg::uvm_get_peek_imp#(class 
t::seq_item,class uvm_pkg::uvm_tlm_fifo_base#(class t::seq_item))', while 
the type of the formal is 'class uvm_pkg::uvm_port_base#(class 
uvm_pkg::uvm_sqr_if_base#(class t::seq_item,class t::seq_item))'. 
Expression: this.fifo.get_peek_export
Source info: this.drv.seq_item_port.connect(this.fifo.get_peek_export)

据我所知,您仍然需要创建一个端口以及自己的seq_item_export的实现,其任务是在它们之间传递序列项。我认为您可以创建一个伪造的音序器来处理它(并让驱动程序不理会)。

答案 1 :(得分:0)

我怀疑,如果没有音序器,我将无法实施问题解决方案。因此结果方案如下:

                  -----       ---------
                 | MON |---->|sequencer|
                  -----      |   ------|
                    ^        |  | fifo |
                    |         --------- 
 -------------      |    -------     |
|             |-------->| slave |    v
|     DUT     |          -------  --------
|             |<-----------------| master |
 -------------                    --------

问题是如何使定序器在不运行序列的情况下写入seq_item_export。如上答案中所述,要实现这一点,我需要在自定义sequencer class中实现get_next_item任务,如下所示:

class fifo_sequencer#(type REQ=uvm_sequence_item,RSP=REQ) extends uvm_sequencer#(REQ,RSP);
    `uvm_component_param_utils(fake_sequencer#(REQ,RSP))

    uvm_tlm_analysis_fifo#(REQ) fifo;

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

    task get_next_item(output REQ t);
        fifo.get_peek_export.get(t);
    endtask

    function void item_done(RSP item = null);
        if (item != null) begin
            seq_item_export.put_response(item);
        end
    endfunction
endclass

请注意,除了get_next_item task之外,还必须实现item_done function(否则您可能会遇到Item_done() called with no outstanding requests fatal_error)。
因此,最小的,可复制的示例将转换为:

`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 = "seq_item");
            super.new(name);
        endfunction: new
    endclass: seq_item

    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 fifo_sequencer#(type REQ=uvm_sequence_item,RSP=REQ) extends uvm_sequencer#(REQ,RSP);
        `uvm_component_param_utils(fifo_sequencer#(REQ,RSP))

        uvm_tlm_analysis_fifo#(REQ) fifo;

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

        task get_next_item(output REQ t);
            fifo.get_peek_export.get(t);
        endtask

        function void item_done(RSP item = null);
            if (item != null) begin
                seq_item_export.put_response(item);
            end
        endfunction
    endclass

    class test extends uvm_test;
        `uvm_component_utils(test)
        uvm_analysis_port#(seq_item) ap;

        driver                      drv;
        fifo_sequencer#(seq_item)   sqr;

        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("apb_ap", this);
            sqr = fifo_sequencer#(seq_item) ::type_id::create("sequencer", this);
            drv = driver                    ::type_id::create("driver", this);
        endfunction: build_phase

        function void connect_phase(uvm_phase phase);
            super.connect_phase(phase);
            ap.connect(sqr.fifo.analysis_export);
            drv.seq_item_port.connect(sqr.seq_item_export);
        endfunction: connect_phase

        task main_phase(uvm_phase phase);
            seq_item trans;
            phase.raise_objection(this);
            repeat(5) begin
                trans = seq_item::type_id::create("inTrans");
                assert(trans.randomize());
                ap.write(trans);
            end
            phase.drop_objection(this);
        endtask
    endclass: test
endpackage

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