通过 Verilog VPI 将 256 位连线传递给 C 函数
我在 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;
}
如您所见,此代码将参数读取为字符串,然后打印出字符串中的每个字符(也称为字节)。这几乎可以完美地工作。但是,字节 00
始终被读取为 20
。例如,如果我按如下方式分配 Verilog reg:
val = 256'h000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;
并使用 $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 进行模拟。
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:
- Is there a better way to read in my 256-bit value from the Verilog?
- What's going on with the
20
? Is this a bug? Am I missing something?
Note: I am using Aldec for simulation.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
vpiStringVal
在预期值是 ASCII 文本时使用,以便获取作为指向 C 字符串的指针的值。如果您想将其与需要 C 字符串的 C 函数一起使用,例如具有%s
格式的printf()
、fopen()< /code> 等。但是,C 字符串不能包含 null 字符(因为 null 用于终止 C 字符串),也不能表示 x 或 z 位,因此如果需要区分,这不是应该使用的格式任何可能的向量值。看起来您使用的模拟器将空字符格式化为空格(0x20);其他模拟器只是跳过它们,但这对你也没有帮助。要区分任何可能的向量值,请使用
vpiVectorVal
(最紧凑的表示形式)或vpiBinStrVal
(每位具有一个 0/1/x/z 字符的二进制字符串)。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 asprintf()
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 eithervpiVectorVal
(the most compact representation) orvpiBinStrVal
(a binary string with one 0/1/x/z character for each bit).