OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [verilog/] [vpi/] [c/] [jp_vpi.c] - Diff between revs 40 and 46

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 40 Rev 46
/*$$HEADER*/
/*$$HEADER*/
/******************************************************************************/
/******************************************************************************/
/*                                                                            */
/*                                                                            */
/*                    H E A D E R   I N F O R M A T I O N                     */
/*                    H E A D E R   I N F O R M A T I O N                     */
/*                                                                            */
/*                                                                            */
/******************************************************************************/
/******************************************************************************/
 
 
// Project Name                   : ORPSoCv2
// Project Name                   : ORPSoCv2
// File Name                      : jp_vpi.c
// File Name                      : jp_vpi.c
// Prepared By                    : jb, jb@orsoc.se
// Prepared By                    : jb, jb@orsoc.se
// Project Start                  : 2009-05-01
// Project Start                  : 2009-05-01
 
 
/*$$COPYRIGHT NOTICE*/
/*$$COPYRIGHT NOTICE*/
/******************************************************************************/
/******************************************************************************/
/*                                                                            */
/*                                                                            */
/*                      C O P Y R I G H T   N O T I C E                       */
/*                      C O P Y R I G H T   N O T I C E                       */
/*                                                                            */
/*                                                                            */
/******************************************************************************/
/******************************************************************************/
/*
/*
  This library is free software; you can redistribute it and/or
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation;
  License as published by the Free Software Foundation;
  version 2.1 of the License, a copy of which is available from
  version 2.1 of the License, a copy of which is available from
  http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
  http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
 
 
  This library is distributed in the hope that it will be useful,
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
  Lesser General Public License for more details.
 
 
  You should have received a copy of the GNU Lesser General Public
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
*/
 
 
/*$$DESCRIPTION*/
/*$$DESCRIPTION*/
/******************************************************************************/
/******************************************************************************/
/*                                                                            */
/*                                                                            */
/*                           D E S C R I P T I O N                            */
/*                           D E S C R I P T I O N                            */
/*                                                                            */
/*                                                                            */
/******************************************************************************/
/******************************************************************************/
//
//
// Implements communication between verilog simulator and RSP server
// Implements communication between verilog simulator and RSP server
//
//
//
//
/*
/*
Functions used via the Verilog Procedural Interface (VPI), in a verilog
Functions used via the Verilog Procedural Interface (VPI), in a verilog
simulation of an OpenRISC processor, providing a means of communication to the
simulation of an OpenRISC processor, providing a means of communication to the
simulatin for a GDB stub.
simulatin for a GDB stub.
 
 
The communication between the GDB stub and this module is via a "custom"
The communication between the GDB stub and this module is via a "custom"
protocol, which is decoded into the verilog debug task module and the
protocol, which is decoded into the verilog debug task module and the
appropriate transactions are performed with the debug interface inside the
appropriate transactions are performed with the debug interface inside the
OpenRISC design.
OpenRISC design.
 
 
Operation:
Operation:
See the verilog file containing the calls to the VPI tasks  we outline in this
See the verilog file containing the calls to the VPI tasks  we outline in this
file for exact details of how they are  used (debug_vpi_module.v), but
file for exact details of how they are  used (debug_vpi_module.v), but
following is a brief outline of how it is meant to work.
following is a brief outline of how it is meant to work.
 
 
The RSP GDB stub is initialised after compile via a VPI callback
The RSP GDB stub is initialised after compile via a VPI callback
(cbEndOfCompile). A process is forked off to run the RSP server, and IPC is via
(cbEndOfCompile). A process is forked off to run the RSP server, and IPC is via
pipes. Note: This is probably an extremely ineffecient way to do this as the
pipes. Note: This is probably an extremely ineffecient way to do this as the
fork() creates a copy of the program, including it's ~200MB memory space, so
fork() creates a copy of the program, including it's ~200MB memory space, so
maybe a different method should be worked out for massive sims, but for smaller
maybe a different method should be worked out for massive sims, but for smaller
OpenRISC designs on a power machine this is not a problem.
OpenRISC designs on a power machine this is not a problem.
 
 
The verilog debug module polls for incoming commands from the GDB stub at a
The verilog debug module polls for incoming commands from the GDB stub at a
#delay rate set in the verilog code.
#delay rate set in the verilog code.
 
 
The port which the GDB server runs on is #define'd in this file by
The port which the GDB server runs on is #define'd in this file by
RSP_SERVER_PORT.
RSP_SERVER_PORT.
 
 
When a GDB connection is established, the state of the processor is downloaded
When a GDB connection is established, the state of the processor is downloaded
by GDB, so expect a slight delay after connection.
by GDB, so expect a slight delay after connection.
 
 
To close down the simulation gracefully, issue a "detach" command from GDB.
To close down the simulation gracefully, issue a "detach" command from GDB.
This will close the connection with the stub and will also send a message to
This will close the connection with the stub and will also send a message to
$finish the simulation.
$finish the simulation.
 
 
Note: Simulation reset is untested, but should probably work OK.
Note: Simulation reset is untested, but should probably work OK.
 
 
Note: Reading uninitialised memory which returns Xs will break things.
Note: Reading uninitialised memory which returns Xs will break things.
Specifically, the CRC generation breaks, and then many other things. So to help
Specifically, the CRC generation breaks, and then many other things. So to help
avoid hours of X tracing, ensure you're reading initialised space from GDB.
avoid hours of X tracing, ensure you're reading initialised space from GDB.
 
 
To Do:
To Do:
* Comment this better! Sorry, it's a little lacking in this area.
* Comment this better! Sorry, it's a little lacking in this area.
* Block transfers (ie. what happens when "load"ing from GDB) ignore any bytes
* Block transfers (ie. what happens when "load"ing from GDB) ignore any bytes
  over the word boundary at the end of a transfer. Currently a warning printf
  over the word boundary at the end of a transfer. Currently a warning printf
  will appear.
  will appear.
* Make the RSP server process not be a complete copy of the vvp image - ie.
* Make the RSP server process not be a complete copy of the vvp image - ie.
  don't fork() in the sim, maybe compile and exec() a separate app for this.
  don't fork() in the sim, maybe compile and exec() a separate app for this.
 
 
*/
*/
 
 
 
 
/* EXAMPLE
/* EXAMPLE
// Associate C Function with a New System Task
// Associate C Function with a New System Task
voi
voi
d registerHelloSystfs() {
d registerHelloSystfs() {
  s_vpi_systf_data task_data_s;
  s_vpi_systf_data task_data_s;
  p_vpi_systf_data task_data_p = &task_data_s;
  p_vpi_systf_data task_data_p = &task_data_s;
  task_data_p->type = vpiSysTask;
  task_data_p->type = vpiSysTask;
  task_data_p->tfname = "$hello";
  task_data_p->tfname = "$hello";
  task_data_p->calltf = hello;
  task_data_p->calltf = hello;
  task_data_p->compiletf = 0;
  task_data_p->compiletf = 0;
 
 
  vpi_register_systf(task_data_p);
  vpi_register_systf(task_data_p);
}
}
 
 
*/
*/
 
 
 
 
/*
/*
To associate your C function with a system task, create a
To associate your C function with a system task, create a
data structure of type s_vpi_systf_data and a pointer to
data structure of type s_vpi_systf_data and a pointer to
that structure. The vpi_systf_data data type is defined in
that structure. The vpi_systf_data data type is defined in
the vpi_user.h include file. Below is the data structure
the vpi_user.h include file. Below is the data structure
of s_vpi_systf_data.
of s_vpi_systf_data.
 
 
 typedef struct t_vpi_systf_data {
 typedef struct t_vpi_systf_data {
   PLI_INT32 type;     // vpiSysTask, vpiSysFunc - task not return val, Func does
   PLI_INT32 type;     // vpiSysTask, vpiSysFunc - task not return val, Func does
   PLI_INT32 sysfunctype; // vpiSysTask, vpi[Int,Real,Time,Sized, SizedSigned]Func - if it's a func, this is the typ of return
   PLI_INT32 sysfunctype; // vpiSysTask, vpi[Int,Real,Time,Sized, SizedSigned]Func - if it's a func, this is the typ of return
   PLI_BYTE8 *tfname;  // First character must be `$'
   PLI_BYTE8 *tfname;  // First character must be `$'
   PLI_INT32 (*calltf)(PLI_BYTE8 *); //pointer to the function
   PLI_INT32 (*calltf)(PLI_BYTE8 *); //pointer to the function
   PLI_INT32 (*compiletf)(PLI_BYTE8 *); // pointer to a function that the simulator calls
   PLI_INT32 (*compiletf)(PLI_BYTE8 *); // pointer to a function that the simulator calls
                                        // when it's compiled - can be NULL
                                        // when it's compiled - can be NULL
   PLI_INT32 (*sizetf)(PLI_BYTE8 *); // For sized function callbacks only, This field is a
   PLI_INT32 (*sizetf)(PLI_BYTE8 *); // For sized function callbacks only, This field is a
                                     // pointer to a routine that returns the size, in bits,
                                     // pointer to a routine that returns the size, in bits,
                                     // of the value that the system task or function returns.
                                     // of the value that the system task or function returns.
   PLI_BYTE8 *user_data; --optional extra data?
   PLI_BYTE8 *user_data; --optional extra data?
 } s_vpi_systf_data, *p_vpi_systf_data;
 } s_vpi_systf_data, *p_vpi_systf_data;
*/
*/
 
 
 
 
 
 
/*$$CHANGE HISTORY*/
/*$$CHANGE HISTORY*/
/******************************************************************************/
/******************************************************************************/
/*                                                                            */
/*                                                                            */
/*                         C H A N G E  H I S T O R Y                         */
/*                         C H A N G E  H I S T O R Y                         */
/*                                                                            */
/*                                                                            */
/******************************************************************************/
/******************************************************************************/
// Date         Version Description
// Date         Version Description
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// 090501               Imported code from "jp" VPI project             jb
// 090501               Imported code from "jp" VPI project             jb
//                      Changed to use pipes instead of sockets         jb
//                      Changed to use pipes instead of sockets         jb
 
 
 
 
 
 
 
 
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <errno.h>
#include <errno.h>
#include <unistd.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fcntl.h>
#include <ctype.h>
#include <ctype.h>
#include <string.h>
#include <string.h>
#include <stdarg.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdint.h>
#include <signal.h>
#include <signal.h>
#include <inttypes.h>
#include <inttypes.h>
 
 
// VPI includes
// VPI includes
#include <vpi_user.h>
#include <vpi_user.h>
 
 
#ifdef CDS_VPI
#ifdef CDS_VPI
// Cadence ncverilog specific include
// Cadence ncverilog specific include
#include <vpi_user_cds.h>
#include <vpi_user_cds.h>
#endif
#endif
 
 
// Includes for the RSP server side of things
// Includes for the RSP server side of things
#include "gdb.h"
#include "gdb.h"
#include "rsp-rtl_sim.h"
#include "rsp-rtl_sim.h"
#include "rsp-vpi.h"
#include "rsp-vpi.h"
 
 
// Define the port we open the RSP server on
// Define the port we open the RSP server on
#define RSP_SERVER_PORT 5555
#define RSP_SERVER_PORT 5555
 
 
//Function to register the function which sets up the sockets interface
//Function to register the function which sets up the sockets interface
void register_init_rsp_server_functions() ;
void register_init_rsp_server_functions() ;
// Function which sets up the socket interface
// Function which sets up the socket interface
void init_rsp_server();
void init_rsp_server();
//install a callback on simulation reset which calls setup
//install a callback on simulation reset which calls setup
void setup_reset_callbacks();
void setup_reset_callbacks();
//install a callback on simulation compilation finish
//install a callback on simulation compilation finish
void setup_endofcompile_callbacks();
void setup_endofcompile_callbacks();
//install a callback on simulation finish
//install a callback on simulation finish
void setup_finish_callbacks();
void setup_finish_callbacks();
//callback function which closes and clears the socket file descriptors
//callback function which closes and clears the socket file descriptors
// on simulation reset
// on simulation reset
void sim_reset_callback();
void sim_reset_callback();
void sim_endofcompile_callback();
void sim_endofcompile_callback();
void sim_finish_callback();
void sim_finish_callback();
 
 
void register_check_for_command();
void register_check_for_command();
void register_get_command_address();
void register_get_command_address();
void register_get_command_data();
void register_get_command_data();
void register_return_command_block_data();
void register_return_command_block_data();
void register_return_command_data();
void register_return_command_data();
void register_get_command_block_data();
void register_get_command_block_data();
void register_return_response();
void register_return_response();
 
 
void check_for_command();
void check_for_command();
void get_command_address();
void get_command_address();
void get_command_data();
void get_command_data();
void get_command_block_data();
void get_command_block_data();
void return_command_data();
void return_command_data();
void return_command_block_data();
void return_command_block_data();
void return_response();
void return_response();
 
 
 
 
#include <time.h>
#include <time.h>
 
 
int vpi_to_rsp_pipe[2]; // [0] - read, [1] - write
uint32_t vpi_to_rsp_pipe[2]; // [0] - read, [1] - write
int rsp_to_vpi_pipe[2]; // [0] - read, [1] - write
uint32_t rsp_to_vpi_pipe[2]; // [0] - read, [1] - write
int command_pipe[2]; // RSP end writes, VPI end reads ONLY
uint32_t command_pipe[2]; // RSP end writes, VPI end reads ONLY
 
 
/* Global static to store the child rsp server PID if we want to kill it */
/* Global static to store the child rsp server PID if we want to kill it */
static pid_t rsp_server_child_pid = (pid_t) 0; // pid_t is just a signed int
static pid_t rsp_server_child_pid = (pid_t) 0; // pid_t is just a signed int
 
 
 
 
/********************************************************************/
/********************************************************************/
/* init_rsp_server
/* init_rsp_server
 *
 *
 * Fork off the rsp server process
 * Fork off the rsp server process
 *                                                                   /
 *                                                                   /
/********************************************************************/
/********************************************************************/
void init_rsp_server(){
void init_rsp_server(){
 
 
 
 
  // First get the port number to start the RSP server on
  // First get the port number to start the RSP server on
 
 
  vpiHandle systfref, args_iter, argh;
  vpiHandle systfref, args_iter, argh;
 
 
  struct t_vpi_value argval;
  struct t_vpi_value argval;
 
 
  int value,i;
  int value,i;
 
 
  int n;
  int n;
 
 
  int portNum;
  int portNum;
 
 
  char* send_buf;
  char* send_buf;
 
 
  /*
  /*
 
 
  // Currently removed - ability to call $rsp_init_server() with a
  // Currently removed - ability to call $rsp_init_server() with a
  // port number as parameter. Hardcoded allows us to run this as
  // port number as parameter. Hardcoded allows us to run this as
  // a callback after compiile (cbEndOfCompile)
  // a callback after compiile (cbEndOfCompile)
 
 
  // Obtain a handle to the argument list
  // Obtain a handle to the argument list
  systfref = vpi_handle(vpiSysTfCall, NULL);
  systfref = vpi_handle(vpiSysTfCall, NULL);
 
 
  // Now call iterate with the vpiArgument parameter
  // Now call iterate with the vpiArgument parameter
  args_iter = vpi_iterate(vpiArgument, systfref);
  args_iter = vpi_iterate(vpiArgument, systfref);
 
 
  // get a handle on the object passed to the function
  // get a handle on the object passed to the function
  argh = vpi_scan(args_iter);
  argh = vpi_scan(args_iter);
 
 
  // now store the command value back in the sim
  // now store the command value back in the sim
  argval.format = vpiIntVal;
  argval.format = vpiIntVal;
 
 
  // Now set the data value
  // Now set the data value
  vpi_get_value(argh, &argval);
  vpi_get_value(argh, &argval);
 
 
  portNum = (int) argval.value.integer;
  portNum = (int) argval.value.integer;
 
 
  // Cleanup and return
  // Cleanup and return
  vpi_free_object(args_iter);
  vpi_free_object(args_iter);
 
 
  // We should now have our port number.
  // We should now have our port number.
 
 
  */
  */
 
 
  // Fork. Let the child run the RSP server
  // Fork. Let the child run the RSP server
  pid_t pid;
  pid_t pid;
  int rv;
  int rv;
 
 
  if(DBG_ON) printf("jp_vpi: init_rsp_server\n");
  if(DBG_JP_VPI) printf("jp_vpi: init_rsp_server\n");
 
 
  // Setup pipes
  // Setup pipes
  if(pipe(vpi_to_rsp_pipe) == -1)
  if(pipe(vpi_to_rsp_pipe) == -1)
    {
    {
      perror("jp_vpi: init_rsp_server pipes");
      perror("jp_vpi: init_rsp_server pipes");
      exit(1);
      exit(1);
    }
    }
  if(pipe(rsp_to_vpi_pipe) == -1)
  if(pipe(rsp_to_vpi_pipe) == -1)
    {
    {
      perror("jp_vpi: init_rsp_server pipes");
      perror("jp_vpi: init_rsp_server pipes");
      exit(1);
      exit(1);
    }
    }
  if(pipe(command_pipe) == -1)
  if(pipe(command_pipe) == -1)
    {
    {
      perror("jp_vpi: init_rsp_server pipes");
      perror("jp_vpi: init_rsp_server pipes");
      exit(1);
      exit(1);
    }
    }
 
 
  // Set command pipe to be non-blocking
  // Set command pipe to be non-blocking
#if defined (STRIDE) || (defined (pfa) && defined (HAVE_PTYS)) || defined (AIX)
#if defined (STRIDE) || (defined (pfa) && defined (HAVE_PTYS)) || defined (AIX)
  {
  {
    int one = 1;
    int one = 1;
    ioctl (command_pipe[0], FIONBIO, &one);
    ioctl (command_pipe[0], FIONBIO, &one);
  }
  }
#endif
#endif
 
 
#ifdef O_NONBLOCK /* The POSIX way */
#ifdef O_NONBLOCK /* The POSIX way */
  fcntl (command_pipe[0], F_SETFL, O_NONBLOCK);
  fcntl (command_pipe[0], F_SETFL, O_NONBLOCK);
#elif defined (O_NDELAY)
#elif defined (O_NDELAY)
  fcntl (command_pipe[0], F_SETFL, O_NDELAY);
  fcntl (command_pipe[0], F_SETFL, O_NDELAY);
#endif /* O_NONBLOCK */
#endif /* O_NONBLOCK */
 
 
  // Check on the child process. If it has not been started it will
  // Check on the child process. If it has not been started it will
  // be 0, else it will be something else and we'll just return
  // be 0, else it will be something else and we'll just return
  if ((int) rsp_server_child_pid > 0)
  if ((int) rsp_server_child_pid > 0)
    return;
    return;
 
 
  switch(pid=fork())
  switch(pid=fork())
    {
    {
    case -1:
    case -1:
      perror("fork");
      perror("fork");
      exit(1);
      exit(1);
      break;
      break;
    case 0: // Child
    case 0: // Child
      run_rsp_server(RSP_SERVER_PORT);
      run_rsp_server(RSP_SERVER_PORT);
      // exit if it ever returns, which it shouldn't
      // exit if it ever returns, which it shouldn't
      exit(0);
      exit(0);
      break;
      break;
    default:
    default:
      //  We're the parent process, so continue on.
      //  We're the parent process, so continue on.
      rsp_server_child_pid = pid;
      rsp_server_child_pid = pid;
      break;
      break;
    }
    }
 
 
  // Parent will only ever get this far...
  // Parent will only ever get this far...
 
 
  return;
  return;
 
 
}
}
 
 
void register_init_rsp_server_functions() {
void register_init_rsp_server_functions() {
  s_vpi_systf_data data = {vpiSysTask,
  s_vpi_systf_data data = {vpiSysTask,
                           0,
                           0,
                           "$init_rsp_server",
                           "$init_rsp_server",
                           (void *)init_rsp_server,
                           (void *)init_rsp_server,
                           0,
                           0,
                           0,
                           0,
                           0};
                           0};
 
 
  vpi_register_systf(&data);
  vpi_register_systf(&data);
 
 
  return;
  return;
}
}
 
 
void print_command_string(unsigned char cmd)
void print_command_string(unsigned char cmd)
{
{
  switch(cmd)
  switch(cmd)
    {
    {
    case 0x1 :
    case 0x1 :
      printf("  TAP instruction register set\n");
      printf("  TAP instruction register set\n");
      break;
      break;
    case 0x2 :
    case 0x2 :
      printf("  set debug chain\n");
      printf("  set debug chain\n");
      break;
      break;
    case 0x3 :
    case 0x3 :
      printf("  CPU control (stall/reset) reg write\n");
      printf("  CPU control (stall/reset) reg write\n");
      break;
      break;
    case 0x4 :
    case 0x4 :
      printf("  CPU control (stall/reset) reg read\n");
      printf("  CPU control (stall/reset) reg read\n");
      break;
      break;
    case 0x5 :
    case 0x5 :
      printf("  CPU reg write\n");
      printf("  CPU reg write\n");
      break;
      break;
    case 0x6 :
    case 0x6 :
      printf("  CPU reg read\n");
      printf("  CPU reg read\n");
      break;
      break;
    case 0x7 :
    case 0x7 :
      printf("  WB write 32\n");
      printf("  WB write\n");
      break;
      break;
    case 0x8 :
    case 0x8 :
      printf("  WB read 32\n");
      printf("  WB read 32\n");
      break;
      break;
    case 0x9 :
    case 0x9 :
      printf("  WB block write 32\n");
      printf("  WB block write 32\n");
      break;
      break;
    case 0xa :
    case 0xa :
      printf("  WB block read 32\n");
      printf("  WB block read 32\n");
      break;
      break;
    case 0xb :
    case 0xb :
      printf("  reset\n");
      printf("  reset\n");
      break;
      break;
    case 0xc :
    case 0xc :
      printf("  read jtag id\n");
      printf("  read jtag id\n");
      break;
      break;
    }
    }
}
}
 
 
// See if there's anything on the FIFO for us
// See if there's anything on the FIFO for us
 
 
void check_for_command(char *userdata){
void check_for_command(char *userdata){
 
 
  vpiHandle systfref, args_iter, argh;
  vpiHandle systfref, args_iter, argh;
 
 
  struct t_vpi_value argval;
  struct t_vpi_value argval;
 
 
  int value,i;
  int value,i;
 
 
  int n;
  int n;
 
 
  unsigned char data;
  unsigned char data;
 
 
  //if(DBG_ON) printf("check_for_command\n");
  //if(DBG_JP_VPI) printf("check_for_command\n");
 
 
  //n = read(rsp_to_vpi_pipe[0], &data, 1);
  //n = read(rsp_to_vpi_pipe[0], &data, 1);
 
 
  n = read(command_pipe[0], &data, 1);
  n = read(command_pipe[0], &data, 1);
 
 
  if ( ((n < 0) && (errno == EAGAIN)) || (n==0) )
  if ( ((n < 0) && (errno == EAGAIN)) || (n==0) )
    {
    {
      // Nothing in the fifo this time, let's return
      // Nothing in the fifo this time, let's return
      return;
      return;
    }
    }
  else if (n < 0)
  else if (n < 0)
    {
    {
      // some sort of error
      // some sort of error
      perror("check_for_command");
      perror("check_for_command");
 
 
      exit(1);
      exit(1);
    }
    }
 
 
  if (DBG_ON)
  if (DBG_JP_VPI)
  {
  {
    printf("jp_vpi: c = %x:",data);
    printf("jp_vpi: c = %x:",data);
    print_command_string(data);
    print_command_string(data);
    fflush(stdout);
    fflush(stdout);
  }
  }
 
 
  // Return the command to the sim
  // Return the command to the sim
 
 
  // Obtain a handle to the argument list
  // Obtain a handle to the argument list
  systfref = vpi_handle(vpiSysTfCall, NULL);
  systfref = vpi_handle(vpiSysTfCall, NULL);
 
 
  // Now call iterate with the vpiArgument parameter
  // Now call iterate with the vpiArgument parameter
  args_iter = vpi_iterate(vpiArgument, systfref);
  args_iter = vpi_iterate(vpiArgument, systfref);
 
 
  // get a handle on the variable passed to the function
  // get a handle on the variable passed to the function
  argh = vpi_scan(args_iter);
  argh = vpi_scan(args_iter);
 
 
  // now store the command value back in the sim
  // now store the command value back in the sim
  argval.format = vpiIntVal;
  argval.format = vpiIntVal;
 
 
  // Now set the command value
  // Now set the command value
  vpi_get_value(argh, &argval);
  vpi_get_value(argh, &argval);
 
 
  argval.value.integer = (unsigned int) data;
  argval.value.integer = (uint32_t) data;
 
 
  // And vpi_put_value() it back into the sim
  // And vpi_put_value() it back into the sim
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
 
 
  // Cleanup and return
  // Cleanup and return
  vpi_free_object(args_iter);
  vpi_free_object(args_iter);
 
 
  n = write(vpi_to_rsp_pipe[1],&data,1);
  n = write(vpi_to_rsp_pipe[1],&data,1);
  if (DBG_ON) printf("jp_vpi: r");
  if (DBG_JP_VPI) printf("jp_vpi: r");
 
 
  if (DBG_ON) printf("\n");
  if (DBG_JP_VPI) printf("\n");
 
 
  return;
  return;
}
}
 
 
void get_command_address(char *userdata){
void get_command_address(char *userdata){
 
 
  vpiHandle systfref, args_iter, argh;
  vpiHandle systfref, args_iter, argh;
 
 
  struct t_vpi_value argval;
  struct t_vpi_value argval;
 
 
  int value,i;
  int value,i;
 
 
  int n;
  int n;
 
 
  unsigned int data;
  uint32_t data;
 
 
  char* recv_buf;
  char* recv_buf;
 
 
  recv_buf = (char *) &data; // cast data as our receive char buffer
  recv_buf = (char *) &data; // cast data as our receive char buffer
 
 
  n = read(rsp_to_vpi_pipe[0],recv_buf,4);
  n = read(rsp_to_vpi_pipe[0],recv_buf,4);
  if (n<0)
  if (n<0)
    {
    {
      //client has closed connection
      //client has closed connection
      //attempt to close and return gracefully
      //attempt to close and return gracefully
      return;
      return;
    }
    }
 
 
  if (DBG_ON) printf("jp_vpi: get_command_address adr=0x%.8x\n",data);
  if (DBG_JP_VPI) printf("jp_vpi: get_command_address adr=0x%.8x\n",data);
 
 
  // now put the address into the argument passed to the task
  // now put the address into the argument passed to the task
 
 
  // Obtain a handle to the argument list
  // Obtain a handle to the argument list
  systfref = vpi_handle(vpiSysTfCall, NULL);
  systfref = vpi_handle(vpiSysTfCall, NULL);
 
 
  // Now call iterate with the vpiArgument parameter
  // Now call iterate with the vpiArgument parameter
  args_iter = vpi_iterate(vpiArgument, systfref);
  args_iter = vpi_iterate(vpiArgument, systfref);
 
 
  // get a handle on the variable passed to the function
  // get a handle on the variable passed to the function
  argh = vpi_scan(args_iter);
  argh = vpi_scan(args_iter);
 
 
  // now store the command value back in the sim
  // now store the command value back in the sim
  argval.format = vpiIntVal;
  argval.format = vpiIntVal;
 
 
  // Now set the address value
  // Now set the address value
  vpi_get_value(argh, &argval);
  vpi_get_value(argh, &argval);
  argval.value.integer = (unsigned int) data;
  argval.value.integer = (uint32_t) data;
 
 
  // And vpi_put_value() it back into the sim
  // And vpi_put_value() it back into the sim
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
 
 
  // Cleanup and return
  // Cleanup and return
  vpi_free_object(args_iter);
  vpi_free_object(args_iter);
 
 
   return;
   return;
 
 
}
}
 
 
void get_command_data(char *userdata){
void get_command_data(char *userdata){
 
 
  vpiHandle systfref, args_iter, argh;
  vpiHandle systfref, args_iter, argh;
 
 
  struct t_vpi_value argval;
  struct t_vpi_value argval;
 
 
  int value,i;
  int value,i;
 
 
  int n = 0;
  int n = 0;
 
 
  unsigned int data;
  uint32_t data;
 
 
  char* recv_buf;
  char* recv_buf;
 
 
  recv_buf = (char *) &data; // cast data as our receive char buffer
  recv_buf = (char *) &data; // cast data as our receive char buffer
 
 
 read_command_data_again:
 read_command_data_again:
  n = read(rsp_to_vpi_pipe[0],recv_buf,4);
  n = read(rsp_to_vpi_pipe[0],recv_buf,4);
 
 
  if ((n < 4) && errno==EAGAIN)
  if ((n < 4) && errno==EAGAIN)
    goto read_command_data_again;
    goto read_command_data_again;
  else if (n < 4)
  else if (n < 4)
    {
    {
      printf("jp_vpi: get_command_data errno: %d\n",errno);
      printf("jp_vpi: get_command_data errno: %d\n",errno);
      perror("jp_vpi: get_command_data read failed");
      perror("jp_vpi: get_command_data read failed");
    }
    }
  if (DBG_ON) printf("jp_vpi: get_command_data = 0x%.8x\n",data);
  if (DBG_JP_VPI) printf("jp_vpi: get_command_data = 0x%.8x\n",data);
 
 
  // Obtain a handle to the argument list
  // Obtain a handle to the argument list
  systfref = vpi_handle(vpiSysTfCall, NULL);
  systfref = vpi_handle(vpiSysTfCall, NULL);
 
 
  // Now call iterate with the vpiArgument parameter
  // Now call iterate with the vpiArgument parameter
  args_iter = vpi_iterate(vpiArgument, systfref);
  args_iter = vpi_iterate(vpiArgument, systfref);
 
 
  // get a handle on the variable passed to the function
  // get a handle on the variable passed to the function
  argh = vpi_scan(args_iter);
  argh = vpi_scan(args_iter);
 
 
  // now store the command value back in the sim
  // now store the command value back in the sim
  argval.format = vpiIntVal;
  argval.format = vpiIntVal;
 
 
  // Now set the data value
  // Now set the data value
  vpi_get_value(argh, &argval);
  vpi_get_value(argh, &argval);
  argval.value.integer = (unsigned int) data;
  argval.value.integer = (uint32_t) data;
 
 
  // And vpi_put_value() it back into the sim
  // And vpi_put_value() it back into the sim
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
 
 
  // Cleanup and return
  // Cleanup and return
  vpi_free_object(args_iter);
  vpi_free_object(args_iter);
 
 
   return;
   return;
 
 
}
}
 
 
 
 
void get_command_block_data(){ // $get_command_block_data(length, mem_array)
void get_command_block_data(){ // $get_command_block_data(length, mem_array)
 
 
  vpiHandle systfref, args_iter, argh;
  vpiHandle systfref, args_iter, argh;
 
 
  struct t_vpi_value argval;
  struct t_vpi_value argval;
 
 
  int value,i;
  int value,i;
 
 
  int n;
  int n;
 
 
  unsigned int data;
  uint32_t data;
  unsigned int length;
  uint32_t length;
 
 
  char* recv_buf;
  char* recv_buf;
 
 
  // Now setup the handles to verilog objects and check things
  // Now setup the handles to verilog objects and check things
  // Obtain a handle to the argument list
  // Obtain a handle to the argument list
  systfref = vpi_handle(vpiSysTfCall, NULL);
  systfref = vpi_handle(vpiSysTfCall, NULL);
 
 
  // Now call iterate with the vpiArgument parameter
  // Now call iterate with the vpiArgument parameter
  args_iter = vpi_iterate(vpiArgument, systfref);
  args_iter = vpi_iterate(vpiArgument, systfref);
 
 
  // get a handle on the length variable
  // get a handle on the length variable
  argh = vpi_scan(args_iter);
  argh = vpi_scan(args_iter);
 
 
  argval.format = vpiIntVal;
  argval.format = vpiIntVal;
 
 
  // get the value for the length object
  // get the value for the length object
  vpi_get_value(argh, &argval);
  vpi_get_value(argh, &argval);
 
 
  // now set length
  // now set length
  length = argval.value.integer;
  length = argval.value.integer;
 
 
  int num_words = length/4;
  int num_words = length/4;
 
 
  if((length % 4) != 0) vpi_printf("length of %d bytes is not exactly word-aligned\n",length);
  //if((length % 4) != 0) vpi_printf("length of %d bytes is not exactly word-aligned\n",length);
  // If non-word aligned we throw away remainder
  // If non-word aligned we throw away remainder
  int throw_away_bytes = length %4;
  int throw_away_bytes = length %4;
 
 
  int loaded_words = 0;
  int loaded_words = 0;
 
 
  if(DBG_ON)printf("jp_vpi: get_command_block_data: length=%d, num_words=%d\n",length,num_words);
  if(DBG_JP_VPI)printf("jp_vpi: get_command_block_data: length=%d, num_words=%d\n",length,num_words);
 
 
  // now get a handle on the next object (memory array)
  // now get a handle on the next object (memory array)
  argh = vpi_scan(args_iter);
  argh = vpi_scan(args_iter);
 
 
  // check we got passed a memory (array of regs)
  // check we got passed a memory (array of regs)
  if (vpi_get(vpiType, argh) != vpiMemory)
  if (vpi_get(vpiType, argh) != vpiMemory)
    {
    {
      vpi_printf("jp_vpi: ERROR: did not pass a memory to get_command_block_data\n");
      vpi_printf("jp_vpi: ERROR: did not pass a memory to get_command_block_data\n");
      return;
      return;
    }
    }
 
 
  // check the memory we're writing into is big enough
  // check the memory we're writing into is big enough
  if (vpi_get(vpiSize, argh) < num_words )
  if (vpi_get(vpiSize, argh) < num_words )
    {
    {
      vpi_printf("jp_vpi: ERROR: buffer passed to get_command_block_data too small. size is %d words, needs to be %d\n",
      vpi_printf("jp_vpi: ERROR: buffer passed to get_command_block_data too small. size is %d words, needs to be %d\n",
                 vpi_get(vpiSize, argh), num_words);
                 vpi_get(vpiSize, argh), num_words);
      return;
      return;
    }
    }
 
 
  vpiHandle array_word;
  vpiHandle array_word;
 
 
  // Loop to load the words
  // Loop to load the words
  while (loaded_words < num_words) {
  while (loaded_words < num_words) {
 
 
    recv_buf = (char *) &data;
    recv_buf = (char *) &data;
 
 
    // blocking receive for data block
    // blocking receive for data block
    n = read(rsp_to_vpi_pipe[0],recv_buf,4);
    n = read(rsp_to_vpi_pipe[0],recv_buf,4);
 
 
    // now get a handle on the current word we want in the array that was passed to us
    // now get a handle on the current word we want in the array that was passed to us
    array_word = vpi_handle_by_index(argh, loaded_words);
    array_word = vpi_handle_by_index(argh, loaded_words);
 
 
    if (array_word != NULL)
    if (array_word != NULL)
      {
      {
        argval.value.integer = (unsigned int) data;
        argval.value.integer = (uint32_t) data;
 
 
        // And vpi_put_value() it back into the sim
        // And vpi_put_value() it back into the sim
        vpi_put_value(array_word, &argval, NULL, vpiNoDelay);
        vpi_put_value(array_word, &argval, NULL, vpiNoDelay);
      }
      }
    else
    else
      return;
      return;
 
 
    loaded_words++;
    loaded_words++;
  }
  }
  // TODO: This is a quick fix, should be delt with properly!!
  // TODO: This is a quick fix, should be delt with properly!!
  if (throw_away_bytes)
  if (throw_away_bytes)
    {
    {
      //printf("reading off %d extra data bytes\n",throw_away_bytes);
      //printf("reading off %d extra data bytes\n",throw_away_bytes);
      n = read(rsp_to_vpi_pipe[0],&data,throw_away_bytes);
      n = read(rsp_to_vpi_pipe[0],&data,throw_away_bytes);
      //printf("read off %d bytes \n",n);
      //printf("read off %d bytes \n",n);
    }
    }
 
 
  // Cleanup and return
  // Cleanup and return
  vpi_free_object(args_iter);
  vpi_free_object(args_iter);
 
 
  return;
  return;
 
 
}
}
 
 
void return_command_data(char *userdata){
void return_command_data(char *userdata){
 
 
  vpiHandle systfref, args_iter, argh;
  vpiHandle systfref, args_iter, argh;
 
 
  struct t_vpi_value argval;
  struct t_vpi_value argval;
 
 
  int value,i;
  int value,i;
 
 
  int n;
  int n;
 
 
  uint32_t data;
  uint32_t data;
 
 
  char* send_buf;
  char* send_buf;
 
 
  // Obtain a handle to the argument list
  // Obtain a handle to the argument list
  systfref = vpi_handle(vpiSysTfCall, NULL);
  systfref = vpi_handle(vpiSysTfCall, NULL);
 
 
  // Now call iterate with the vpiArgument parameter
  // Now call iterate with the vpiArgument parameter
  args_iter = vpi_iterate(vpiArgument, systfref);
  args_iter = vpi_iterate(vpiArgument, systfref);
 
 
  // get a handle on the object passed to the function
  // get a handle on the object passed to the function
  argh = vpi_scan(args_iter);
  argh = vpi_scan(args_iter);
 
 
  // now store the command value back in the sim
  // now store the command value back in the sim
  argval.format = vpiIntVal;
  argval.format = vpiIntVal;
 
 
  // Now set the data value
  // Now set the data value
  vpi_get_value(argh, &argval);
  vpi_get_value(argh, &argval);
 
 
  data = (unsigned int) argval.value.integer;
  data = (uint32_t) argval.value.integer;
 
 
  // Cleanup and return
  // Cleanup and return
  vpi_free_object(args_iter);
  vpi_free_object(args_iter);
 
 
  if (DBG_ON) printf("jp_vpi: return_command_data 0x%.8x\n",data);
  if (DBG_JP_VPI) printf("jp_vpi: return_command_data 0x%.8x\n",data);
 
 
  send_buf = (char *) &data; //cast our long as a char buf
  send_buf = (char *) &data; //cast our long as a char buf
 
 
  // write the data back
  // write the data back
  n = write(vpi_to_rsp_pipe[1],send_buf,4);
  n = write(vpi_to_rsp_pipe[1],send_buf,4);
 
 
  return;
  return;
 
 
}
}
 
 
void return_command_block_data(){
void return_command_block_data(){
 
 
  vpiHandle systfref, args_iter, argh;
  vpiHandle systfref, args_iter, argh;
 
 
  struct t_vpi_value argval;
  struct t_vpi_value argval;
 
 
  int value,i;
  int value,i;
 
 
  int n;
  int n;
 
 
  unsigned int data;
  uint32_t data;
  unsigned int length;
  uint32_t length;
 
 
 
  char *block_data_buf;
 
  uint32_t *block_word_data_buf_ptr;
 
 
  char* recv_buf;
  int num_words;
 
  int sent_words = 0;
 
 
 
  vpiHandle array_word;
 
 
  // Now setup the handles to verilog objects and check things
  // Now setup the handles to verilog objects and check things
  // Obtain a handle to the argument list
  // Obtain a handle to the argument list
  systfref = vpi_handle(vpiSysTfCall, NULL);
  systfref = vpi_handle(vpiSysTfCall, NULL);
 
 
  // Now call iterate with the vpiArgument parameter
  // Now call iterate with the vpiArgument parameter
  args_iter = vpi_iterate(vpiArgument, systfref);
  args_iter = vpi_iterate(vpiArgument, systfref);
 
 
  // get a handle on the length variable
  // get a handle on the length variable
  argh = vpi_scan(args_iter);
  argh = vpi_scan(args_iter);
 
 
  argval.format = vpiIntVal;
  argval.format = vpiIntVal;
 
 
  // get the value for the length object
  // get the value for the length object
  vpi_get_value(argh, &argval);
  vpi_get_value(argh, &argval);
 
 
  // now set length
  // now set length
  length = argval.value.integer;
  length = argval.value.integer;
 
 
  // now get a handle on the next object (memory array)
  // now get a handle on the next object (memory array)
  argh = vpi_scan(args_iter);
  argh = vpi_scan(args_iter);
 
 
  // check we got passed a memory (array of regs)
  // check we got passed a memory (array of regs)
  if (vpi_get(vpiType, argh) != vpiMemory)
  if (vpi_get(vpiType, argh) != vpiMemory)
    {
    {
      vpi_printf("jp_vpi: ERROR: did not pass a memory to return_command_block_data\n");
      vpi_printf("jp_vpi: ERROR: did not pass a memory to return_command_block_data\n");
      return;
      return;
    }
    }
 
 
  vpiHandle array_word;
  // We have to alloc memory here for lengths > 4
 
  if (length > 4);
 
  {
 
    block_data_buf = (char*) malloc(length * sizeof(char));
 
    if (block_data_buf == NULL)
 
      {
 
        vpi_printf("jp_vpi: return_command_block_data: Error. Could not allocate memory\n");
 
        // Cleanup and return
 
        vpi_free_object(args_iter);
 
        return;
 
      }
 
 
  int num_words = length/4;
    // Now cast it as a uint32_t array
 
    block_word_data_buf_ptr = (uint32_t *) block_data_buf;
 
  }
 
 
  int sent_words = 0;
  num_words = length / 4; // We're always going to be dealing with whole words here
 
 
 
  if (DBG_JP_VPI) printf("jp_vpi: return_command_block_data: num_words %d\n",
 
                         num_words);
 
 
  // Loop to load the words
    // Loop to load the words
  while (sent_words < num_words) {
  while (sent_words < num_words) {
 
 
    // now get a handle on the current word we want in the array that was passed to us
    // Get a handle on the current word we want in the array that was passed to us
    array_word = vpi_handle_by_index(argh, sent_words);
    array_word = vpi_handle_by_index(argh, sent_words);
 
 
    if (array_word != NULL)
    if (array_word != NULL)
      {
      {
        vpi_get_value(array_word, &argval);
        vpi_get_value(array_word, &argval);
 
 
        data = (unsigned int) argval.value.integer;
        data = (uint32_t) argval.value.integer;
 
 
 
        block_word_data_buf_ptr[sent_words] = data;
      }
      }
    else
    else
      return;
      return;
 
 
    recv_buf = (char *) &data;
    if (DBG_JP_VPI) printf ( "jp_vpi: return_command_block_data: word %d 0x%.8x\n",
 
                             sent_words, data);
 
    sent_words++;
 
  }
 
 
    n = write(vpi_to_rsp_pipe[1],recv_buf,4);
  if (!(length > 4))
 
    {
 
      block_data_buf = (char *) &data;
 
    }
 
 
    sent_words++;
  n = write(vpi_to_rsp_pipe[1],block_data_buf,length);
 
 
 
 
 
  if (length > 4)
 
    {
 
      // Free the array
 
      free(block_data_buf);
  }
  }
 
 
 
 
  // Cleanup and return
  // Cleanup and return
  vpi_free_object(args_iter);
  vpi_free_object(args_iter);
 
 
  return;
  return;
 
 
}
}
 
 
 
 
 
 
void return_response(char *userdata){
void return_response(char *userdata){
 
 
  int n;
  int n;
 
 
  char resp = 0;
  char resp = 0;
 
 
  // send a response byte
  // send a response byte
  n = write(vpi_to_rsp_pipe[1],&resp,1);
  n = write(vpi_to_rsp_pipe[1],&resp,1);
 
 
  if (DBG_ON) printf("jp_vpi: ret\n\n");
  if (DBG_JP_VPI) printf("jp_vpi: ret\n\n");
 
 
  return;
  return;
 
 
}
}
 
 
void register_check_for_command() {
void register_check_for_command() {
  s_vpi_systf_data data = {vpiSysTask,
  s_vpi_systf_data data = {vpiSysTask,
                           0,
                           0,
                           "$check_for_command",
                           "$check_for_command",
                           (void *)check_for_command,
                           (void *)check_for_command,
                           0,
                           0,
                           0,
                           0,
                           0};
                           0};
 
 
  vpi_register_systf(&data);
  vpi_register_systf(&data);
 
 
  return;
  return;
}
}
 
 
void register_get_command_address() {
void register_get_command_address() {
  s_vpi_systf_data data = {vpiSysTask,
  s_vpi_systf_data data = {vpiSysTask,
                           0,
                           0,
                           "$get_command_address",
                           "$get_command_address",
                           (void *)get_command_address,
                           (void *)get_command_address,
                           0,
                           0,
                           0,
                           0,
                           0};
                           0};
 
 
  vpi_register_systf(&data);
  vpi_register_systf(&data);
 
 
  return;
  return;
}
}
 
 
void register_get_command_data() {
void register_get_command_data() {
  s_vpi_systf_data data = {vpiSysTask,
  s_vpi_systf_data data = {vpiSysTask,
                           0,
                           0,
                           "$get_command_data",
                           "$get_command_data",
                           (void *)get_command_data,
                           (void *)get_command_data,
                           0,
                           0,
                           0,
                           0,
                           0};
                           0};
 
 
  vpi_register_systf(&data);
  vpi_register_systf(&data);
 
 
  return;
  return;
}
}
 
 
void register_get_command_block_data() {
void register_get_command_block_data() {
  s_vpi_systf_data data = {vpiSysTask,
  s_vpi_systf_data data = {vpiSysTask,
                           0,
                           0,
                           "$get_command_block_data",
                           "$get_command_block_data",
                           (void *)get_command_block_data,
                           (void *)get_command_block_data,
                           0,
                           0,
                           0,
                           0,
                           0};
                           0};
 
 
  vpi_register_systf(&data);
  vpi_register_systf(&data);
 
 
  return;
  return;
}
}
 
 
 
 
void register_return_command_block_data() {
void register_return_command_block_data() {
  s_vpi_systf_data data = {vpiSysTask,
  s_vpi_systf_data data = {vpiSysTask,
                           0,
                           0,
                           "$return_command_block_data",
                           "$return_command_block_data",
                           (void *)return_command_block_data,
                           (void *)return_command_block_data,
                           0,
                           0,
                           0,
                           0,
                           0};
                           0};
 
 
  vpi_register_systf(&data);
  vpi_register_systf(&data);
 
 
  return;
  return;
}
}
 
 
void register_return_command_data() {
void register_return_command_data() {
  s_vpi_systf_data data = {vpiSysTask,
  s_vpi_systf_data data = {vpiSysTask,
                           0,
                           0,
                           "$return_command_data",
                           "$return_command_data",
                           (void *)return_command_data,
                           (void *)return_command_data,
                           0,
                           0,
                           0,
                           0,
                           0};
                           0};
 
 
  vpi_register_systf(&data);
  vpi_register_systf(&data);
 
 
  return;
  return;
}
}
 
 
void register_return_response() {
void register_return_response() {
  s_vpi_systf_data data = {vpiSysTask,
  s_vpi_systf_data data = {vpiSysTask,
                           0,
                           0,
                           "$return_response",
                           "$return_response",
                           (void *)return_response,
                           (void *)return_response,
                           0,
                           0,
                           0,
                           0,
                           0};
                           0};
 
 
  vpi_register_systf(&data);
  vpi_register_systf(&data);
 
 
  return;
  return;
}
}
 
 
 
 
void setup_reset_callbacks()
void setup_reset_callbacks()
{
{
 
 
  // here we setup and install callbacks for 
  // here we setup and install callbacks for 
  // the setup and management of connections to
  // the setup and management of connections to
  // the simulator upon simulation start and 
  // the simulator upon simulation start and 
  // reset
  // reset
 
 
  static s_vpi_time time_s = {vpiScaledRealTime};
  static s_vpi_time time_s = {vpiScaledRealTime};
  static s_vpi_value value_s = {vpiBinStrVal};
  static s_vpi_value value_s = {vpiBinStrVal};
  static s_cb_data cb_data_s =
  static s_cb_data cb_data_s =
    {
    {
      cbEndOfReset, // or start of simulation - initing socket fds etc
      cbEndOfReset, // or start of simulation - initing socket fds etc
      (void *)sim_reset_callback,
      (void *)sim_reset_callback,
      NULL,
      NULL,
      &time_s,
      &time_s,
      &value_s
      &value_s
    };
    };
 
 
  cb_data_s.obj = NULL;  /* trigger object */
  cb_data_s.obj = NULL;  /* trigger object */
 
 
  cb_data_s.user_data = NULL;
  cb_data_s.user_data = NULL;
 
 
  // actual call to register the callback
  // actual call to register the callback
  vpi_register_cb(&cb_data_s);
  vpi_register_cb(&cb_data_s);
 
 
}
}
 
 
void sim_reset_callback()
void sim_reset_callback()
{
{
 
 
  // nothing to do!
  // nothing to do!
 
 
  return;
  return;
 
 
}
}
 
 
void setup_endofcompile_callbacks()
void setup_endofcompile_callbacks()
{
{
 
 
  // here we setup and install callbacks for 
  // here we setup and install callbacks for 
  // simulation finish
  // simulation finish
 
 
  static s_vpi_time time_s = {vpiScaledRealTime};
  static s_vpi_time time_s = {vpiScaledRealTime};
  static s_vpi_value value_s = {vpiBinStrVal};
  static s_vpi_value value_s = {vpiBinStrVal};
  static s_cb_data cb_data_s =
  static s_cb_data cb_data_s =
    {
    {
      cbEndOfCompile, // end of compile
      cbEndOfCompile, // end of compile
      (void *)sim_endofcompile_callback,
      (void *)sim_endofcompile_callback,
      NULL,
      NULL,
      &time_s,
      &time_s,
      &value_s
      &value_s
    };
    };
 
 
  cb_data_s.obj = NULL;  /* trigger object */
  cb_data_s.obj = NULL;  /* trigger object */
 
 
  cb_data_s.user_data = NULL;
  cb_data_s.user_data = NULL;
 
 
  // actual call to register the callback
  // actual call to register the callback
  vpi_register_cb(&cb_data_s);
  vpi_register_cb(&cb_data_s);
 
 
}
}
 
 
void sim_endofcompile_callback()
void sim_endofcompile_callback()
{
{
  // Init the RSP server
  // Init the RSP server
  init_rsp_server(); // Start the RSP server from here!
  init_rsp_server(); // Start the RSP server from here!
 
 
}
}
 
 
 
 
void setup_finish_callbacks()
void setup_finish_callbacks()
{
{
 
 
  // here we setup and install callbacks for 
  // here we setup and install callbacks for 
  // simulation finish
  // simulation finish
 
 
  static s_vpi_time time_s = {vpiScaledRealTime};
  static s_vpi_time time_s = {vpiScaledRealTime};
  static s_vpi_value value_s = {vpiBinStrVal};
  static s_vpi_value value_s = {vpiBinStrVal};
  static s_cb_data cb_data_s =
  static s_cb_data cb_data_s =
    {
    {
      cbEndOfSimulation, // end of simulation
      cbEndOfSimulation, // end of simulation
      (void *)sim_finish_callback,
      (void *)sim_finish_callback,
      NULL,
      NULL,
      &time_s,
      &time_s,
      &value_s
      &value_s
    };
    };
 
 
  cb_data_s.obj = NULL;  /* trigger object */
  cb_data_s.obj = NULL;  /* trigger object */
 
 
  cb_data_s.user_data = NULL;
  cb_data_s.user_data = NULL;
 
 
  // actual call to register the callback
  // actual call to register the callback
  vpi_register_cb(&cb_data_s);
  vpi_register_cb(&cb_data_s);
 
 
}
}
 
 
void sim_finish_callback()
void sim_finish_callback()
{
{
  printf("Closing RSP server\n");
  printf("Closing RSP server\n");
  // Close down the child process, if it hasn't already
  // Close down the child process, if it hasn't already
  kill(rsp_server_child_pid,SIGTERM);
  kill(rsp_server_child_pid,SIGTERM);
}
}
 
 
 
 
 
 
// Register the new system task here
// Register the new system task here
void (*vlog_startup_routines[ ] ) () = {
void (*vlog_startup_routines[ ] ) () = {
  register_init_rsp_server_functions,
  register_init_rsp_server_functions,
#ifdef CDS_VPI
#ifdef CDS_VPI
  // this installs a callback on simulator reset - something which 
  // this installs a callback on simulator reset - something which 
  // icarus does not do, so we only do it for cadence currently
  // icarus does not do, so we only do it for cadence currently
  setup_reset_callbacks,
  setup_reset_callbacks,
#endif
#endif
  setup_endofcompile_callbacks,
  setup_endofcompile_callbacks,
  setup_finish_callbacks,
  setup_finish_callbacks,
  register_check_for_command,
  register_check_for_command,
  register_get_command_address,
  register_get_command_address,
  register_get_command_data,
  register_get_command_data,
  register_get_command_block_data,
  register_get_command_block_data,
  register_return_command_data,
  register_return_command_data,
  register_return_command_block_data,
  register_return_command_block_data,
  register_return_response,
  register_return_response,
  0  // last entry must be 0 
  0  // last entry must be 0 
};
};
 
 
 
 
 
 
// Entry point for testing development of the vpi functions
// Entry point for testing development of the vpi functions
int main(int argc, char *argv[])
int main(int argc, char *argv[])
{
{
 
 
  return 0;
  return 0;
 
 
}
}
 
 
 
 
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.