Есть ли способ подключить uvm_tlm_analysis_fifo к uvm_driver?

Мне нужно подключить выход модуля к его входу, управляемому 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?

что значит "не удается подключиться"? что ты пробовал?

Serge 16.07.2019 12:48

Какая ошибка у вас была? вы не предоставили определения классов driver и seq_item.

Serge 16.07.2019 14:21

@Serge, добавлен минимальный воспроизводимый пример и его ошибка. Содержимое классов seq_item и драйвера я ранее не уточнял, так как оно совершенно неактуально в данном вопросе и будет только отвлекать. seq_item может быть как сложным классом с кучей полей, так и пустой заготовкой, унаследованной от uvm_sequence_item. Драйвером может быть либо axi4_s_master_driver, либо просто драйвер, который вытаскивает seq_items и тут же вызывает item_done. Решение лежит где-то на уровне агента или среды.

Андрей Солодовников 16.07.2019 14:46
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
530
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужен uvm_sequencer с seq_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 с задачей передачи элементов последовательности между ними. Я думаю, что вы можете создать поддельный секвенсор, чтобы справиться с этим (и оставить драйвер в покое).

Да, я знаю про вариант подключения секвенсора к драйверу, но не знаю, как писать в порт секвенсора вручную (как отмечено в вопросе), т.к. при традиционном использовании секвенсоры стартуют на нем, а я не могу передавать данные из fifo в последовательность. Модифицировать драйвер тоже мне кажется плохой идеей, так как используется уже написанный мастер axi4_stream, а прелесть uvm в повторном использовании.

Андрей Солодовников 16.07.2019 16:16
Ответ принят как подходящий

Как я и подозревал, я не могу реализовать схему вопросов без секвенсора. Таким образом, схема результата будет следующей:

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

Вопрос заключался в том, как заставить секвенсор записывать в seq_item_export без запуска последовательности. Для этого, как указано в ответе выше, мне нужно было реализовать задачу 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

Другие вопросы по теме