Parameterized task

I have a task (that is part of a class) which
reads file from the user and drives the data to the
dut. Each test category can have distinct no. of inputs
to drive which comes from the input file. So, there will
be as much number of columns in the file as the no. of inputs
to drive and each column corresponds to the inputs.

Now, I want to parameterize this method by passing an arguement
to the task that tells the no. of inputs (and so, the number of columns)
coming from the file. The data widht of the inputs could be
different and so I need to paratermize it as well based on the input size.

Also, as the number of output data from this task (which goes to the dut input)
varies, I can use it as array but the individual data widht of the
various inputs could be different.

For example,

task read_file (filename, dataout[i], input_no);

for (i=0; i<= input_no; i++)
dataout[i] =

endtask

Which is the best way I can acheive such parameterized tasks in sv?

Thanks,
Babu

Babu,

You can use a dynamic array (or queue) that can change the number of elements in an array, but you can’t dynamically change the width of any variable including the width of an array elements in SystemVerilog.

You could create what is called a 2-dimensional irregular array where the number of elements in the second dimension are not the same

typedef bit IR_t[$];

This is a dynamic array of a queue of bits.

task read_file (input string filename, output IR_t dataout, input int input_no);
dataout = new[input_no];
foreach(dataout[i]) begin
for(int j=0;j<(expr_for_size_of_input);j++)
dataout[i].push_back(some_bit_from_file);
end
endtask

You can use bitstream casts and the streaming operators to reformat unpacked array to bit-vectors.

Instead of using a queue of bits, some people just create a bit-vector that is the largest possible width and just pull the needed part-select from that. That could be expensive depending on the range of vector sizes and the number of inputs.

Dave,

Thanks for the solution.

One more place I need clarification in this problem is,
dealing with fscanf that needs the no. of columns (as arguments ) to read from the file.

for example,

If the file has 2 columns, i will have to assign the array data_out as

$fscanf(file_handle, “%h %h”, data_out[1], data_out[0]);

So, how do I automate the no. of columns (%h for as much no. of columns) and
how do I assign it to a dyanamic array, this part looks confusing for me.

Dave,

never mind, I got that part to work

foreach(input_out_int1[i])
begin
input_pi = $fscanf(input_file_handle, “%h”, input_out_int1[i]);
end

This did that.

My bad … it did not work …

The problem was, my objective was to create an array for
each columns. i.e

dataout[0] = an array of first column entries in the file
dataout[1] = an array of second column entries in the file
dataout[N-1] = an array of Nth column entries in the file

But the problem is,

I do not know, how do I do fscanf on to the file that has N no. of %h and loading into
this dynamic array.

Is there a better way to deal with this problem?

In reply to Babu Raghunathan:

Assuming that each column has the same number of rows of numbers, you will have to use $fscanf to read one number at a time, and then push that number on the appropriate dataout array.

Hi Dave,

Let me explain it more.

say this is how my file looks in category 1

1a 2a
1b 2b
1c 2c
1d 2d
1e 2e

My task reads this will look like this

task read_file (input string filename, no_of_args output integer dyn_array);

This task gets the no. of columns as input, i.e no_of_args = 2.

So, my dynamic array will look like :
integer dyn_array[0] =

1a
1b
1c
1d
1e

integer dyn_array[1] =

2a
2b
2c
2d
2e

Similarly, if the no of arguments = 5, then there should be arrays from
dyn_array[0] to dyn_array[4].

To read the file, I can do this

$fscanf(handle, “%h”, data);

But, Dynamic array is always one dimensional, so, I’m not sure how do I specify the
no. of arguments,

and so, I cannot do

integer dyn_array;

dyn_array= new[no_of_args];

In this case, it will be treated as an 4 entries of integer type which I do not want.
Instead, I want N (no_of_args) arrays having no_of_column entries holding integers.

In the above example, I want 2 arrays having 5 columns of integers.

I do not know how do I handle this.

Thanks,
Babu

In reply to Babu Raghunathan:

Babu,

A dynamic array is one dimension of an array, but you can have arrays of arrays. In this case, since you do not know how many rows there are, it would be better to push values on the the end of a queue instead of resizing a dynamic array. Try the following:

module top;
   typedef  bit [31:0] word_t;
   parameter EOF = -1;
  
   word_t mydata[][$];

   function void read_file(input string  filename,
			   output word_t dataout[][$],
			   input int 	 input_no);
      int file;
      word_t data;
      file=$fopen(filename,"r");
      dataout=new[input_no];
      forever begin : each_row
	foreach(dataout[i]) begin : each_column
	  if($fscanf(file,"%h",data) != EOF)
	    dataout[i].push_back(data);
	  else
	    return;
	end : each_column
      end : each_row  
   endfunction : read_file
   
   initial begin : my_test
      read_file("mydata",mydata,2);
      foreach(mydata[i,j])
	   $display("%3d %3d %0h",i,j, mydata[i][j]);
   end : my_test
   
endmodule : top

The assumes each column is 32 bits or less. You can adjust word_t to the size of the largest column.

Dave,

That was a smart method, thanks a lot, that worked.

Babu