3

当我询问SystemVerilog 遍历层次结构 时,有人建议我使用 SystemVerilog VPI 代码来解决它。我发布了我的尝试,但意识到在强制净值后我需要释放它。vpi_put_value(vpi_handle_by_index(net,position),&val,NULL,vpiForceFlag);

我使用release_reg()cbForce.

我的问题是,因为我在许多网络上循环,所以我想cb_handle = vpi_register_cb(&cb_data_s);在每次回调后释放句柄。

我的尝试是将回调句柄传递cb_handle给回调函数,但它会产生分段错误。

vpi_remove_cb每个之后的正确方法是vpiReleaseFlag什么?

这是我的尝试:

#include <sv_vpi_user.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define NULL 0

typedef struct {
  vpiHandle net_handle;
  vpiHandle cb_handle;
} handle_struct;

//Callback function to relase the vpiForceFlag
int release_reg(p_cb_data cb_data_p) {
  vpi_printf ("Releasing bits \n");
  handle_struct *hdls;
  hdls = (handle_struct *)cb_data_p->user_data;
  vpi_put_value(hdls->net_handle,cb_data_p->value,NULL,vpiReleaseFlag);

  vpi_remove_cb(hdls->cb_handle); //<- this line causes the pb.
  return(0);
}

void reg_flips() {
  vpiHandle module_iter;
  vpiHandle module_obj;
  vpiHandle module_regblk;
  vpiHandle reg_nets;
  vpiHandle put_handle;

  //Starting from the RegBlock
  module_regblk = vpi_handle_by_name("DUT.RegBlock",NULL);
  //Iterator over all register in RegBlock
  module_iter = vpi_iterate(vpiModule,module_regblk);

  while (module_iter) {
    module_obj = vpi_scan(module_iter);
    if (module_obj) {
      const char* module_name;
      module_name = vpi_get_str(vpiName, module_obj);
      reg_nets = vpi_iterate(vpiReg,module_obj); //Iterator over all registers within regblock
      while (reg_nets) {
        vpiHandle net;
        net = vpi_scan(reg_nets);
        if (net) {
          const char* net_name = vpi_get_str(vpiName, net);  
          int position = rand()%32; //Position of the bit flip
          vpiHandle obj_net;
          obj_net = vpi_handle_by_index(net,position); //Getting the net of given position
          s_vpi_value val_after; //Value of the net before bit flip
          s_vpi_value val_before; //value of the net after bit flip
          val_before.format = vpiIntVal;
          val_after.format = vpiIntVal;
          vpi_get_value(obj_net,&val_before); //Getting the initial value of the net
          val_after.value.integer = val_before.value.integer ^ 1; //Flipping the bit
          vpi_printf ("Forcing bits in %s - %s[%d] = %d\n",module_name,net_name,position,val_after.value.integer);
            //Forcing the value at a given position.                      

          put_handle = vpi_put_value(obj_net,&val_after,NULL,vpiForceFlag);
          //Here we define the parameter for the callback function that will release the force statement
          vpiHandle cb_handle;
          s_cb_data  cb_data_s; //Callback object
          s_vpi_time time_s; //VPI time object
          handle_struct *hdls;
          hdls = (handle_struct *)malloc(sizeof(hdls));
          hdls->net_handle = obj_net;
          hdls->cb_handle = cb_handle;

          time_s.type = vpiSimTime; //Simulation time
          cb_data_s.reason = cbForce; //Callback is triggered by a force statement
          cb_data_s.obj = put_handle; //For cbforce handle of the vpi_put_value needed
          //cb_data_s.user_data = malloc(sizeof(hdls));
          cb_data_s.user_data = hdls;
          cb_data_s.cb_rtn = release_reg; //Function to execute in the callback
          cb_data_s.time = &time_s;
          cb_data_s.value = &val_after; //Releasing to the same value
          cb_handle = vpi_register_cb(&cb_data_s); //PB We need to call vpi_remove_cb on the cb_handle
          vpi_release_handle(cb_handle);
        }
        else {
          reg_nets = NULL;
        }
      }
    }
    else {
      module_iter = NULL;
    }
  }
}
4

1 回答 1

1

这里有一些关于如何使用 vpi 在不强制的情况下将值放入(注入)信号的建议。

首先,正如您所提到的,大多数信号都可以在仿真周期中由verilog重新评估,因此您输入的值有可能被verilog覆盖。有几种方法可以避免它想到的(可能更多)。

  1. 一个明显的,只存入主要输入,这些输入实际上是模拟中的任何非驱动变量。

  2. 当触发器处于非活动状态时,在触发器逻辑的输出中存入一个信号。即,如果您@(posedge clk)在时钟更改时有存款。

  3. 潜在地,您可以存入由此类触发器驱动的任何信号,除非您有一个组合循环会导致对该信号的重新评估。

  4. 您还可以根据需要在模拟时间事件(如或其他事件)上安排cbNextSimTime注射cbNBASynch

以上所有内容都可以生成单个模拟事件,该事件将根据它重新评估所有负载。这种注入很可能会在接下来的几个模拟周期中被覆盖。

然而,在某些情况下,需要将force一个值转换为几个时钟周期的信号。在 force 事件中立即释放它没有任何意义。这与简单注入的行为方式相同。

您还必须记住,一些模拟器会牺牲强制和注入能力来进行优化。因此,您需要了解在编译中使用哪些限定符和/或如何配置您的模拟器以允许强制或注入寄存器和/或网络。

于 2017-08-26T22:38:49.937 回答