📄 read_stimulus_vpi.c
字号:
/**********************************************************************
* $read_stimulus_?? example -- PLI application using VPI routines
*
* C source to read a stimulu value from a file and apply the stimulus
* value to a Verilog simulation and the simulation time specified in
* in the file.
*
* Each line in the test vector file contains a delay time and a vector
* value, separated by white space. Delay values define when the
* vector is to be applied to simulation. Delays may be relative to
* the previous time, or absolute to time 0. The test vector value
* may be in binary or hex. An example file is:
*
* 100 00000000
* 70 10111001
* ...
*
* Usage:
*
* initial
* $read_stimulus_<base><delay_type>("file_name", verilog_reg);
*
* where:
* <base> is b or h (for binary or hex vectors).
* <delay_type> is r or a for relative or absolute times.
* "file_name" is the name of the file to be read, in quotes.
* verilog_reg is a verilog register data type of the same bit
* width as the patterns to be read.
*
* Output: none
*
* Verbose debugging output is enabled with a +readstim_debug
* invocation option to the simulation
*
* NOTES:
* There is no error checking on the data read from the file.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Book copyright 1999, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland.com or (503) 692-0898
*********************************************************************/
#include <stdlib.h> /* ANSI C standard library */
#include <stdio.h> /* ANSI C standard input/output library */
#include <malloc.h> /* ANSI C standard memory allocation library */
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
#include "veriuser.h" /* IEEE 1364 PLI TF routine library
(using TF routines for simulation control) */
/* include utility routines to work with tfargs */
#include "vpi_utilities.c"
/* prototypes of routines in this PLI application */
int PLIbook_ReadStim_calltf(), PLIbook_ReadStim_compiletf();
int PLIbook_StartOfSim(), PLIbook_ReadNextStim(), PLIbook_ReadStimEnd();
/**********************************************************************
* Define storage structure for file pointer and vector handle.
*********************************************************************/
typedef struct ReadStimData {
FILE *file_ptr; /* test vector file pointer */
vpiHandle obj_h; /* pointer to store handle for a Verilog object */
int mode; /* 0 & 1 = binary values, 2 & 3 = hex values */
/* 0 & 2 = absolute time, 1 & 3 = relative time */
int debug; /* print debug messages if true */
} s_ReadStimData, *p_ReadStimData;
/**********************************************************************
* VPI Registration Data
*********************************************************************/
void PLIbook_ReadStim_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.calltf = PLIbook_ReadStim_calltf;
tf_data.compiletf = PLIbook_ReadStim_compiletf;
tf_data.sizetf = NULL;
tf_data.tfname = "$read_stimulus_ba"; /* binary, absolute time */
tf_data.user_data = "ba";
vpi_register_systf(&tf_data);
tf_data.tfname = "$read_stimulus_br"; /* binary, relative time */
tf_data.user_data = "br";
vpi_register_systf(&tf_data);
tf_data.tfname = "$read_stimulus_ha"; /* hex, absolute time */
tf_data.user_data = "ha";
vpi_register_systf(&tf_data);
tf_data.tfname = "$read_stimulus_hr"; /* hex, relative time */
tf_data.user_data = "hr";
vpi_register_systf(&tf_data);
}
/**********************************************************************
* compiletf routine
*********************************************************************/
int PLIbook_ReadStim_compiletf(char *user_data)
{
s_cb_data cb_data_s;
vpiHandle systf_h, arg_itr, arg_h;
int tfarg_type, err = 0;
char *file_name;
systf_h = vpi_handle(vpiSysTfCall, NULL);
arg_itr = vpi_iterate(vpiArgument, systf_h);
if (arg_itr == NULL) {
vpi_printf("ERROR: $read_stimulus_?? requires 2 arguments\n");
tf_dofinish();
return(0);
}
arg_h = vpi_scan(arg_itr); /* get handle for first tfarg */
if (vpi_get(vpiType, arg_h) != vpiConstant) {
vpi_printf("$read_stimulus_?? arg 1 must be a quoted file name\n");
err = 1;
}
else if (vpi_get(vpiConstType, arg_h) != vpiStringConst) {
vpi_printf("$read_stimulus_?? arg 1 must be a string\n");
err = 1;
}
arg_h = vpi_scan(arg_itr); /* get handle for second tfarg */
tfarg_type = vpi_get(vpiType, arg_h);
if ( (tfarg_type != vpiReg) &&
(tfarg_type != vpiIntegerVar) &&
(tfarg_type != vpiTimeVar) ) {
vpi_printf("$read_stimulus_?? arg 2 must be a register type\n");
err = 1;
}
if (vpi_scan(arg_itr) != NULL) {
vpi_printf("read_stimulus_?? requires only 2 arguments\n");
vpi_free_object(arg_itr);
err = 1;
}
if (err)
tf_dofinish();
/* setup a callback for start of simulation */
cb_data_s.reason = cbStartOfSimulation;
cb_data_s.cb_rtn = PLIbook_StartOfSim;
cb_data_s.obj = NULL;
cb_data_s.time = NULL;
cb_data_s.value = NULL;
cb_data_s.user_data = (char *)systf_h; /* pass systf_h to callback */
vpi_register_cb(&cb_data_s);
return(0);
}
/**********************************************************************
* calltf routine -- registers an immediate callback to the
* ReadNextStim application.
*********************************************************************/
int PLIbook_ReadStim_calltf(char *user_data)
{
s_cb_data data_s;
s_vpi_time time_s;
vpiHandle systf_h;
p_ReadStimData StimData; /* pointer to a ReadStimData structure */
/* get ReadStimData pointer from work area for this task instance */
systf_h = vpi_handle(vpiSysTfCall, NULL);
StimData = (p_ReadStimData)PLIbook_get_vpiworkarea(systf_h);
/* look at user data to set the stimulus mode flag */
if (strcmp(user_data, "ba") == 0) StimData->mode = 0;
else if (strcmp(user_data, "br") == 0) StimData->mode = 1;
else if (strcmp(user_data, "ha") == 0) StimData->mode = 2;
else StimData->mode = 3;
/* setup immediate callback to ReadNextStim routine */
systf_h = vpi_handle(vpiSysTfCall, NULL);
time_s.type = vpiSimTime;
time_s.low = 0;
time_s.high = 0;
data_s.reason = cbReadWriteSynch;
data_s.cb_rtn = PLIbook_ReadNextStim;
data_s.obj = NULL;
data_s.time = &time_s;
data_s.value = NULL;
data_s.user_data = (char *)systf_h;
vpi_register_cb(&data_s);
return(0);
}
/**********************************************************************
* ReadNextStim callback -- Reads a time and vector from a file.
* Schedules the vector to be applied at the specified time.
* Schedules a callback to self that same time (to read next line).
*********************************************************************/
int PLIbook_ReadNextStim(p_cb_data cb_data)
{
char vector[1024]; /* fixed max. size, should use malloc instead */
int delay;
vpiHandle systf_h;
s_cb_data data_s;
s_vpi_time time_s;
s_vpi_value value_s;
p_ReadStimData StimData; /* pointer to a ReadStimData structure */
/* retrieve system task handle from user_data */
systf_h = (vpiHandle)cb_data->user_data;
/* get ReadStimData pointer from work area for this task instance */
StimData = (p_ReadStimData)PLIbook_get_vpiworkarea(systf_h);
/* read next line from the file */
if ( (fscanf(StimData->file_ptr,"%d %s\n", &delay, vector)) == EOF) {
/* At EOF, schedule ReadStimEnd callback at end of this time */
time_s.type = vpiSimTime;
time_s.low = 0;
time_s.high = 0;
data_s.reason = cbReadOnlySynch;
data_s.cb_rtn = PLIbook_ReadStimEnd;
data_s.obj = NULL;
data_s.time = &time_s;
data_s.value = NULL;
data_s.user_data = (char *)StimData->file_ptr;
vpi_register_cb(&data_s);
}
if (StimData->debug) {
vpi_printf("Values read from file: delay=%d vector=%s\n",
delay, vector);
}
/* convert absolute delay from file to relative delay if needed */
time_s.type = vpiScaledRealTime;
if (StimData->mode == 0 || StimData->mode == 2) {
vpi_get_time(cb_data->obj, &time_s);
time_s.real = ((double)delay - time_s.real);
}
else
time_s.real = (double)delay;
/* schedule the vector to be applied after the delay period */
if (StimData->mode == 0 || StimData->mode == 1)
value_s.format = vpiBinStrVal;
else
value_s.format = vpiHexStrVal;
value_s.value.str = vector;
vpi_put_value(StimData->obj_h, &value_s, &time_s, vpiTransportDelay);
/* schedule callback to this routine when time to read next vector */
data_s.reason = cbAfterDelay;
data_s.cb_rtn = PLIbook_ReadNextStim;
data_s.obj = systf_h; /* object required for scaled delays */
data_s.time = &time_s;
data_s.value = NULL;
data_s.user_data = (char *)systf_h;
vpi_register_cb(&data_s);
if (vpi_chk_error(NULL))
vpi_printf("An error occurred registering ReadNextStim callback\n");
return(0);
}
/**********************************************************************
* StartOfSim callback -- opens the test vector file and saves the
* file pointer and other info in an instance-specific work area.
*********************************************************************/
int PLIbook_StartOfSim(p_cb_data cb_data)
{
char *file_name;
FILE *vector_file;
vpiHandle systf_h, tfarg_itr, tfarg1_h, tfarg2_h;
s_cb_data data_s;
s_vpi_time time_s;
s_vpi_value argVal;
s_vpi_vlog_info options_s;
p_ReadStimData StimData; /* pointer to a ReadStimData structure */
int i, debug;
/* retrieve system task handle from user_data */
systf_h = (vpiHandle)cb_data->user_data;
/* get tfarg handles (compiletf already verified args are correct) */
tfarg_itr = vpi_iterate(vpiArgument, systf_h);
tfarg1_h = vpi_scan(tfarg_itr);
tfarg2_h = vpi_scan(tfarg_itr);
vpi_free_object(tfarg_itr); /* free iterator--did not scan to null */
/* read file name from first tfarg */
argVal.format = vpiStringVal;
vpi_get_value(tfarg1_h, &argVal);
if (vpi_chk_error(NULL)) {
vpi_printf("ERROR: $read_stimulus_?? could not get file name\n");
return(0);
}
file_name = argVal.value.str;
if ( !(vector_file = fopen(file_name,"r")) ) {
vpi_printf("$read_stimulus_?? could not open file %s\n",file_name);
tf_dofinish();
return(0);
}
/* check for +readstim_debug invocation option */
debug = 0; /* assume not invoked with debug flag */
vpi_get_vlog_info(&options_s);
for (i=1; i<options_s.argc; i++) {
if (strcmp(options_s.argv[i], "+readstim_debug") == 0) {
debug = 1; /* invocation option found */
break;
}
}
/* allocate memory to store information about this instance */
StimData = (p_ReadStimData)malloc(sizeof(s_ReadStimData));
StimData->file_ptr = vector_file;
StimData->obj_h = tfarg2_h;
StimData->debug = debug;
PLIbook_set_vpiworkarea(systf_h, (char *)StimData);
return(0);
}
/**********************************************************************
* End-Of-Simulation callback -- close file and exit simulation.
*********************************************************************/
int PLIbook_ReadStimEnd(p_cb_data cb_data_p)
{
vpi_printf("$read_stimulus_?? reached End-Of-File.\n");
fclose((FILE *)cb_data_p->user_data);
tf_dofinish();
return(0);
}
/*********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -