UVM——寄存器模型相關的一些函數


 

0. 引言

  在UVM支持的寄存器操作中,有get、update、mirror、write等等一些方法,在這里整理一下他們的用法。

  寄存器模型中的寄存器值應該與DUT保持同步,但是由於DUT的值是實時更新的,所以寄存器模型並不能實時知道這種更新,在寄存器模型中專門有個值來盡可能與DUT中寄存器的值保持一致,叫鏡像值(mirrorred value)。寄存器模型中還有一個值叫期望值(respected value),這個值保存我們希望寫入寄存器的值。比如希望向DUT某個寄存器寫入'h1,用set函數設置期望值,然后用update任務(update會比較鏡像值和期望值,如果不一樣,將期望值寫入DUT,並更新鏡像值)。

 

1.  函數

1.1 set 

virtual function void set (	uvm_reg_data_t 	value,	 string 	fname	 = 	"",int 	lineno	 = 	0	)

  設置模型中寄存器的期望值,不會改變DUT中這個寄存器的值。

1.2 get

virtual function uvm_reg_data_t get(	string 	fname	 = 	"", int 	lineno	 = 	0	)

  返回模型中寄存器的期望值,而不是DUT中的寄存器值

1.3 get_mirrored_value

virtual function uvm_reg_data_t get_mirrored_value(	string 	fname	 = 	"", int 	lineno	 = 	0	)

  返回模型中寄存器的鏡像值。

1.4 get_reset

virtual function uvm_reg_data_t get_reset(	string 	kind	 = 	"HARD"	)

  返回寄存器的復位值。

1.5 predict

virtual function bit predict (	uvm_reg_data_t 	value,	  	
  uvm_reg_byte_en_t 	be	 = 	-1,
  uvm_predict_e 	kind	 = 	UVM_PREDICT_DIRECT,
  uvm_path_e 	path	 = 	UVM_FRONTDOOR,
  uvm_reg_map 	map	 = 	null,
  string 	fname	 = 	"",
  int 	lineno	 = 	0	)

  更新模型中的鏡像值。新的鏡像值通過value參數傳入。

  當在DUT中實現一個計數器的時候,模型中的計數器是靜止的。如果想在模型中得到DUT的技術值,這就需要手動更新鏡像值,又不能對DUT進行操作,這可以通過predict函數。

第三個參數是uvm_predict_e枚舉類型,他有如下三個元素:

UVM_PREDICT_DIRECT Predicted value is as-is
UVM_PREDICT_READ Predict based on the specified value having been read
UVM_PREDICT_WRITE Predict based on the specified value having been written

如果想要更新鏡像值又不對DUT進行操作,要用UVM_PREDICT_DIRECT。

  write、read、peek和poke在完成對DUT的讀寫之后也會調用這個函數,更新鏡像值。

1.6 randomize

  無論是uvm_reg,還是uvm_field、uvm_block,都是支持randomize()。

assert(rm.invert.reg_data.randomize());
assert(rm.invert.randomize());
assert(rm.randomize()):

  

  當寄存器隨機化后,期望值會被隨機,但是鏡像值不變,之后調用update任務,可以更新DUT中的寄存器值。

  但是一個field能夠被隨機化,需要:

    1. 在filed的configure第八個參數設為1.

    2. filed為rand類型。

    3. filed的讀寫類型為可寫的。

 

2. 任務

2.1  update

virtual task update(	output 	uvm_status_e 	status,	  	
  input 	uvm_path_e 	path	 = 	UVM_DEFAULT_PATH,
  input 	uvm_reg_map 	map	 = 	null,
  input 	uvm_sequence_base 	parent	 = 	null,
  input 	int 	prior	 = 	-1,
  input 	uvm_object 	extension	 = 	null,
  input 	string 	fname	 = 	"",
  input 	int 	lineno	 = 	0	)

  將模型中的期望值更新到DUT中。改變DUT中的寄存器。update會檢查模型中的期望值和鏡像值,如果兩者不相等,那么將期望值更新到DUT中,並且更新鏡像值。update與mirror操作相反。

  如果鏡像值和期望值相同,那么不會寫DUT寄存器,也就不會產生總線transaction。

2.2 mirror

virtual task mirror(	output 	uvm_status_e 	status,	  	
  input 	uvm_check_e 	check	 = 	UVM_NO_CHECK,
  input 	uvm_path_e 	path	 = 	UVM_DEFAULT_PATH,
  input 	uvm_reg_map 	map	 = 	null,
  input 	uvm_sequence_base 	parent	 = 	null,
  input 	int 	prior	 = 	-1,
  input 	uvm_object 	extension	 = 	null,
  input 	string 	fname	 = 	"",
  input 	int 	lineno	 = 	0	)

  讀DUT中寄存器的值,與update操作相反。如果第二個參數check為UVM_CHECK,那么會檢查讀取的值與鏡像值是否一樣,如果不一樣報錯。通過mirror讀取DUT的寄存器值之后,會調用predict函數,更新鏡像值。

  mirror有兩種應用場景:一是在仿真中不斷調用,但此時是UVM_NO_CHECK,保證鏡像值與DUT中的值相等;二是在仿真結束的時候調用,這時是UVM_CHECK檢查模型中的鏡像值與DUT中的寄存器值是否一致。

2.3 write

virtual task write(	output 	uvm_status_e 	status,	  	
  input 	uvm_reg_data_t 	value,	  	
  input 	uvm_path_e 	path	 = 	UVM_DEFAULT_PATH,
  input 	uvm_reg_map 	map	 = 	null,
  input 	uvm_sequence_base 	parent	 = 	null,
  input 	int 	prior	 = 	-1,
  input 	uvm_object 	extension	 = 	null,
  input 	string 	fname	 = 	"",
  input 	int 	lineno	 = 	0	)

  模仿DUT的行為,通過前門或者后門方式向DUT中寫入寄存器值,會產生總線transaction。並且調用predict更新鏡像值。

  uvm_path_e定義寄存器操作類型,如下:

UVM_FRONTDOOR Use the front door
UVM_BACKDOOR Use the back door
UVM_PREDICT Operation derived from observations by a bus monitor via the uvm_reg_predictor class.
UVM_DEFAULT_PATH Operation specified by the context

  我在使用中,如果用set_auto_predict(1)——采取自動更行鏡像值的方式,write之后,調用get和get_mirrored_value都能得到新寫入的值。  

  如果關閉auto_predict,用uvm_reg_predict來更新鏡像值,我在在使用中write之后,調用get和get_mirrored_value得到0

  如果是read任務,那么無論是auto_predict還是uvm_reg_predict都會自動更新鏡像值和期望值。

  鏈接:https://github.com/east1203/uvm_codes/tree/master/tb1_wd/a.uvm_reg_predict

2.4 read

virtual task read(	output 	uvm_status_e 	status,	  	
  output 	uvm_reg_data_t 	value,	  	
  input 	uvm_path_e 	path	 = 	UVM_DEFAULT_PATH,
  input 	uvm_reg_map 	map	 = 	null,
  input 	uvm_sequence_base 	parent	 = 	null,
  input 	int 	prior	 = 	-1,
  input 	uvm_object 	extension	 = 	null,
  input 	string 	fname	 = 	"",
  input 	int 	lineno	 = 	0	)

  模仿DUT的行為,通過前門或者后門方式讀取DUT中寄存器的值,並更新鏡像值,會產生總線transaction

2.5 peek

virtual task poke(	output 	uvm_status_e 	status,	  	
  input 	uvm_reg_data_t 	value,	  	
  input 	string 	kind	 = 	"",
  input 	uvm_sequence_base 	parent	 = 	null,
  input 	uvm_object 	extension	 = 	null,
  input 	string 	fname	 = 	"",
  input 	int 	lineno	 = 	0	)

  通過后門訪問方式讀取寄存器的值,不關心DUT的行為,即使寄存器的讀寫類型是不能讀,也可以將值讀出來

   對於read clear類型的field,peek讀操作不會clear。所以有的時候peek和read操作結果不一樣

2.6 poke

virtual task peek(	output 	uvm_status_e 	status,	  	
  output 	uvm_reg_data_t 	value,	  	
  input 	string 	kind	 = 	"",
  input 	uvm_sequence_base 	parent	 = 	null,
  input 	uvm_object 	extension	 = 	null,
  input 	string 	fname	 = 	"",
  input 	int 	lineno	 = 	0	)

  通過后門訪問方式寫入寄存器的值,不關心DUT的行為,即使寄存器的讀寫類型是不能寫,也可以將值寫進去

   對於write clear類型的filed,poke操作不會clear,所以有的時候poke和write操作結果不一樣。

 


免責聲明!

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



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