Casting int to string yields different results

Hi,

I recently stumbled upon this problem when casting an integral value to string. I tried casting from int to string using $sformat() and also using the static cast operator string’. Here’s my piece of code:


function void test_vars();
  int myInt = 32'h1200d2d5;
  string myString, myOtherString;
    
  $display("myInt = %h", myInt);
    
  // first cast
  $sformat(myString, myInt);
  // second cast
  myOtherString = string'(myInt);
    
  $display("myString = %h, myOtherString = %h", myString, myOtherString);
  $display("myString = %d, myOtherString = %d", myString, myOtherString);
endfunction : test_vars

And here are the results:
myInt = 1200d2d5
myString = 1220d2d5, myOtherString = 12d2d5
myString = 304141013, myOtherString = 1233621

I was wondering why, in the first cast, I get the third byte transformed from x00 to x20 while in the second cast I get that byte completely removed from the string. I checked the SV LRM and section 6.16 (String data type) says

All “\0” characters in the string literal are ignored (i.e., removed from the string).

but that’s not the case here, as \0 is NUL in ASCII.

What am I missing?

In reply to rodrigoportella:

Your code has a few problems

  • It’s illegal to initialize a static variable in a procedural block without an explicit static keyword declaration. Or, if your intent was to have the variable initialized each time you enter the function, do something to make it have an automatic lifetime. See this link.
  • You are using $sformat() incorrectly. The second argument is supposed to be a formatting string. I believe you may have wanted to use
$sformat(myString, "%s", myInt);
  • It’s illegal to use the %h or %d format specifier on an argument that does not have an integral type. If you want to see the individual byte values of a string, do something like
typedef byte bytes_t[];
$displayh("myString = %p, myOtherString = %h", bytes_t'(myString), bytes_t'(myOtherString));

In reply to dave_59:

Thanks, Dave, I have changed the code to the following:


  function void test_vars();
    static int myInt = 32'h1200d2d5;
    automatic string myString, myOtherString;
    
    $display("myInt = %h", myInt);
    
    // first cast
    $sformat(myString, "%s", myInt);
    // second cast
    myOtherString = string'(myInt);
    
    $displayh("myString = %p, myOtherString = %p", bytes_t'(myString), bytes_t'(myOtherString));
  endfunction : test_vars

What I get is this:
myInt = 1200d2d5
myString = '{18, 32, -46, -43} , myOtherString = '{18, -46, -43}

While I would like to have seen this:
myString = '{18 , 00, -46, -43}

Still, the first cast is translating 0x00 to 0x20 (32 in decimal), while the second cast completely ignores the 0x00 byte.

In reply to rodrigoportella:

A string in SystemVerilog is not allowed to contain a 0x0 byte. How $sformat %s interprets that is undefined. Use the bytes_t to define a variable if you need a series of bytes where one of them is 0.