UVM utility 和 field macros

2023-10-24
UVM

UVM使用 factory 的概念,所有object都向 factory 註冊(register),以便在需要時返回所需類型的object。用utility macros方便將每個object註冊到 factory 中。

UVM還導入了很多自動化機制,用來實現 printcopycompare object,並定義在macro裡面。

Object Utility

所有直接從 uvm_objectuvm_transaction 衍生的類別都需要使用 uvm_object_utils macro進行註冊。並且每個class都必須定義 new fucntion,並將class實例(instance)的名稱當參數。

1
2
3
4
5
6
7
8
class mydata extends uvm_object;
`uvm_object_utils(mydata)

// declare data properties
function new(string name="mydata_inst");
super.new(name);
endfunction
endclass

Component Utility

所有直接或間接從 uvm_component 衍生的類別都需要使用 uvm_component_utils macro進行註冊。並且每個直接或間接從 uvm_component 衍生的class,都必須定義 new fucntion,並將class實例(instance)的名稱和該object被實例化(instantiated)的parent class的當參數。

1
2
3
4
5
6
7
8
9
class my_comp extends uvm_component;

`uvm_component_utils(my_comp)

// declare data properties
function new(string name, uvm_component parent=null);
super.new(name,parent);
endfunction
endclass

Macro Expansion: detail

如果詳細去trace UVM code的話,可以看到 uvm_object_utils 會被展開為其 *_begin 和 *_end 形式,開始和結束中間沒有任何內容。 *_begin 實做了 UVM factory所需的其他macro。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// copy from uvm-1.2\docs\html\src\macros\uvm_object_defines.svh
`define uvm_object_utils(T) \
`uvm_object_utils_begin(T) \
`uvm_object_utils_end

`define uvm_object_param_utils(T) \
`uvm_object_param_utils_begin(T) \
`uvm_object_utils_end

`define uvm_object_utils_begin(T) \
`m_uvm_object_registry_internal(T,T) \
`m_uvm_object_create_func(T) \
`m_uvm_get_type_name_func(T) \
`uvm_field_utils_begin(T)

`define uvm_object_param_utils_begin(T) \
`m_uvm_object_registry_param(T) \
`m_uvm_object_create_func(T) \
`uvm_field_utils_begin(T)

`define uvm_object_utils_end \
end \
endfunction \

再詳細進去看uvm_object_utils_begin展開的這幾個macro可以看到register/create/get type name這些function的實作內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// copy from uvm-1.2\docs\html\src\macros\uvm_object_defines.svh

// m_uvm_object_registry_internal
// ------------------------------

//This is needed due to an issue in of passing down strings
//created by args to lower level macros.
`define m_uvm_object_registry_internal(T,S) \
typedef uvm_object_registry#(T,`"S`") type_id; \
static function type_id get_type(); \
return type_id::get(); \
endfunction \
virtual function uvm_object_wrapper get_object_type(); \
return type_id::get(); \
endfunction


// m_uvm_object_create_func
// ------------------------

`define m_uvm_object_create_func(T) \
function uvm_object create (string name=""); \
T tmp; \
`ifdef UVM_OBJECT_DO_NOT_NEED_CONSTRUCTOR \
tmp = new(); \
if (name!="") \
tmp.set_name(name); \
`else \
if (name=="") tmp = new(); \
else tmp = new(name); \
`endif \
return tmp; \
endfunction


// m_uvm_get_type_name_func
// ----------------------

`define m_uvm_get_type_name_func(T) \
const static string type_name = `"T`"; \
virtual function string get_type_name (); \
return type_name; \
endfunction

uvm_component_utils 也是一樣的道理,就不詳細作筆記了。

Creation of class object

建議所有class object都透過呼叫 ``m_uvm_object_create_func 定義的 type_id::create()` 方法來建立。這樣可以讓任何child class物件透過factory機制create和return,增加testbench的彈性和重複使用性。

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class mydata extends uvm_object;
`uvm_object_utils(mydata)

function new(string name = "mydata");
super.new(name);
endfunction
endclass

class base_test extends uvm_test;
`uvm_component_utils(base_test)

function new(string name = "base_test", uvm_component parent=null);
super.new(name, parent);
endfunction

virtual function void build_phase(uvm_phase phase);
mydata data = mydata::type_id::create("abc_inst");
endfunction
endclass

Field Macros

``uvm_field_*` 是用來操作class屬性並提供自動實作像是(copy、compare和print)method的macro。讓使用者節省實作每個class自定義 do_copy、do_compare 和 do_print function的時間。

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
class mydata extends uvm_object;
rand bit [15:0] m_addr;
rand bit [15:0] m_data;

`uvm_object_utils_begin(mydata)
`uvm_field_int(m_addr, UVM_DEFAULT)
`uvm_field_int(m_data, UVM_DEFAULT)
`uvm_object_utils_end

function new(string name = "mydata");
super.new(name);
endfunction
endclass

不同的變數,要使用與他data type相對應的 ``uvm_field_*macro。例如變量類型為intbitbyte的變數要用uvm_field_int,如果變數類型為 string的變數則要使用uvm_field_string`。這種macro至少要 ARG 和 FLAG 這兩個參數。
ARG要輸入變數名稱
FLAG根據不同使用狀況有以下幾種FLAG

Flag DescriptionPrice
UVM_ALL_ON Set all operations on.
UVM_DEFAULT This is the recommended set of flags to pass to the field macros. Currently, it enables all of the operations, making it functionally identical to UVM_ALL_ON. In the future however, additional flags could be added with a recommended default value of off.
UVM_NOCOPY Do not copy this field.
UVM_NOCOMPARE Do not compare this field.
UVM_NOPRINT Do not print this field.
UVM_NOPACK Do not pack or unpack this field.
UVM_REFERENCE For object types, operate only on the handle (e.g. no deep copy)
UVM_PHYSICAL Treat as a physical field. Use physical setting in policy class for this field.
UVM_ABSTRACT Treat as an abstract field. Use the abstract setting in the policy class for this field.
UVM_READONLY Do not allow setting of this field from the set_*_local methods or during uvm_component::apply_config_settings operation.

除了對操作的控制,``uvm_field_*` macro還可以控制變數的基數,其可以取以下值。此值可以與上表中列出的操作標誌進行 OR 運算。如果沒有指定,則 UVM_HEX 是default value。

Radix Description
UVM_BIN Print / record the field in binary (base-2).
UVM_DEC Print / record the field in decimal (base-10).
UVM_UNSIGNED Print / record the field in unsigned decimal (base-10).
UVM_OCT Print / record the field in octal (base-8).
UVM_HEX Print / record the field in hexadecimal (base-16).
UVM_STRING Print / record the field in string format.
UVM_TIME Print / record the field in time format.