输出开放数组作为DPI-C中的形式参数

问题描述 投票:2回答:1

我有C代码(预测模型),可以生成一个可变长度的数组作为其结果。在调用C代码之前不知道这个数组的大小是多少,并且涉及一些随机化(噪声建模)

我需要从SystemVerilog调用这个C预测模型,然后返回输出结果数组。

作为DPI-C的新手,我遇到了3个限制:

  1. 需要在调用C代码之前分配SV侧的结果数组。由于我不知道它的大小,我有机会进行分配或不合作。
  2. 我无法在导出函数中从C - > SV传递一个开放数组。
  3. 导出函数不能用于类方法(!)

为了解决这个问题,我在2个接口和全局变量/任务之间创建了一个hacky juggling。

我发布了我的解决方案并且工作正常,但我想知道是否有人有比这更优雅的解决方案。我特别不喜欢使用全局变量。

EN:

export "DPI-C" function allocate_mem;
export "DPI-C" function set_item;
import "DPI-C" context function void predictForMe (input int noiseA, input int noiseB);

int result[];

function void allocate_mem(int size);
  result = new[size];
endfunction

function void set_item(int index, int item);
  result[index] = item;
endfunction

class my_class;
  // constructor etc etc - assume is valid

  // my_func
  function void my_func();
    int noiseA = 10; // hardcode to simplify example
    int noiseB = 20; // hardcode to simplify example

    // call imported function
    predictForMe( noiseA, noiseB );
  endfunction
endclass

C:

extern void allocate_mem(int size);
extern void set_item(int index, int item);

void predictForMe(int noiseA, int noiseB)
{
  // do some calcualation based on noiseA and noiseB
  // generates an answer_array with num elements = X

  allocate_mem(X);
  for(i = 0; i < X; i++) set_item(i, answer_array[i]);

}

欢迎任何更好的解决方案。

c system-verilog uvm system-verilog-dpi
1个回答
0
投票

您无法从C代码传递开放数组,因为C代码不知道如何分配这样的数据结构。我想这是因为如果在C代码中分配的数组与SV侧的数组类型不匹配会有问题。例如,假设您在SV端定义了一个100元素固定大小的数组,并且您尝试从C传递一个10元素数组。在C端指定一个可以分配SV数组数据结构的函数也可能很困难。 。大小和布局不仅取决于元素的数量,还取决于元素的类型。

但是,可以将已分配的数组作为输出参数传递。但是,您必须知道要预分配的元素数量。正如@NominaAnimal建议的那样,你必须通过单独的函数调用传递你将从C接收的元素数量:

import "DPI-C" function int get_num_elems(args...);
import "DPI-C" function void get_elems(output int elems, args...);

class some_class;

  function void some_func();
    int result[]; // not a global variable
    result = new[get_num_elems(args...)];
    get_elems(result, args...);
  endfunction

endclass

在C端,您可以使用svGetArrElemPtr1(...)获取指向传入的result数组的每个元素的指针,并相应地更新它。你可以这样做,因为类型是int,并且两种语言的表示都是相同的:

void get_elems(svOpenArray elems, args...) {
  // compute elems based on 'args...'

  for (int i = 0; i < svSize(elems); i++)
    *(svGetArrElemPtr1(elems, i)) = ...[i];
}
© www.soinside.com 2019 - 2024. All rights reserved.