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

📄 sci_alu_sequential_acc.c

📁 pli_handbook_examples_pc verilog hdl 与C的接口的典型例子
💻 C
字号:
/**********************************************************************
 * $scientific_alu example -- PLI application using TF routines
 *
 * C model of a Scientific Arithmetic Logic Unit.
 *   Sequential logic version (output values are not stored).
 *
 * 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
 *
 * Routine definitions for a veriusertfs array:
 *  /* routine prototypes -/
 *   extern int PLIbook_ScientificALU_checktf(),
 *              PLIbook_ScientificALU_calltf(),
 *  /* table entries -/
 *   {usertask,                         /* type of PLI routine -/
 *     0,                               /* user_data value -/
 *     PLIbook_ScientificALU_checktf,   /* checktf routine -/
 *     0,                               /* sizetf routine -/
 *     PLIbook_ScientificALU_calltf,    /* calltf routine -/
 *     0,                               /* misctf routine -/
 *     "$scientific_alu",               /* system task/function name -/
 *     1                                /* forward reference = true -/
 *   },
 *********************************************************************/

/**********************************************************************
 * C model of a Scientific Arithmetic Logic Unit.
 *   Sequential logic version (outputs change on a clock edge).
 *********************************************************************/
#include <stdio.h>
#include <math.h>
#include <ERRNO.h>
void PLIbook_ScientificALU_C_model(
       int     clock,    /* input */
       double  a,        /* input */
       double  b,        /* input */
       int     opcode,   /* input */
       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 */
{
  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 "veriuser.h"  /* IEEE 1364 PLI TF  routine library */
#include "acc_user.h"  /* IEEE 1364 PLI ACC routine library */

#define ALU_CLOCK  1  /* system task arg 1 is ALU clock input      */
#define ALU_A      2  /* system task arg 2 is ALU A input          */
#define ALU_B      3  /* system task arg 3 is ALU B input          */
#define ALU_OP     4  /* system task arg 4 is ALU opcode input     */
#define ALU_RESULT 5  /* system task arg 5 is ALU result output    */
#define ALU_EXCEPT 6  /* system task arg 6 is ALU exception output */
#define ALU_ERROR  7  /* system task arg 7 is ALU error output     */

/**********************************************************************
 * Definition for a structure to hold the data to be passed from 
 * calltf routine to the ALU interface (a VCL consumer routine).
 *********************************************************************/
typedef struct PLIbook_SciALU_data {
  handle  clock_h, a_h, b_h, opcode_h, result_h, excep_h, err_h;
} PLIbook_SciALU_data_s, *PLIbook_SciALU_data_p;

/**********************************************************************
 * VCL simulation callback routine: Serves as an interface between
 * Verilog simulation and the C model.  Called whenever the C model 
 * clock input changes value, reads the values of all model inputs,
 * passes the values to the C model, and writes the C model outputs
 * into simulation.
 *********************************************************************/
int PLIbook_ScientificALU_interface(p_vc_record vc_record) 
{
  double          a, b, result;
  int             opcode, excep, err;
  s_setval_value  value_s;
  s_setval_delay  delay_s;
  s_acc_time      time_s;

  PLIbook_SciALU_data_p  ALUdata;

  acc_initialize();

  /* Retrieve pointer to ALU data structure from VCL user_data field */
  ALUdata = (PLIbook_SciALU_data_p)vc_record->user_data;

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


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


  /* Write the C model outputs onto the Verilog signals */
  delay_s.model      = accNoDelay;
  delay_s.time       = time_s;
  delay_s.time.type  = accRealTime;
  delay_s.time.real  = 0.0;

  value_s.format     = accRealVal;
  value_s.value.real = result;
  acc_set_value(ALUdata->result_h, &value_s, &delay_s); 

  value_s.format        = accIntVal;
  value_s.value.integer = excep;
  acc_set_value(ALUdata->excep_h, &value_s, &delay_s); 

  value_s.value.integer = err;
  acc_set_value(ALUdata->err_h, &value_s, &delay_s); 

  acc_close();
  return(0);
}

/**********************************************************************
 * calltf routine: Registers a callback to the C model interface
 * whenever the clock input to the C model changes value
 *********************************************************************/
int PLIbook_ScientificALU_calltf()
{
  PLIbook_SciALU_data_p  ALUdata;
  
  acc_initialize();
  
  ALUdata=(PLIbook_SciALU_data_p)malloc(sizeof(PLIbook_SciALU_data_s));

  /* get handles for all signals in Verilog which connect to C model */
  ALUdata->clock_h  = acc_handle_tfarg(ALU_CLOCK);
  ALUdata->a_h      = acc_handle_tfarg(ALU_A);
  ALUdata->b_h      = acc_handle_tfarg(ALU_B);
  ALUdata->opcode_h = acc_handle_tfarg(ALU_OP);
  ALUdata->result_h = acc_handle_tfarg(ALU_RESULT);
  ALUdata->excep_h  = acc_handle_tfarg(ALU_EXCEPT);
  ALUdata->err_h    = acc_handle_tfarg(ALU_ERROR);

  /* add VCL flag to the clock input to the C model */
  /* pass pointer to storage for handles as user_data value */
  acc_vcl_add(ALUdata->clock_h, PLIbook_ScientificALU_interface,
              (char*)ALUdata, vcl_verilog_logic);

  acc_close();
  return(0);
}

/**********************************************************************
 * checktf 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_checktf()
{
  acc_initialize();
  
  if (tf_nump() != 7)
    tf_error("$scientific_alu requires 7 arguments");
    
  else {
    if (!(acc_object_of_type(acc_handle_tfarg(ALU_CLOCK), accWire)))
      tf_error("$scientific_alu arg 1 must be a net\n");
    else if (acc_fetch_size(acc_handle_tfarg(ALU_CLOCK)) != 1)
      tf_error("$scientific_alu arg 1 must be scalar\n");

    if (!(acc_object_of_type(acc_handle_tfarg(ALU_A), accRealVar)))
      tf_error("$scientific_alu arg 2 must be a real variable\n");

    if (!(acc_object_of_type(acc_handle_tfarg(ALU_B), accRealVar)))
      tf_error("$scientific_alu arg 3 must be a real variable\n");

    if (!(acc_object_of_type(acc_handle_tfarg(ALU_OP), accWire)))
      tf_error("$scientific_alu arg 4 must be a net\n");
    else if (acc_fetch_size(acc_handle_tfarg(ALU_OP)) != 4)
      tf_error("$scientific_alu arg 4 must be a 4-bit vector\n");

    if (!(acc_object_of_type(acc_handle_tfarg(ALU_RESULT),accRealVar)))
      tf_error("$scientific_alu arg 5 must be a real variable\n");

    if (!(acc_object_of_type(acc_handle_tfarg(ALU_EXCEPT), accReg)))
      tf_error("$scientific_alu arg 6 must be a reg\n");
    else if (acc_fetch_size(acc_handle_tfarg(ALU_EXCEPT)) != 1)
      tf_error("$scientific_alu arg 6 must be scalar\n");

    if (!(acc_object_of_type(acc_handle_tfarg(ALU_ERROR), accReg)))
      tf_error("$scientific_alu arg 7 must be a reg\n");
    else if (acc_fetch_size(acc_handle_tfarg(ALU_ERROR)) != 1)
      tf_error("$scientific_alu arg 7 must be scalar\n");
  }

  acc_close();
  return(0);
}
/*********************************************************************/

⌨️ 快捷键说明

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