I came from this bueatiful world of specman, where casting was as easy as “.as_a” .
Now working in SV I realised that all my classes are designed with concept of inheritance. Once I use inheritance, downcasting and upcasting becomes the norm. But in SV I need to always use this $cast function which is such a coding pain. It requires 3 lines of code. One to declare a cast variable, second to write the $cast line and third comes the access.
I am pasting a example code to highlite my worry.
class a;
int a ;
virtual task test_a();
$display(“TEST A CALLED”);
endtask
endclass
class b extends a;
int b ;
virtual task test_a();
$display(“TEST B_A CALLED”);
endtask
endclass
One of the coding guidelines for OOP state that you should not access class properties directly and instead access them by a virtual method. Class properties should be protected unless you have a very good reason (usually laziness) for making them public.
When declaring a_array, I presume you will be dynamically setting each element to a class a or class b handle. What’s supposed to happen if you try to access int b, but have a handle to class a? $cast should be used as a function to check that the class handle is a valid reference to class b.
By directly referencing int b, your program block is now dependent on the existence of class b. It’s difficult to suggest a better alternative without know more what you are trying to accomplish.
Take the classic ethernet example. We have a base_ethernet_frame class which may have src ,dest and the frame type feilds, from it we derive maybe a PPPoE class, maybe a SNAP Class and so on. Now in another class called ethernet_frame, I instantiate a queue of base_ethernet_frame class . Now depending on some ingress algorithm, in run time I decide how to fill up this queue of base class. q[0] may point to pppoe frame, q[1] may point to snap frame etc. Dont think too much why in network protocol would this happen. Its just a hypothetical case.
Now I have another egress algorithm where in I read this queue of base classes. Now with the type feild in the base class, i predict that q[0] is a pppoe frame. but when I do a q[0].PPPoEfiled, I get vlog errors. Hence I got to downcast q[0] to pppoe frame type and then access the feilds.
This is very easy in specman with as_a directive. Is it factory that i must use to acheive as_a equivalence in SV. or is it the same upcast and downcast jugglery
Your recent post indicates that you do not know which index of queue will carry which type of object. In this case you will have to use cast to know the type of object. Then only you could access the properties. I am not sure how would you achieve this in one step in beautiful world of specman.
But in sv world - i have quoted a simple example code to show what you could do.
And in the example you will see that when you are poping out of the queue, you need to know which type this index is carrying. Else you will need to use the $cast to check.
I have also shown the case where you know the type of object at a index.
module tb();
class base1;
int a;
function new();
a=5;
endfunction
endclass
class base_child1 extends base1;
int b;
function new();
super.new();
endfunction
endclass
class base_child2 extends base1;
int c;
function new();
super.new();
endfunction
endclass
class env;
base1 bq[$:4];
base_child1 bc1;
base_child2 bc2;
function new();
bc1 = new();
bc2 = new();
endfunction
function construct();
bc1.b = 10;
bc2.a = 20;
bc2.c = 30;
bq.push_back(bc1);
bq.push_back(bc2);
endfunction
endclass
initial begin
int check;
// ctype = 1 - c2, 2 - c3
int ctype;
base_child1 c2 = new();
base_child2 c3 = new();
env e = new();
e.construct();
// assuming you do not know the type of class at this index
if($cast(c2,e.bq[0]))
ctype = 1;
else
ctype = 2;
if(ctype == 1) begin
c2 = e.bq.pop_front();
c2.b = 100;
$display("b = %0d", c2.b);
end
else
c3 = e.bq.pop_front();
// How do you achieve the above scenario in specman world ??
// assuming you know the type of class at this index
c3 = e.bq.pop_front();
$display("a = %0d c= %0d", c3.a,c3.c);
end
endmodule
In reading through this it sounds like you need to do the type check whether you are in e or sv, so your steps 2 and 3 are happening in either case (right?).
If I understand what you are saying, you want to have code like:
if (something_tells_me_q0_is_pppoe) begin
pppoe_type'(q[0]).PPPoEFiled();
end
And instead you have to do:
begin
pppoe_type is_pppoe;
if($cast(is_pppoe, q[0])) begin
is_pppoe.PPPoEFiled();
end
end
So your issue is with the temporary variable that you had to create and use (I only have the begin/end block keep the code together).
If this is your issue, there isn’t anything else you can do in SV about it. Generally, as Dave said earlier, the more correct OO methodology would be to have some virtual method to have the derived class implement.
For instance, in your ethernet example you may have a virtual method called post_frame (or whatever) that gets called on completed frames. Then, your code would just be:
q[0].post_frame();
And the fact that the particular frame calls PPPoEfiled() at this point doesn’t really matter.
Anyway, the only way I can think of to avoid the temporary variable is to use virtual methods… and, I realize that does not work in all cases.
As Dave suggested, the use of factory is good but that works for polymorphic virtual task/functions only and there is nothing that factory can do for field access of derived classes. Sad for me.
John you understood my problem very correctly. But again your approach points to vitual methods/task .
Agreed. I will make a class that has all the feilds of ever perceived ethernet protocols or for that matter any protocol. Then I run into issues like packing. Because if u have superset classes with all possible feilds and minimal use of inheritance in terms of feild definitions, then u have very little option but to define a do_pack of ur own. similarly do_print and the list of specialisation goes on.
Secondly, u end up having so many contraints to nullify feilds of a class that do not hold relevance when the class type is differrent. Meaning, PPPoE feilds will be set to -1 in a constraint when the frame type is SNAP or something like that.
Now my basic woe is that if specman can give a as_a() function to dynamic cast a class, what is the basic OOP methodology constraint that is stopping OVM experts to develop a similar as_a function for SV. Dave/John :: Please make an effort to clarify this doubt for me. It will help me to go on with SV. I am so nostalgic of specman and my mind works to make classes as compact and heavily dependent on inheritance.
Agreed. I will make a class that has all the feilds of ever perceived ethernet protocols or for that matter any protocol. Then I run into issues like packing. Because if u have superset classes with all possible feilds and minimal use of inheritance in terms of feild definitions, then u have very little option but to define a do_pack of ur own. similarly do_print and the list of specialisation goes on.
Secondly, u end up having so many contraints to nullify feilds of a class that do not hold relevance when the class type is differrent. Meaning, PPPoE feilds will be set to -1 in a constraint when the frame type is SNAP or something like that.
You should not have to be doing this. I think you are trying top learn SV and OVM at the same time, which is a mistake. (even if unavoidable due to schedules) Maybe you should contact your vendor for more direct help than can be provided in this forum.
The as_a() function is e is exactly the same as $cast for doing dynamic casts. The only difference (as far as I can tell) is that, with as_a(), you are able to chain the call with the implicitly created variable so that you don’t have to create a temporary variable.
You certainly should not be putting everything in the base class. The correct thing to do is to use inheritance, use polymorphism where it makes sense and use dynamic casting where that makes sense.
Where you need to use dynamic casting, there is no way in SV to avoid the extra temporary variables (it just isn’t part of the current syntax). I haven’t personally found this to be a major issue, but I can understand the irritation.
As Dave suggests, contacting your vendor directly may be the best plan for you in this case.