본문 바로가기

SystemVerilog

[ SystemVerilog ] static변수와 함수의 의미, protected란?

systemverilog에서 static 변수란, globa variable과 비슷한 의미이다.

만약 class 변수를 static으로 선언한다면 여러 class object들, 혹은 코드 여러 곳에서 바라본 이 variable이, 

단 하나의 data member copy임을 의미한다. 

그러니까 쉽게 말해, one and only~! 실제 객체는 하나뿐이며, 이 객체가 할당된 메모리 한 곳만을 모두가 바라본다는 사실~

그럼, 클래스 하나로 여러개의 인스턴스를 생성했을 때, 모든 인스턴스의 static member는 같은 레퍼런스이며,

한 곳에서 수정되면 다른 모든 곳에서 수정된다는 뜻이다.

마치 global variable처럼 말이다.

 

원래 우리는 programming 할때 global variable 사용을 지양하도록 배워왔다. 

왜? Debugging 이 어렵기 때문이다.

1) type을 알기 어려움

사용된 곳과 선언된 곳이 달라 type을 알아내려면 다른 source file들을 몽땅 뒤져야 한다.

 

2) program의 여러 곳에서 사용되므로 내가 모르는 사이에 값이 변할 수 있다.

특히 여러 사람이 함께 작업하는 코드라면 더 그렇다.

 

하지만 Testbench에서 Global Variable은 잘 쓰면 유용하다. 

DUT에 data를 driving하는 part나 DUT로부터 값을 읽는 part가 있을 때,

이 둘의 transaction을 global location에 저장하고, 결과를 비교하는 3rd part component인 self-checking tool을 사용하면 매우 유용할 것이다.

 

 

 

Static Variable 선언하기.

이전에 알던 class의 개념을 잘 떠올려보자. 

class object(인스턴스)를 위한 메모리는 언제 할당될까? 

 바로 new() 메소드(constructor)를 호출할 때! 

그전까지 그 클래스 변수(아마도 이름뿐인 그것)는 빈 공간을 가리키는 handle일 뿐이다. (전문용어로 placeholder라고 했던가...)

사실 이건 반만 맞는 이야기이다.

만약 시스템베릴로그 클래스에서, data member앞에 static이란 키워드를 사용하여 선언하면,

클래스 정의와 동시에 variable을 위한 공간이 allocate 된다. (static variable)

(왜 그런가 생각을 해봤더니, static이란 그 클래스 정의를 공유하는 모든 오브젝트가 공유한다고 했지 않는가..?

애초에 new()를 통해 이뤄지는 instantiation이랑은 관계가 없는 변수였다. 그러므로 class defintion과 동시에 메모리가 할당된다. )

 

또한 앞서 말했듯이 해당 class를 여러번 instantiate 한다고 해도 static data members는 단하나만 존재한다.

(재차 강조합니다 one and only 원앤온리.. 그냥 거기에 있는 애)

여러 클래스 오브젝트들이 단 하나의 data member copy인 static variable를 바라보고 공유하며 이는 global variable인 셈이다. 

 

 

 

lion cage예제

class lion_cage;
	static lion cage[$];
endclass : lion_cage

- lion_cage의 인스턴스를 생성하지 않아도  'cage' variable에 접근할 수 있다.

- cage는 lion타입의 변수들을 담을 수 있는 큐(Queue)이다. 

 

 

initial begin
	lion lion_h;
    lion_h = new(2,"kimba");
    lion_cage::cage.push_back(lion_h);    
    lion_h = new(3,"simba");
    lion_cage::cage.push_back(lion_h);
    lion_h = new(2,"mustafa");
    lion_cage::cage.push_back(lion_h);
    $display("lions in cage");
    foreach(lion_cage::cage[i])
    	$display(lion_cage::cage[i].get_name());

결과는 아마도 

=============

lions in cage 

kimba

simba

mustafa

=============

위 코드의 분석..

1) static variable의 장점

- 코드 어디서나 이 변수에 access가능하다. lion_cage::cage를 통해서!

- 그리고 일반적인 이 변수가 어디서 선언 됐는 지도 곧바로 알 수 있다. 

::를 사용해 class hierarchy를 보여주므로...

 

2) 그러나 static variable에 직접 access 하는 것은 poor coding style이다.

lion_cage::cage.push를 통해 cage variable에 직접 access 했지만 

static method를 작성해서 static variable들을 다루는 것이 더욱 우아하다 할 수 있다~ 

 

 

static method 사용하기

class lion_cage;
	protected static lion cage[$];
    
    static function void cage_lion(lion l)
    	cage.push_back(l);
    endfuction : cage_lion
    
    static function void list_lions();
    	$display("lions in cage");
        foreach(cage[i])
        	$display(cage[i].get_name());
    endfunction : list_lions
    
endclass : lion_cage

static method를 사용한 새로운 버전의 lion_cage는 보다 safer & easier

1) protected keyword

protected라는 키워드를 사용하면, 만약 class method를 사용하지 않고 user가 직접 access 할 경우 compile error를 띄움

 

2) static methods

cage라는 static member에 직접 접근하는 대신, 클래스 메소드를 통해 접근하게 하는 wrapper method.

static method란.. 호출시 동일한 memory location을 공유하고 사용한다. 

호출할 때마다 새로운 메모리를 alloc & access 해서 과거 데이터가 초기화되는 것이 아니라, history가 남는다.

 

3) 위 코드의 단점은 lion class만 담을 수 있는 cage라는 것이다.

하나의 코드로 다른 동물을 보관하는 cage도 만들 수 없을까? 

chicken cage를 만들려면 저 위 코드들을 전부 copy & paste해서 lion만 chicken으로 바꿔줘야 할까? 

같은 기능을 하는데 2개의 copy 코드를 작성하는 것은 매우 비효율이다. 

뿐만 아니라 buggy 하다. 

만약 기능 업데이트가 되거나 수정이 이뤄지면, 전체 소스코드에서 cage가 있는 모든 곳을 찾아가서 

따로따로 수정해줘야 하거든요.

그러니까 앞으로 우리가 추가적으로 배워야 할 것은! parameterized class definition. 

 

static variable과 마찬가지로 parameterized class 또한 UVM을 이해하기 위한 key feature 임을 알아주세요~