Friday, March 02, 2012

Casting

Casting

It is always legal to assign a subclass variable to a variable of a class higher in the inheritance tree. It is never legal to directly assign a superclass variable to a variable of one of its subclasses. However, it is legal to assign a superclass handle to a subclass variable if the superclass handle refers to an object of the given subclass.

To check if the assignment is legal, the dynamic cast function $cast() is used.

The syntax for $cast() is:

task $cast( singular dest_handle, singular source_handle );

Out of block declarations:

It is convenient to be able to move method definitions out of the body of the class declaration. This is done in two steps. Declare, within the class body, the method prototypes—whether it is a function or task, any qualifiers (local, protected or virtual), and the full argument specification plus the extern qualifier. The extern qualifier indicates that the body of the method (its implementation) is to be found outside the declaration.

Then, outside the class declaration, declare the full method—like the prototype but without the qualifiers— and, to tie the method back to its class, qualify the method name with the class name and a pair of colons:

class Packet;
Packet next;
function Packet get_next(); // single line
get_next = next;
endfunction
// out-of-body (extern) declaration
extern protected virtual function int send(int value);
endclass
function int Packet::send(int value);
// dropped protected virtual, added Packet::
// body of method
...
endfunction

Typedef class:

Sometimes a class variable needs to be declared before the class itself has been declared. For example, if two classes each need a handle to the other. When, in the course of processing the declaration for the first class, the compiler encounters the reference to the second class, that reference is undefined and the compiler flags it as an error.

This is resolved using typedef to provide a forward declaration for the second class:

typedef class C2; // C2 is declared to be of type class
class C1;
C2 c;
endclass
class C2;
C1 c;
endclass

// typedef class or forward reference

typedef class Transaction2; // The typedef of class Transaction2 allows the compiler to process Transaction1 before //Transaction2 is fully defined.
// Compilation fails if class Transaction2 is not defined to be of typedef class
class Transaction1;
Transaction2 tr2; // refers to Class Transaction2, which is not yet defined
int j;
function new(int k=32'd16);
j = k;
tr2 = new();
tr2.i = 32'd15;
endfunction : new
endclass : Transaction1

class Transaction2;
int i;
endclass : Transaction2

program typedef_class;
Transaction1 tr1;
initial begin
tr1 = new(20);
$display("Value of i = %0d\nValue of j = %0d\n", tr1.tr2.i, tr1.j);
end
endprogram : typedef_class

OUTPUT:

Value of i = 15
Value of j = 20

class frame;
rand logic [7:0] A1;
rand logic [7:0] error_A2_0;
virtual function void display();
$display("frame0 = %0d\t\terror_A2_0 = %0d\n", A1,error_A2_0);
endfunction : display
endclass : frame

class badframe1 extends frame;
rand logic [7:0] error_A1;
rand logic [7:0] error_A2_1;
virtual function void display();
super.display();
$display("frame1 = %0d\t\terror_A2_1 = %0d\n", error_A1,error_A2_1);
endfunction : display
endclass : badframe1

program dynamic_casting;
frame base;
badframe1 derv1;
initial begin
//assigning derived class to base class
derv1 = new;
base = derv1;
if(derv1.randomize())
$display("Randomization Passed\n");
else
$display("Randomization Failed\n");
base.display();
$display("frame0 : error_A2_0 = %0d\n", derv1.error_A2_0);
end
endprogram : dynamic_casting


OUTPUT:

Randomization Passed
frame0 = 110 error_A2_0 = 116
frame1 = 84 error_A2_1 = 136
frame0 : error_A2_0 = 116

class frame;
rand logic [7:0] A1;
logic [7:0] error_A2_0;
virtual function void display();
$display("frame0 = %0d\n", A1);
endfunction : display
endclass : frame

class badframe1 extends frame;
rand logic [7:0] error_A1;
logic [7:0] error_A2_1;
virtual function void display();
$display("frame1 = %0d\n", error_A1);
endfunction : display
endclass : badframe1

class badframe2 extends frame;
rand logic [7:0] error_A1;
logic [7:0] error_A2_2;
virtual function void display();
$display("frame2 = %0d\n", error_A1);
endfunction : display
endclass : badframe2

program dynamic_casting;
frame base;
badframe1 derv1;
badframe2 derv2;
initial begin
//assigning base class to derived class using $cast
derv2 = new;
base = derv2;
derv2.error_A2_0 = 8'd14;
derv2.error_A2_2 = 8'd15;
$cast(derv2, base); // $cast as a task - correct syntax, simulation error if mismatch
// if(!$cast(derv2, base)) // $cast as a function
// $display("Cannot assign base to derived\n");
$display("error_A2_0 = %0d", derv2.error_A2_0);
$display("error_A2_2 = %0d", derv2.error_A2_2);
end
endprogram : dynamic_casting

OUTPUT:

error_A2_0 = 14
error_A2_2 = 15

No comments:

Post a Comment

Popular Posts