ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [SystemVerilog] 클래스 3 다형성2
    개발/SystemVerilog 2022. 1. 24. 16:36

    다형성을 활용하기 위해 virtual method를 알아본다.

     

    이전 글에서 정의한 클래스를 그대로 갖고왔다.

    다만 packet 클래스 내부에 display() 태스크 앞에 virtual 키워드가 붙었다.

    virtual method를 정의하기 위해선 virtual 키워드를 function / task 앞에 쓰면 된다.

    class packet;
        bit [31:0] addr;
        
        function new (bit [31:0] addr);
        	this.addr = addr;
        endfunction
        
        virtual task display();
        	$display("[base] addr = 0x%0h", addr);
        endtask
        
    endclass
    
    
    class extpacket extends packet;
        bit [31:0] data;
        
        function new (bit [31:0] addr, data);
        	super.new(addr);
            this.data = data;
        endfunction
        
        task display();
        	$display("[child] addr = 0x%0h, data = 0x%0h", addr, data);
        endtask
    endclass

     

    위의 클래스를 갖고 테스트를 해보자.

    module tb;
        packet bc;
        extpacket sc1;
        
        initial begin
        	sc1 = new(32'hfeed_feed, 32'hface_cafe);
          	sc1.display();
          
          	bc = sc1;
            bc.display(); 
        end
    
    endmodule

    sc1 핸들을 bc에 할당하고 bc핸들에서 display() 태스크를 호출했다.

    이전글에선 클래스 핸들타입에 따라서 메서드가 실행된다고 했다.

    하지만 부모클래스의 메서드가 virtual 이라면, 자식클래스의 메서드가 오버라이딩 되어 실행된다.

     

     

     

     

    vitual method와 dynamic look up에 대해 알아보자.

    아래에 새로운 클래스를 추가하고 테스트를 실행했다.

    class packet;
        bit [31:0] addr;
        function new (bit [31:0] addr);
        	this.addr = addr;
        endfunction
        
        task display();
        	$display("[base] addr = 0x%0h", addr);
        endtask
    endclass
    
    
    class extpacket extends packet;
        bit [31:0] data;
        function new (bit [31:0] addr, data);
        	super.new(addr);
            this.data = data;
        endfunction
    endclass
    
    
    class errpacket extends extpacket;
    	int errorcount = 0;
        function new(bit [31:0] addr, data);
          super.new(addr, data);
          ++this.errorcount;
        endfunction
      
        task display();
    	    $display("[errpacket] errorcount = %d", errorcount);
        endtask
      
    endclass
          
    
    module tb;
        packet bc;
        extpacket sc1;
        errpacket ec1;
        
        initial begin
          sc1 = new(32'hfeed_feed, 32'hface_cafe);
          ec1 = new(32'haaaa_aaaa, 32'hbbbb_bbbb);
    
          bc = sc1;
          bc.display();
    
          bc = ec1;
          bc.display(); 
        end
    endmodule

    이전에 설명한 대로 virtual method가 아니라면 클래스 핸들의 타입에 의해서 메서드가 결정된다.

    extpacket 클래스에는 display() 메서드가 정의되지 않았다. 이런 경우엔 상위에 있는 가장 가까운 클래스에서 메서드를 호출한다. (complile time resolution)

     

     

     

     

     

    이번에는 베이스클래스의 메서드가 virtual 으로 선언됬을 경우를 알아본다.

    packet 클래스의 메서드가 virtual 으로 선언된것만 제외하고는 위와 동일한 코드이다.

    class packet;
        bit [31:0] addr;
        function new (bit [31:0] addr);
        	this.addr = addr;
        endfunction
        
        virtual task display();
        	$display("[base] addr = 0x%0h", addr);
        endtask
    endclass
    
    
    class extpacket extends packet;
        bit [31:0] data;
        function new (bit [31:0] addr, data);
        	super.new(addr);
            this.data = data;
        endfunction
    endclass
    
    
    class errpacket extends extpacket;
    	int errorcount = 0;
        function new(bit [31:0] addr, data);
          super.new(addr, data);
          ++this.errorcount;
        endfunction
      
        task display();
    	    $display("[errpacket] errorcount = %d", errorcount);
        endtask
      
    endclass
          
    
    module tb;
        packet bc;
        extpacket sc1;
        errpacket ec1;
        
        initial begin
          sc1 = new(32'hfeed_feed, 32'hface_cafe);
          ec1 = new(32'haaaa_aaaa, 32'hbbbb_bbbb);
    
          bc = sc1;
          bc.display();
    
          bc = ec1;
          bc.display(); 
        end
    endmodule

    sc1의 핸들을 받아서 display() 호출했을 때는 이전의 케이스와 같다.

    하지만 ec1 핸들을 받아서 display() 호출하면 ec1의 메서드가 실행된다.

    이런 경우엔 오브젝트 타입에 따라서 메서드가 결정된다. (run time resolution)

     

     

     

     

     

    클래스를 virtual 으로 정의할 수 있다.

    virtual class packet;
        bit [31:0] addr;
        
        function new (bit [31:0] addr);
        	this.addr = addr;
        endfunction
           
    endclass

    virtual class 는 바로 오브젝트를 생성할 수 없다.

     

     

     

    virtual class 내부에서 정의한 메서드를 pure virtual method 라고 한다.

    pure 키워드를 사용한다.

    virtual class packet;
        bit [31:0] addr;
        
        function new (bit [31:0] addr);
        	this.addr = addr;
        endfunction
        
        pure virtual task display();
        pure virtual function int getAddr();
        
    endclass

    이것은 virtual 클래스를 만들 때, 프로토타입만 정의를 하고 나머지 부분은 하위 클래스에서 구현해야한다.

    하위클래스에서 구현된 메서드는 pure virtual 메서드를 오버라이드 한다.

     

    '개발 > SystemVerilog' 카테고리의 다른 글

    [SystemVerilog] 랜덤변수 1  (0) 2022.01.25
    [SystemVerilog] 클래스 4 데이터 은닉  (0) 2022.01.24
    [SystemVerilog] 클래스 3 다형성  (0) 2022.01.24
    [SystemVerilog] 클래스 3 상속  (0) 2022.01.24
    [SystemVerilog] 클래스 1  (0) 2022.01.17
Designed by Tistory.