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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_70/] [or1ksim/] [vapi/] [vapi.c] - Rev 293

Go to most recent revision | Compare with Previous | Blame | View Log

/* vapi.c -- Verification API Interface
   Copyright (C) 2001, Marko Mlinar, markom@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
//#include "config.h"
 
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <signal.h>
#include <errno.h>
 
/* Added by CZ 24/05/01 */
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <inttypes.h>
 
//#include "sim-config.h"
 
unsigned int serverIP = 0;
 
struct {
  struct {
    unsigned int server_port;
  } vapi;
} config;
 
unsigned int server_fd = 0;
unsigned int vapi_fd = 0;
void server_request(void);
 
static int tcp_level = 0;
 
struct vapi_handler {
  unsigned long id;
  void (*read_func)(int);
  struct vapi_handler *next;
} *vapi_handler;
 
/* Added by CZ 24/05/01 */
int get_server_socket(const char* name,const char* proto,int port)
{
  struct servent *service;
  struct protoent *protocol;
  struct sockaddr_in sa;
  struct hostent *hp;  
  int sockfd;
  char myname[256];
  int flags;
  char sTemp[256];
 
  /* First, get the protocol number of TCP */
  if(!(protocol = getprotobyname(proto))) {
    sprintf(sTemp,"Unable to load protocol \"%s\"",proto);
    perror(sTemp);
    return 0;
  }
  tcp_level = protocol->p_proto; /* Save for later */
 
  /* If we weren't passed a non standard port, get the port
     from the services directory. */
  if(!port) {
    if(service = getservbyname(name,protocol->p_name))
      port = ntohs(service->s_port);
  }
 
  /* Create the socket using the TCP protocol */
  if((sockfd = socket(PF_INET,SOCK_STREAM,protocol->p_proto)) < 0) {
    perror("Unable to create socket");
    return 0;
  }
 
  flags = 1;
  if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0) {
    sprintf(sTemp,"Can not set SO_REUSEADDR option on socket %d",sockfd);
    perror(sTemp);
    close(sockfd);
    return 0;
  }
 
  /* The server should also be non blocking. Get the current flags. */
  if(fcntl(sockfd,F_GETFL,&flags) < 0) {
    sprintf(sTemp,"Unable to get flags for socket %d",sockfd);
    perror(sTemp);
    close(sockfd);
    return 0;
  }
 
  /* Set the nonblocking flag */
  if(fcntl(sockfd,F_SETFL, flags | O_NONBLOCK) < 0) {
    sprintf(sTemp,"Unable to set flags for socket %d to value 0x%08x",
            sockfd,flags | O_NONBLOCK);
    perror(sTemp);
    close(sockfd);
    return 0;
  }
 
  /* Find out what our address is */
  memset(&sa,0,sizeof(struct sockaddr_in));
  gethostname(myname,sizeof(myname));
  if(!(hp = gethostbyname(myname))) {
    perror("Unable to read hostname");
    close(sockfd);
    return 0;
  }
 
  /* Bind our socket to the appropriate address */
  sa.sin_family = hp->h_addrtype;
  sa.sin_port = htons(port);
  if(bind(sockfd,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)) < 0) {
    sprintf(sTemp,"Unable to bind socket %d to port %d",sockfd,port);
    perror(sTemp);
    close(sockfd);
    return 0;
  }
  serverIP = sa.sin_addr.s_addr;
  flags = sizeof(struct sockaddr_in);
  if(getsockname(sockfd,(struct sockaddr*)&sa,&flags) < 0) {
    sprintf(sTemp,"Unable to get socket information for socket %d",sockfd);
    perror(sTemp);
    close(sockfd);
    return 0;
  }
  config.vapi.server_port = ntohs(sa.sin_port);
 
  /* Set the backlog to 1 connections */
  if(listen(sockfd,1) < 0) {
    sprintf(sTemp,"Unable to set backlog on socket %d to %d",sockfd,1);
    perror(sTemp);
    close(sockfd);
    return 0;
  }
 
  return sockfd;
}
 
void server_request()
{
  struct sockaddr_in sa;
  struct sockaddr* addr = (struct sockaddr*)&sa;
  int n = sizeof(struct sockaddr_in);
  int fd = accept(server_fd,addr,&n);
  int on_off = 0; /* Turn off Nagel's algorithm on the socket */
  int flags;
  char sTemp[256];
 
  if(fd < 0) {
    /* This is valid, because a connection could have started,
       and then terminated due to a protocol error or user
       initiation before the accept could take place. */
    if(errno != EWOULDBLOCK && errno != EAGAIN) {
      perror("accept");
      close(server_fd);
      server_fd = 0;
      config.vapi.server_port = 0;
      serverIP = 0;
      }
    return;
  }
 
  if(vapi_fd) {
    close(fd);
    return;
  }
 
  if(fcntl(fd,F_GETFL,&flags) < 0) {
    sprintf(sTemp,"Unable to get flags for vapi socket %d",fd);
    perror(sTemp);
    close(fd);
    return;
  }
 
  if(fcntl(fd,F_SETFL, flags | O_NONBLOCK) < 0) {
    sprintf(sTemp,"Unable to set flags for vapi socket %d to value 0x%08x",
            fd,flags | O_NONBLOCK);
    perror(sTemp);
    close(fd);
    return;
  }
 
  if(setsockopt(fd,tcp_level,TCP_NODELAY,&on_off,sizeof(int)) < 0) {
    sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",fd);
    perror(sTemp);
    close(fd);
    return;
  }
 
  vapi_fd = fd;
}
 
static int vapi_write_stream(void* buf, int len)
{
  int n;
  char* w_buf = (char*)buf;
  struct pollfd block;
 
  while(len) {
    if((n = write(vapi_fd,w_buf,len)) < 0) {
      switch(errno) {
      case EWOULDBLOCK: /* or EAGAIN */
        /* We've been called on a descriptor marked
           for nonblocking I/O. We better simulate
           blocking behavior. */
        block.fd = vapi_fd;
        block.events = POLLOUT;
        block.revents = 0;
        poll(&block,1,-1);
        continue;
      case EINTR:
        continue;
      case EPIPE:
        close(vapi_fd);
        vapi_fd = 0;
        return -1;
      default:
        return -1;
      }
    } else {
      len -= n;
      w_buf += n;
    }
  }
  return 0;
}
 
static int vapi_read_stream(void* buf, int len)
{
  int n;
  char* r_buf = (char*)buf;
  struct pollfd block;
 
  while(len) {
    if((n = read(vapi_fd,r_buf,len)) < 0) {
      switch(errno) {
      case EWOULDBLOCK: /* or EAGAIN */
        /* We've been called on a descriptor marked
           for nonblocking I/O. We better simulate
           blocking behavior. */
        block.fd = vapi_fd;
        block.events = POLLIN;
        block.revents = 0;
        poll(&block,1,-1);
        continue;
      case EINTR:
        continue;
      default:
        return -1;
      }
    } else if(n == 0) {
      close(vapi_fd);
      vapi_fd = 0;
      return -1;
    } else {
      len -= n;
      r_buf += n;
    }
  }
  return 0;
}
 
static int write_packet (unsigned long id, unsigned long data) {
  id = htonl (id);
  if (vapi_write_stream(&id, sizeof (id)) < 0)
    return 1;
  data = htonl (data);
  if (vapi_write_stream(&data, sizeof (data)) < 0)
    return 1;
  return 0;
}  
 
static int read_packet (unsigned long *id, unsigned long *data) {
  if (vapi_read_stream(id, sizeof (unsigned long)) < 0)
    return 1;
  *id = htonl (*id);
  if (vapi_read_stream(data, sizeof (unsigned long)) < 0)
    return 1;
  *data = htonl (*data);
  return 0;
}  
 
static void vapi_request()
{
  unsigned long id, data;
  struct vapi_handler *t;
  if(read_packet (&id, &data)) {
    if(vapi_fd) {
      perror("vapi read");
      close(vapi_fd);
      vapi_fd = 0;
    }
    return;
  }
 
  printf ("[%08x, %08x]\n", id, data);
  t = vapi_handler;
  while (t && t->id != id)
    t = t->next;
  if (!t && t->read_func)
    fprintf (stderr, "WARNING: packet sent to undefined id %x, %x\n", id, data);
  else
    t->read_func(data);
  write_packet (id, data + 1);
}
 
void vapi_check ()
{
  struct pollfd fds[2];
  int nfds = 0;
  int o_serv_fd = server_fd;
 
  if(!o_serv_fd && !vapi_fd)
    return;
 
  if(o_serv_fd) {
    fds[nfds].fd = o_serv_fd;
    fds[nfds].events = POLLIN;
    fds[nfds++].revents = 0;
  }
  if(vapi_fd) {
    fds[nfds].fd = vapi_fd;
    fds[nfds].events = POLLIN;
    fds[nfds++].revents = 0;
  }
 
  while(1) {
    switch(poll(fds,nfds,0)) {
    case -1:
      if(errno == EINTR)
        continue;
      perror("poll");
      server_fd = 0;
      break;
    case 0: /* Nothing interesting going on */
      return;
    default:
      /* Make sure to handle the vapi port first! */
      if((fds[0].revents && (vapi_fd && !o_serv_fd) ||
          fds[1].revents && (server_fd && vapi_fd))) {
        int revents = o_serv_fd ? fds[1].revents : fds[0].revents;
 
        if(revents & POLLIN)
          vapi_request();
        else { /* Error Occurred */
          fprintf(stderr,"Received flags 0x%08x on vapi socket. Shutting down.\n",revents);
          close(vapi_fd);
          vapi_fd = 0;
        }
      }
      if(fds[0].revents && o_serv_fd) {
        if(fds[0].revents & POLLIN)
          server_request();
        else { /* Error Occurred */
          fprintf(stderr,"Received flags 0x%08x on server. Shutting down.\n",fds[0].revents);
          close(o_serv_fd);
          server_fd = 0;
          config.vapi.server_port = 0;
          serverIP = 0;
        }
      }
      break;
    } /* End of switch statement */
  } /* End of while statement */
}
 
int vapi_init () {
{
  if(server_fd = get_server_socket("or1ksim","tcp",config.vapi.server_port))
    printf("VAPI Server started on port %d\n",config.vapi.server_port);
  else
    perror ("Connection");
 
  freopen("/dev/fd/0", "w+", stdout);
}
 
void vapi_done () {}
 
/* Installs a vapi handler to VAPI id */
void vapi_install_handler (unsigned long id, void (*read_func) (unsigned long)) {
  struct vapi_handler **t = &vapi_handler;
  struct vapi_handler *tt;
  if (readfunc == NULL) {
    while ((*t) && (*t)->id != id)
      t = &(*t)->next;
    if (!t) {
      fprintf (stderr, "Cannot uninstall VAPI read handler from id %x\n", id);
      exit (1);
    }
    tt = *t;
    (*t) = (*t)->next;
    free (tt);
  } else {
    while ((*t))
      t = &(*t)->next;
    tt = (struct vapi_handler *)malloc (sizeof (struct vapi_handler));
    tt->next = NULL;
    tt->id = id;
    tt->read_func = read_func;
    (*t) = tt;
  }
}
 
int main () {
  vapi_init ();
  while (1) {
    vapi_check();
  }
  vapi_done ();
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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