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 Rich
Mentor Graphics
http://go.mentor.com/drich
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?
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.
Dave Rich
Mentor Graphics
http://go.mentor.com/drich
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
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 : topThe assumes each column is 32 bits or less. You can adjust word_t to the size of the largest column.
Dave Rich
Mentor Graphics
http://go.mentor.com/drich
Dave,
That was a smart method, thanks a lot, that worked.
Babu