Strange $sscanf() behavior in string with two hex values with 0x prefixes

I am getting a situation with $sscanf() where it parses the first value correctly, however the second value does not correctly capture. The code snippet are included below up to the $sscanf() call:

    task automatic do_axi_mst_w (
        input cmd_generic_t cmd,
        ref mailbox         axi_mst_mb,
        input integer       loud = 0
    );
        logic [31:0]   addr;
        logic [31:0]   data;
        axi_mst_trx_t  axi_transaction;
        static integer trx_count = 1;

        // Parse the command string for the address and data. If valid, post the
        // transaction and wait for response.
        if ($sscanf(cmd.arg_str, "%x %x", addr, data)) begin
            if (loud) tb_msg($sformatf("%m : AXI Write %0d: Addr: %h Data: %h", trx_count, addr, data));

The value of cmd.arg_str is 0xa0000004 0x1 (obtained from prior print statement, and also from code variable inspection in simulation.) After $sscanf(), the value of addr is 32’ha000_0004. After $sscanf(), the value of data is 32’h0000_00x1.

The LRM does say that %h%x can accept values including X and x, and it seems like in this instance, it’s reading x as undefined, rather than the prefix 0x. Oddly enough, it did it correctly in the first argument!

I suspect it might be since the variable is specified as logic [31:0] $sscanf() is anticipating more characters to fill the variable, thus it’s reading the 0x as a 0 and an undefined in its attempt to match string to value.

Is this correct? Is there any way to $sscanf() for hex values shorter than the full logic width, properly accepting the 0x prefix?

Seems like putting the prefix in the $sscanf() string solves the issue. So $sscanf(“0x%h 0x%h”, var, var) works fine and parses correctly. The exact reason why the prior did not work I still suspect has something to do with the size of the logic variable that was being read in, and $sscanf() did its best to fit the text to the variable definition. No idea if that’s correct but makes a certain sort of sense. $sscanf() definitely doesn’t work quite like C sscanf (researching this problem kept bringing up references to C which kept saying %x or %h should properly ignore 0x but it’s also just trying to read into integers, and not physical variable types.)

Correct. SystemVerilog uses x to represent unknown values. C does not have this concepts, thus sscanf cannot work exactly the same.

1 Like