⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 read_stimulus_vpi.c

📁 pli_handbook_examples_pc verilog hdl 与C的接口的典型例子
💻 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 + -