UVM OOP

김기찬·2024년 7월 12일

class : variables(properites), subroutines(methods)를 포함.
class는 다른 class에서 extend하여 사용하거나 composition(객체 생성)을 통해 사용할 수 있다.

member : variables(변수) + subroutines(함수)

OOP : inheritance
extends : 상위 class를 상속받아 사용

bad_packet extends packet //bad_packet이 packet의 하위 class일 때 

packet pkt = new();
bad_packet bad_pkt = new();

pkt = bad_pkt; //가능. upcasting
bad_pkt = pkt; //불가능. 
$cast(bad_pkt, pkt) //가능. downcasting. cast를 통해 두 type이 같을 때 pkt값 bad_pkt에 할당
	

typedef: class를 미리 선언 후 밑에서 구현

typedef class s2;
class s1;
	s2 S2;
    ...
endclass

class s2;
	...
endclass

typedef stack #(bit[31:0]) stack32;
program automatic test;
	static32 addr_stack;
endprogram

extern : function을 생성 전에 미리 선언. 뒤에서 기술

class packet;
	extern virtual function int get_crc(); //class 내부에 미리 선언
endclass
function int packet::get_crc(); //나중에 구현
	...
endfunction

static : 다른 class도 share 가능.(global은 아니라서 create해줘야 memory에 올라감)
class::function 의 형태로 불러서 사용.
static은 수정할 수 없으므로 virtual로 선언 불가.

같은 메모리를 공유
class packet;
	static int count = 0;
    int id;
    function new();
    	id = count++; //new 될 때마다 count증가. 즉 몇개의 packet이 만들어졌는지 확인 가능.
    endfunction
    
    static function void print_count(); //function을 static으로 설정
    	$display("create %0d packets",count);
    endfunction
endclass 

function void test::end_of_test();
	packet::print_count(); //packet.print_count 함수를 불러서 사용
endfunction

OOP의 design pattern

singleton object(pattern) : globally access 가능한 static object.

  • 다른 class에서 사용 가능
  • static object는 하나만 존재
  • static, non-static member를 포함
class service_class;
	protected static service_class me = get(); //me가 선언되면 get호출, singleton instance 생성
    //protected : 이 class에서만 접근 가능
    static function service_class get();
    	if(me == null) me = new(); //me가 없다면 생성. 하나의 instance만 존재.
    endfunction
    extern virtual function void error(string msg);
endclass

singleton pattern : protect로 instance 선언 후 static function으로 외부에서 instance생성 or 불러올 수 있게(이미 instance 존재할 때) 만드는 형태
global하게 사용
service_class service_object = service_class::get(); //singleton instance를 얻음
service_object.error("error"); //class 사용

proxy object(pattern) : class가 해야할 일을 대신해줌(create)
왜 굳이 대신 해주는가? 캡슐화등 OOP를 위해

class proxy_class #(type T=base);
	typedef proxy_class# (T) this_type;
    static this_type me = get(); //this_type 크기의 변수 me 생성 후 get()호출
    
    -----singleton pattern----------
    protected function new(); endfunction
    static function this_type get(); //this_type 크기의 값 return
    	if(me == null) me = new();
        return me;
    endfunction 
    --------------------------------
    -----static factory method------
    static function T create();
    	create = new(); //new의 이름을 create로 바꿈.
    endfunction
    -------------------------------
endclass

-------proxy pattern 사용 예시------
class driver extends base;
	typedef proxy_class#(driver) proxy;
endclass

class environment;
	driver drv;
    function new();
    	drv = driver::proxy::create();// 그냥 new랑 똑같음. 근데 왜? OOP를 위해
    endfunction
endclass

pure: pure로 선언된 함수는 extends해서 구현해야함

factory class

virtual class proxy_base; //virtual class는 extend하여 사용해야함.
	virtual function base create_object(string type_name); //base 타입(사용자 정의) 반환. 하위 class에서 재정의 가능
    	return null;
    endfunction
    
    pure virtual function string get_typename(): //하위 class에서 반드시 구현해야함
endclass
	
class factory;
	static proxy_base registry[string]; //proxy_base type의 공간 할당
    ----------singleton pattern---------
    static factory me = get(); //factory type me생성
    static function factory get();
    	if(me == null) me = new(); return me; 
    endfunction 
    ------------------------------------
    function void register(proxy_base proxy);
    	registry[proxy.get_typename()] = proxy; //proxy_base type을 registry에 등록
    endfunction
    
    function base create_object_by_type(proxy_base proxy, string name);
    	proxy = find_override(proxy); 
        return proxy.create_object(name);
    endfunction
    
    static string override[string];
    static function void override_type(string type_name, override_typename);
    	override[type_name] = override_typename;
    endfunction
    
    function proxy_base find_override(proxy_base proxy);
    	if(override.exists(proxy.get_typename()))
        	return registry[override[proxy.get_typename()]];
        return proxy;
    endfunction
endclass

class proxy_class# (type T=base, string Tname = "T") extends proxy_base;
	typedef proxy_class# (T,Tname) this_type;
    static string type_name = Tname;
    static this_type me = get();
    static function this_type get();
    	if(me == null) begin me = new();
        return me;
    endfunction
    
    static function T create(string name);
    	$cast(create, factory::get().create_object_by_type(me,name));
    endfunction
    
    virtual function base create_object(string name);
    	T object_represented = new(name);
        return object_represented;
    endfunction
    
    virtual function string get_typename();
    	return type_name;
    endfunction
endclass  

set, get : protected로 선언되어 내부에서만 접근 가능한 값을 외부에서 설정하거나(set), 가져올 수 있도록(get) 함. 이렇게 하는 이유? 외부에서 마음대로 설정해서는 안되는 값들을 보호하기 위해

profile
SoC개발자

0개의 댓글