3

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

我需要从 SystemVerilog 调用这个 C 预测器模型,并取回输出结果数组。

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

  1. SV 端的结果数组需要在调用 C 代码之前分配。因为我不知道大小会是多少,所以我有可能过度分配或分配不足。
  2. 我无法在导出函数中从 C -> SV 传递一个开放数组。
  3. 导出函数不能用于类方法(!)

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

我已经发布了我的解决方案,它运行良好,但我想知道是否有人有比这更优雅的解决方案。我特别不喜欢使用全局变量。

SV:

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]);

}

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

4

1 回答 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];
}
于 2017-12-23T16:22:07.127 回答