UVM sequence的多個用法


1.sequence的啟動方式

1.sequence完成定義和實例化后,調用start任務直接啟動,一般不用;

2.default_sequence,這種方式有兩種調用方式,分別是:

1 uvm_config_db#(uvm_object_wrapper)::set(null,"$full_path(sequencer.main_phase)","default_sequence",xx_sequence::type_id::get());   

1 function xx::build_phase(uvm_phase phase);
2     super.build_phase(phase);
3     xx_sequence m_xx_sequence;
4     m_xx_sequence = new("m_xx_sequence");
5     uvm_config_db#(uvm_sequence_base)::set(null,"$full_path","default_sequence",m_xx_sequence);
6 
7 endfunction

兩種方式的實現有差別,第一種的默認方式寫死了,比如你是在env下面使用這個sequence作為default,那么在具體的case里面再設是沒用的了,

第二種方式允許在具體的case里面再進行設置default_sequence。

所以,我們一般不要在env下面去設置默認的sequence,具體case具體的驅動反而實用。

 

2.sequence的仲裁機制

1.同一個case啟動多個sequence

1 fork 
2     m_seq0.start($full_path(sqr));      
3     m_seq1.start($full_path(sqr)); 
4 join     

  現象是sequence0和sequence1里面的transaction交替發送到sequencer,經由sequencer發給driver。(sequence0/1使用uvm_do后者uvm_do_with);

2.優先級的仲裁機制

  UVM內部包含自己的一套對於sequence的仲裁算法。使用uvm_do_pri或者uvm_do_pri_with。

  相較於uvm_do/uvm_do_with,多了一個參數,數值大於-1,越高代表優先級越大。

  但是如果單純的使用這個參數的話,會發現還是交替發送,因為UVM有很多的仲裁算法,默認的SEQ_ARB_FIFO是先進先出的,加權無效。

  所以需要對sequencer的set_arbitration這個進行選擇具體的仲裁算法。

 1 $full_path(sequencer).set_arbitration(XXX); 

  仲裁算法有:SEQ_ARB_FIFO,SEQ_ARB_WEIGHTED,SEQ_ARB_RANDOM,...等等。

3.lock操作

  某個sequence的請求比較特殊,當這個sequence獲得執行權,希望一直連續的發送transaction給driver,這時候就需要用到lock操作;

  用法:在具體的sequence中,在需要lock操作的前面進行lock,uvm_do結束后unlock掉;

4.grap操作

  與lock操作類似,不同的是他一出現就擁有了sequencer的所有權,優先級最高,並且等待執行完才釋放;lock不會,lock會等待隊列中先處理完

再進行lock

5.失效操作

  某個sequence希望在一段時間內不參與仲裁; sequence的is_relevant()函數的返回值為1說明有效,反之無效,可以通過具體場景設置其值來使

sequence失效。

 

3.virtual suquence

  virtual用來解決sequence之間的同步問題,也是sequence之間的執行順序問題。使用virtual sequence用來調度其他sequence,本身不發送transaction,

  具體的做法如下:

 1 //vsqr
 2 class vsqr extends uvm_sequencer;
 3     xx_sequencer0 m_xx_sequencer0;
 4     xx_sequencer1 m_xx_sequencer1;
 5     xx_sequencer2 m_xx_sequencer2;
 6 ....
 7 endclass 
 8 
 9 //base case 
10 class base_test extends uvm_test;
11     vsqr m_vsqr;
12     env  m_env;
13 ....
14 endclass 
15 
16 function void xx_test::build_phase(uvm_phase phase);
17     super.build_phase(phase);
18     m_vsqr = vsqr::type_id::create("m_vsqr",this);
19 ...
20 endfunction
21 
22 function void xx_test::connect_phase(uvm_phase phase);
23     super.connect_phase(phase);
24     m_vsqr.m_xx_sequencer0 = m_env.i_agt.sqr;
25     m_vsqr.m_xx_sequencer1 = m_env.i_agt.sqr;
26     ...
27 endfunction
28 
29 //case0
30 class case0 extends uvm_sequence;
31     `uvm_object_utils(case0)
32     `uvm_declare_p_sequencer(m_vsqr)
33     
34     virtual task body();
35         xx_trans m_xx_trans;
36         xx_sequence0 m_xx_sequence0;
37         xx_sequence1 m_xx_sequence1;
38         `uvm_do_on(m_xx_sequence0,p_sequencer.m_xx_sequencer0);
39     `uvm_do_on(m_xx_sequence1,p_sequencer.m_xx_sequencer1);
40 ... 41 endtask 42 ... 43 endclass

 

 4.sequence宏

1.uvm_do系列

  uvm_do(xx_trans)

  uvm_do_pri(xx_trans,pri_num)

  uvm_do_with(xx_trans,{xx_trans.xx = xx; xx_trans.xx = xx;})

  uvm_do_pri_with(xx_trans,pri_num,{xx_trans.xx = xx;})

  uvm_do_on(xx_trans,xx_sqr)

  uvm_do_on_pri(xx_trans,xx_sqr,pri_num)

  uvm_do_on_with(xx_trans,xx_sqr,{xx_trans.xx = xx;})

  uvm_do_on_pri_with(xx_trans,xx_sqr,pri_num,{xx_trans.xx = xx;})

 

2.嵌套的sequence

  假設已經定義了兩個sequence:sequence0、sequence1,現在想產生一個新的

sequence,這個新的sequence發的包是sequence0、sequence1交替產生。

 1 class sequence2 extends uvm_sequence #(xx_trans);
 2 ...
 3     virtual task body();
 4         sequence0 m_sequence0;
 5         sequence1 m_sequence1;
 6         repeat(10) begin
 7             `uvm_do(m_sequence0)
 8             `uvm_do(m_sequence1)
 9         end
10     endtask 
11 endclass

  上述例子意味着uvm_do系列宏第一個參數可以是sequence的指針。

 

3.在sequence中使用隨機值

  一般情況下,我們習慣在transaction中產生隨機值發送給driver,然后在具體sequence使用uvm_do_with對

一些我們需要自己定義的參數進行賦值約束,其實也可以在sequence里面使用rand bit xx;這種寫法,只不過在

sequence里面的變量名要和transaction里的變量名區分,因為編譯器首先到transaction里面尋找。

 

5.在sequence中使用config_db獲取參數

1.sequence路徑問題

  config_db對於sequence機制提供了支持,可以使用config_db設置一些比如發包的長度,數量等等。由於

sequence不在UVM樹中,那么如何設置config_db的路徑呢?可以使用get_full_name()在sequence的pre_body

一般路徑為:uvm_test_top.xx_env.xx_agent.xx_sequencer.xx_sequence

  uvm_config_db#(xx)::get(null,uvm_test_top.xx_env.xx_agent.xx_sequencer.xx_sequence,"xx",xx);

2.wait_modified

  假設sequence希望在處理一些異常情況的時候發出一個信號給scoreboard,scoreboard會實時監測這個信號,

一旦起來了,進行相應的比對。如何實現這種機制?

  使用wait_modified,sequence使用uvm_config_db::set發,scoreboard使用uvm_config_db:wait_modified

等待收。

 1 task xx_scoreboard::main_phase(uvm_phase phase);
 2     ...
 3 fork 
 4     while(1) begin
 5     uvm_config_db#(xx)::wait_modified(null,"$full_path()","xx");
 6     ...
 7     end 
 8 join
 9 ...
10 endtask 

  wait_modified的使用場景絕不僅限於此。

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM