Object Oriented Programming

SungchulCHA·2024년 8월 29일
0

System Verilog

목록 보기
4/6
RTLOOP
Block definitionmoduleclass
Block instanceinstanceobject
Block nameinstance nameobject handle
Data typesregisters and wiresvariables
Functionalitytasks, functions, behavioral blocks(always, initial)subroutines(tasks, functions)

OOP Encapsulation

class Packet;
  string name;
  bit[3:0] sa, da;
  bit[7:0] payload[];
  
  task send();
    send_addrs();
    send_pad();
    send_payload();
  endtask: send
endclass: Packet

Variables = properties
Subroutines = methods
Properteis & methods = members of class

Constructing OOP Objects

program automatic test;
  Packet pkt1 = new();
  Packet pkt2;
  
  initial begin
    pkt2 = new();
    pkt1.sa = 3;
  end
endprogram: test

Initialization

program automatic test;
  class Packet;
    string name;
    bit[3:0] sa, da;
    bit[7:0] payload[];
    
    function new(bit[3:0] init_sa, init_da, int init_payload_size);
      this.sa = init_sa;
      this.da = init_da;
      this.payload = new[init_payload_size];
    endfunction: new
  
    task send();
      send_addrs();
      send_pad();
      send_payload();
    endtask: send
  endclass: Packet

  initial begin
    Packet pkt1 = new(3, 7, 2);
  end
endprogram

Garbage Collection

VCS는 garbage collector 있음.

class Packet;
  int count;
  Payload p;
endclass: Packet

Packet pkt1 = new();
Packet pkt1_copy;
pkt1_copy = new pkt1;

pkt1_copy 가 원래 가리키던 메모리 공간 접근 불가하므로 garage collector가 제거함.
class 안에 있는 class(Payload p)는 카피가 안됨. copy() 함수 구현해서 사용.

Data Hiding

program automatic test;
  class driver;
    local int max_err_cnt = 0, err_cnt = 0;
    task run();
      if (error_cond()) err_cnt++;
      if ((max_err_cnt != 0) && (err_cnt >= max_err_cnt))
        $finish;
    endtask
    
    function set_max_err_cnt(int max_err_cnt);
      if (max_err_cnt < 0) begin
        this.max_er_cnt = 0;
        return;
      end
      else this.max_err_cnt = max_err_cnt;
    endfunction
    
    function new();
    endfunction
    
  endclass: driver
  
  initial begin
    driver drv = new();
    drv.set_max_err_cnt(-1);
    drv.run();
  end
endprogram: test

static Members

class Packet;
  static int count = 0;
  int id;
  static function int get_count();
    return count;
  endfunction
  function new();
    this.id = count++;
  endfunction
endclass: Packet

virtual subroutines는 접근 못함
class의 모든 objects가 공유함

const Properties

class Packet;
  static int count = 0;
  const int id;                              // instance constant
  static const string type_name = "Packet";  // global constant
  static function int get_count();
    return count;
  endfunction
  function new();
    this.id = count++;                      // instance constant can only be assigned in new()
  endfunction
endclass: Packet

Global constant - tipically declared static
Instance constant - can not be static

Concurrency

  • class 안에는 initial, always 사용 불가
  • fork-join_none으로 구현
class Driver
  task run();
    fork
      forever
        send();
    join_none
  endtask: run
endclass: Driver

Parameterized Classes

program automatic test;
  typedef class stack;
  
  stack addr_stack;
  stack #(Packet, 128) data_stack;
  
  class stack #(type T = int, bit[11:0] depth = 1024);
    protected T items[$:depth];
    function T pop();
    function viod push ( T a );
    ...
  endclass: stack
  
  initial begin
  
  ...
  
  end
endprogram: test

그 외

class node;
  static int count = 0;
  node next;
  ...
  extern task ping();
endcalss: node

task node::ping();
  ...
endtask: ping

namespace 사용가능

Virtual Interfaces

  • Interfaces can not be created at object construction.
class Driver;
  virtual router_io.TB rtr_io_ref;
  ...
  
  function new(virtual router_io.TB rtr_io_arg);
    this.rtr_io_ref = rtr_io_arg;
  endfunction: new
  
  task send_addrs();
    this.rtr_io_ref.cb.frame_n[sa] <= 1'b0;
    for (int i = 0; i < 4; i++) begin
      this.rtr_io_ref.cb.din[sa] <= da[i];
      @(this.rtr_io_ref.cb);
    end
  endtask: send_addrs
  
endclass: Driver

Packages

  • modules
  • programs
  • interfaces
  • Parameters
  • variables and nets
  • type definitions
  • task, functions
  • sequence and property declarations
  • classes

공유 가능

package ComplexPkg;
  class Complex;
    float i, r;
    extern virtual task display();
  endclass: Complex
  
  function automatic Complex add(Complex a, b);
    add = new();
    add.r = a.r + b.r;
    add.i = a.i + b.i;
  endfunction: add
  
  function automatic Complex mul(Complex a, b);
    mul = new();
    mul.r = (a.r * b.r) - (a.i * b.i);
    mul.i = (a.r * b.i) + (a.i * b.r);
  endfunction: mul
endpackage: ComplexPkg

processes 쓰면 안됨 - wire 도 안됨
hierarchical references 쓰면 안됨

ComplexPkg::Complex count = ComplexPkg::mul(a, b); 로 사용
import ComplexPkg::*; 도 가능
Packages를 import 해서 package 만들었으면 export ComplexPkg::*; 사용


OOP Based Randomization

  • randomize() : function built into every class
  • rand : 주사위 굴리기
  • randc : 카드 뽑기
class Packet;
  randc bit[3:0] sa, da;
  rand  bit[7:0] payload[];
endclass: Packet

program automatic test;
  int run_for_n_pkts = 100;
  Packet pkt = new();
  
  initial begin
    ...
    
    repeat (run_for_n_pkts)
    beegin
      if(!pkt.randomize()) ... ;
      
      fork
        send();
        recv();
      join
      check();
    end
  end
endprogram: test

Controlling Random Variables

class Packet;
  randc bit[3:0] sa, da;
  rand  bit[7:0] payload[];
  
  constraint corner_test {
    sa == 12;
    da inside {2,4, [6:10]};
    payload.size() >= 2;
    payload.size() <= 4;
  }
endclass: Packet

Weighted Constraints

constraint Limit {
  sa dist {[5:7]:=30, 9:=20};  // 5,6,7의 weight는 30, 9는 20
  da dist {[5:7]:/30, 9:=20};  // 5,6,7의 weight는 10, 9는 20
}

Implication Operator

class Config;
  rand bit[7:0] addrs[10];
  rand bit drivers_in_use[16];
  rand int num_of_driers, one_addr;
  
  constraint limit {
    num_of_drivers inside { [1:16] };
    drivers_in_use.sum() with (int'(item)) == num_of_drivers;
    foreach(addrs[idx]) (idx > 0) -> addrs[idx] > addrs[idx-1];
    one_addr inside addrs;
  }
endclass: Config

Equivalence Operator

typedef enum { low, mid, high, any } AddrTyp_e;
class MyBus;
  rand bit[7:0] addr;
  rand AddrTyp_e atype;
  constraint addr_range {
    (atype == low ) <=> addr inside { [0:15] };
    (atype == mid ) <=> addr inside { [16:127] };
    (atype == high) <=> addr inside { [128:255] };
  }
endclass: MyBus

Uniqueness Constraint

class C;
  rand bit [2:0] a[7];
  rand bit [2:0] b;
  constraint cst1 {
    unique { a[0:2], a[6]. b };
  }
endclass: C

unique 안에 있는 값들은 서로 다른 값을 가진다.

Constraint Solver Order

randcrand보다 우선순위

class MyBus;
  rand bit flag;
  rand bit[11:0] addr;
  
  constraint addr_range {
    if ( flag == 0 ) addr == 0;
    else addr inside { [1:1024] };
    solve flag before addr;
  }
endclass: MyBus

Inline Constraints

program automatic test;
  class demo;
    rand int x, y, z;
    constraint Limit1 { x > 0; x <= 5; }
  endclass: demo
  
  initial bgin
    demo obj_a = new();
    
    if (!obj_a.randomize() with { x > 3 && x < 10; }) ...;
  end
endprogram: test

Soft Constraints

class Packet;
  rand bit [11:0] len;
  rand int min, max;
  constraint len_c { soft len inside {[min:max]};}
  constraint range { soft min == 0; soft max == 10;}
endclass: Packet

Packet p,q;
int tmin,tmax;

stat = p.randomize() with {
    soft len inside {[tmin:tmax]};
    }

rand 변수만 가능. randc 불가능
inline constraint가 우선임

randomize()

class Packet;
  int test_mode;
  rand bit[3:0]  sa, da;
  rand bit[7:0]  payload[];
       bit[15:0] crc;
  constraint LimitA {
    sa inside { [0:7] };
    da inside { [0:7] };
    payload.size() inside {[2:4]};
  }
  
  function void pre_randomize();
    if(test_mode) sa.rand_mode(0)
  endfunction
  
  function void post_randomize();
    gen_crc();  // user method
  endfunction
endclass: Packet

randomize() 호출시
pre_randomize() 호출하고
변수 랜덤 돌리고
post_randomize() 호출
rand_mode(0 | 1)
rand_mode()programinitial 안에서도 사용가능

constraint_mode()

class demo;
  rand int x, y, z;
  constraint no_error { x > 0; x <= 5; }
  static constraint with_err { x > 0; x <= 32; }
endclass: demo

program automatic test;
  initial begin
    demo obj_a = new();
    obj_a.no_error.constraint_mode(0);
    if(!obj_a.randomize()) ... ;
  end
endprogram: test

seed 값을 저장하는 습관을 가지자!


OOP Inheritance

class BadPacket extends Packet; 으로 상속

$cast(bad_pkt, pkt); 또는 pkt = bad_pkt; 로 derive 가능

handle이 다르면 안됨.
즉, 부모 클래스 핸들에 자식 클래스 핸들을 주는건 가능 반대는 불가능
$cast 사용시에도 같음.

부모 호출시에

function bit[31:0] compute_crc()
  this.crc = super.compute_crc();
  return(crc = is_bad ? ~crc : crc);
endfunction: compute_crc

OOP Polymorphism

virtual 함수로 parent꺼 말고 child꺼 사용가능

task transmit(Packet pkt);
  ...
  pkt.crc = pkt.compute_crc();
  ...
endtask: transmit

Packet p = new();
BadPacket bp = new();
p.crc = p.compute_crc();
bp.crc = bp.compute_crc();
transmit(p);
transmit(bp);

직접 호출시에는 상관없는데
transmit task 같은 경우 부모꺼만 호출됨
부모 함수에 virtual keyword 사용

Modifying Constraints

class data;
  rand bit[31:0] x, y;
  constraint valid {
    x > 0; y >= 0;
  }
endclass: data

class Generator;
  data blueprint;
  ...
  while (...)
    ...
    blueprint.randomize();
    ...
endclass: Generator

program automatic test_corner_case;
  class test_data extends data;
    constraint corner_case {
      x == 5; y == 10;
    }
  endclass: test_data
  
  initial begin
    test_data tdata = new();
    Generator gen = new();
    gen.blueprint = tdata;
    ...
  end
endprogram: test_corner_case

Data Protection

local : members of a base class are not accessible in the derived class

protected : members of a base class are accessible in the derived class but not to external code

new() 문제점

program test;

  class A;
    protected int a;
    function int get_a();
      get_a = a;
    endfunction
    function new(int b);
      a = b;
    endfunction
  endclass

  class B extends A;
    protected int b = 1000;
    
    function new(int b);
      super.new(b);
    endfunction
    
    task print_a();
      $display("a is %d", get_a());
    endtask: print_a
  endclass

  class C extends B;
    function new(int c);
      a = c;
    endfunction
  endclass

  initial begin
    C test_c = new(10);
    test_c.print_a();
  end

endprogram

B class에서 new() function 없으면 에러 발생

profile
Myongji UNIV. B.S. in Electronic Engineering

0개의 댓글