Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a 256-bit wire to a C function through the Verilog VPI

Tags:

c

verilog

I have a 256-bit value in Verilog:

reg [255:0] val;

I want to define a system task $foo that calls out to external C using the VPI, so I can call $foo like this:

$foo(val);

Now, in the C definition for the function 'foo', I cannot simply read the argument as an integer (PLI_INT32), because I have too many bits to fit in one of those. But, I can read the argument as a string, which is the same thing as an array of bytes. Here is what I wrote:

static int foo(char *userdata) {
  vpiHandle systfref, args_iter, argh;
  struct t_vpi_value argval;
  PLI_BYTE8 *value;

  systfref = vpi_handle(vpiSysTfCall, NULL);
  args_iter = vpi_iterate(vpiArgument, systfref);

  argval.format = vpiStringVal;
  argh = vpi_scan(args_iter);
  vpi_get_value(argh, &argval);
  value = argval.value.str;

  int i;

  for (i = 0; i < 32; i++) {
    vpi_printf("%.2x ", value[i]);
  }
  vpi_printf("\n");

  vpi_free_object(args_iter);
  return 0;
}

As you can see, this code reads the argument as a string and then prints out each character (aka byte) in the string. This works almost perfectly. However, the byte 00 always gets read as 20. For example, if I assign the Verilog reg as follows:

 val = 256'h000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;

And call it using $foo(val), then the C function prints this at simulation time:

VPI: 20 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f

I have tested this with many different values and have found that the byte 00 always gets mapped to 20, no matter where or how many times it appears in val.

Also, note that if I read the value in as a vpiHexStrVal, and print the string, it looks fine.

So, two questions:

  1. Is there a better way to read in my 256-bit value from the Verilog?
  2. What's going on with the 20? Is this a bug? Am I missing something?

Note: I am using Aldec for simulation.

like image 342
pheaver Avatar asked Feb 17 '10 17:02

pheaver


1 Answers

vpiStringVal is used when the value is expected to be ASCII text, in order to get the value as a pointer to a C string. This is useful if you want to use it with C functions that expect a C string, such as printf() with the %s format, fopen(), etc. However, C strings cannot contain the null character (since null is used to terminate C strings), and also cannot represent x or z bits, so this is not a format that should be used if you need to distinguish any possible vector value. It looks like the simulator you are using formats the null character as a space (0x20); other simulators just skip them, but that doesn't help you either. To distinguish any possible vector value use either vpiVectorVal (the most compact representation) or vpiBinStrVal (a binary string with one 0/1/x/z character for each bit).

like image 125
mark4o Avatar answered Oct 14 '22 23:10

mark4o