通过Verilog VPI将256位导线传递到C函数

通过Verilog VPI将256位导线传递到C函数,c,verilog,C,Verilog,我在Verilog中有一个256位的值: reg [255:0] val; 我想定义一个系统任务$foo,它使用VPI调用外部C,所以我可以这样调用$foo: $foo(val); 现在,在函数“foo”的C定义中,我不能简单地将参数作为整数(PLI_INT32)来读取,因为我有太多的位不能放入其中一个。但是,我可以将参数读取为字符串,这与字节数组是一样的。以下是我写的: static int foo(char *userdata) { vpiHandle systfref, args_

我在Verilog中有一个256位的值:

reg [255:0] val;
我想定义一个系统任务$foo,它使用VPI调用外部C,所以我可以这样调用$foo:

$foo(val);
现在,在函数“foo”的C定义中,我不能简单地将参数作为整数(PLI_INT32)来读取,因为我有太多的位不能放入其中一个。但是,我可以将参数读取为字符串,这与字节数组是一样的。以下是我写的:

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;
}
并使用
$foo(val)
调用它,然后C函数在模拟时打印:

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
我用许多不同的值对此进行了测试,发现字节
00
总是映射到
20
,无论它在
val
中出现在哪里或多少次

另外,请注意,如果我以
vpiHexStrVal
的形式读取中的值,并打印字符串,则看起来很好

因此,有两个问题:

  • 有没有更好的方法从Verilog读取我的256位值
  • 20发生了什么事?这是虫子吗?我错过什么了吗

  • 注意:我正在使用Aldec进行模拟。

    vpiStringVal
    在值预期为ASCII文本时使用,以便将值作为指向C字符串的指针。如果您希望将它与期望使用C字符串的C函数一起使用,例如使用
    %s
    格式的
    printf()
    fopen()
    等。但是,C字符串不能包含null字符(因为null用于终止C字符串),也不能表示x或z位,因此,如果需要区分任何可能的向量值,则不应使用这种格式。看起来您正在使用的模拟器将空字符格式化为空格(0x20);其他模拟器只是跳过它们,但这也帮不了你。要区分任何可能的向量值,请使用
    vpibectroval
    (最简洁的表示法)或
    vpibistrval
    (每个位有一个0/1/x/z字符的二进制字符串)。

    我不想使用
    vpibistrval
    vpivectroval
    ,因为一次格式化一位输入很不方便。我实际上希望将数据格式化为32个8位值;最后,我只是拼接了256位的导线,并将其作为8个32位输入发送,可以读取为
    vpiIntVal
    ,然后简单地将其转换为32字节的数组;不是一点一点的。是的,你是对的,我说错了。我的意思是我想要一个实际的积分值,而不是一个有x和z的值。不过没什么大不了的,我可以转换它。如果你不关心x和z,你可以只读取
    aval
    字段,忽略
    bval
    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