How to read formatted data from a file (with example)?

Hi All,

Here is my input file (the first line is the comments):


// dsp_rx_valid[7:0]  dsp_rx_first[7:0]     dsp_rx_id[5:0][7:0]      dsp_rx_q_data[15:0][7:0]    dsp_rx_i_data[15:0][7:0]
      11111111            11111111       08 07 06 05 04 03 02 01     07 06 05 04 03 02 01 00     80 70 60 50 40 30 20 10
      11111111            11111111       09 08 07 06 05 04 03 02     07 06 05 04 03 02 01 00     80 70 60 50 40 30 20 10

I need to read the values from the input files to the TestBench variables.

E.g. after reading the first line after the comments, the following variables should get the following values:
dsp_rx_valid = 8’b11111111;
dsp_rx_first = 8’b11111111;
dsp_rx_id = '{6’h08,6’h07,6’h06,6’h05,6’h04,6’h03,6’h02,6’h01};
dsp_rx_q_data = '{16’h07,16’h06,16’h05,16’h04,16’h03,16’h02,16’h01,16’h00};
dsp_rx_i_data = '{16’h08,16’h07,16’h06,16’h05,16’h04,16’h03,16’h02,16’h01};

How can I do this with the $fscanf or another SystemVerilog command?

Thank you!

In reply to ldm_as:

There’s no way to read a string name and find a matching variable name with SystemVerilog. There are solutions using the VPI (C interface to the simulator) and tool specific mechanisms, but those will all have poor performance implications.

A better solutions might be to convert your text file to a file with executable SystemVerilog syntax.

If the variables names are fixed and you just need to read the data. then you can use $fscanf to read the data into intermediate variables and cast them to the actual needed variables.

In reply to dave_59:

If the variables names are fixed and you just need to read the data. then you can use $fscanf to read the data into intermediate variables and cast them to the actual needed variables.

Could you please provide an example how to do this? Thank you

In reply to dmitryl:
Actually, you have only single unpacked dimensions. It would be easer to hard code this.

module top;
   string line;
   int 	  FILE,code;
   bit [7:0]  dsp_rx_valid,  dsp_rx_first;
   bit [5:0]  dsp_rx_id[7:0];
   bit [15:0] dsp_rx_q_data[7:0], dsp_rx_i_data[7:0];
   
   
   initial begin
      FILE=$fopen("fscanf.txt","r");
      while($fgets(line,FILE)) begin
	 // strip comments
	 if(line.match("(\/\/.*)?$"))
	   line = line.prematch();
	 // skip lines without data
	 if (!line.match("[0-f]")) continue;
	 code =$sscanf(line, "%b %b %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h",
		 dsp_rx_valid,  dsp_rx_first, 
		 dsp_rx_id[7],dsp_rx_id[6],dsp_rx_id[5],dsp_rx_id[4],dsp_rx_id[3],dsp_rx_id[2],dsp_rx_id[1],dsp_rx_id[0],
		 dsp_rx_q_data[7],dsp_rx_q_data[6],dsp_rx_q_data[5],dsp_rx_q_data[4],dsp_rx_q_data[3],dsp_rx_q_data[2],dsp_rx_q_data[1],dsp_rx_q_data[0],
		 dsp_rx_i_data[7],dsp_rx_i_data[6],dsp_rx_i_data[5],dsp_rx_i_data[4],dsp_rx_i_data[3],dsp_rx_i_data[2],dsp_rx_i_data[1],dsp_rx_i_data[0]);
	 $displayh("code %d\n%b %b %p %p %p", code, dsp_rx_valid,  dsp_rx_first, dsp_rx_id, dsp_rx_q_data, dsp_rx_i_data);
      end
   end 	    
endmodule : top

In reply to dave_59:

Hi Dave, We need to undo the $fgets function in one of our projects. Is there a “$unfgets” function in SystemVerilog similar to “ungetc” function in C language?

Appreciate the help.

Thanks,
Satya

In reply to Satyaa:

There is only $ungetc. You would have to push back one character at a time from the lime.

I’ve got to believe there is a better way of structuring your code so you don’t have to undo file I/O operations.

In reply to dave_59:

In reply to Satyaa:
There is only $ungetc. You would have to push back one character at a time from the lime.
I’ve got to believe there is a better way of structuring your code so you don’t have to undo file I/O operations.

file content:

20000000000001002184804 1 // BLK(0)
400000000000000000000bf 2 // BLK(0)
20000000000001002180804 1 // BLK(1)
20000000000001002184804 1 // BLK(1)
400000000000000000000bf 2 // BLK(1)
20000000000001002184804 1 // BLK(2)
400000000000000000000bf 2 // BLK(3)
20000000000001002180804 1 // BLK(3)
20000000000001002184804 1 // BLK(4)
400000000000000000000bf 2 // BLK(5)

Hi Dave,

Thanks a lot for your quick reply.

The function must return one block’s worth of data for each call. BLK(x) in the above file specifies the block index. We would not know the block boundary until we read the following line with the new block index. I was thinking of undoing the read by unfgetc if available. If it is not available, I can solve this by maintaining two-pointers.

Sample code with unfgets:


while($fgets(line, fd)) begin
.....// parse the line and extract the block index
    if (curr_blk_indx > old_blk_indx) begin // new block data
      $unfgets(line, fd);
      return <blk_data>;
    end
end
 
Sample code with two pointers:
while($fgets(line, fd)) begin
.....// parse the line and extract the block index
  if (curr_blk_indx > old_blk_indx) begin // new block data
       fd = fd1;
       return <blk_data>;
  end
  else begin
    $fgets(line1, fd1);
  end
end

Please suggest if there is a better way to do it.

Thanks,
Satya