Sophie

Sophie

distrib > Fedora > 13 > i386 > by-pkgid > 507bc49db4d931250bab05d0619a9dd6 > files > 170

gplcver-2.12a-1.fc13.i686.rpm

/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */

/*
 * test of set delays vpi_ tasks - read and sets (puts) same delay value
 * for primitives and paths only
 */

#include <stdio.h>
#include <string.h>

#include "vpi_user.h"
#include "cv_vpi_user.h"

#define TRUE 1
#define FALSE 0

int (*iproc_rtn)();

/* local function prototypes */
static void process_inst(vpiHandle); 
static char *get_tchknam(char *, int);

/* global function prototypes */
extern int process_all_insts(struct t_cb_data *);
extern int prt_inst_delays(vpiHandle);
extern int my_error_handler(struct t_cb_data *);
extern void register_scan_cb(void);

/*
 * routine to get and zero all delays in design 
 */
int process_all_insts(struct t_cb_data *cbp)
{
 int isiz;
 vpiHandle topiter, topiref;

 /* build the iterator for each module */
 topiter = vpi_iterate(vpiModule, NULL);
 isiz = vpi_get(vpiSize, topiter);
 vpi_printf("  There are %d top level modules.\n", isiz);
 for (;;)
  {
   if ((topiref = vpi_scan(topiter)) == NULL) break;
   process_inst(topiref);
  }
 vpi_printf("  All instances processed.\n");
 /* notice Verilog model is not run, just data for PLI */
 vpi_sim_control(vpiFinish, 0);
 return(0);
}

/*
 * process one instance and recursively process all under instances
 * processing is top down depth first
 */
static void process_inst(vpiHandle up_ihref) 
{
 int isiz;
 vpiHandle iter, ihref;

 iproc_rtn(up_ihref);
 if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return;
 isiz = vpi_get(vpiSize, iter);
 vpi_printf("  There are %d instances in %s.\n", isiz,
  vpi_get_str(vpiFullName, up_ihref));
  for (;;)
  {
   if ((ihref = vpi_scan(iter)) == NULL) break;
   process_inst(ihref);
  }
}

/*
 * simplest processing routine - just print delays
 */
int prt_inst_delays(vpiHandle ihref)
{
 register int di;
 int tctyp;
 vpiHandle iter, href;
 s_vpi_delay idrec, odrec;
 s_vpi_time idelarr[12], odelarr[12];
 char s1[1024], s2[1024];

 idrec.da = &(idelarr[0]);
 idrec.time_type = vpiSimTime;
 /* idrec.time_type = vpiScaledRealTime; */
 idrec.mtm_flag = FALSE;
 idrec.append_flag = FALSE;
 idrec.pulsere_flag = FALSE;
 /* gates - use scan returns nil, nil iterator pattern */ 
 idrec.no_of_delays = 3;

 odrec.da = &(odelarr[0]);
 odrec.time_type = idrec.time_type;
 odrec.mtm_flag = FALSE;
 odrec.append_flag = TRUE;
 odrec.pulsere_flag = FALSE;
 /* gates - use scan returns nil, nil iterator pattern */ 
 odrec.no_of_delays = 3;

 iter = vpi_iterate(vpiPrimitive, ihref);
 for (;;)
  {
   if ((href = vpi_scan(iter)) == NULL) break;
   if (vpi_iterate(vpiDelay, href) == NULL) continue;

   vpi_get_delays(href, &idrec);
   for (di = 0; di < idrec.no_of_delays; di++) odrec.da[di] = idrec.da[di]; 
   vpi_put_delays(href, &odrec);
   vpi_get_delays(href, &idrec);

   /* expect delays to always fit in 31 bits */
   if (vpi_get(vpiType, href) == vpiUdp) strcpy(s1, "udp");
   else strcpy(s1, "gate");
   strcpy(s2, vpi_get_str(vpiDefName, href));
   /* -- */
   vpi_printf("  %s %s %s has delay #(%d, %d, %d).\n",
    s2, s1, vpi_get_str(vpiFullName, href), idrec.da[0].low, idrec.da[1].low,
    idrec.da[2].low);
   /* --- */
   /* ---
   vpi_printf("  %s %s %s has delay #(%d, %d).\n",
    s2, s1, vpi_get_str(vpiFullName, href), idrec.da[0].low, idrec.da[1].low);
   --- */
  /* ---
   vpi_printf("  %s %s %s has delay #(%5.2f, %5.2f).\n",
    s2, s1, vpi_get_str(vpiFullName, href), idrec.da[0].real,
    idrec.da[1].real);
  --- */
  }
 /* contas */
 iter = vpi_iterate(vpiContAssign, ihref);
 for (;;)
  {
   if ((href = vpi_scan(iter)) == NULL) break;
   if (vpi_iterate(vpiDelay, href) == NULL) continue;

   vpi_get_delays(href, &idrec);
   /* expect delays to always fit in 31 bits */
   vpi_printf("  continuous assign at **%s(%d) has delay #(%d, %d, %d).\n",
    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
    idrec.da[0].low, idrec.da[1].low, idrec.da[2].low);
  }
 /* paths */
 idrec.no_of_delays = 6;
 idrec.time_type = vpiScaledRealTime; 
 iter = vpi_iterate(vpiModPath, ihref);
 for (;;)
  {
   if ((href = vpi_scan(iter)) == NULL) break;

   vpi_get_delays(href, &idrec);
   for (di = 0; di < idrec.no_of_delays; di++) odrec.da[di] = idrec.da[di]; 
   vpi_put_delays(href, &odrec);
   vpi_get_delays(href, &idrec);
   /* expect delays to always fit in 31 bits */
   /* --- */
   vpi_printf("  path at **%s(%d) has delay #(%g, %g, %g, %g, %g, %g).\n",
    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
    idrec.da[0].real, idrec.da[1].real, idrec.da[2].real, idrec.da[3].real,
    idrec.da[4].real, idrec.da[5].real);
   /* --- */ 
   /* ---
   vpi_printf("  path at **%s(%d) has delay #(%d, %d, %d, %d, %d, %d).\n",
    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
    idrec.da[0].low, idrec.da[1].low, idrec.da[2].low, idrec.da[3].low,
    idrec.da[4].low, idrec.da[5].low);
   --- */
   /* ---
   vpi_printf(
    "  path at **%s(%d) has delay #(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d).\n",
    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
    idrec.da[0].low, idrec.da[1].low, idrec.da[2].low, idrec.da[3].low,
    idrec.da[4].low, idrec.da[5].low, idrec.da[6].low, idrec.da[7].low,
    idrec.da[8].low, idrec.da[9].low, idrec.da[10].low, idrec.da[11].low);
   --- */
   /* ---
   vpi_printf("  path at **%s(%d) has delay #(%d, %d).\n",
    vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
    idrec.da[0].low, idrec.da[1].low, idrec.da[2].low);
   --- */
  }
 /* timing checks */
 /* paths */
 /* drec.no_of_delays = 2; */
 idrec.time_type = vpiSimTime;
 /* drec.time_type = vpiScaledRealTime; */ 
 idrec.time_type = vpiScaledRealTime; 
 iter = vpi_iterate(vpiTchk, ihref);
 for (;;)
  {
   if ((href = vpi_scan(iter)) == NULL) break;
   tctyp = vpi_get(vpiTchkType, href);
   if (tctyp == vpiWidth || tctyp == vpiSetupHold) idrec.no_of_delays = 2;
   else idrec.no_of_delays = 1;
   vpi_get_delays(href, &idrec);
   get_tchknam(s1, tctyp);
   vpi_printf("  %s timing check at **%s(%d) limit %g.\n",
    s1, vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href), idrec.da[0].real);
   /* ---
   vpi_printf("  %s timing check at **%s(%d) 1st limit %d, 2nd limit %d.\n",
    s1, vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
    idrec.da[0].low, idrec.da[1].low);
   --- */    
  }
 return(0);
}

/*
 * notice need user routine - no str property
 */
char *get_tchknam(char *s, int ttyp)
{
 switch (ttyp) {
  case vpiSetup: strcpy(s, "$setup"); break;
  case vpiHold: strcpy(s, "$hold"); break;
  case vpiPeriod: strcpy(s, "$period"); break;
  case vpiWidth: strcpy(s, "$width"); break;
  case vpiSkew: strcpy(s, "$skew"); break;
  case vpiRecovery: strcpy(s, "$recovery"); break;
  case vpiNoChange: strcpy(s, "$nochange"); break;
  case vpiSetupHold: strcpy(s,  "$setuphold"); break;
  default: strcpy(s, "**out of range**");  break;
 } 
 return(s);
}

/*
 * routine to build an error indication string 
 */
int my_error_handler(struct t_cb_data *cbp)
{
 struct t_vpi_error_info einfotab;
 struct t_vpi_error_info *einfop;
 char s1[128];

 einfop = &einfotab;
 vpi_chk_error(einfop);

 if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
 else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
 else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
 else strcpy(s1, "**unknown**");

 vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
  einfop->code, s1, einfop->level, einfop->file, einfop->line,
  einfop->message);

 /* if serious error give up */
 if (einfop->level == vpiError || einfop->level == vpiSystem
  || einfop->level == vpiInternal)
  {
   vpi_printf("**FATAL: encountered error - giving up\n");
   vpi_sim_control(vpiFinish, 0);
  }
 return(0);
}


/* Template functin table for added user systf tasks and functions.
   See file vpi_user.h for structure definition
   Note only vpi_register_systf and vpi_ or tf_ utility routines that 
   do not access the simulation data base may be called from these routines
*/ 

/* all routines are called to register cbs */
/* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
/* before source is read */ 
void (*vlog_startup_routines[]) () =
{
 register_scan_cb, 
 0
};

/* routine to do the systf registering - probably should go in other file */
/* usually only vpi_ PLI 2.0 systf or cb registering is done here */

/*
 * register the start of sim scan call back and set up error handling
 *
 * notice making version of Cver that prints some stuff to start but
 * is a normal Cver 
 *
 * since handle not save (passed back?), no way to find out cb info
 */
void register_scan_cb(void)
{
 vpiHandle href, href2;
 struct t_cb_data *ecbp, *cbp;
 struct t_cb_data cbrec;

 /* notice cb records must be in global storage */
 ecbp = &cbrec;
 ecbp->reason = cbPLIError;
 ecbp->cb_rtn = my_error_handler; 
 ecbp->obj = NULL;
 ecbp->time = NULL;
 ecbp->value = NULL; 
 ecbp->user_data = NULL;

 /* probably should check for error here */
 if ((href = vpi_register_cb(ecbp)) == NULL)
  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");

 cbp = &cbrec;
 cbp->reason = cbStartOfSimulation;
 cbp->cb_rtn = process_all_insts;
 cbp->obj = NULL;
 cbp->time = NULL;
 cbp->value = NULL; 
 cbp->user_data = NULL;

 /* probably should check for error here */
 if ((href2 = vpi_register_cb(cbp)) == NULL)
  vpi_printf(
   "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
 /* if not registered will be no call backs */

 /* set the processing routine */
 iproc_rtn = prt_inst_delays;
}

/* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
/* in standard PLI vlog_startup_routines table */
void vpi_compat_bootstrap(void)
{
 int i;

 for (i = 0;; i++) 
  {
   if (vlog_startup_routines[i] == NULL) break; 
   vlog_startup_routines[i]();
  }
}