본문 바로가기

UVM

[UVM] Class와 Factory 이해하기

UVM환경에서 클래스 생성과 활용: Randomization 및 Factory Mechanism 이해해보자!
 
 
UVM에서 random constraint를 작성하는 class를 만들 때, 그냥 class를 쓸지, uvmobject에서 상속받아 쓸지, uvm_component에서 상속 받아서 쓸지 고민하게 된다.
보통 uvm_object를 상속받아서 작성한다.
그 이유는 uvm_object는 uvm의 기본적인 class로, 어떤 class든 상속받아서 쓰지 않을 때보다 더 많은 기본 코드들을 사용할 수 있다.
uvm_component의 경우, 주로 Testbench의 구조를 정의하는데 사용한다. 즉, uvm_object의 경우 데이터 관리에 더 초점을 맞추고 있으므로 randomization이나 contraint를 적용하는데는 uvm_object를 상속받아서 사용하는 것이 더 유용하다.

 

uvm_object를 상속받아서 class를 작성하면, UVM의 기본 기능을 쉽게 활용할 수있다.

 

1. Randomization: uvm_object는 uvm이 추가로 제공하는 randomize() 기능을 더 세밀하게 사용할 수 있다. 예를 들어 pre_randomize()나 post_randomize()와 같은 hook 메소드는 uvm을 사용해야지만 사용할 수 있다.

2. Factory registration: uvm_object는 uvm factory에 자동으로 등록되므로, 이름 기반의 생성과 override의 메커니즘을 적용할 수 있다. ( 이후에 추가 설명)

3. print, copy와 comparison : uvm_object에서 파생된 class는 copy와 comparison 메소드를 사용 할 수 있다.

4. configuration: uvm_config_db를 사용하여, class내 값에 접근하여 설정 할 수있다. (ex. uvm_config_db#(int)::set(null, “obj”,”x”,10);

4. transaction과 recording: uvm_object에서 파생된 class는 UVM의 TLM과 함께 사용하면, 자동으로 transaction recoding을 지원한다.

5. print 와 pack: uvm_object를 사용하므로, 필드를 문자열로 변환하거나, 패킷으로 압축하는 메소드도 사용할 수있다.

1. Randomzation
class my_obj extends uvm_object;
rand int x;
rand int y;

constraint c { x +y <10; }

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

function void pre_randomize();
 `uvm_info("PRE_RADOMIZE","Randomizing x and y", UVM_LOW)endfucntion

function void post_radomize(); `uvm_info("POST_RANDOMIZE","$sformatf("Randomize value: x = %0d, y = %0d,x,y),UVM_LOW)
endfucntion

my_obj obj = new();
obj.randomzie();
2. Factory 

class my_obj extends uvm_object;
 `uvm_object_utils(my_obj); // Factory에 my_obj를 등록

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

class my_test extends uvm_test;
 my_obj obj;

 fuction new(string name = "my_test");
  super.new(name);
 endfunction

 task run_phase(uvm_pahse phase);
  obj = my_obj::type_id::create("obj"); // my_test에서 factory를 통해 my_obj생성
 ...
 endtask
endclass
3. copy and comparison
class my_obj extends uvm_object;
...
endclass

my_obj obj1 = new();
my_obj obj2 = new();

obj1.print(uvm_default_printer::get()); // obj1을 출력
obj1.copy(obj2); //obj2의 값을 obj1에 복사

if(obj1.compare(obj2))) `uvm_info("INFO","obj1 and obj2 are equal", UVM_LOW) // 비교
4. configuration
class my_obj extends uvm_object;
 int x;
...
endclass

my_obj obj= new();

uvm_config_db#(int)::set(null,"obj","x",10); //obj의 x를 10으로 설정
or 
obj.x = 10;

int x;
uvm_config_db#(int)::get(null,"obj","x",x); //x에 obj의 x값을 가져올 수 있다. 
if(!obj.randomize()) `uvm_error("RANDOMIZE","Randomization Fail") // obj를 10으로 세팅한 후, randomize한다.

위에서 설명한 예시는 대표적 uvm_object를 사용할 때 이점에 대한 예시이다.
이에외도 uvm_object에 포함되어있는 여러가지 메쏘드를 사용할 수 있다.
추가적으로 , systemverilog에서 제공하는 randomize를 control 할 수 있는 기능이 있다.
1. rand_mode() : 객체 필드에 대한 randomization을 활성화 비활성화 한다.
2. constraint_mode(): 특정 제약 조건을 확성화 하거나 비활성화 한다.

예를 살펴보자

class my_obj;
 rand int x;
 rand int y;
 constraint c {x+y <10;}
endclass

my_obj obj =new();
obj.x.rand_mode(0);
obj.randomize(); // y만 randomize가능

obj.constraint_mode(0);
obj.randomize(); // x와 y는 constraint 조건 없이 random.

위에처럼 rand_mode를 통해 rand속성에 대해서만 사용하여 random을 컨트롤할 수있고,
constraint_mode는 rand의 속성 뿐 아니라 obj자체도 컨트롤 할 수 있다.


” 나의 사용법 “

  1. uvm test 내에 constraint 파일을 인스턴스하고, build_phase내에서 create해준다. 그리고 uvm_config_db를 통해 set해준다.
  2. uvm_sequence내에서 다시 constraint 파일을 인스턴스하고, pre_body function에서 uvm_config_db를 통해 get해준다.
  3. uvm_sequence내에서 body에서 constraint파일을 randomize 해준다.

test파일은 각 과제로 사용하고, sequence파일은 과제내의 testcase혹은 block하나로 만들어준다.
test내에서 constraint파일을 create해주었기 때문에, test 파일이 계속생성되어도 재사용이 가능하고, 어떠한 sequence내에서도 get해서 가져올 수 있다.
--> 위에 방법을 쓰기 위해서는 constraint 파일을 uvm_test, uvm_sequence 두개의 파일에 모두 `include해줘야한다. --> 이를 피하기 위해서는 constraint파일을 헤더 파일에 `include해서 해당 클래스를 한번만 include하게 하는 방법을 사용하면 편하다.

'UVM' 카테고리의 다른 글

UVM에서 시퀀스 실행 방법  (0) 2024.07.14
[UVM] UVM Testbench 환경 구조  (0) 2024.07.09