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

📄 sci_alu_synchronized_vpi.c

📁 pli_handbook_examples_pc verilog hdl 与C的接口的典型例子
💻 C
字号:
/**********************************************************************
 * $scientific_alu example -- PLI application using VPI routines
 *
 * C model of a Scientific Arithmetic Logic Unit.
 *   Combinational logic version, with the interface callbacks
 *   synchronized to the end of the time step in which an input to
 *   the model changes value.
 *
 * 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 <math.h>
#include <ERRNO.h>
void PLIbook_ScientificALU_C_model(
       double *result,   /* output from ALU */
       int    *excep,    /* output; set if result is out of range */
       int    *err,      /* output; set if input is out of range */
       double  a,        /* input */
       double  b,        /* input */
       int     opcode)   /* input */
{
  switch (opcode) {
    case 0x0: *result = pow    (a, b);      break;
    case 0x1: *result = sqrt   (a);         break;
    case 0x2: *result = exp    (a);         break;
    case 0x3: *result = ldexp  (a, (int)b); break;
    case 0x4: *result = fabs   (a);         break;
    case 0x5: *result = fmod   (a, b);      break;
    case 0x6: *result = ceil   (a);         break;
    case 0x7: *result = floor  (a);         break;
    case 0x8: *result = log    (a);         break;
    case 0x9: *result = log10  (a);         break;
    case 0xA: *result = sin    (a);         break;
    case 0xB: *result = cos    (a);         break;
    case 0xC: *result = tan    (a);         break;
    case 0xD: *result = asin   (a);         break;
    case 0xE: *result = acos   (a);         break;
    case 0xF: *result = atan   (a);         break;
  }
  *err   = (errno == EDOM);   /* arg to math func. out of range */
  *excep = (errno == ERANGE); /* result of math func. out of range */
  errno = 0;                  /* clear the error flag */
  if (*err) *result = 0.0;    /* set result to 0 if error occurred */
  return;
}
/*********************************************************************/


#include <stdlib.h>    /* ANSI C standard library */
#include <stdio.h>     /* ANSI C standard input/output 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) */

/* prototypes of routines in this PLI application */
int PLIbook_ScientificALU_calltf(), PLIbook_ScientificALU_compiletf();
int PLIbook_ScientificALU_interface();
int PLIbook_EndOfTimeStep_callback();

/**********************************************************************
 * VPI Registration Data
 *********************************************************************/
void PLIbook_ScientificALU_register()
{
  s_vpi_systf_data tf_data;
  tf_data.type      = vpiSysTask;
  tf_data.tfname    = "$scientific_alu";
  tf_data.calltf    = PLIbook_ScientificALU_calltf;
  tf_data.compiletf = PLIbook_ScientificALU_compiletf;
  tf_data.sizetf    = NULL;
  tf_data.user_data = NULL;
  vpi_register_systf(&tf_data);
}

/**********************************************************************
 * Definition for a structure to hold the data to be passed from 
 * calltf routine to the ALU interface.
 *********************************************************************/
typedef struct PLIbook_ScientificALU_data {
  vpiHandle  clock_h, a_h, b_h, opcode_h, result_h, excep_h, err_h;
  short int  sync_flag;
} PLIbook_ALU_data_s, *PLIbook_ALU_data_p;

/**********************************************************************
 * Value change simulation callback routine: Schedules a read-write
 * synchronize simulation callback at the end of the current time step.
 * Only schedules one callback for a time step.
 *********************************************************************/
int PLIbook_ScientificALU_interface(p_cb_data cb_data) 
{
  s_cb_data           cb_data_s;
  s_vpi_time          time_s;
  PLIbook_ALU_data_p  ALUdata;

  /* Retrieve pointer to ALU data structure from VCL user_data field */
  /* The structure contains a flag indicating if a synchronize       */
  /* callback has already been scheduled */
  ALUdata = (PLIbook_ALU_data_p)cb_data->user_data;

  /* If the sync_flag is 0, then no read-write synchronize callback  */
  /* has been scheduled for this time step (the sync_flag is set to  */
  /* 1 by this routine, and set to 0 by the read-write synchronize   */
  /* callback after a callback is processed. */
  
  if (!ALUdata->sync_flag) {
    /* Schedule a synchronize simulation callback for this instance */
    ALUdata->sync_flag = 1; /* set sync_flag */
    time_s.type         = vpiSuppressTime;
    cb_data_s.reason    = cbReadWriteSynch;
    cb_data_s.user_data = (char *)ALUdata;
    cb_data_s.cb_rtn    = PLIbook_EndOfTimeStep_callback;
    cb_data_s.obj       = NULL;
    cb_data_s.time      = &time_s;
    cb_data_s.value     = NULL;
    vpi_register_cb(&cb_data_s);
  }
  return(0);
}

/**********************************************************************
 * Read-write synchronize simulation callback routine: Serves as an
 * interface between Verilog simulation and the C model.  Passes the
 * values to the C model, and puts the C model outputs into simulation.
 *
 * NOTE: The handles for the arguments to $scientific_alu were obtained
 * in the calltf routine and saved in application-allocated memory.  A
 * pointer to this memory is passed to this callback via the user_data
 * field.
 *********************************************************************/
int PLIbook_EndOfTimeStep_callback(p_cb_data cb_data) 
{
  double       a, b, result;
  int          opcode, excep, err;
  s_vpi_value  value_s;

  PLIbook_ALU_data_p  ALUdata;

  /* Retrieve pointer to ALU data structure from callback user_data. */
  /* The structure contains the handles for the $scientific_alu args */
  ALUdata = (PLIbook_ALU_data_p)cb_data->user_data;

  /* Set the sync_flag to 0 to indicate that this callback has been */
  /* processed */
  ALUdata->sync_flag = 0;

  /* Read current values of C model inputs from Verilog simulation */
  value_s.format = vpiRealVal;
  vpi_get_value(ALUdata->a_h, &value_s);
  a = value_s.value.real;
  
  vpi_get_value(ALUdata->b_h, &value_s);
  b = value_s.value.real;
  
  value_s.format = vpiIntVal;
  vpi_get_value(ALUdata->opcode_h, &value_s);
  opcode = value_s.value.integer;

  /******  Call the C model  ******/
  PLIbook_ScientificALU_C_model(&result, &excep, &err, a, b, opcode);

  /* Write the C model outputs onto the Verilog signals */
  value_s.format = vpiRealVal;
  value_s.value.real = result;
  vpi_put_value(ALUdata->result_h, &value_s, NULL, vpiNoDelay);

  value_s.format = vpiIntVal;
  value_s.value.integer = excep;
  vpi_put_value(ALUdata->excep_h, &value_s, NULL, vpiNoDelay);

  value_s.value.integer = err;
  vpi_put_value(ALUdata->err_h, &value_s, NULL, vpiNoDelay);

  return(0);
}

/**********************************************************************
 * calltf routine: Registers a callback to the C model interface
 * whenever any input to the C model changes value
 *********************************************************************/
int PLIbook_ScientificALU_calltf(char *user_data)
{
  vpiHandle    instance_h, arg_itr;
  s_vpi_value  value_s;
  s_vpi_time   time_s;
  s_cb_data    cb_data_s;
  
  PLIbook_ALU_data_p  ALUdata;

  /* allocate storage to hold $scientific_alu argument handles */
  ALUdata = (PLIbook_ALU_data_p)malloc(sizeof(PLIbook_ALU_data_s));
  
  /* obtain a handle to the system task instance */
  instance_h = vpi_handle(vpiSysTfCall, NULL);

  /* obtain handles to system task arguments */
  /* compiletf has already verified arguments are correct */
  arg_itr = vpi_iterate(vpiArgument, instance_h);
  ALUdata->a_h      = vpi_scan(arg_itr); /* 1st arg is a input */
  ALUdata->b_h      = vpi_scan(arg_itr); /* 2nd arg is b input */
  ALUdata->opcode_h = vpi_scan(arg_itr); /* 3rd arg is opcode input */
  ALUdata->result_h = vpi_scan(arg_itr); /* 4th arg is result output */
  ALUdata->excep_h  = vpi_scan(arg_itr); /* 5th arg is excep output */
  ALUdata->err_h    = vpi_scan(arg_itr); /* 6th arg is error output */
  vpi_free_object(arg_itr);  /* free iterator--did not scan to null */

  /* setup value change callback options */
  time_s.type      = vpiSuppressTime;
  cb_data_s.reason = cbValueChange;
  cb_data_s.cb_rtn = PLIbook_ScientificALU_interface;
  cb_data_s.time   = &time_s;
  cb_data_s.value  = &value_s;

  /* add value change callbacks to all signals which are inputs to  */
  /* pass pointer to storage for handles as user_data value */
  cb_data_s.user_data = (char *)ALUdata;
  value_s.format = vpiRealVal;
  cb_data_s.obj = ALUdata->a_h;
  vpi_register_cb(&cb_data_s);

  cb_data_s.obj = ALUdata->b_h;
  vpi_register_cb(&cb_data_s);

  value_s.format = vpiIntVal;
  cb_data_s.obj = ALUdata->opcode_h;
  vpi_register_cb(&cb_data_s);

  /* clear the callback sync_flag to indicate that no read-write */
  /* synchronize callbacks have been processed */
  ALUdata->sync_flag = 0;

  return(0);
}

/**********************************************************************
 * compiletf routine: Verifies that $scientific_alu() is used correctly
 *   Note: For simplicity, only limited data types are allowed for
 *   task arguments.  Could add checks to allow other data types.
 *********************************************************************/
int PLIbook_ScientificALU_compiletf(char *user_data)
{
  vpiHandle systf_h, arg_itr, arg_h;
  int       err = 0;

  systf_h = vpi_handle(vpiSysTfCall, NULL);
  arg_itr = vpi_iterate(vpiArgument, systf_h);
  if (arg_itr == NULL) {
    vpi_printf("ERROR: $scientific_alu requires 6 arguments\n");
    tf_dofinish();
    return(0);
  }

  arg_h = vpi_scan(arg_itr); /* 1st arg is a input */
  if (vpi_get(vpiType, arg_h) != vpiRealVar) {
    vpi_printf("$scientific_alu arg 1 (a) must be a real variable\n");
    err = 1;
  }

  arg_h = vpi_scan(arg_itr); /* 2nd arg is b input */
  if (vpi_get(vpiType, arg_h) != vpiRealVar) {
    vpi_printf("$scientific_alu arg 2 (b) must be a real variable\n");
    err = 1;
  }

  arg_h = vpi_scan(arg_itr); /* 3rd arg is opcode input */
  if (vpi_get(vpiType, arg_h) != vpiNet) {
    vpi_printf("$scientific_alu arg 3 (opcode) must be a net\n");
    err = 1;
  }
  else if (vpi_get(vpiSize, arg_h) != 4) {
    vpi_printf("$scientific_alu arg 3 (opcode) must be 4-bit vector\n");
    err = 1;
  }

  arg_h = vpi_scan(arg_itr); /* 4th arg is result output */
  if (vpi_get(vpiType, arg_h) != vpiRealVar) {
    vpi_printf("$scientific_alu arg 4 (result) must be a real var.\n");
    err = 1;
  }

  arg_h = vpi_scan(arg_itr); /* 5th arg is exception output */
  if (vpi_get(vpiType, arg_h) != vpiReg) {
    vpi_printf("$scientific_alu arg 5 (exception) must be a reg\n");
    err = 1;
  }
  else if (vpi_get(vpiSize, arg_h) != 1) {
    vpi_printf("$scientific_alu arg 5 (exception) must be scalar\n");
    err = 1;
  }

  arg_h = vpi_scan(arg_itr); /* 6th arg is error output */
  if (vpi_get(vpiType, arg_h) != vpiReg) {
    vpi_printf("$scientific_alu arg 6 (error) must be a reg\n");
    err = 1;
  }
  else if (vpi_get(vpiSize, arg_h) != 1) {
    vpi_printf("$scientific_alu arg 6 (error) must be scalar\n");
    err = 1;
  }

  if (vpi_scan(arg_itr) != NULL) { /* should not be any more args */
    vpi_printf("ERROR: $scientific_alu requires only 6 arguments\n");
    vpi_free_object(arg_itr);
    err = 1;
  }
  
  if (err) {
    tf_dofinish();
    return(0);
  }
}

/*********************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -