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.
