фазы выполнения UVM используются для управления порядком происходящих событий .Если дела выполняются на разных этапах, то вы можете гарантировать, что что-то сделанное на более позднем этапе произойдет раньше, чем что-то сделанное на более раннем этапе.
Ваш исходный код создает два новых фазовых домена и помещает двух агентов в эти новые домены.Остальная часть тестового стенда находится в исходном домене.Если вы не синхронизируете домены, вы больше не можете гарантировать, в каком порядке будут происходить события.
Итак, я внес несколько изменений в ваш код:
i) Я добавилссылка на последовательность в агенте:
m_sequence seq;
ii) Я добавил код в основную фазу агента, чтобы (а) выдвинуть возражение и (б) запустить последовательность.Теперь (а) каждая последовательность запускается в нужное время в своем домене, и (б) критически важно, чтобы фаза не заканчивалась до тех пор, пока последовательность не будет завершена.(Вы возражаете против окончания фазы, поэтому теперь каждому main_phase нужно свое собственное возражение.)
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
iii) Я добавил дополнительный параметр к вашему вызову метода set_domain
, чтобы потомки объектаагенты также помещаются в новый домен (по умолчанию это не так):
ag1.set_domain(d1,1);
ag2.set_domain(d2,1);
iv) Я поместил код для создания последовательностей в configure_phase теста.Я сомневаюсь, что это гарантирует, что последовательности создаются до начала основных фаз, так что это работает скорее благодаря удаче, чем суждению.(Вам необходимо использовать тот факт, что фазы гарантируют порядок выполнения, чтобы точно настроить это.)
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
v) Наконец, чтобы гарантировать, что скачок фазы произойдет после завершения последовательностей, я добавилзадержка перед его выполнением:
#1 e.d1.jump(uvm_pre_reset_phase::get());
Это что-то вроде хака.Опять же, учитывая, что вы попали в мир фазовых доменов, вы, вероятно, захотите использовать фазы, чтобы гарантировать это.
Но наконец ... фазовые прыжки - это что-то вроде хака.Я бы рекомендовал использовать его только в качестве крайней меры.Не существует ли более простого, более традиционного способа повторения последовательности для домена 1?
`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