Trung tâm đào tạo thiết kế vi mạch Semicon


  • ĐĂNG KÝ TÀI KHOẢN ĐỂ TRUY CẬP NHIỀU TÀI LIỆU HƠN!
  • Đăng ký
    *
    *
    *
    *
    *
    Fields marked with an asterisk (*) are required.
semi1_solvingproblems.jpg

SystemVerilog Parameterized Classes

Email In PDF.

A Parameter is a kind of a constant that represents a value change or a data type. The compiler evaluates Parameter expression as part of its elaboration and code generation phases before the Simulation starts.

So we can use the Parameter as part of the declaration of another type or use a Parameter value in lets say range of an array declaration. Note: We can not change a Parameter once a Simulation starts.

SystemVerilog uses a “#” sign to list the Parameter names in a Class Header to define a Generic Class. When we reference the Generic Class we also use the pound (#) sign to provide a list of Parameter Assignments or Overrides. When we specify a default Parameter in a Class Header, we don’t have to provide an Overrides for that Parameter when referencing that Class.

A Generic Class & actual Parameter values is called a Specialization.

Following SystemVerilog code demonstrates the usage of Parameterized Class Vs Base Class Inheritance with Non-default Specialization.

///// Parameterized Class Declaration

class transaction #(type T = int, type A = bit, int R = 3);

  /// CRC Declaration

 T crc;

  /// Source Address

 bit [R:0] SA;

  /// Dynamic Array Declaration

 T dynam [];

 /// Constructor

 function new (A a);

   SA = a;

 endfunction: ne

/// Calculate CRC Task

 task CalCrc (T t);

   this.crc = t;

 endtask: CalCrc

  /// Print Function

 function void print; $display("Value of R = %0d, Source Address = %b, No. of DyArr entries = %0d, CRC = %b, Dynamic Ele

ment[3] = %b ", this.R, this.SA, this.dynam.size(), this.crc, dynam[3]);

 endfunction: print

 endclass: transaction

 ///// Extended Class with Non-default Specialization

class my_transaction extends transaction #(bit [3:0], int, 9);

 ///  Newly Added Property

 int errBit;

 /// Constructor

 function new (A b);

   super.new(b);

 endfunction: new

 endclass: my_transaction

 ///// Top Module

module top;

 initial begin

   fork

     begin

      transaction #(bit [7:0], bit [3:0]) txn;

      txn = new(4);

      txn.dynam = new[5];

      foreach (txn.dynam[i])

        txn.dynam[i] = i;

      txn.CalCrc(6);

      txn.print;

     end

     begin

      my_transaction mtxn;

      mtxn = new(5);

      mtxn.dynam = new[5];

      foreach (mtxn.dynam[i])

        mtxn.dynam[i] = i;

      mtxn.CalCrc(7);

      mtxn.print;

    end 

  join

 end

  endmodule: top

In the above code, we’ve a Parameterized Base Class i.e. transaction. Three Parameters i.e. T, A & R are declared with their default type in this Base Class. Three Properties i.e. crc, SA & dynam are declared using Parameters. Two Methods i.e constructor & CalCrc() are also declared. A print() Method is also declared to display the values of different Properties.

An Extended Class i.e my_transaction is declared with Non-default Specialization. Note, in case we define the Extended Class without any customized Parameters, default Parameters types will be applied to the Extended Class.

Inside the top module, with-in fork…join, two process threads are spawned. One thread is for Base Class Object and another one is for Extended Class Object. Base Class variable is declared with the intended choice of types for the declared Parameters. Base Class Object is constructed with required argument. Dynamic array is constructed & initialized with different values. Method CalCrc() is called with a choosed argument and finally the Method print() is called to display the expected values.

Almost similar operation is performed for the another spawned thread i.e. for Extended Class. But, notice that Parameter size or type is different & results from the print() Method call for the Extended Class Object is also different.

Hence from this example, its evident that Class Parameterization offers a Great Flexibility to provide various different types of inputs without touching the Source Code.

Parameterized Classes with Static Properties:

We know from Static Properties & Methods in earlier post that Static Properties gets allocated and initialized before time zero but thats does not hold true as soon as declaring a Generic Class with Parameters. The distinction between a Parameterized Class Generic template Vs the Specialization of that Class becomes very important. Static Class Properties do not get allocated unless their Class is Specialized. There is an unique instance in initialization of its Static Properties for each Specialization.

Lets observe this behavior using the following SystemVerilog code:

///// Parameterized Class Declaration

class txn_param #(type T = int);

  /// Static CRC Declaration

 static T crc; 

 endclass: txn_param

 ///// Class without Parameterization

class txn_without_param;

 /// Static CRC Declaration

 static int wcrc;

 endclass: txn_without_param

 module top;

 initial begin

  $display("wcrc = %0d", txn_without_param::wcrc);

  $display("crc = %0d", txn_param::crc);

 end

 endmodule: top

In this code, we’ve taken two Classes i.e. “txn_without_param” & “txn_param“. One Class is Parameterized and another is without any Parameter declaration. There is a Static Member i.e “crc” and “wcrc” in each of the Classes. Using the $display inside the initial procedural statement, we can see that Static Property “wcrc” is accessed and initialized using the Class definition without any Object construction. Yet trying to access the Static Property “crc” inside the Parameterized Class “txn_param” in exactly same way generates following Warning/Future version ERROR by the EDA tool:

Warning-[PCSRMIO] Class scope used outside of class

testbench.sv, 25 "txn_param::crc"

An unspecialized class scope '::' reference was seen. This refers to the generic class, and may only be used inside the class 'txn_param'. To access a static member of the default specialization outside the class 'txn_param', use 'txn_param#()::' instead. This will be an error in a future release.

In case we run the above code with following modified line, there is NO Warning/Future Error:

$display("crc = %0d", txn_param::crc);

$display("crc = %0d", txn_param #()::crc);

In the above line, Specialization is done using the Default Parameters values. Hence, Bottom line is – Static Properties do not get allocated until Generic Parameterized Classes are Specialized.

Now moving further, lets analyze, What happens in terms of Static Properties when the Generic Parameterized Class is Specialized in different ways and having multiple instances?

Every Specialization has unique set of Static Properties. So N number of Specialization will create N number of Static Properties. Lets undergo with an example below to comprehend it more in detail:

program param_stack;

 class stack #(type T = int);

int m_cnt;

 static int counter = 2;

function new

m_cnt = counter++;

 endfunction: new 

 endclass: stack

class stacked extends stack #(real);

 endclass: stacked

 typedef stack #(byte) stack_byte;

typedef stack #() stact_int;

 stack_byte S1 = new();

 stack_byte S2 = new();

 stack S3 = new();

 stack #(bit) S4 = new();

 stacked S5 = new();

 initial begin 

 $display ("Counter value of S1 instance = %0d", stack #(byte)::counter);

 $display ("Counter value of S2 instance = %0d", stack_byte:: counter);

 $display ("Counter value of S3 instance = %0d", stack #()::counter);

 $display ("Counter value of S4 instance = %0d", stack#(bit)::counter);

 $display ("Counter value of S5 instance = %0d", stacked::counter);

end

 endprogram: param_stack

Looking at the above example code, we’ve added a Static Property i.e. counter as part of the Generic Class i.e. “stack“. But there is no allocation of the “counter” until there is a reference that Specializes the Class “stack“. The two typedef create two unique Specializations of the Generic Class “stack” and therefore two instances of Static Property “counter” are created. We allocated the first counter upon Specializing “stack” with a byte type and allocated the second counter upon Specializing the “stack” with its default type, an ‘int‘.

As the next step, first we declare two variables S1 & S2 of Specialized “stack_byte” type and constructs the two Object that share the same Static Property i.e.”counter“. So after both initialization the “counter” associated with this Specialization is left with value 4.  Variable S3 is declared next & creates an Object of the Class “stack” with the default Parameter is set to an “int“. Since this Specialization matches to the Specialization created when we created a typedefstack_int” above, it uses the existing Specialization & the “counter” associated with default Specialization will left at 3.

In the next line, we declare another variable S4 & created another unique Specialization of Generic Class “stack” of type “bit“. The counter value after this initialization will be 3 again. Finally, we declared a variable i.e. S5 for the Extended Class “stacked” & constructed an unique Specialization of type “real“. Counter value of S5 will be again 3.

To confirm the values of Static Member “counter” out of these unique Specialization of different Classes, Generic as well as Extended, we used the $display statements with Class Scope Operator i.e. “::” as shown in the code above.

So the key learning from this topic is that every time an Unique Specialization is created for a Parameterized Class, a new instance of Static Property is initialized.

With this, we reached to the end of this post about “Parameterized Classes” and its application with Static Properties. As a recap, we discussed about how a Class can use Parameters to transform into a Generic Class, about Specialization, about Static Properties behavior in Parameterized Classes, about Class Scope operator usage with Parameterized Classes. We’ve gone through different example codes to comprehend these topics.

I believe all this will certainly provide a fair information to you about SystemVerilog OOP based Parameterized Classes. For further information, please refer the many other resources available online/offline. Please share your inputs/suggestions/comments. I’ll look forward to hear from you.

Bạn Có Đam Mê Với Vi Mạch hay Nhúng      -     Bạn Muốn Trau Dồi Thêm Kĩ Năng

Mong Muốn Có Thêm Cơ Hội Trong Công Việc

Và Trở Thành Một Người Có Giá Trị Hơn

Bạn Chưa Biết Phương Thức Nào Nhanh Chóng Để Đạt Được Chúng

Hãy Để Chúng Tôi Hỗ Trợ Cho Bạn. SEMICON  

 

Lần cập nhật cuối ( Thứ hai, 19 Tháng 7 2021 15:39 )  

CÁC BÀI VIẾT LIÊN QUAN