[SEQREQZMB] 跑reset test出现的UVM_ERROR原因及解决方法

本文详细记录了解决UVM_ERROR:[SEQREQZMB]Thetaskresponsibleforrequestingawait_for_grantonsequencer...的过程中遇到的问题及解决方法。错误源于在resettest时,sequence在仲裁队列中的状态变为KILLED,导致死锁。通过阅读UVM源码,发现可以使用`stop_sequences()`方法在reset后清除队列,从而避免错误发生。该方法有效地清除了KILLED状态的sequence,使系统恢复正常运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今日调试reset test时,出现了如下UVM_ERROR:

[SEQREQZMB] The task responsible for requesting a wait_for_grant on
sequencer ‘uvm_test_top.m_env.m_xxx_agent.m_sequencer’ for sequence
‘case_rstn_rand_vseq’ has been killed, to avoid a deadlock the
sequence will be removed from the arbitration queues.

在网上搜索了该ERROR的信息,发现均与将sequence强行停止有关,但并没有特别契合我的案例,总之依旧未能够找到合适的解决方法。经过自己的摸索后,解决了这个问题,因此将该过程记录下来,以便之后再遇能够快速解决。如果恰好能帮上你的忙,那将是意外收获!

出现的原因

  1. 出现error首先应当查看原代码,因此我读了一下UVM源码中该error的出处:
function int uvm_sequencer_base::m_choose_next_request();
  int i, temp;
  int avail_sequence_count;
  int sum_priority_val;
  integer avail_sequences[$];
  integer highest_sequences[$];
  int highest_pri;
  string  s;
 
  avail_sequence_count = 0;
 
  grant_queued_locks();
 
  for (i = 0; i < arb_sequence_q.size(); i++) begin
 
    if((arb_sequence_q[i].process_id.status == process::KILLED)||
       (arb_sequence_q[i].process_id.status == process::FINISHED))begin
      `uvm_error("SEQREQZMB",$sformatf("The task reponsible for requesting a wait_for_grant on sequencer '%s' for sequence '%s' has been killed,to avoid a deadlock the sequence will be removed from the arbitration queues",this,get_full_name(),arb_sequence_q[i].sequence_ptr.get_full_name))
     
      remove_sequence_from_queues(arb_sequence_q[i].sequence_ptr);
      continue;
    end
    
    //the rest content is omitted
    ...
    
endfunction

该function后续代码由于与本文讨论的问题无关,因此省略。从代码中可见,这个UVM_ERROR是由于arb_sequence_q的成员status为KILLED或FINISHED,为了避免死锁deadlock的产生,强行将该成员从queue中移除。

继续往前追溯,m_choose_next_request()这个函数在task m_select_sequence中被调用,而这个task又被task get_next_item所调用。

看到这里,问题的原因已经比较清晰:

  1. 我的case所定义的item,会进入sequencer的一个仲裁队列中。sequencer在driver要求get_next_item时,对队列中的request进行仲裁,再将request item发送给driver。
  2. 仲裁队列中的item,在reset生效时被kill掉,从而满足了该ERROR的条件。当reset释放时,driver重新要求get_next_item就会引发该UVM_ERROR。

解决的方法

sequencer在发现该ERROR后,采取了remove_sequence_from_queues的做法,将KILLED状态的item从队列中清除掉。

那么,我是否可以在reset生效后,就将队列中的item人为清除掉,从而避免该UVM_ERROR的产生呢?

于是,查看UVM sequencer的源码,其提供了如下的方法:

// Function- stop_sequences
//
// Tells the sequencer to kill all sequences and child sequences currently
// operating on the sequencer, and remove all requests, locks and responses
// that are currently queued.  This essentially resets the sequencer to an
// idle state.
//
function void uvm_sequencer::stop_sequences();
  REQ t;
  super.stop_sequences();
  sequence_item_requested  = 0;
  get_next_item_called     = 0;
  // Empty the request fifo
  if (m_req_fifo.used()) begin
    uvm_report_info(get_full_name(), "Sequences stopped.  Removing request from sequencer fifo");
    while (m_req_fifo.try_get(t));
  end
endfunction

这个方法可以同时完成将sequences kill掉并从队列中remove的行为。

的确,这样做之后这个UVM_ERROR不再出现了。

class vbase_test extends uvm_test; `uvm_component_utils(vbase_test) env m_env; vseqr m_vseqr; int unsigned simSeed; function new(string name, uvm_component parent); super.new(name, parent); endfunction : new extern function void build_phase (uvm_phase phase); extern function void connect_phase (uvm_phase phase); extern task reset_phase(uvm_phase phase); extern task reset_reg_model(); extern function void end_of_elaboration_phase(uvm_phase phase); extern function void start_of_simulation_phase(uvm_phase phase); extern task main_phase(uvm_phase phase); // report test result extern virtual function void report_phase(uvm_phase phase); endclass : vbase_test function void vbase_test::build_phase (uvm_phase phase); super.build_phase(phase); m_env = env::type_id::create(.name("m_env"), .parent(this)); // virtual sequencer m_vseqr = vseqr::type_id::create(.name("m_vseqr"), .parent(this)); uvm_config_db# (uvm_object_wrapper)::set(this,"m_vseqr.main_phase","default_sequence",vBaseSeq::type_id::get()); //uvm_config_db# (uvm_object_wrapper)::set(this,"m_vseqr.main_phase","default_sequence",vUniBaseSeq#()::type_id::get()); endfunction : build_phase function void vbase_test::connect_phase (uvm_phase phase); m_vseqr.p_rm = m_env.m_reg_model; m_vseqr.i2c_seqr = m_env.m_i2c_agent.m_seqr; endfunction : connect_phase task vbase_test::reset_phase(uvm_phase phase); //`uvm_info(get_type_name(), {"REGISTER MODEL:\n", m_reg_model.sprint()}, UVM_MEDIUM) reset_reg_model(); super.reset_phase(phase); endtask task vbase_test::reset_reg_model(); forever begin wait (tb_top.reset_n == 0); m_env.m_reg_model.reset(); `uvm_info(get_type_name(), "Reseting Complete", UVM_MEDIUM) wait (tb_top.reset_n == 1); end endtask function void vbase_test::end_of_elaboration_phase(uvm_phase phase); int handle; $system("rm -rf TEST_RUNNING"); simSeed = $get_initial_random_seed(); handle = $fopen($psprintf("TEST_RUNNING_%0d",simSeed),"w"); $fclose(handle); handle = $fopen("caseSeed","w"); $fwrite(handle,"%0d",simSeed); $fclose(handle); if($test$plusargs("uvm_tree")) uvm_top.print_topology(); endfunction : end_of_elaboration_phase function void vbase_test::start_of_simulation_phase(uvm_phase phase); `uvm_info(get_type_name(), {"start of simulation for ", get_full_name()}, UVM_HIGH); endfunction : start_of_simulation_phase task vbase_test::main_phase(uvm_phase phase); phase.phase_done.set_drain_time(this, 200ns); endtask : main_phase // report test result function void vbase_test::report_phase(uvm_phase phase); uvm_report_server server; int handle; int unsigned err_num; super.report_phase(phase); server = get_report_server(); err_num = (server.get_severity_count(UVM_ERROR) + server.get_severity_count(UVM_FATAL)); simSeed = $get_initial_random_seed(); $display("\n********************************************************************************************\n"); if (err_num != 0) begin $display("TEST CASE FAILED!!!"); handle = $fopen($psprintf("TEST_FAILED_%0d",simSeed),"w"); end else begin $display("TEST CASE PASSED!!!"); handle = $fopen($psprintf("TEST_PASSED_%0d",simSeed),"w"); end $fclose(handle); $display("\n********************************************************************************************\n"); $system("rm -rf TEST_RUNNING*"); endfunction `endif
07-25
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值