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.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.