1

this topic has a similar question like mine. But they don't figured out any solution.

I have defined a class with subclasses. The subclass contains a vector, which width should be different in the array.

array[0] class with subclasses and vector width 32

array[1] class with subclasses and vector width 64

array[2] class with subclasses and vector width 128

and so on.

The definition of the class is the same, only the size of the vector differs.

Example

Class-definition:

package classes;

    class subsubclass#(int width);
          logic  [width:0]                  data3;      
    endclass

    class subclass#(int width); 
          subsubclass #(width)              data2 = new;
          logic                             auto2;
    endclass 

    class my_class#(int width);
          subclass #(width)                 data1 = new;
          logic                             auto1;      
    endclass

endpackage

Testbench:

my_class#(32) my_array [0:5];

initial begin
        int x;
        for (int x=0; x<6; x++) begin
           my_array[x] = new;       
        end
end

In this situation i am creating an array of classes with same width. How can i change this? I tried various things, but i can't figure out if there is a solution.

for e.g.   
    my_array[0].subclass.subsubclass.data3 
    and 
    my_array[1].subclass.subsubclass.data3

should differ. But how? And yes in need it with an array because of using it later in many for loops.

update#1 @dave_59

simplified Class-definition:

virtual class base;
    pure virtual function logic [511:0] get_data();
    pure virtual function int getwidth();
endclass

 class my_class#(int width) extends base;
    logic                                   auto;
    logic  [width:0]                        data; 
    virtual function logic [511:0] get_data();
              return data;
    endfunction
    virtual function int getwidth(); 
             return width; 
    endfunction
endclass

base  my_array [0:4];

Testbench:

    initial begin
           my_array[0] = my_class#(16)::new;     
           my_array[1] = my_class#(8)::new;     
           my_array[2] = my_class#(64)::new;     
           my_array[3] = my_class#(128)::new;     
           my_array[4] = my_class#(256)::new;
    end

I tried different definitions: test0, test1 and test2. I got an error that "my_array" is an unkown type. Any idea how to fix it? :)

my_array[0] test0; // or
my_array    test1; // or
my_array[0].get_data() test2;

update#2 @dave_59

    package classes;

    class subsubclass#(int width);
       logic  [width-1:0]                  data3 = '1;      
    endclass

    class subclass#(int width); 
       subsubclass #(width)              data2 = new;
       logic                             auto2;
    endclass 

       virtual               class base;
          pure virtual function logic [511:0] get_data();
       pure virtual function int get_width();
    endclass

    class my_class#(int width) extends base;
       logic                 auto;
       subclass#(width)          data1 = new;

       virtual               function logic [511:0] get_data();
          return data1.data2.data3;
       endfunction
       virtual               function int get_width(); 
          return width; 
       endfunction
    endclass

    endpackage : classes

Testbench

       module top;

       import classes::*;
       base  my_array [0:4];

        initial begin
               my_array[0] = my_class#(16)::new;     
               my_array[1] = my_class#(8)::new;     
               my_array[2] = my_class#(64)::new;     
               my_array[3] = my_class#(128)::new;     
               my_array[4] = my_class#(256)::new;
           foreach(my_array[i]) $display("i: %0d, width:%0d, data3:%0h",
                         i, my_array[i].get_width(), my_array[i].get_data());
        end

my_array[0].data1.auto2 = 1;

    endmodule : top

How can i set for example a "1" for auto? I tried

my_array[0].data1.auto2 = 1;

It would be nice because i need to do some looped assignments.

I can't expand the subclasses in modelsim.

I got this error

near "[": syntax error, unexpected '[', expecting IDENTIFIER or TYPE_IDENTIFIER

update#3

class package simplified

package classes;    
    class subclass#(int width); 

    logic  [width-1:0]                  data2 = '1; 

    endclass 

    virtual class base;

        logic                   auto2;
        logic                   auto;
        pure virtual function logic [511:0] get_data();
        pure virtual function int get_width();

    endclass

    class my_class#(int width) extends base;

       subclass#(width)          data1 = new;

       virtual               function logic [511:0] get_data();
          return data1.data2;
       endfunction
       virtual               function int get_width(); 
          return width; 
       endfunction
    endclass
endpackage : classes

Testbench

module top;
  import classes::*;  
  base  my_array [0:4];

        initial begin
               my_array[0] = my_class#(2)::new;     
               my_array[1] = my_class#(4)::new;     
               my_array[2] = my_class#(8)::new;     
               my_array[3] = my_class#(16)::new;     
               my_array[4] = my_class#(32)::new;
        end


        genvar x;
        int temp [4:0] = {3500, 600, 200, 10, 3};

        generate  

            for (x=0; x<5; x++) begin 

                assign my_array[x].data1.data2 = temp[x];

            end
        endgenerate
endmodule : top

The assignment for every data2 is just an example, but it should visualize what i am looking for. My target is to have an array of the same class but with a different data width. Later i want to access for assignments via for loops (see above). Now i can expand the hierarchy but still can't access it like "my_array[x]. ..." (screenshot of modelsim). Is there any way to access the parameterized "data" and set assignments?

I got this error: Field/method name (data1) not in 'my_array'

update#4 (edit: question/problem fixed)

class package simplified

    package classes;    
class subclass#(int width); 

logic  [width-1:0]                  data2; 

endclass 

virtual class base;


    logic                   auto2;
    logic                   auto;
    pure virtual function logic [511:0] get_data();
    pure virtual function int get_width();
    pure virtual task  set_data(int i);

endclass

class my_class#(int width) extends base;

   subclass#(width)          data1 = new;

   virtual               function logic [511:0] get_data();
      return data1.data2;
   endfunction

   virtual               function int get_width(); 
      return width; 
   endfunction

  virtual task set_data(int i); 
        data1.data2 = i;
  endtask


endclass
    endpackage : classes

Testbench

 module top;
      import classes::*;  
      base  my_array [0:4];

            initial begin
                   my_array[0] = my_class#(2)::new;     
                   my_array[1] = my_class#(4)::new;     
                   my_array[2] = my_class#(8)::new;     
                   my_array[3] = my_class#(16)::new;     
                   my_array[4] = my_class#(32)::new;

                   my_array[0].set_data(2);
                   my_array[1].set_data(4);
                   my_array[2].set_data(6);
                   my_array[3].set_data(8);
                   my_array[4].set_data(10);
            end

       /*   
            genvar x;
            int temp [4:0] = {3500, 600, 200, 10, 3};

             generate  

                for (x=0; x<5; x++) begin 

                    assign my_array[x].data1.data2 = temp[x];

                end
            endgenerate
 */
    endmodule : top

I have updated my (simplified) example with a task to set the data in data2. Inside the inital begin block are the calls of the task for whole array. I don't get any error messages but the problem is, that the data is not set. After the compilation and simulation the values of data2 are still zero. Suggestions? Edit: Mistake was using "logic" instead of "integer" at the class task.

William
  • 15
  • 1
  • 7

1 Answers1

3

You need to create a common base class variable that can store handles to the different class specializations with different width parameters. Then you need to have a pure virtual method in the base class that returns a common type for accessing data3, perhaps the maximum size of width expected. You can do this with the top level class

virtual class base;
  pure virtual function logic [63:0] get_data3();
  pure virtual function int getwidth();
endclass
class my_class#(int width) extends base;
      subclass #(width)                 data1 = new;
      logic                             auto1;   
      virtual function logic [63:0] get_data3();
          return data1.data2.data3;
      endfunction
      virtual function int getwidth(); return width; endfunction
endclass
base  my_array [0:5];
initial begin
           my_array[0] = my_class#(32)::new;     
           my_array[1] = my_class#(32)::new;     
           my_array[2] = my_class#(8)::new;     
           my_array[3] = my_class#(8)::new;     
           my_array[4] = my_class#(8)::new;     
           ...

Now you can refer to my_array[0].get_data3() and my_array[4].get_data3() and the data3 value will be right justified. There is a lot of other ways you could return the data, like a dynamic stream of bits or bytes.

Instead of extending the top level class, you could also just create a base class for the subsubclass. Then you dont have to parameterize my_class and subclass, unless of course those classes need the width.

Here is a complete, self-contained example

package classes;

class subsubclass#(int width);
   logic  [width-1:0]                  data3 = '1;      
endclass

class subclass#(int width); 
   subsubclass #(width)              data2 = new;
   logic                             auto2;
endclass 

   virtual               class base;
      pure virtual function logic [511:0] get_data();
   pure virtual function int get_width();
endclass

class my_class#(int width) extends base;
   logic                 auto;
   subclass#(width)          data1 = new;

   virtual               function logic [511:0] get_data();
      return data1.data2.data3;
   endfunction
   virtual               function int get_width(); 
      return width; 
   endfunction
endclass

endpackage : classes

   module top;

   import classes::*;
   base  my_array [0:4];

    initial begin
           my_array[0] = my_class#(16)::new;     
           my_array[1] = my_class#(8)::new;     
           my_array[2] = my_class#(64)::new;     
           my_array[3] = my_class#(128)::new;     
           my_array[4] = my_class#(256)::new;
       foreach(my_array[i]) $display("i: %0d, width:%0d, data3:%0h",
                     i, my_array[i].get_width(), my_array[i].get_data());
    end
endmodule : top
dave_59
  • 39,096
  • 3
  • 24
  • 63
  • Thank you for the quick response. I got an error Class 'my_class' is parameterized. Parameterized nested classes currently not supported. Should be there a "endclass" before or after "base my_array [0:5];"? – William Jun 25 '15 at 06:42
  • 1
    If fixed the example. I had duplicated `class my_class` lines. – dave_59 Jun 25 '15 at 14:54
  • Ok i already figured the typo out, thanks. I've updated my example in my first message, but i got a "unkown type" error (see above). Suggestions? – William Jun 25 '15 at 21:45
  • It always helps to provide a complete, self-contained example. – dave_59 Jun 25 '15 at 22:47
  • Ok thank you. I have updated my first post. How can i set up e.g. the logic auto2 as "1" of my_array[0]? Like this: my_array[0].data1.auto2 = 1 (see above); – William Jun 27 '15 at 17:42
  • There are a few things you can do. First, put any member that is not parameterized (like `my_class:: auto`) into the base class. Then you can access it directly from a `base` class variable. Otherwise you will have to create virtual sett/methods methods to access anything not in the base class, like you did with get_data(). Another option is to $cast the class handle up to a subclass variable. – dave_59 Jun 28 '15 at 00:47
  • My problem is i have to use the parameterized "data3" in a for loop making assignments. How can i access (in this example) data3 with the different width without making single ("by hand") assignments? Thank you for the paper. I have updated the example to visualize what i mean. – William Jun 28 '15 at 12:46
  • I use in an another module "input base my_array [0:5]" So my_array should be an input (array of inputs with different data width), the problem is i cant access the paramterized data3 respectively i have yet no idea how to realize it. I got this error "Field/method name (data1) not in base'". So modelsim "sees" only the base class? – William Jun 28 '15 at 13:17
  • The problem you are having is not specific to an array. It is _how do you access derived class members from a base class variable?_ See my comment above. You tried the first suggestion, but not the other two. – dave_59 Jun 29 '15 at 15:06
  • Thank you for your tips. I've tried the possible solution with the method "task" to set the data of every data2 of the array. I got no error message, but the values are not set. I've updated my post (@ update#4). Suggestions? – William Jun 29 '15 at 22:08
  • Ok, i figured out my mistake. I have to use integer because i do not commit a logic value. I've updated my code. – William Jun 29 '15 at 22:29
  • I tried to solve it with "$cast" but it doesn't work. Do you have an example accessing a subclass through a parent class using $cast? (I can't use the generate block anymore for the assignments (@update#4). – William Jun 30 '15 at 07:42