0
votes

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.

1

1 Answers

2
votes

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