How do I write a binary dump file of an array in my testbench

Hello,

I’m trying to do a binary dump of large 8 bit logic array into a file. I’ve run into these 2 problems:

  1. Anytime I try to write character 8’h00, it gets replaced with character 8’h20.
  2. Anytime I try to write character 8’h0A, 2 characters come out, first 8’h0D, then 8’h0A.

Here is an example test code:

integer fout_pointer;
fout_pointer= $fopen("test_file.bin","w");

for (int i=0;i<256;i++)  $fwrite(fout_pointer,"%s",8'(i)) ;

$fclose(fout_pointer);

This code is supposed to generate a file where if I analyze it with a hex editor, it should go from 8’h00 the 8’hFF. But, the 8’h00 position has an 8’h20 and the 8’h0A position has a 8’h0D instead, then the 8’h0A comes next.

A larger test dumping a larger array such as:

logic [7:0] array_table [0:65535] = '{8'h##, 8'h##, 8'h##, ..... };

Reveals every 8’h00 is replaced with 8’h08, and every 8’h0A has a new byte 8’h0D placed in just before the 8’h0A.

Is there a way to binary dump/write that array_table into a file. And I do not mean an ascii file with binary or hex values written as text in it. I mean a true data .bin file.

Thanks,
BrianHG.

In reply to BrianHG:

Is there a way to binary dump/write that array_table into a file. And I do not mean an ascii file with binary or hex values written as text in it. I mean a true data .bin file.


fout_pointer= $fopen("test_file.bin","wb");

LRM section 21.3.1 Opening and closing files

w" or “wb” Truncate to zero length or create for writing

“The “b” in the preceding types exists to distinguish binary files from text files. Many systems make no
distinction between binary and text files, and on these systems the “b” is ignored. However, some systems
perform data mappings on certain binary values written to and read from files that are opened for text access.”*

You may need to check the endianess required and change your logic accordingly

HTH,
-R

In reply to rgarcia07:

Ok, you have solved 1 problem with the ‘wb’.
When printing the character 8’0A, it is no longer preceded by a 8’h0D.
However, when sending character 8’00, the output is still 8’h20.
Unless there is a different way of sending characters, I still can’t seem to write a 8’h00.

Unfortunately, there is no $fputc command. Is there any other way to send binary characters I do not know about.

Even $fwrite(fout_pointer,8’h00); only outputs in ascii text → " 0".

Is there a way to maybe define a set of characters in a string to be sen which contain a 8’h00. I know that in old school C development, 8’h00 is usually reserved to delineate an end of a string when using the old fopen/fprint/fputc/fgetc.

In reply to BrianHG:

Use the %u instead of %s format.

In reply to dave_59:

Ok, so with %u, I have the problem of every time I use it, I must write 4 bytes. This is a problem if I have 6 or 7 bytes to write from 1 array before other processes which can be integer aligned.

There is another issue leaving me a loss for words…
This 4 megabyte write:

for (int i=0;i<(2048*2048);i+=4)    $fwrite(fout_pointer,"%u",{bitmap[i+3],bitmap[i+2],bitmap[i+1],bitmap[i]}) ;

Took a total of 8 seconds, while this identical 4 megabyte write:

for (int i=0;i<(2048*2048);i+=4)    $fwrite(fout_pointer,"%s",{bitmap[i],bitmap[i+1],bitmap[i+2],bitmap[i+3]}) ;

was too quick to even measure the time it took to write. Only that all the 8’h00 have been replaced with 8’h20. If fact, if I were to abandon the 8’h00 for 8’h01 by doing this:

    for (int i=0;i<(2048*2048);i++)        begin
                                           if      (bitmap[i]==8'h00)  $fwrite(fout_pointer,"%s",8'h01) ; //
                                           else                        $fwrite(fout_pointer,"%s",bitmap[i]) ;  // 
                                           end

The 4 megabytes are also written almost instantly. Is there some reason why the %u is something like 20x slower than a %s?
Are there any other means of outputting a binary file, IE dumping the entire logic register bitmap[7:0][4meg]?

In reply to BrianHG:
What about %c?

In reply to dave_59:

Ok, %c solves the problem for small odd bytes, but it’s doing something weird when writing 4 megabytes.

Example:

for (int i = 0 ; i < (2048*2048) ; i++)  bitmap[i] = 8'h00 ;
    for (int i=0;i<(2048*2048);i+=4)    $fwrite(fout_pointer,"%c%c%c%c",bitmap[i],bitmap[i+1],bitmap[i+2],bitmap[i+3]) ;

The data is correct, but it takes an astounding 32 seconds to write.

for (int i = 0 ; i < (2048*2048) ; i++)  bitmap[i] = 8'h(any random number from 1-255) ;
    for (int i=0;i<(2048*2048);i+=4)    $fwrite(fout_pointer,"%c%c%c%c",bitmap[i],bitmap[i+1],bitmap[i+2],bitmap[i+3]) ;

The data is correct and it writes everything instantly, under a second.

for (int i=0;i<(2048*2048);i+=4)    $fwrite(fout_pointer,"%u",{bitmap[i+3],bitmap[i+2],bitmap[i+1],bitmap[i]}) ;

With the %u, the data content doesn’t matter, it takes 8 seconds to write.

LOL, does ModelSim have something against writing null bytes 8’h00?..

Between %c and %u I can manage, but that weird %c writing 8’h00 is 50x slower than writing any other character from 1-255. And %s is as fast as %c (when %c not writing 8’h00), but %s writes 8’h20 in place of 8’h00. Something smells fishy.

I guess I can manage for now with %u, but, I would have liked to go up to 64 megabytes. %c would have been perfect if my data didn’t contain so many 8’h00 in it & %u will take 2 minutes to write VS %c 16 seconds if my data doesn’t have huge blocks of 8’h00. I guess my manageable limit would be 16 megabytes.