7. VPI (Under developing from Version 2.16 )

Veritak supports very limited subset of VPI.
Figure below shows basic structure of using VPI.


7.1 VPI samples

7.1.1
You can see VPI samples on samples/vpi/ in installed package.
Let' run following sample projects.

first_callback.vtakprj



hello.vtakprj



callback_test.vtakprj



cbReadonlySynch_sample.vtakprj



print_nets.vtakprj



my_findwindow.vtakprj






my_cb_value.vtakprj




read_test_vector.vtakprj




 Here are VPI sources.

samples/vpi/vpi_sources/syst_table.c

# include  "vpi_user.h"

extern void sys_math_vpi_register(void);



__declspec(dllexport) void (*vlog_startup_routines[])() = {
      sys_math_vpi_register,
      0
};




samples/vpi/vpi_sources/math_vpi.cpp

//Jul.25.2006
//www.sugawara-systems.com
//Veritak VPI sample 

# include  "vpi_user.h"
#include "stdafx.h"
#include "shellapi.h"
//#include "KLdebug.h"
#include <math.h>
#include <stdlib.h>
# include  <string.h>
#include <assert.h>
#include <vector>
#include <fstream>
#include <iostream>
#include <strstream>
#include "time.h" //Jun.13.2006
# include  <iomanip> //setw
using namespace std;



//32bit 
static int sys_systems_size_tf(PLI_BYTE8*)//Aug.42003
{
        return 32;
}




static int sys_system_calltf(char*  name)
{
 
 vpiHandle systfref, argsiter, argh;
  t_vpi_value value;


                 systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
                 argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                 argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
             if(!argh){
                          vpi_printf("$VPI missing parameter.\n");
                          return 0;
                 }
                 
                value.format = vpiStringVal;
        vpi_get_value(argh, &value);
        char *s = value.value.str;
                
                 int result=system(s);//Do command on DOS!
                 
                 value.value.integer =result;
                 value.format = vpiIntVal;/* return the result */

                 vpi_put_value(systfref, &value, NULL, vpiNoDelay);
                 vpi_free_object(argsiter);

                return(0);
         
 }
 static int sys_shell_execute_calltf(char*  name)
{
 
 vpiHandle systfref, argsiter, argh;
  t_vpi_value value;


                 systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
                 argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                 argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
             if(!argh){
                          vpi_printf("$VPI missing parameter.\n");
                          return 0;
                 }
                 
                value.format = vpiStringVal;
        vpi_get_value(argh, &value);
        char *s = value.value.str;
                
                 //Do shell command on DOS!
                 int result=reinterpret_cast<int>(      ShellExecute(NULL, "open", s,
                   NULL, NULL, SW_SHOWNORMAL));
                 value.value.integer =result;//;
                 value.format = vpiIntVal;/* return the result */

                 vpi_put_value(systfref, &value, NULL, vpiNoDelay);
                 vpi_free_object(argsiter);

                return(0);
         
 }
 //Jun.11.2006
 static int sys_FindWindow_calltf(char*  name)
{
 
 vpiHandle systfref, argsiter, argh;
  t_vpi_value value;


                 systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
                 argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                 argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
             if(!argh){
                          vpi_printf("$VPI missing parameter.\n");
                          return 0;
                 }
                 
                value.format = vpiStringVal;
        vpi_get_value(argh, &value);
        char *s = value.value.str;
                while (*s==' '){//Skip space
                        s++;
                }
                

                 //Do shell command on DOS!
                 int result=reinterpret_cast<int>(FindWindow(NULL,s));
                 value.value.integer =result;//;
                 value.format = vpiIntVal;/* return the result */

                 vpi_put_value(systfref, &value, NULL, vpiNoDelay);
                 vpi_free_object(argsiter);

                return(0);
         
 }
 
 int sys_get_time_of_day(char*  name)
{
 
 vpiHandle systfref, argsiter, argh;
  t_vpi_value value;


                systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
                argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
            if(!argh){
                          vpi_printf("$VPI Error:sys_get_time_of_day.\n");
                          return 0;
                }
                if(vpi_get(vpiType, argh) !=vpiReg){ 
                          vpi_printf("$VPI Error:sys_get_time_of_day 1st parameter must be variable type.\n");
                          return 0;
                }
        unsigned wwid = vpi_get(vpiSize,argh);
        if (wwid%8!=0 || !wwid){
                         vpi_printf("$VPI Error:sys_get_time_of_day size of 1st parameter must be multiple of 8.\n");
                          return 0;
                        
                }       
                time_t timer;
         
                time(&timer);
                
#ifdef VC7
                char* buffer=ctime(&timer);//Get Local time. use new secure version
#else
                char buffer[27];
                ctime_s(buffer,27,&timer);//Get Local time. use new secure version
#endif          
                value.format =vpiStringVal;//Put by string
                value.value.str=buffer;
        
                vpi_put_value(argh, &value, NULL, vpiNoDelay);
                return(0);
         
 }
 

 
 //Jun.11.2006
 static int sys_Sleep_calltf(char*  name)
{
 
 vpiHandle systfref, argsiter, argh;
  
s_vpi_value value;

                 systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
                 argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                 
        
                
                argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
                if(!argh){
                                vpi_printf("$VPI sys_Sleep_calltf: missing parameter. \n");
//                               vpi_sim_control(vpiFinish, 1);
                                 
                                  return 0;
                                
                        }       
                value.format = vpiIntVal;
                vpi_get_value(argh, &value);
                Sleep(value.value.integer);//Wait val msec
                
                if(argh) vpi_free_object(argsiter);

                return(0);
         
 }
 
//Jun.11.2006 
 static int sys_PostMessage(char*  name)
{
 
 vpiHandle systfref, argsiter, argh;
  
  s_vpi_value value;

  systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
  argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                 
  unsigned message_parameter[4];        
  for (unsigned i=0;i<4;i++){                   
                argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
                if(!argh){
                                vpi_printf("$VPI sys_PostMessage: missing parameter. \n");
//                               vpi_sim_control(vpiFinish, 1);
                                 
                                  return 0;
                                
                        }       
                        
                value.format = vpiIntVal;
                vpi_get_value(argh, &value);
                message_parameter[i]=value.value.integer;
        }       
                
                
        ::PostMessage(reinterpret_cast<HWND>(message_parameter[0]),//handle
                                  message_parameter[1],//WM_COMMAND
                                  message_parameter[2],//WPARAM
                                  message_parameter[3]);//LPARAM
                                        
                
                if(argh) vpi_free_object(argsiter);

                return(0);
         
 }

static int sys_SendMessage(char*  name)
{
 
 vpiHandle systfref, argsiter, argh;
  
  s_vpi_value value;

  systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
  argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                 
  unsigned message_parameter[4];        
  for (unsigned i=0;i<4;i++){                   
                argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
                if(!argh){
                                vpi_printf("$VPI sys_SendMessage: missing parameter. \n");
//                               vpi_sim_control(vpiFinish, 1);
                                 
                                  return 0;
                                
                        }       
                        
                value.format = vpiIntVal;
                vpi_get_value(argh, &value);
                message_parameter[i]=value.value.integer;
        }       
                
                
 unsigned result=       ::SendMessage(reinterpret_cast<HWND>(message_parameter[0]),//handle
                                  message_parameter[1],//WM_COMMAND
                                  message_parameter[2],//WPARAM
                                  message_parameter[3]);//LPARAM
                                        
                
                if(argh) vpi_free_object(argsiter);
                
                 value.value.integer =result;//;
                 value.format = vpiIntVal;/* return the result */

                 vpi_put_value(systfref, &value, NULL, vpiNoDelay);
                 
                return(0);
         
 }
static int sys_MessageBox(char*  name)
{
 
 vpiHandle systfref, argsiter, argh;
  
  s_vpi_value value;

  systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
  argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                 
  
  unsigned message_id=0;
  string str_message;
  string str_caption;
  for (unsigned i=0;i<2;i++){                   
                argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
                if(!argh){
                                vpi_printf("$VPI sys_MessageBox: missing parameter. \n");
//                               vpi_sim_control(vpiFinish, 1);
                                 
                                  return 0;
                                
                        }       
                        
                value.format = vpiStringVal;
                vpi_get_value(argh, &value);
                if (i==0)               str_message=value.value.str;
                else if (i==1)  str_caption=value.value.str;

        }       
    argh = vpi_scan(argsiter);
        if (argh) {
                value.format = vpiIntVal;
                vpi_get_value(argh, &value);
                message_id=value.value.integer;
        }
        unsigned result=MessageBox(0,str_message.c_str(),
                                str_caption.c_str(),message_id);

                
                
 
                
                if(argh) vpi_free_object(argsiter);
                
                 value.value.integer =result;//;
                 value.format = vpiIntVal;/* return the result */

                 vpi_put_value(systfref, &value, NULL, vpiNoDelay);
                 
                return(0);
         
 }
#define CLOCK_HALF_CYCLE 50

static int clock_iterator(p_cb_data cb)
{

//Reserve next clock cycle
      struct t_vpi_time time;
          time.type = vpiSimTime;
      time.high = 0;
      time.low = CLOCK_HALF_CYCLE;
      struct t_cb_data new_cb;

      new_cb.reason = cbAfterDelay;
      new_cb.cb_rtn = clock_iterator;
      new_cb.time = &time;
      new_cb.obj = cb->obj;
        
          new_cb.value=0;
      new_cb.user_data = 0;
      vpi_register_cb(&new_cb);

        s_vpi_value value;
        value.format = vpiScalarVal;
        vpi_get_value(new_cb.obj, &value);
        value.value.scalar ^=1;
        vpi_put_value(cb->obj, &value, NULL, vpiNoDelay);//write inverted value clock=~clock;
        return 0;
}

static int load_iterator(p_cb_data cb)
{

        s_vpi_value value;
        value.format = vpiScalarVal;
        value.value.scalar =vpi0;
        vpi_put_value(cb->obj, &value, NULL, vpiNoDelay);//write inverted value clock=~clock;
        return 0;
}


static int callback(p_cb_data cb)
{
 s_vpi_time  now;
    s_vpi_value value;
         value.format = vpiIntVal;
         value.value.integer=255;
         vpi_put_value(cb->obj, &value, NULL, vpiNoDelay);
        
      now.type = vpiSimTime;
      vpi_get_time(0, &now);
          vpi_printf("callback r/w time=%d val=%d\n",now.low,value.value.integer);
          
          
          
          return 0;
}
static int callback_ab(p_cb_data cb)
{

s_vpi_time  now;
    s_vpi_value value;
         value.format = vpiIntVal;
         vpi_get_value(cb->obj, &value);
        
      now.type = vpiSimTime;
      vpi_get_time(0, &now);
          vpi_printf("callback ab time=%d val=%d\n",now.low,value.value.integer);
 
          return 0;
}

static int callback_ro(p_cb_data cb)
{

s_vpi_time  now;
    s_vpi_value value;
         value.format = vpiIntVal;
         vpi_get_value(cb->obj, &value);
        
      now.type = vpiSimTime;
      vpi_get_time(0, &now);
          vpi_printf("callback r/o time=%d val=%d\n",now.low,value.value.integer);

          return 0;
}
static int run_cb_test(char* name)
{
vpiHandle systfref, argsiter, argh;
  


  systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
  argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
  argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
   
//Reserve  reset=0 after CLOCK_HALF_CYCLEx5
s_vpi_time  time;

struct t_cb_data cb;
 cb.reason = cbReadOnlySynch;
      cb.cb_rtn = callback_ro;//next callback address
      cb.time = &time;
 time.type = vpiSimTime;
          time.high=0;
          time.low = 100;
      cb.obj =argh;
      cb.value = 0;
      cb.user_data = 0;
      vpi_register_cb(&cb);


          time.type = vpiSimTime;
      time.high = 0;
      time.low = 100;

      cb.reason = cbReadWriteSynch;
      cb.cb_rtn = callback;//next callback address
      cb.time = &time;
      cb.obj =argh;
      cb.value = 0;
      cb.user_data = 0;
      vpi_register_cb(&cb);

//struct t_cb_data cb;
      cb.reason = cbAtStartOfSimTime;
      cb.cb_rtn = callback_ab;//next callback address
      cb.time = &time;
          time.low = 200;
      cb.obj =argh;
      cb.value = 0;
      cb.user_data = 0;
      vpi_register_cb(&cb);


    
        return 0;
}

static int callback_cbReadOnlySynch(p_cb_data cb)
{

        s_vpi_time  now;
    s_vpi_value value;
        value.format = vpiIntVal;
        vpi_get_value(cb->obj, &value);
        
    now.type = vpiSimTime;
    vpi_get_time(0, &now);
        vpi_printf("callback_cbReadOnlySynch time=%d val=%d\n\n",now.low,value.value.integer);

   
        return 0;
}

static int callback_cbNextSimTime(p_cb_data cb)
{

        s_vpi_time  now;
    s_vpi_value value;
        value.format = vpiIntVal;
        vpi_get_value(cb->obj, &value);
        
    now.type = vpiSimTime;
    vpi_get_time(0, &now);
        vpi_printf("callback_cbNextSimTime time=%d val=%d\n",now.low,value.value.integer);

    struct t_cb_data new_cb;
        new_cb.reason = cbNextSimTime;
    new_cb.cb_rtn = callback_cbNextSimTime;//next callback address
    new_cb.time = 0;
    new_cb.obj = cb->obj;
    new_cb.value = 0;
    new_cb.user_data = 0;
    vpi_register_cb(&new_cb);
        

        struct t_cb_data new1_cb;
        new1_cb.reason = cbReadOnlySynch;
    new1_cb.cb_rtn = callback_cbReadOnlySynch;//next callback address
    s_vpi_time  now1;
        now1.type = vpiSuppressTime;
        now1.low=0;
        now1.high=0;

    new1_cb.time = &now1;//s_vpi_time definition is must. 
    new1_cb.obj = cb->obj;
    new1_cb.value = 0;
    new1_cb.user_data = 0;
    vpi_register_cb(&new1_cb);

        return 0;
}

static int next_time_cbReadOnlySynch_sample(char*name)
{
vpiHandle systfref, argsiter, argh;
  


  systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
  argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                 
                        
   argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
 
    
   if(argh){    
          struct t_cb_data cb;
          s_vpi_time  time;

          time.type = vpiSimTime;
      time.high = 0;
      time.low = 0;

      cb.reason = cbReadOnlySynch;
      cb.cb_rtn = callback_cbNextSimTime;//next callback address
      cb.time = &time;
      cb.obj = argh;
      cb.value = 0;
      cb.user_data = 0;
      vpi_register_cb(&cb);
          
   }
        return 0;
}


 static int run_test_port(char*  name)
{
 
 vpiHandle systfref, argsiter, argh;
  
  s_vpi_value value;

  systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
  argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                 
  
  vpiHandle clock_handle=0;
  vpiHandle load_handle=0;
  vpiHandle reset_handle=0;
  
  for (unsigned i=0;i<4;i++){                   
                argh = vpi_scan(argsiter);/* get the one argument - add loop for more args */
                if(!argh){
                                vpi_printf("$VPI run_test_port: missing parameter. \n");
                                 vpi_sim_control(vpiFinish, 1);
                                 
                                  return 0;
                                
                        }       
                string str=vpi_get_str(vpiName,argh);
                if(vpi_get(vpiType, argh) !=vpiReg){ 
                          vpi_printf("$VPI Error:run_test_port requires variable type of parameter.\n");
                          vpi_sim_control(vpiFinish, 1);                        
                          return 0;
                }
                if (!str.compare("clock")) {
                        
                        value.value.scalar=vpi0;
                        value.format=vpiScalarVal;
                        vpi_put_value(argh, &value, NULL, vpiNoDelay);//write clock=0;
                        clock_handle=argh;//for save
                }else if (!str.compare("reset")){ 
                        value.value.scalar=vpi1;
                        value.format=vpiScalarVal;
                        vpi_put_value(argh, &value, NULL, vpiNoDelay);//write reset=1;
                        reset_handle=argh;
                }else if (!str.compare("load")){ 
                        value.value.scalar=vpi1;
                        value.format=vpiScalarVal;
                        vpi_put_value(argh, &value, NULL, vpiNoDelay);//write load=0;
                        load_handle=argh;
                }else if(!str.compare("load_data")){
                        unsigned wwid = vpi_get(vpiSize, argh);
                        value.format=vpiVectorVal;
                        unsigned words=(wwid+31)/32;
                        value.value.vector =(t_vpi_vecval*) calloc(words, sizeof(s_vpi_vecval));//
                        for (unsigned i=0;i<words;i++){
                                value.value.vector[i].aval=0xabcdffff;//Initialize abcdffff as initial counter value
                                value.value.vector[i].bval=0;
                        }
                        vpi_put_value(argh, &value, NULL, vpiNoDelay);//write load_data=0;
                        free(value.value.vector);//free vector
                }
        }       
  if (!load_handle || !reset_handle || !clock_handle) {
                vpi_printf("$VPI Error:run_test_port some parameter is missing.\n");
            vpi_sim_control(vpiFinish, 1);                      
            return 0;
  }

        if(argh) vpi_free_object(argsiter);

//Reserve next clock cycle
      struct t_vpi_time time;
          time.type = vpiSimTime;
      time.high = 0;
      time.low = CLOCK_HALF_CYCLE;
          struct t_cb_data cb;

      cb.reason = cbAfterDelay;
      cb.cb_rtn = clock_iterator;//next callback address
      cb.time = &time;
      cb.obj = clock_handle;
      cb.value = 0;
      cb.user_data = 0;
      vpi_register_cb(&cb);

//Reserve  reset=0 after CLOCK_HALF_CYCLEx5
          time.type = vpiSimTime;
      time.high = 0;
      time.low = CLOCK_HALF_CYCLE*6;

      cb.reason = cbAfterDelay;
      cb.cb_rtn = load_iterator;//next callback address
      cb.time = &time;
      cb.obj = reset_handle;
      cb.value = 0;
      cb.user_data = 0;
      vpi_register_cb(&cb);


//Reserve  load=0 after CLOCK_HALF_CYCLEx11
          time.type = vpiSimTime;
      time.high = 0;
      time.low = CLOCK_HALF_CYCLE*12;

      cb.reason = cbAfterDelay;
      cb.cb_rtn = load_iterator;//next callback address
      cb.time = &time;
      cb.obj = load_handle;
      cb.value = 0;
      cb.user_data = 0;
      vpi_register_cb(&cb);



        return(0);
         
 }

static int sys_end_of_simulation(p_cb_data cb_data)
{
     vpi_printf("Simulation Finished. Reported by vpi. Good Bye.. \n\n");
      return 0;
}  

static int sys_start_of_simulation(p_cb_data cb_data)
{
     vpi_printf("Simulation Starts. Reported by vpi. Thanks a lot..\n\n");
      return 0;
}  

static int sys_hello(char* name)
{
     vpi_printf("Hello! Verilog VPI world.\n");
      return 0;
}  



static void print_net_in_module(vpiHandle module_handle)
{
        char* module_name   = vpi_get_str(vpiName, module_handle);
        vpi_printf("module %s has :\n",module_name);
        //vpiNet
    vpiHandle net_iterator=vpi_iterate(vpiNet,module_handle);
        vpi_printf("    vpiNet:\n");
        if(net_iterator){
                while( vpiHandle netHandle = vpi_scan(net_iterator)){
                        string NetFullName = vpi_get_str(vpiFullName, netHandle);//prepare another string buffer for another vpi operation
                        string NetName=vpi_get_str(vpiName,netHandle);//prepare another string buffer for another vpi operation
                        vpi_printf("            %s %s\n",NetFullName.c_str(),NetName.c_str());
                        
                        //Check by vpi_handle_by_name function
                        
                        vpiHandle net= vpi_handle_by_name(const_cast<char*>(NetFullName.c_str()),(vpiHandle) NULL);
                        string  NetFullName2=vpi_get_str(vpiFullName,net);
                        if (NetFullName.compare(NetFullName2)){
                                assert(0);
                        }
                }
        }else {
                vpi_printf("            No nets.\n");
        }

        {//vpiReg
         vpiHandle net_iterator=vpi_iterate(vpiReg,module_handle);
         vpi_printf("   vpiReg:\n");
         if(net_iterator){
                while( vpiHandle netHandle = vpi_scan(net_iterator)){
                        string NetFullName = vpi_get_str(vpiFullName, netHandle);
                        string NetName=vpi_get_str(vpiName,netHandle);
                        vpi_printf("            %s %s\n",NetFullName.c_str(),NetName.c_str());
                        
                }
         }else {
                vpi_printf("            No variable.\n");
         }
        }

        vpi_printf("\n");
}
static int printModules(char *){

     vpiHandle topModIterator;
     vpiHandle topModHandle;
    
   
  
     
     /* create a module iterator that starts at the top  as indicated by NULL */
     topModIterator = vpi_iterate(vpiModule,NULL);
     
     if( !topModIterator ){
                return 0;
     }

     /* use vpi_scan to iterate throught modules */
     while( topModHandle = vpi_scan(topModIterator)){
                print_net_in_module(topModHandle);
                vpiHandle module_iterator=vpi_iterate(vpiModule,topModHandle);
                if (module_iterator){
                        vpiHandle module_handle;
                        while (module_handle=vpi_scan(module_iterator)){
                                print_net_in_module(module_handle);
                        }
                }       
        }
        return 0;
}

//Jul.23.2006
static int my_cb_1(p_cb_data cb)
{
      
       vpi_printf("Time %5.3f: %s = %s\n",
             cb->time->real,
             cb->user_data,
             cb->value->value.str);
      return 0;
}


 static int my_cb_change(char*  name)//Jul.19.2006
{
 
 vpiHandle systfref, argsiter, argh;
  
  s_vpi_value value;

  systfref = vpi_handle(vpiSysTfCall, NULL); /* get system function that invoked C routine */
  argsiter = vpi_iterate(vpiArgument, systfref);/* get iterator (list) of passed arguments */
                 
  while (argh = vpi_scan(argsiter)){    /* get the one argument - add loop for more args */
      unsigned type=vpi_get(vpiType,argh);
          if (type !=vpiReg && //
                  type !=vpiNet &&  
                  type !=vpiIntegerVar &&
                  type !=vpiTimeVar//
                  ) {
                        vpi_printf("invalid arguments in $my_monitor.%d\n",type);
                         vpi_sim_control(vpiFinish, 1);
          }
      struct t_cb_data cb;
          s_vpi_time  now;
          
          now.type       = vpiScaledRealTime;
      value.format    = vpiBinStrVal;
      cb.reason = cbValueChange;
      cb.cb_rtn = my_cb_1;//next callback address
      cb.time = &now;
      cb.obj = argh;
      cb.value = &value;
          char* net_name = vpi_get_str(vpiFullName, argh);
      cb.user_data = strdup(net_name);//allocate and copy
      vpi_register_cb(&cb);

  }
        return(0);
         
 }

 
int my_read_test_vector(p_cb_data cb_data)//Jul.24.2006
{
        vpiHandle topModIterator;
        vpiHandle topModHandle;
    s_vpi_vlog_info  options_s;
        s_vpi_value value;
        
        bool go_this_routine=false;
        bool debug=false;
    vpi_get_vlog_info(&options_s);
        for (int i=1; i<options_s.argc; i++) {
                string temp=options_s.argv[i];
        if (strcmp(options_s.argv[i], "+DEBUG_VPI") == 0) {
                debug = true; ///flag on
                
        }
                if (strcmp(options_s.argv[i], "+READ_TEST_VECTOR") == 0) {
                go_this_routine = true; ///flag on
                
        }
                
        }
        if (!go_this_routine) return 0;//Stop further processing if +READ_TEST_VECTOR is not defined at command line. See "Edit Display" of the project 

        
        /* create a module iterator that starts at the top  as indicated by NULL */
     topModIterator = vpi_iterate(vpiModule,NULL);
     
     if( !topModIterator ){
                return 0;
     }

     /* use vpi_scan to iterate throught modules */
     topModHandle = vpi_scan(topModIterator);
         if (!topModHandle) return 0;
         string top_module_name=vpi_get_str(vpiDefName,topModHandle);
                        
         if (debug) {
                vpi_printf("Top module name=%s\n",top_module_name.c_str());     
         }      
         

         string clock=top_module_name;
         clock+=".";
         clock+="clock";
         vpiHandle clock_handle=vpi_handle_by_name((char*)clock.c_str(),topModHandle);
         if (!clock_handle){
                vpi_printf("Missing =%s\n",clock.c_str());      
                return 0;
         }      
         
         string load=top_module_name;
         load+=".";
         load+="load";
         vpiHandle load_handle=vpi_handle_by_name((char*)load.c_str(),topModHandle);
         if (!load_handle){
                vpi_printf("Missing =%s\n",load.c_str());
                return 0;
         }      

         string load_data=top_module_name;
         load_data +=".";
         load_data+="load_data";
         vpiHandle load_data_handle=vpi_handle_by_name((char*)load_data.c_str(),topModHandle);
         if (!load_data_handle){
                vpi_printf("Missing =%s\n",load_data.c_str());
                return 0;
         }      
 
         string reset=top_module_name;
         reset +=".";
         reset +="reset";
         vpiHandle reset_handle=vpi_handle_by_name((char*)reset.c_str(),topModHandle);
         if (!reset_handle){
                vpi_printf("Missing =%s\n",reset.c_str());      
                return 0;
         }      
         string file_name="read_vector.txt";
         FILE* fp=fopen(file_name.c_str(),"r");
         if (!fp) {
                vpi_printf("Missing=%s\n",file_name.c_str());   
         }      
         char buffer[1000];
         string o_clock,o_reset,o_load,o_load_data;
         while (1) {
                if(fgets(buffer,1000,fp) ==NULL) break;
                char clock_char[4];
                char reset_char[4];
                char load_char[4];
                char load_data_char[100];
                unsigned t;
                sscanf(buffer,"%d:%[^','],%[^','],%[^','],%[^';']",&t,clock_char,reset_char,load_char,load_data_char);//Use delimiter
                
                if (debug) {
                        vpi_printf("%s\n",buffer);
                }
                
                string clock_str=clock_char;
                string reset_str=reset_char;
                string load_str=load_char;
                string load_data_str=load_data_char;

                s_vpi_time       time_s;

                time_s.type      = vpiSimTime;
                time_s.low       = t;
                time_s.high      = 0;

                if (clock_str.compare(o_clock)){//Only changed value makes scheduling.No changed value makes no scheduling.
                                o_clock=clock_str;
                                value.format = vpiBinStrVal;
                                value.value.str =clock_char;
                                vpi_put_value(clock_handle, &value, &time_s, vpiTransportDelay);

                }
                if (reset_str.compare(o_reset)){
                                o_reset=reset_str;
                                
                                value.format = vpiBinStrVal;
                                value.value.str =reset_char;
                                vpi_put_value(reset_handle, &value, &time_s, vpiTransportDelay);

                }

                if (load_str.compare(o_load)){
                                o_load=load_str;
                                value.format = vpiBinStrVal;
                                value.value.str =load_char;
                                vpi_put_value(load_handle, &value, &time_s, vpiTransportDelay);

                }
                if (load_data_str.compare(o_load_data)){
                                o_load_data=load_data_str;
                                value.format = vpiHexStrVal;
                                value.value.str =load_data_char;
                                vpi_put_value(load_data_handle, &value, &time_s, vpiTransportDelay);

                }
         }
        return(0);
         
 }

//work struct
struct read_test_vector_work {
         read_test_vector_work(){
                        fp=0;
                        debug=false;
                        previous_time.low=0;
                        previous_time.high=0;
                        previous_time.type=vpiSimTime;
         }

         struct handle_format{
                        vpiHandle handle;
                        int format;
                        string name;
                        
         };

 
         FILE* fp;
         vector<handle_format> vpi_handles;
         bool debug;
         s_vpi_time  previous_time;

 };
int do_last_time_slot(p_cb_data cb_data)
{
         vpi_printf("Ending.. \n");
         vpi_sim_control(vpiFinish, 1);
         return 0;                               

}
void read_line(read_test_vector_work* work_ptr);

int Read_Next_line(p_cb_data cb_data)//Jul.24.2006
{
         read_test_vector_work* work_ptr=(read_test_vector_work* )(cb_data->user_data);
         read_line(work_ptr);
         return 0;
}

void read_line(read_test_vector_work* work_ptr)
{
        FILE* fp=work_ptr->fp;
        bool debug=work_ptr->debug;
    s_vpi_value value;
        s_cb_data        data_s;
    char buffer[1000];
         
        if(fgets(buffer,1000,fp) ==NULL) {
                
                data_s.reason    = cbReadOnlySynch;
                data_s.cb_rtn    = do_last_time_slot;
                data_s.obj       = 0; 
                data_s.time      = 0;
                data_s.value     = 0;
                data_s.user_data = 0;
                vpi_register_cb(&data_s);
                return ;
        }
                char clock_char[4];
                char reset_char[4];
                char load_char[4];
                char load_data_char[100];
                unsigned t;
                sscanf(buffer,"%d:%[^','],%[^','],%[^','],%[^';']",&t,clock_char,reset_char,load_char,load_data_char);//Use delimiter
                
                if (debug) {
                        vpi_printf("%s\n",buffer);
                }
                
                

                s_vpi_time       time_s;

                time_s.type      = vpiSimTime;
                time_s.low       = t-work_ptr->previous_time.low;//Set relative time
                time_s.high      = 0;
                
                work_ptr->previous_time.low=t;

                for (unsigned i=0;i<  work_ptr->vpi_handles.size();i++){
                        value.format = work_ptr->vpi_handles[i].format;
                        switch (i) {
                                case(0):value.value.str =clock_char; break;
                                case(1):value.value.str =reset_char; break;
                                case(2):value.value.str =load_char; break;
                                case(3):value.value.str =load_data_char; break;
                                default: assert(0);
                        }
                        
                        vpi_put_value(work_ptr->vpi_handles[i].handle, &value, &time_s, vpiTransportDelay);
                }
                
                
                /* schedule callback to this routine when time to read next vector */
  

                        
  data_s.reason    = cbAfterDelay;
  data_s.cb_rtn    = Read_Next_line;
  data_s.obj       = 0; 
  data_s.time      = &time_s;
  data_s.value     = NULL;
  data_s.user_data = reinterpret_cast<char *>(work_ptr);//
  vpi_register_cb(&data_s);
            
}
int my_read_test_vector_long(p_cb_data cb_data)//Jul.24.2006
{
        vpiHandle topModIterator;
        vpiHandle topModHandle;
    s_vpi_vlog_info  options_s;
        s_vpi_value value;
        
        bool go_this_routine=false;
        bool debug=false;
    vpi_get_vlog_info(&options_s);
        for (int i=1; i<options_s.argc; i++) {
                string temp=options_s.argv[i];
        if (strcmp(options_s.argv[i], "+DEBUG_VPI") == 0) {
                debug = true; ///flag on
                
        }
                if (strcmp(options_s.argv[i], "+READ_TEST_VECTOR_LONG") == 0) {
                go_this_routine = true; ///flag on
                
        }
                
        }
        if (!go_this_routine) return 0;//Stop further processing if +READ_TEST_VECTOR is not defined at command line. See "Edit Display" of the project 

        
        /* create a module iterator that starts at the top  as indicated by NULL */
     topModIterator = vpi_iterate(vpiModule,NULL);
     
     if( !topModIterator ){
                return 0;
     }

     /* use vpi_scan to iterate throught modules */
     topModHandle = vpi_scan(topModIterator);
         if (!topModHandle) return 0;
         string top_module_name=vpi_get_str(vpiDefName,topModHandle);
                        
         if (debug) {
                vpi_printf("Top module name=%s\n",top_module_name.c_str());     
         }      
         

         string clock=top_module_name;
         clock+=".";
         clock+="clock";
         vpiHandle clock_handle=vpi_handle_by_name((char*)clock.c_str(),topModHandle);
         if (!clock_handle){
                vpi_printf("Missing =%s\n",clock.c_str());      
                return 0;
         }      
         
         string load=top_module_name;
         load+=".";
         load+="load";
         vpiHandle load_handle=vpi_handle_by_name((char*)load.c_str(),topModHandle);
         if (!load_handle){
                vpi_printf("Missing =%s\n",load.c_str());
                return 0;
         }      

         string load_data=top_module_name;
         load_data +=".";
         load_data+="load_data";
         vpiHandle load_data_handle=vpi_handle_by_name((char*)load_data.c_str(),topModHandle);
         if (!load_data_handle){
                vpi_printf("Missing =%s\n",load_data.c_str());
                return 0;
         }      
 
         string reset=top_module_name;
         reset +=".";
         reset +="reset";
         vpiHandle reset_handle=vpi_handle_by_name((char*)reset.c_str(),topModHandle);
         if (!reset_handle){
                vpi_printf("Missing =%s\n",reset.c_str());      
                return 0;
         }      
         string file_name="read_vector.txt";
         FILE* fp=fopen(file_name.c_str(),"r");
         if (!fp) {
                vpi_printf("Missing=%s\n",file_name.c_str());   
         }      

         //Now initial check complete
        //Make some work area
        read_test_vector_work * work_ptr=new read_test_vector_work;
        work_ptr->fp=fp;
        read_test_vector_work::handle_format hf;

        hf.format=vpiBinStrVal;
        hf.name="clock";
        hf.handle=clock_handle;
        work_ptr->vpi_handles.push_back(hf);

    hf.format=vpiBinStrVal;
        hf.name="reset";
        hf.handle=reset_handle;
        work_ptr->vpi_handles.push_back(hf);

    hf.format=vpiBinStrVal;
        hf.name="load";
        hf.handle=load_handle;
        work_ptr->vpi_handles.push_back(hf);

    hf.format=vpiHexStrVal;
        hf.name="load_data";
        hf.handle=load_data_handle;
        work_ptr->vpi_handles.push_back(hf);

        read_line(work_ptr);
        
        return(0);
         
 }

extern "C" void sys_math_vpi_register()//VPI call/callback register routine
{
      s_vpi_systf_data tf_data;

      tf_data.type      = vpiSysFunc;//
      tf_data.sysfunctype =vpiIntFunc;//
      tf_data.tfname    = "$system";
      tf_data.user_data = "$system";
      tf_data.calltf    = sys_system_calltf;
      tf_data.compiletf = 0;
      tf_data.sizetf    = sys_systems_size_tf;//
      vpi_register_systf(&tf_data);

      tf_data.type      = vpiSysFunc;//Define as function
      tf_data.sysfunctype       =vpiIntFunc;//return by integer
      tf_data.tfname    = "$shell_execute";
      tf_data.user_data = "$shell_execute";
      tf_data.calltf    = sys_shell_execute_calltf;
      tf_data.compiletf = 0;
      tf_data.sizetf    = sys_systems_size_tf;//func
      vpi_register_systf(&tf_data);
    
      tf_data.type      =vpiSysFunc;//Function Jun.11.2006
      tf_data.sysfunctype       =vpiIntFunc;//return by integer
      tf_data.tfname    = "$FindWindow";
      tf_data.user_data = "$FindWindow";
      tf_data.calltf    = sys_FindWindow_calltf;
      tf_data.compiletf = 0;
      tf_data.sizetf    = sys_systems_size_tf;//func
          vpi_register_systf(&tf_data);

          tf_data.type      = vpiSysTask;//Task Jun.11.2006
      tf_data.tfname    = "$Sleep";
      tf_data.user_data = "$Sleep";
      tf_data.calltf    = sys_Sleep_calltf;
      tf_data.compiletf = 0;
      vpi_register_systf(&tf_data);

          tf_data.type      = vpiSysTask;//Task Jun.11.2006
      tf_data.tfname    = "$PostMessage";
      tf_data.user_data = "$PostMessage";
      tf_data.calltf    = sys_PostMessage;
      tf_data.compiletf = 0;
      vpi_register_systf(&tf_data);

      tf_data.type      = vpiSysTask;//Task Jun.11.2006
      tf_data.tfname    = "$GetTimeofDay";
      tf_data.user_data = "$GetTimeofDay";
      tf_data.calltf    = sys_get_time_of_day;//call address
      tf_data.compiletf = 0;
      vpi_register_systf(&tf_data);

      tf_data.type      = vpiSysTask;//Task Jun.15.2006
      tf_data.tfname    = "$Hello";
      tf_data.user_data = "$Hello";
      tf_data.calltf    = sys_hello;//call address
      tf_data.compiletf = 0;
      vpi_register_systf(&tf_data);

      s_cb_data cb_data;
          cb_data.time=0;//
          cb_data.value=0;//
          
          
// cbStartOfSimulation

          cb_data.reason = cbStartOfSimulation;
      cb_data.cb_rtn = sys_start_of_simulation;
      cb_data.user_data = 0;
      vpi_register_cb(&cb_data);//register callback

// cbEndOfSimulation
          cb_data.reason = cbEndOfSimulation;
      cb_data.cb_rtn = sys_end_of_simulation;
      cb_data.user_data = 0;
      vpi_register_cb(&cb_data);//register callback

      tf_data.type      = vpiSysTask;//Task Jun.11.2006
      tf_data.tfname    = "$run_test_port";
      tf_data.user_data = "$run_test_port";
      tf_data.calltf    = run_test_port;
      tf_data.compiletf = 0;
      vpi_register_systf(&tf_data);

          tf_data.type      = vpiSysTask;//Task Jun.11.2006
      tf_data.tfname    = "$run_cb_test";
      tf_data.user_data = "$run_cb_test";
      tf_data.calltf    = run_cb_test;
      tf_data.compiletf = 0;
      vpi_register_systf(&tf_data);

  

//next_time_cbReadOnlySynch_sample

  tf_data.type      = vpiSysTask;
  tf_data.tfname    = "$cbReadOnlySynch_sample";
  tf_data.calltf    = next_time_cbReadOnlySynch_sample;
  tf_data.compiletf = NULL;
  tf_data.sizetf    = NULL;
  tf_data.user_data = "$cbReadOnlySynch_sample";
  vpi_register_systf(&tf_data);



//$PrintNets
      tf_data.type      = vpiSysTask;
      tf_data.tfname    = "$PrintNets";
      tf_data.calltf    = printModules;
      tf_data.compiletf = 0;
      tf_data.sizetf    = 0;
      vpi_register_systf(&tf_data);

//Jul.11.2006
      tf_data.type      =vpiSysFunc;//
      tf_data.sysfunctype       =vpiIntFunc;//
      tf_data.tfname    = "$SendMessage";
      tf_data.user_data = "$SendMessage";
      tf_data.calltf    = sys_SendMessage;
      tf_data.compiletf = 0;
      tf_data.sizetf    = sys_systems_size_tf;//func
          vpi_register_systf(&tf_data);

      tf_data.type      =vpiSysFunc;//
      tf_data.sysfunctype       =vpiIntFunc;//
      tf_data.tfname    = "$MessageBox";
      tf_data.user_data = "$MessageBox";
      tf_data.calltf    = sys_MessageBox;
      tf_data.compiletf = 0;
      tf_data.sizetf    = sys_systems_size_tf;//func
          vpi_register_systf(&tf_data);


//Jul.23.2006     
          tf_data.type      = vpiSysTask;
      tf_data.tfname    = "$MyCB_Change";
      tf_data.calltf    = my_cb_change;
      tf_data.compiletf = 0;
      tf_data.sizetf    = 0;
      vpi_register_systf(&tf_data);

 //Jul.23.2006    
          cb_data.reason = cbStartOfSimulation;
      cb_data.cb_rtn = my_read_test_vector;
      cb_data.user_data = 0;
          tf_data.compiletf = 0;
          tf_data.sizetf    = 0;
      vpi_register_cb(&cb_data);//register callback


//Jul.24.2006     
          cb_data.reason = cbStartOfSimulation;
      cb_data.cb_rtn = my_read_test_vector_long;
      cb_data.user_data = 0;
          tf_data.compiletf = 0;
          tf_data.sizetf    = 0;
      vpi_register_cb(&cb_data);//register callback
}

7.1.2 Callback implementation in Veritak

 See code sample ,samples/vpi/mycosim/shared_class/shared_file.cpp



7.2 Supported Compiler/Deliverables
 
Supported Compiler: Visual C++ Only
 
 vpi_user.h : header file -samples/vpi/vpi_source
 veritak2.lib: import library file -samples/vpi/vpi_source
 sys_table.c: sample vpi source for mydll5.dll -samples/vpi/vpi_source
 math_vpi.cpp: sample vpi source for mydll5.dll -samples/vpi/vpi_source

7.3 How to use Visual C++ Express Edition

In Visual C++ Express Edition needs some patch described below.

http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/default.aspx

This patch is required to in order to build DLL as VPI for Express Edition.
(If you have purchased edition, it is not necessary.)

How to make DLL
If you have installed Visual C++ express edition successfully, then Let's make DLL by sample source.

Select Win32 Console Application




Select DLL, and press Finish.




You should see following screen.

It depends on your debugging environment.
But one option is to copy all vpi_sources files to debug folder on Visual c++.

Then add sources on Visual C++ project as follows.





Press No.




Open property window on mydll5 project

Set Precompiled header as follows.





This is veritak unique, but set Struct Member Alighnment by 4 as follows.

User multi-byte character set.








Now all the settings are finished! Let's build mydll5.dll


How to debug mydll5.dll

You need to invoke DLL from Simulation Engine of veritak2.exe.
For simplicity of explanations, the following config. is assumed here in tutorial.




For example, if you run the sample project, print_nets.vtakprj, you will see veritak_command.txt in the same folder.
This is a text file that GUI passes the command line to simulation engine veritak2.exe.
Copy & paste the arguments, that makes to be easier to invoke debugger on Visual C++.




Set mydll5's debug property as follows.

Command: veritak2.exe
Command Arguments: Copy & Paste above
Working Directory : folder above



Set appropriate breakpoint.
Start Debug!



Since no debug symbols of Veritak2.exe cannot be found ,the following will be displayed.
Press Yes.



Here comes the breakpoint.
Now debug your own source.


Note1:Please exit GUI, VeritakWin.exe in case of debugging.. If this process exists, any debugging is impossible.
Note2:The sample project of DLL name was changed from 3.01A to my_vpi5.dll.@

How to add DLL to veritak project


It is very simple like normal source addition.
Set Files of type => all files.

Add "mydll5.dll" to the project just like normal source file.