SystemVerilog VPI освобождает дескриптор обратного вызова после vpiForceFlag
Когда я спросил 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;
}
}
}
1 ответ
Вот несколько советов о том, как поместить (ввести) значение в сигнал, не форсируя, используя vpi.
Прежде всего, как вы упомянули, большинство сигналов может быть переоценено verilog во время цикла моделирования, поэтому есть вероятность, что значение, которое вы установили, будет перезаписано verilog. Есть несколько способов избежать этого, которые приходят на ум (может быть и больше).
очевидный, только вклад в первичные входные данные, которые на самом деле являются любой неискаженной переменной в симуляции.
подать сигнал на выход логики флопа в тот момент, когда флоп не активен. т.е. если у вас есть
@(posedge clk)
депозит при смене часов, когда он идет вниз.потенциально вы можете внести в любой сигнал, управляемый таким флопом, если у вас нет комбинаторного цикла, который вызовет переоценку этого сигнала.
Вы также можете запланировать свои инъекции на время моделирования событий, таких как
cbNextSimTime
или жеcbNBASynch
или другие, в зависимости от ваших потребностей.
Все вышеперечисленное хорошо для генерации одного события моделирования, которое будет переоценивать все нагрузки в зависимости от него. Скорее всего, эта инъекция будет перезаписана в следующие несколько циклов моделирования.
Однако в некоторых случаях необходимо force
значение в сигнал для нескольких тактов. Не имеет смысла выпускать его сразу же после события силы. Это ведет себя так же, как простая инъекция.
Также вы должны помнить, что некоторые симуляторы жертвуют способностями форсирования и впрыска для оптимизации. Итак, вам необходимо понять, какие квалификаторы использовать при компиляции и / или как настроить симулятор, чтобы разрешать или вводить регистры и / или сети.