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

📄 sci_alu_latched_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 latched output values.
 *
 * 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
 *********************************************************************/


/**********************************************************************
 * Structure definition to store output values when the ALU is latched.
 *********************************************************************/
 typedef struct PLIbook_ScientificALU_outputs {
   double result;    /* stored result of previous operation */
   int    excep;
   int    err;
 } PLIbook_ALU_outputs_s, *PLIbook_ALU_outputs_p;


/**********************************************************************
 * C model with latched outputs.  When enable is 1, the ALU returns
 * the currently calculated outputs, and when 0, the ALU returns the
 * latched previous results.
 *********************************************************************/
#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 */
       int     enable,   /* input; 0 = latched */
       PLIbook_ALU_outputs_p  LatchedOutputs) /* input */
{
  if (enable) { /* ALU is not latched, calculate outputs and store */
    switch (opcode) {
      case 0x0: LatchedOutputs->result = pow    (a, b);      break;
      case 0x1: LatchedOutputs->result = sqrt   (a);         break;
      case 0x2: LatchedOutputs->result = exp    (a);         break;
      case 0x3: LatchedOutputs->result = ldexp  (a, (int)b); break;
      case 0x4: LatchedOutputs->result = fabs   (a);         break;
      case 0x5: LatchedOutputs->result = fmod   (a, b);      break;
      case 0x6: LatchedOutputs->result = ceil   (a);         break;
      case 0x7: LatchedOutputs->result = floor  (a);         break;
      case 0x8: LatchedOutputs->result = log    (a);         break;
      case 0x9: LatchedOutputs->result = log10  (a);         break;
      case 0xA: LatchedOutputs->result = sin    (a);         break;
      case 0xB: LatchedOutputs->result = cos    (a);         break;
      case 0xC: LatchedOutputs->result = tan    (a);         break;
      case 0xD: LatchedOutputs->result = asin   (a);         break;
      case 0xE: LatchedOutputs->result = acos   (a);         break;
      case 0xF: LatchedOutputs->result = atan   (a);         break;
    }
    LatchedOutputs->err   = (errno == EDOM);  /* arg out of range */
    LatchedOutputs->excep = (errno == ERANGE);/* result out of range */
    errno = 0;                               /* clear the error flag */
    if (LatchedOutputs->err) LatchedOutputs->result = 0.0;
  }
  
  /* return the values stored in the C model */
  *result = LatchedOutputs->result;  
  *err    = LatchedOutputs->err;  
  *excep  = LatchedOutputs->excep;  

  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();

/**********************************************************************
 * 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.  Also allocates a structure
 * to store the latched output values of the ALU.  This storage is
 * allocated for each instance of the C model.
 *********************************************************************/
typedef struct PLIbook_ScientificALU_data {
  vpiHandle  enable_h, a_h, b_h, opcode_h, result_h, excep_h, err_h;
  PLIbook_ALU_outputs_s  LatchedOutputs;  /* storage for outputs */
} PLIbook_ALU_data_s, *PLIbook_ALU_data_p;


/**********************************************************************
 * Value change simulation callback routine: Serves as an interface
 * between Verilog simulation and the C model.  Called whenever the
 * C model inputs change value, 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_ScientificALU_interface(p_cb_data cb_data) 
{
  double       a, b, result;
  int          opcode, excep, err, enable;
  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;

  /* 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;

  vpi_get_value(ALUdata->enable_h, &value_s);
  enable = value_s.value.integer;

  /******  Call the C model  ******/
  PLIbook_ScientificALU_C_model(&result, &excep, &err, a, b, opcode,
                                enable, &ALUdata->LatchedOutputs);

  /* 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->enable_h = vpi_scan(arg_itr); /* 1st arg is enable input */
  ALUdata->a_h      = vpi_scan(arg_itr); /* 2nd arg is a input */
  ALUdata->b_h      = vpi_scan(arg_itr); /* 3rd arg is b input */
  ALUdata->opcode_h = vpi_scan(arg_itr); /* 4th arg is opcode input */
  ALUdata->result_h = vpi_scan(arg_itr); /* 5th arg is result output */
  ALUdata->excep_h  = vpi_scan(arg_itr); /* 6th arg is excep output */
  ALUdata->err_h    = vpi_scan(arg_itr); /* 7th 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);

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

  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 7 arguments\n");
    tf_dofinish();
    return(0);
  }

  arg_h = vpi_scan(arg_itr); /* 1st arg is enable input */
  if (vpi_get(vpiType, arg_h) != vpiNet) {
    vpi_printf("$scientific_alu arg 1 (enable) must be a net\n");
    err = 1;
  }
  else if (vpi_get(vpiSize, arg_h) != 1) {
    vpi_printf("$scientific_alu arg 1 (enable) must be scalar\n");
    err = 1;
  }

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

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

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

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

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

  arg_h = vpi_scan(arg_itr); /* 7th arg is error output */
  if (vpi_get(vpiType, arg_h) != vpiReg) {
    vpi_printf("$scientific_alu arg 7 (error) must be a reg\n");
    err = 1;
  }
  else if (vpi_get(vpiSize, arg_h) != 1) {
    vpi_printf("$scientific_alu arg 7 (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 7 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 + -