Для всех моих компонентов (монитор, драйвер, секвенсор и т. д.) мне нужно создать задачу, которая вызывается каждые 100 или около того циклов. Я думаю, что есть способ сделать это с помощью пользовательских фаз, но не уверен, как это сделать. Любая помощь.
UVM: создайте задачу, которая вызывается примерно каждые 100 циклов для всех компонентов.
Ответы (4)
Функция псевдомножественного наследования, представленная в 1800-2012 годах через «класс интерфейса» и «реализует», является лучшим решением. Чтобы удовлетворить ваши требования, вы можете применить шаблон проектирования Observer. Ниже приведен пример кода
interface class tick;
pure virtual task trigger_tick(....);
end class
class observer extends uvm_components;
......
tick tick_list[$];
virtual function void register_tick(tick t);
tick_list.push_back(t);
endfunction
virtual task run_phase(uvm_phase phase);
forever begin
repeat(100) @(posedge top.clock);
foreach (tick_list[i]) tick_list[i].trigger_tick();
end
endtask
end class
class my_component extends uvm_component implements tick;
......
virtual task trigger_tick();
//do something
endtask
end class
Затем вы можете создать экземпляр наблюдателя и зарегистрировать все компоненты в экземпляре.
Я не думаю, что вам нужно реализовывать пользовательские фазы для этого. Вот пример того, как вы можете это сделать.
task run_phase(uvm_phase phase);
forever begin
// wait for reset ....
fork
your_task1();
join_none
// do other things .....
end
endtask : run_phase
task your_task1(); // this task will keep running forever..
int count=1;
forever begin
@(posedge vif.clk);
if(count%100 == 0) // will be true only when count becomes multiple of 100
your_task2();
count++;
end
endtask : your_task1
task your_task2(); // one which you wanted to call every 100 clk cycles
// add your logic
endtask : your_task2
Надеюсь это поможет.
Вы можете добавить эту логику в run_phase
каждого компонента следующим образом.
task run_phase (uvm_phase phase);
fork
begin
forever
begin
repeat (100) @(posedge virtual_interface.clk);
your_task();
end
end
// Other threads
join_none
wait_fork;
endtask
Вы можете использовать uvm_events, например, из каждого компонента генерировать событие в 100-м цикле, а из вашего собственного класса перехватывать это событие и вызывать задачу.
Не могли бы вы объяснить, почему вам нужно запускать задачу для каждого из компонентов? Я предполагаю, что вы что-то отлаживаете, может быть, запись транзакций или uvm_printer были бы здесь более полезными.