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 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) 함. 이렇게 하는 이유? 외부에서 마음대로 설정해서는 안되는 값들을 보호하기 위해