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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc1/] [or1ksim/] [vapi/] [vapi.c] - Blame information for rev 336

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

Line No. Rev Author Line
1 293 markom
/* vapi.c -- Verification API Interface
2
   Copyright (C) 2001, Marko Mlinar, markom@opencores.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20 336 markom
#include "config.h"
21 293 markom
 
22
#include <stdio.h>
23
#include <ctype.h>
24
#include <string.h>
25
#include <stdlib.h>
26
#include <unistd.h>
27
#include <stdarg.h>
28
#include <signal.h>
29
#include <errno.h>
30
 
31
/* Added by CZ 24/05/01 */
32
#include <sys/stat.h>
33
#include <sys/types.h>
34
#include <sys/socket.h>
35
#include <netinet/in.h>
36
#include <sys/select.h>
37
#include <sys/poll.h>
38
#include <fcntl.h>
39
#include <netdb.h>
40
#include <netinet/tcp.h>
41
#include <inttypes.h>
42
 
43 336 markom
#include "sim-config.h"
44 293 markom
 
45 304 markom
static unsigned int serverIP = 0;
46 293 markom
 
47 304 markom
static unsigned int server_fd = 0;
48
static unsigned int nhandlers = 0;
49
 
50 293 markom
void server_request(void);
51
 
52
static int tcp_level = 0;
53
 
54 304 markom
static struct vapi_handler {
55
  int fd;
56 293 markom
  unsigned long id;
57 336 markom
  void (*read_func)(unsigned long, unsigned long);
58 293 markom
  struct vapi_handler *next;
59 304 markom
  int temp;
60 293 markom
} *vapi_handler;
61
 
62 304 markom
/* Structure for polling, it is cached, that it doesn't have to be rebuilt each time */
63
static struct pollfd *fds = NULL;
64
static int nfds = 0;
65
 
66
/* Rebuilds the fds structures; see fds.  */
67
void rebuild_fds () {
68
  struct vapi_handler *t;
69
  if (fds)
70
    free (fds);
71
  fds = (struct pollfd *) malloc (sizeof (struct pollfd) * (nhandlers + 1));
72
  if (!fds) {
73
    fprintf (stderr, "FATAL: Out of memory.\n");
74
    exit (1);
75
  }
76
 
77
  nfds = 0;
78
  fds[nfds].fd = server_fd;
79
  fds[nfds].events = POLLIN;
80
  fds[nfds++].revents = 0;
81
 
82
  for (t = vapi_handler; t; t = t->next) {
83
    if (t->fd) {
84
      t->temp = nfds;
85
      fds[nfds].fd = t->fd;
86
      fds[nfds].events = POLLIN;
87
      fds[nfds++].revents = 0;
88
    } else
89
      t->temp = -1;
90
  }
91
}
92
 
93
/* Finds a handler with given ID, return it, NULL if not found.  */
94
static struct vapi_handler *find_handler (unsigned long id) {
95
  struct vapi_handler *t = vapi_handler;
96
  while (t && t->id != id)
97
    t = t->next;
98
  return t;
99
}
100
 
101
/* Adds a handler with given id and returns it.  */
102
static struct vapi_handler *add_handler (unsigned long id) {
103
  struct vapi_handler **t = &vapi_handler;
104
  struct vapi_handler *tt;
105
  while ((*t))
106
    t = &(*t)->next;
107
  tt = (struct vapi_handler *)malloc (sizeof (struct vapi_handler));
108
  tt->next = NULL;
109
  tt->id = id;
110
  tt->read_func = NULL;
111
  tt->fd = 0;
112
  (*t) = tt;
113
  free (fds);
114
  fds = NULL;
115
  nhandlers++;
116
  rebuild_fds ();
117
  return tt;
118
}
119
 
120
static int vapi_write_stream(int fd, void* buf, int len)
121
{
122
  int n;
123
  char* w_buf = (char*)buf;
124
  struct pollfd block;
125
 
126
  while(len) {
127
    if((n = write(fd, w_buf, len)) < 0) {
128
      switch(errno) {
129
      case EWOULDBLOCK: /* or EAGAIN */
130
        /* We've been called on a descriptor marked
131
           for nonblocking I/O. We better simulate
132
           blocking behavior. */
133
        block.fd = fd;
134
        block.events = POLLOUT;
135
        block.revents = 0;
136
        poll(&block,1,-1);
137
        continue;
138
      case EINTR:
139
        continue;
140
      case EPIPE:
141
        close(fd);
142
        fd = 0;
143
        return -1;
144
      default:
145
        return -1;
146
      }
147
    } else {
148
      len -= n;
149
      w_buf += n;
150
    }
151
  }
152
  return 0;
153
}
154
 
155
static int vapi_read_stream(int fd, void* buf, int len)
156
{
157
  int n;
158
  char* r_buf = (char*)buf;
159
  struct pollfd block;
160
 
161
  while(len) {
162
    if((n = read(fd,r_buf,len)) < 0) {
163
      switch(errno) {
164
      case EWOULDBLOCK: /* or EAGAIN */
165
        /* We've been called on a descriptor marked
166
           for nonblocking I/O. We better simulate
167
           blocking behavior. */
168
        block.fd = fd;
169
        block.events = POLLIN;
170
        block.revents = 0;
171
        poll(&block,1,-1);
172
        continue;
173
      case EINTR:
174
        continue;
175
      default:
176
        return -1;
177
      }
178
    } else if(n == 0) {
179
      close(fd);
180
      fd = 0;
181
      return -1;
182
    } else {
183
      len -= n;
184
      r_buf += n;
185
    }
186
  }
187
  return 0;
188
}
189
 
190 293 markom
/* Added by CZ 24/05/01 */
191
int get_server_socket(const char* name,const char* proto,int port)
192
{
193
  struct servent *service;
194
  struct protoent *protocol;
195
  struct sockaddr_in sa;
196
  struct hostent *hp;
197
  int sockfd;
198
  char myname[256];
199
  int flags;
200
  char sTemp[256];
201
 
202
  /* First, get the protocol number of TCP */
203
  if(!(protocol = getprotobyname(proto))) {
204
    sprintf(sTemp,"Unable to load protocol \"%s\"",proto);
205
    perror(sTemp);
206
    return 0;
207
  }
208
  tcp_level = protocol->p_proto; /* Save for later */
209
 
210
  /* If we weren't passed a non standard port, get the port
211
     from the services directory. */
212
  if(!port) {
213
    if(service = getservbyname(name,protocol->p_name))
214
      port = ntohs(service->s_port);
215
  }
216 336 markom
 
217 293 markom
  /* Create the socket using the TCP protocol */
218
  if((sockfd = socket(PF_INET,SOCK_STREAM,protocol->p_proto)) < 0) {
219
    perror("Unable to create socket");
220
    return 0;
221
  }
222 336 markom
 
223 293 markom
  flags = 1;
224
  if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0) {
225
    sprintf(sTemp,"Can not set SO_REUSEADDR option on socket %d",sockfd);
226
    perror(sTemp);
227
    close(sockfd);
228
    return 0;
229
  }
230
 
231
  /* The server should also be non blocking. Get the current flags. */
232
  if(fcntl(sockfd,F_GETFL,&flags) < 0) {
233
    sprintf(sTemp,"Unable to get flags for socket %d",sockfd);
234
    perror(sTemp);
235
    close(sockfd);
236
    return 0;
237
  }
238
 
239
  /* Set the nonblocking flag */
240
  if(fcntl(sockfd,F_SETFL, flags | O_NONBLOCK) < 0) {
241
    sprintf(sTemp,"Unable to set flags for socket %d to value 0x%08x",
242
            sockfd,flags | O_NONBLOCK);
243
    perror(sTemp);
244
    close(sockfd);
245
    return 0;
246
  }
247
 
248
  /* Find out what our address is */
249
  memset(&sa,0,sizeof(struct sockaddr_in));
250
  gethostname(myname,sizeof(myname));
251
  if(!(hp = gethostbyname(myname))) {
252
    perror("Unable to read hostname");
253
    close(sockfd);
254
    return 0;
255
  }
256
 
257
  /* Bind our socket to the appropriate address */
258
  sa.sin_family = hp->h_addrtype;
259
  sa.sin_port = htons(port);
260
  if(bind(sockfd,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)) < 0) {
261
    sprintf(sTemp,"Unable to bind socket %d to port %d",sockfd,port);
262
    perror(sTemp);
263
    close(sockfd);
264
    return 0;
265
  }
266
  serverIP = sa.sin_addr.s_addr;
267
  flags = sizeof(struct sockaddr_in);
268
  if(getsockname(sockfd,(struct sockaddr*)&sa,&flags) < 0) {
269
    sprintf(sTemp,"Unable to get socket information for socket %d",sockfd);
270
    perror(sTemp);
271
    close(sockfd);
272
    return 0;
273
  }
274
  config.vapi.server_port = ntohs(sa.sin_port);
275
 
276
  /* Set the backlog to 1 connections */
277
  if(listen(sockfd,1) < 0) {
278
    sprintf(sTemp,"Unable to set backlog on socket %d to %d",sockfd,1);
279
    perror(sTemp);
280
    close(sockfd);
281
    return 0;
282
  }
283
 
284
  return sockfd;
285
}
286
 
287
void server_request()
288
{
289
  struct sockaddr_in sa;
290
  struct sockaddr* addr = (struct sockaddr*)&sa;
291
  int n = sizeof(struct sockaddr_in);
292 336 markom
  int fd = accept(server_fd, addr, &n);
293 293 markom
  int on_off = 0; /* Turn off Nagel's algorithm on the socket */
294
  int flags;
295
  char sTemp[256];
296
 
297
  if(fd < 0) {
298
    /* This is valid, because a connection could have started,
299
       and then terminated due to a protocol error or user
300
       initiation before the accept could take place. */
301
    if(errno != EWOULDBLOCK && errno != EAGAIN) {
302
      perror("accept");
303
      close(server_fd);
304
      server_fd = 0;
305 304 markom
      config.vapi.enabled = 0;
306 293 markom
      serverIP = 0;
307 336 markom
    }
308 293 markom
    return;
309
  }
310
 
311
  if(fcntl(fd,F_GETFL,&flags) < 0) {
312
    sprintf(sTemp,"Unable to get flags for vapi socket %d",fd);
313
    perror(sTemp);
314
    close(fd);
315
    return;
316
  }
317
 
318
  if(fcntl(fd,F_SETFL, flags | O_NONBLOCK) < 0) {
319
    sprintf(sTemp,"Unable to set flags for vapi socket %d to value 0x%08x",
320
            fd,flags | O_NONBLOCK);
321
    perror(sTemp);
322
    close(fd);
323
    return;
324
  }
325
 
326
  if(setsockopt(fd,tcp_level,TCP_NODELAY,&on_off,sizeof(int)) < 0) {
327
    sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",fd);
328
    perror(sTemp);
329
    close(fd);
330
    return;
331
  }
332 304 markom
 
333
  /* Install new handler */
334
  {
335
    unsigned long id;
336
    struct vapi_handler *t;
337
    if (vapi_read_stream (fd, &id, sizeof (id))) {
338
      perror ("Cannot get id");
339
      close (fd);
340
      return;
341 293 markom
    }
342 304 markom
    t = find_handler (id);
343
    if (t)
344
      if (t->fd) {
345
        fprintf (stderr, "WARNING: Test with id %x already connected. Ignoring.\n", id);
346
        close (fd);
347
        return;
348
      } else t->fd = fd;
349
    else {
350
      t = add_handler (id);
351
      t->fd = fd;
352
      rebuild_fds ();
353 293 markom
    }
354 304 markom
    if(config.sim.verbose)
355 336 markom
      printf ("\nConnection with test (id %x) established.\n", id);
356 293 markom
  }
357
}
358
 
359
static int write_packet (unsigned long id, unsigned long data) {
360 304 markom
  struct vapi_handler *t = find_handler (id);
361
  if (!t || !t->fd)
362
    return 1;
363 293 markom
  id = htonl (id);
364 304 markom
  if (vapi_write_stream(t->fd, &id, sizeof (id)) < 0)
365 293 markom
    return 1;
366
  data = htonl (data);
367 304 markom
  if (vapi_write_stream(t->fd, &data, sizeof (data)) < 0)
368 293 markom
    return 1;
369
  return 0;
370
}
371
 
372 304 markom
static int read_packet (unsigned long id, unsigned long *data) {
373
  unsigned long t_id;
374
  struct vapi_handler *t = find_handler (id);
375
  if (!t || !t->fd)
376 293 markom
    return 1;
377 304 markom
  if (vapi_read_stream(t->fd, &t_id, sizeof (unsigned long)) < 0)
378 293 markom
    return 1;
379 304 markom
  t_id = htonl (t_id);
380
  if (t_id != id) {
381
    fprintf (stderr, "IDs not the same (got %x, expected %x)\n", t_id, id);
382
    return 1;
383
  }
384
  if (vapi_read_stream(t->fd, data, sizeof (unsigned long)) < 0)
385
    return 1;
386 293 markom
  *data = htonl (*data);
387
  return 0;
388 304 markom
}
389 293 markom
 
390 304 markom
static void vapi_request (struct vapi_handler *t) {
391
  unsigned long data;
392
  if(read_packet (t->id, &data)) {
393
    if(t->fd) {
394 293 markom
      perror("vapi read");
395 304 markom
      close(t->fd);
396
      t->fd = 0;
397 293 markom
    }
398
    return;
399
  }
400
 
401 304 markom
  debug ("[%08x, %08x]\n", t->id, data);
402
  if (!t->read_func)
403
    fprintf (stderr, "WARNING: packet sent to undefined id %x, %x\n", t->id, data);
404 293 markom
  else
405 336 markom
    t->read_func(t->id, data);
406 293 markom
}
407
 
408
void vapi_check ()
409
{
410 304 markom
  struct vapi_handler *t;
411 293 markom
 
412 304 markom
  if (!server_fd || !fds) {
413
    fprintf (stderr, "FATAL: Unable to maintain VAPI server.\n");
414
    exit (1);
415 293 markom
  }
416
 
417 304 markom
  /* Handle everything in queue. */
418 293 markom
  while(1) {
419 304 markom
    switch(poll(fds, nfds, 0)) {
420 293 markom
    case -1:
421
      if(errno == EINTR)
422
        continue;
423
      perror("poll");
424 304 markom
      if (server_fd)
425
        close(server_fd);
426
      config.vapi.enabled = 0;
427
      serverIP = 0;
428
      return;
429 293 markom
    case 0: /* Nothing interesting going on */
430
      return;
431
    default:
432 304 markom
      /* Handle the vapi ports first. */
433
      for (t = vapi_handler; t; t = t->next)
434
        if (t->temp >= 0 && fds[t->temp].revents)
435
          vapi_request (t);
436 293 markom
 
437 304 markom
      if(fds[0].revents) {
438 293 markom
        if(fds[0].revents & POLLIN)
439
          server_request();
440
        else { /* Error Occurred */
441 304 markom
          fprintf(stderr,"Received flags 0x%08x on server. Shutting down.\n", fds[0].revents);
442
          if (server_fd)
443
            close(server_fd);
444 293 markom
          server_fd = 0;
445 304 markom
          config.vapi.enabled = 0;
446 293 markom
          serverIP = 0;
447
        }
448
      }
449
      break;
450
    } /* End of switch statement */
451
  } /* End of while statement */
452
}
453
 
454 304 markom
/* Inits the VAPI, according to sim-config */
455
int vapi_init ()
456 293 markom
{
457 304 markom
  nhandlers = 0;
458
  vapi_handler = NULL;
459
  if (!config.vapi.enabled)
460
    return 0; /* Nothing to do */
461
 
462
  if (!config.vapi.server_port) {
463
    fprintf (stderr, "WARNING: server_port = 0, shutting down VAPI\n");
464
    config.vapi.enabled = 0;
465
    return 1;
466
  }
467 335 markom
  if (server_fd = get_server_socket("or1ksim", "tcp", config.vapi.server_port))
468
    printf("VAPI Server started on port %d\n", config.vapi.server_port);
469 304 markom
  else {
470 293 markom
    perror ("Connection");
471 304 markom
    return 1;
472
  }
473
 
474
  rebuild_fds ();
475
  return 0;
476
}
477
 
478
/* Closes the VAPI */
479
void vapi_done ()
480
{
481
  int i;
482
  struct vapi_handler *t = vapi_handler;
483 293 markom
 
484 304 markom
  for (i = 0; i < nfds; i++)
485
    if (fds[i].fd)
486 306 markom
      close (fds[i].fd);
487 304 markom
  server_fd = 0;
488
  config.vapi.enabled = 0;
489
  serverIP = 0;
490
  free (fds);
491
  fds = 0;
492
  while (vapi_handler) {
493
    t = vapi_handler;
494
    vapi_handler = vapi_handler->next;
495
    free (t);
496
  }
497 293 markom
}
498
 
499
/* Installs a vapi handler to VAPI id */
500 336 markom
void vapi_install_handler (unsigned long id, void (*read_func) (unsigned long, unsigned long))
501 304 markom
{
502 293 markom
  struct vapi_handler *tt;
503 304 markom
  if (read_func == NULL) {
504
    struct vapi_handler **t = &vapi_handler;
505 293 markom
    while ((*t) && (*t)->id != id)
506
      t = &(*t)->next;
507
    if (!t) {
508
      fprintf (stderr, "Cannot uninstall VAPI read handler from id %x\n", id);
509
      exit (1);
510
    }
511
    tt = *t;
512
    (*t) = (*t)->next;
513
    free (tt);
514 304 markom
    nhandlers--;
515 293 markom
  } else {
516 304 markom
    tt = add_handler (id);
517 293 markom
    tt->read_func = read_func;
518
  }
519
}
520
 
521 304 markom
/* Returns number of unconnected handles.  */
522 336 markom
int vapi_num_unconnected (int printout)
523 304 markom
{
524
  struct vapi_handler *t = vapi_handler;
525
  int numu = 0;
526 336 markom
  for (; t; t = t->next) {
527
    if (!t->fd) {
528
      numu++;
529
      if (printout) printf (" %x", t->id);
530
    }
531
  }
532 304 markom
  return numu;
533
}
534
 
535 305 markom
/* Sends a packet to specified test */
536
int vapi_send (unsigned long id, unsigned long data)
537
{
538
  write_packet (id, data);
539
}
540
 
541
 
542
/*
543 304 markom
int main ()
544
{
545
  config.vapi.enabled = 1;
546
  config.vapi.server_port = 9999;
547 293 markom
  vapi_init ();
548
  while (1) {
549
    vapi_check();
550 304 markom
    usleep(1);
551 293 markom
  }
552
  vapi_done ();
553 335 markom
}*/

powered by: WebSVN 2.1.0

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