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

📄 sci_alu_latched_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.
 *   latched logic version (output values are 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 -/
 *   },
 *********************************************************************/

/**********************************************************************
 * Definition for a structure to store output values when the ALU is
 * latched.  When enable is 1, the ALU returns the currently calculated
 * outputs, and when 0, the ALU returns the latched previous results.
 *********************************************************************/
 #include <stdio.h>
 typedef struct PLIbook_SciALUoutputs  *PLIbook_SciALUoutputs_p; 
 typedef struct PLIbook_SciALUoutputs {
   char *instance_p; /* shows which task instance owns this space */
   double result;    /* stored result of previous operation */
   int    excep;
   int    err;
   PLIbook_SciALUoutputs_p next_ALU_outputs; /* next stack location */
 } PLIbook_SciALUoutputs_s;

  /* declare global stack pointer */
  static PLIbook_SciALUoutputs_p ALU_outputs_stack = NULL;


/**********************************************************************
 * C model of a Scientific Arithmetic Logic Unit.
 *   Latched outputs version.
 *********************************************************************/
#include <math.h>
#include <ERRNO.h>
void PLIbook_ScientificALU_C_model(
       int     enable,     /* input; 0 = latched */
       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 */
       char   *instance_p) /* input; pointer to system task instance */
{
  PLIbook_SciALUoutputs_p ALU_outputs;

  /* Locate the output storage in the stack for this model instance  */
  /* If no storage is found, then allocate a storage block and add   */
  /* the storage to the stack.                                       */
  ALU_outputs = ALU_outputs_stack; /* top-of-stack is in global var. */
  while (ALU_outputs && (ALU_outputs->instance_p != instance_p))
    ALU_outputs = ALU_outputs->next_ALU_outputs;

  /* If no storage area found for this model instance, create one */
  if (ALU_outputs == NULL) { 
    ALU_outputs = 
      (PLIbook_SciALUoutputs_p)malloc(sizeof(PLIbook_SciALUoutputs_s));
    ALU_outputs->instance_p = instance_p; /* set owner of this space */
    ALU_outputs->next_ALU_outputs = NULL;
    ALU_outputs_stack = ALU_outputs; /* save new top-of-stack */
  }

  if (enable) { /* ALU is not latched, calculate outputs and store */
    switch (opcode) {
      case 0x0: ALU_outputs->result = pow    (a, b);      break;
      case 0x1: ALU_outputs->result = sqrt   (a);         break;
      case 0x2: ALU_outputs->result = exp    (a);         break;
      case 0x3: ALU_outputs->result = ldexp  (a, (int)b); break;
      case 0x4: ALU_outputs->result = fabs   (a);         break;
      case 0x5: ALU_outputs->result = fmod   (a, b);      break;
      case 0x6: ALU_outputs->result = ceil   (a);         break;
      case 0x7: ALU_outputs->result = floor  (a);         break;
      case 0x8: ALU_outputs->result = log    (a);         break;
      case 0x9: ALU_outputs->result = log10  (a);         break;
      case 0xA: ALU_outputs->result = sin    (a);         break;
      case 0xB: ALU_outputs->result = cos    (a);         break;
      case 0xC: ALU_outputs->result = tan    (a);         break;
      case 0xD: ALU_outputs->result = asin   (a);         break;
      case 0xE: ALU_outputs->result = acos   (a);         break;
      case 0xF: ALU_outputs->result = atan   (a);         break;
    }
    ALU_outputs->err   = (errno == EDOM);   /* arg out of range */
    ALU_outputs->excep = (errno == ERANGE); /* result out of range */
    errno = 0;                              /* clear the error flag */
    if (ALU_outputs->err) ALU_outputs->result = 0.0;
  }
  
  /* return the values stored in the C model */
  *result = ALU_outputs->result;  
  *err    = ALU_outputs->err;  
  *excep  = ALU_outputs->excep;  

  return;
}
/*********************************************************************/


#include "veriuser.h"  /* IEEE 1364 PLI TF  routine library */
#include "acc_user.h"  /* IEEE 1364 PLI ACC routine library */

#define ALU_ENABLE 1  /* system task arg 1 is ALU enable 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     */

/**********************************************************************
 * VCL 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.
 *********************************************************************/
int PLIbook_ScientificALU_interface(p_vc_record vc_record) 
{

  double          a, b, result;
  int             opcode, excep, err, enable;
  handle          instance_h, result_h, excep_h, err_h,
                  a_h, b_h, opcode_h, enable_h;
  s_setval_value  value_s;
  s_setval_delay  delay_s;
  s_acc_time      time_s;

  acc_initialize();

  /* Retrieve instance handle from VCL user_data field */
  instance_h = (handle)vc_record->user_data;

  /* Obtain handles to all task arguments */
  enable_h = acc_handle_itfarg(ALU_ENABLE, instance_h);
  a_h      = acc_handle_itfarg(ALU_A,      instance_h);
  b_h      = acc_handle_itfarg(ALU_B,      instance_h);
  opcode_h = acc_handle_itfarg(ALU_OP,     instance_h);
  result_h = acc_handle_itfarg(ALU_RESULT, instance_h);
  excep_h  = acc_handle_itfarg(ALU_EXCEPT, instance_h);
  err_h    = acc_handle_itfarg(ALU_ERROR,  instance_h);

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

  acc_fetch_value(enable_h, "%%", &value_s);
  enable = value_s.value.integer;

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

  /* 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(result_h, &value_s, &delay_s); 

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

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

  acc_close();
  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()
{
  handle  instance_h, enable_h, a_h, b_h, opcode_h;
  
  acc_initialize();

  /* get handles for signals in task args which are C model inputs */
  enable_h = acc_handle_tfarg(ALU_ENABLE);
  a_h      = acc_handle_tfarg(ALU_A);
  b_h      = acc_handle_tfarg(ALU_B);
  opcode_h = acc_handle_tfarg(ALU_OP);

  /* get handles for this system task instance to pass to VCL app. */
  instance_h = acc_handle_tfinst();

  /* add VCL flags to all signals which are inputs to the C model  */
  /* pass handle for task instance as the user_data value          */
  acc_vcl_add(enable_h, PLIbook_ScientificALU_interface,
              (char*)instance_h, vcl_verilog_logic);
  acc_vcl_add(a_h, PLIbook_ScientificALU_interface,
              (char*)instance_h, vcl_verilog_logic);
  acc_vcl_add(b_h, PLIbook_ScientificALU_interface,
              (char*)instance_h, vcl_verilog_logic);
  acc_vcl_add(opcode_h, PLIbook_ScientificALU_interface,
              (char*)instance_h, 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_ENABLE), accWire)))
      tf_error("$scientific_alu arg 1 must be a net\n");
    else if (acc_fetch_size(acc_handle_tfarg(ALU_ENABLE)) != 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 6 must be a reg\n");
    else if (acc_fetch_size(acc_handle_tfarg(ALU_ERROR)) != 1)
      tf_error("$scientific_alu arg 6 must be scalar\n");
  }

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

⌨️ 快捷键说明

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