virtual sequencer class
※ vseqr.sv |
class vseqr_c extends uvm_sequencer; `uvm_component_utils(vseqr_c) pipe_sequencer_c pipe_seqr; virtual interface pipe_if vif; function new(string name, uvm_component parent); super.new(name, parent); endfunction virtual function void build_phase(uvm_phase phase); super.build_phase(phase); `uvm_info(get_type_name(), $sformatf("build_phase() starts.."), UVM_LOW) //Get interface from uvm_config_db if (!uvm_config_db#(virtual pipe_if)::get(this, "", "vif", vif)) begin `uvm_fatal(get_type_name(), {"virtual interface must be set for: ", get_full_name(), ".vif"}) end endfunction virtual function void connect_phase(uvm_phase phase); super.connect_phase(phase); endfunction endclass |
virtual sequencer 는 검증 환경에서 사용하는 여러 sequencer 들을 모아놓은 component 로 top sequencer 라고도 한다. test sequence 에서 transaction item 은 driver 를 지나기 전 sequencer 를 통해 전달해야 하는데, 직접적으로 sequencer 를 pin-to-pin 으로 연결하여 전달할 수가 없다.
개인적인 생각으로는 uvc 안 에서는 interface 를 virtual 로 가져와서 사용한 것처럼 driver 내 sequencer 를 바로 사용할 수 없으니 virtual sequencer 를 따로 만든 것으로, 사용하는 의도가 비슷하여 이름을 지은 것으로 생각된다.
하지만 진짜 virtual sequencer 의 강점은 sequencer 연결이 아니라 virtual interface 역시 가져와서 sequence 에서 사용할 수 있다는 점이다. ⑾ test sequence 에서 더 자세히 설명하겠지만 sequence 에서 virtual sequencer 를 uvm_decare_p_sequencer 의 uvm api 를 사용하여 p_sequencer 로 선언할 수 있고 p_sequencer 를 통해 interface 의 신호들을 run_phase() 동안에 직접 컨트롤하거나 모니터링을 할 수 있다. 다시 돌아와서 결론은 virtual sequencer 를 p_sequencer 로 선언하고 sequence 내 transaction item 을 pointing 한 sequencer 로 지정하면 driver 를 통해 DUT 로 전송이 가능해진다.