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 551

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 439 erez
#include "vapi.h"
45 293 markom
 
46 304 markom
static unsigned int serverIP = 0;
47 293 markom
 
48 304 markom
static unsigned int server_fd = 0;
49
static unsigned int nhandlers = 0;
50
 
51 293 markom
static int tcp_level = 0;
52
 
53 304 markom
static struct vapi_handler {
54
  int fd;
55 477 erez
  unsigned long base_id, num_ids;
56 336 markom
  void (*read_func)(unsigned long, unsigned long);
57 293 markom
  struct vapi_handler *next;
58 304 markom
  int temp;
59 442 erez
} *vapi_handler = NULL;
60 293 markom
 
61 304 markom
/* Structure for polling, it is cached, that it doesn't have to be rebuilt each time */
62
static struct pollfd *fds = NULL;
63
static int nfds = 0;
64
 
65
/* Rebuilds the fds structures; see fds.  */
66
void rebuild_fds () {
67
  struct vapi_handler *t;
68
  if (fds)
69
    free (fds);
70
  fds = (struct pollfd *) malloc (sizeof (struct pollfd) * (nhandlers + 1));
71
  if (!fds) {
72
    fprintf (stderr, "FATAL: Out of memory.\n");
73
    exit (1);
74
  }
75
 
76
  nfds = 0;
77
  fds[nfds].fd = server_fd;
78
  fds[nfds].events = POLLIN;
79
  fds[nfds++].revents = 0;
80
 
81
  for (t = vapi_handler; t; t = t->next) {
82
    if (t->fd) {
83
      t->temp = nfds;
84
      fds[nfds].fd = t->fd;
85
      fds[nfds].events = POLLIN;
86
      fds[nfds++].revents = 0;
87
    } else
88
      t->temp = -1;
89
  }
90
}
91
 
92 477 erez
/* Determines whether a certain handler handles an ID */
93
static inline int handler_fits_id( const struct vapi_handler *t, unsigned long id ) {
94
  return ((id >= t->base_id) && (id < t->base_id + t->num_ids));
95
}
96
 
97 304 markom
/* Finds a handler with given ID, return it, NULL if not found.  */
98
static struct vapi_handler *find_handler (unsigned long id) {
99
  struct vapi_handler *t = vapi_handler;
100 477 erez
  while (t && !handler_fits_id (t, id))
101 304 markom
    t = t->next;
102
  return t;
103
}
104
 
105
/* Adds a handler with given id and returns it.  */
106 477 erez
static struct vapi_handler *add_handler (unsigned long base_id, unsigned long num_ids) {
107 304 markom
  struct vapi_handler **t = &vapi_handler;
108
  struct vapi_handler *tt;
109
  while ((*t))
110
    t = &(*t)->next;
111
  tt = (struct vapi_handler *)malloc (sizeof (struct vapi_handler));
112
  tt->next = NULL;
113 477 erez
  tt->base_id = base_id;
114
  tt->num_ids = num_ids;
115 304 markom
  tt->read_func = NULL;
116
  tt->fd = 0;
117
  (*t) = tt;
118
  free (fds);
119
  fds = NULL;
120
  nhandlers++;
121
  rebuild_fds ();
122
  return tt;
123
}
124
 
125 439 erez
void vapi_write_log_file(VAPI_COMMAND command, unsigned long devid, unsigned long data)
126 419 erez
{
127 439 erez
  if (!runtime.vapi.vapi_file)
128
    return;
129 477 erez
  if (!config.vapi.hide_device_id && devid <= VAPI_MAX_DEVID)
130 440 erez
    fprintf (runtime.vapi.vapi_file, "%04x", devid);
131 439 erez
  fprintf (runtime.vapi.vapi_file, "%1x%08x\n", command, data);
132 419 erez
}
133
 
134 304 markom
static int vapi_write_stream(int fd, void* buf, int len)
135
{
136
  int n;
137
  char* w_buf = (char*)buf;
138
  struct pollfd block;
139
 
140
  while(len) {
141
    if((n = write(fd, w_buf, len)) < 0) {
142
      switch(errno) {
143
      case EWOULDBLOCK: /* or EAGAIN */
144
        /* We've been called on a descriptor marked
145
           for nonblocking I/O. We better simulate
146
           blocking behavior. */
147
        block.fd = fd;
148
        block.events = POLLOUT;
149
        block.revents = 0;
150
        poll(&block,1,-1);
151
        continue;
152
      case EINTR:
153
        continue;
154
      case EPIPE:
155
        close(fd);
156
        fd = 0;
157
        return -1;
158
      default:
159
        return -1;
160
      }
161
    } else {
162
      len -= n;
163
      w_buf += n;
164
    }
165
  }
166
  return 0;
167
}
168
 
169
static int vapi_read_stream(int fd, void* buf, int len)
170
{
171
  int n;
172
  char* r_buf = (char*)buf;
173
  struct pollfd block;
174
 
175
  while(len) {
176
    if((n = read(fd,r_buf,len)) < 0) {
177
      switch(errno) {
178
      case EWOULDBLOCK: /* or EAGAIN */
179
        /* We've been called on a descriptor marked
180
           for nonblocking I/O. We better simulate
181
           blocking behavior. */
182
        block.fd = fd;
183
        block.events = POLLIN;
184
        block.revents = 0;
185
        poll(&block,1,-1);
186
        continue;
187
      case EINTR:
188
        continue;
189
      default:
190
        return -1;
191
      }
192
    } else if(n == 0) {
193
      close(fd);
194
      fd = 0;
195
      return -1;
196
    } else {
197
      len -= n;
198
      r_buf += n;
199
    }
200
  }
201
  return 0;
202
}
203
 
204 293 markom
/* Added by CZ 24/05/01 */
205
int get_server_socket(const char* name,const char* proto,int port)
206
{
207
  struct servent *service;
208
  struct protoent *protocol;
209
  struct sockaddr_in sa;
210
  struct hostent *hp;
211
  int sockfd;
212
  char myname[256];
213
  int flags;
214
  char sTemp[256];
215
 
216
  /* First, get the protocol number of TCP */
217
  if(!(protocol = getprotobyname(proto))) {
218
    sprintf(sTemp,"Unable to load protocol \"%s\"",proto);
219
    perror(sTemp);
220
    return 0;
221
  }
222
  tcp_level = protocol->p_proto; /* Save for later */
223
 
224
  /* If we weren't passed a non standard port, get the port
225
     from the services directory. */
226
  if(!port) {
227
    if(service = getservbyname(name,protocol->p_name))
228
      port = ntohs(service->s_port);
229
  }
230 336 markom
 
231 293 markom
  /* Create the socket using the TCP protocol */
232
  if((sockfd = socket(PF_INET,SOCK_STREAM,protocol->p_proto)) < 0) {
233
    perror("Unable to create socket");
234
    return 0;
235
  }
236 336 markom
 
237 293 markom
  flags = 1;
238
  if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0) {
239
    sprintf(sTemp,"Can not set SO_REUSEADDR option on socket %d",sockfd);
240
    perror(sTemp);
241
    close(sockfd);
242
    return 0;
243
  }
244
 
245
  /* The server should also be non blocking. Get the current flags. */
246
  if(fcntl(sockfd,F_GETFL,&flags) < 0) {
247
    sprintf(sTemp,"Unable to get flags for socket %d",sockfd);
248
    perror(sTemp);
249
    close(sockfd);
250
    return 0;
251
  }
252
 
253
  /* Set the nonblocking flag */
254
  if(fcntl(sockfd,F_SETFL, flags | O_NONBLOCK) < 0) {
255
    sprintf(sTemp,"Unable to set flags for socket %d to value 0x%08x",
256
            sockfd,flags | O_NONBLOCK);
257
    perror(sTemp);
258
    close(sockfd);
259
    return 0;
260
  }
261
 
262
  /* Find out what our address is */
263
  memset(&sa,0,sizeof(struct sockaddr_in));
264
  gethostname(myname,sizeof(myname));
265
  if(!(hp = gethostbyname(myname))) {
266
    perror("Unable to read hostname");
267
    close(sockfd);
268
    return 0;
269
  }
270
 
271
  /* Bind our socket to the appropriate address */
272
  sa.sin_family = hp->h_addrtype;
273
  sa.sin_port = htons(port);
274
  if(bind(sockfd,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)) < 0) {
275
    sprintf(sTemp,"Unable to bind socket %d to port %d",sockfd,port);
276
    perror(sTemp);
277
    close(sockfd);
278
    return 0;
279
  }
280
  serverIP = sa.sin_addr.s_addr;
281
  flags = sizeof(struct sockaddr_in);
282
  if(getsockname(sockfd,(struct sockaddr*)&sa,&flags) < 0) {
283
    sprintf(sTemp,"Unable to get socket information for socket %d",sockfd);
284
    perror(sTemp);
285
    close(sockfd);
286
    return 0;
287
  }
288 551 markom
  runtime.vapi.server_port = ntohs(sa.sin_port);
289 293 markom
 
290
  /* Set the backlog to 1 connections */
291
  if(listen(sockfd,1) < 0) {
292
    sprintf(sTemp,"Unable to set backlog on socket %d to %d",sockfd,1);
293
    perror(sTemp);
294
    close(sockfd);
295
    return 0;
296
  }
297
 
298
  return sockfd;
299
}
300
 
301 442 erez
static void server_request()
302 293 markom
{
303
  struct sockaddr_in sa;
304
  struct sockaddr* addr = (struct sockaddr*)&sa;
305
  int n = sizeof(struct sockaddr_in);
306 336 markom
  int fd = accept(server_fd, addr, &n);
307 293 markom
  int on_off = 0; /* Turn off Nagel's algorithm on the socket */
308
  int flags;
309
  char sTemp[256];
310
 
311
  if(fd < 0) {
312
    /* This is valid, because a connection could have started,
313
       and then terminated due to a protocol error or user
314
       initiation before the accept could take place. */
315
    if(errno != EWOULDBLOCK && errno != EAGAIN) {
316
      perror("accept");
317
      close(server_fd);
318
      server_fd = 0;
319 551 markom
      runtime.vapi.enabled = 0;
320 293 markom
      serverIP = 0;
321 336 markom
    }
322 293 markom
    return;
323
  }
324
 
325
  if(fcntl(fd,F_GETFL,&flags) < 0) {
326
    sprintf(sTemp,"Unable to get flags for vapi socket %d",fd);
327
    perror(sTemp);
328
    close(fd);
329
    return;
330
  }
331
 
332
  if(fcntl(fd,F_SETFL, flags | O_NONBLOCK) < 0) {
333
    sprintf(sTemp,"Unable to set flags for vapi socket %d to value 0x%08x",
334
            fd,flags | O_NONBLOCK);
335
    perror(sTemp);
336
    close(fd);
337
    return;
338
  }
339
 
340
  if(setsockopt(fd,tcp_level,TCP_NODELAY,&on_off,sizeof(int)) < 0) {
341
    sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",fd);
342
    perror(sTemp);
343
    close(fd);
344
    return;
345
  }
346 304 markom
 
347
  /* Install new handler */
348
  {
349
    unsigned long id;
350
    struct vapi_handler *t;
351
    if (vapi_read_stream (fd, &id, sizeof (id))) {
352
      perror ("Cannot get id");
353
      close (fd);
354
      return;
355 293 markom
    }
356 304 markom
    t = find_handler (id);
357 355 markom
    if (t) {
358 304 markom
      if (t->fd) {
359
        fprintf (stderr, "WARNING: Test with id %x already connected. Ignoring.\n", id);
360
        close (fd);
361
        return;
362 355 markom
      } else {
363
        t->fd = fd;
364
        rebuild_fds ();
365
      }
366
    } else {
367
      fprintf (stderr, "WARNING: Test with id %x not registered. Ignoring.\n", id);
368
      close(fd); /* kill the connection */
369
      return;
370 293 markom
    }
371 304 markom
    if(config.sim.verbose)
372 336 markom
      printf ("\nConnection with test (id %x) established.\n", id);
373 293 markom
  }
374
}
375
 
376
static int write_packet (unsigned long id, unsigned long data) {
377 304 markom
  struct vapi_handler *t = find_handler (id);
378
  if (!t || !t->fd)
379
    return 1;
380 293 markom
  id = htonl (id);
381 304 markom
  if (vapi_write_stream(t->fd, &id, sizeof (id)) < 0)
382 293 markom
    return 1;
383
  data = htonl (data);
384 304 markom
  if (vapi_write_stream(t->fd, &data, sizeof (data)) < 0)
385 293 markom
    return 1;
386
  return 0;
387 442 erez
}
388 293 markom
 
389 442 erez
static int read_packet (int fd, unsigned long *id, unsigned long *data)
390
{
391 477 erez
  if (fd <= 0)
392 293 markom
    return 1;
393 477 erez
  if (vapi_read_stream(fd, id, sizeof(unsigned long)) < 0)
394 293 markom
    return 1;
395 442 erez
  *id = ntohl (*id);
396 477 erez
  if (vapi_read_stream(fd, data, sizeof(unsigned long)) < 0)
397 304 markom
    return 1;
398 442 erez
  *data = ntohl (*data);
399 293 markom
  return 0;
400 304 markom
}
401 293 markom
 
402 442 erez
static void vapi_request (struct vapi_handler *t)
403
{
404
  unsigned long id, data;
405
 
406
  if (read_packet(t->fd, &id, &data)) {
407 477 erez
    if (t->fd > 0) {
408 293 markom
      perror("vapi read");
409 304 markom
      close(t->fd);
410
      t->fd = 0;
411 361 markom
      rebuild_fds ();
412 293 markom
    }
413
    return;
414
  }
415
 
416 442 erez
  vapi_write_log_file (VAPI_COMMAND_REQUEST, id, data);
417
  debug (4, "[%08x, %08x]\n", id, data);
418
 
419
  /* This packet may be for another handler */
420 477 erez
  if (!handler_fits_id (t, id))
421 442 erez
    t = find_handler (id);
422
  if (!t || !t->read_func)
423
    fprintf (stderr, "WARNING: Received packet for undefined id %08x, data %08x\n", id, data);
424 293 markom
  else
425 442 erez
    t->read_func(id, data);
426 293 markom
}
427
 
428
void vapi_check ()
429
{
430 304 markom
  struct vapi_handler *t;
431 293 markom
 
432 304 markom
  if (!server_fd || !fds) {
433
    fprintf (stderr, "FATAL: Unable to maintain VAPI server.\n");
434
    exit (1);
435 293 markom
  }
436
 
437 361 markom
  debug(5, ".");
438 355 markom
 
439 304 markom
  /* Handle everything in queue. */
440 293 markom
  while(1) {
441 304 markom
    switch(poll(fds, nfds, 0)) {
442 293 markom
    case -1:
443
      if(errno == EINTR)
444
        continue;
445
      perror("poll");
446 304 markom
      if (server_fd)
447
        close(server_fd);
448 551 markom
      runtime.vapi.enabled = 0;
449 304 markom
      serverIP = 0;
450
      return;
451 293 markom
    case 0: /* Nothing interesting going on */
452
      return;
453
    default:
454 304 markom
      /* Handle the vapi ports first. */
455
      for (t = vapi_handler; t; t = t->next)
456
        if (t->temp >= 0 && fds[t->temp].revents)
457
          vapi_request (t);
458 293 markom
 
459 304 markom
      if(fds[0].revents) {
460 293 markom
        if(fds[0].revents & POLLIN)
461
          server_request();
462
        else { /* Error Occurred */
463 304 markom
          fprintf(stderr,"Received flags 0x%08x on server. Shutting down.\n", fds[0].revents);
464
          if (server_fd)
465
            close(server_fd);
466 293 markom
          server_fd = 0;
467 551 markom
          runtime.vapi.enabled = 0;
468 293 markom
          serverIP = 0;
469
        }
470
      }
471
      break;
472
    } /* End of switch statement */
473
  } /* End of while statement */
474
}
475
 
476 304 markom
/* Inits the VAPI, according to sim-config */
477
int vapi_init ()
478 293 markom
{
479 304 markom
  nhandlers = 0;
480
  vapi_handler = NULL;
481 551 markom
  if (!runtime.vapi.enabled)
482 304 markom
    return 0; /* Nothing to do */
483
 
484 551 markom
  runtime.vapi.server_port = config.vapi.server_port;
485
  if (!runtime.vapi.server_port) {
486 304 markom
    fprintf (stderr, "WARNING: server_port = 0, shutting down VAPI\n");
487 551 markom
    runtime.vapi.enabled = 0;
488 304 markom
    return 1;
489
  }
490 551 markom
  if (server_fd = get_server_socket("or1ksim", "tcp", runtime.vapi.server_port))
491
    printf("VAPI Server started on port %d\n", runtime.vapi.server_port);
492 304 markom
  else {
493 293 markom
    perror ("Connection");
494 304 markom
    return 1;
495
  }
496
 
497
  rebuild_fds ();
498 355 markom
 
499 361 markom
  if ((runtime.vapi.vapi_file = fopen (config.vapi.vapi_fn, "wt+")) == NULL)
500 355 markom
    fprintf (stderr, "WARNING: cannot open VAPI log file\n");
501
 
502 304 markom
  return 0;
503
}
504
 
505
/* Closes the VAPI */
506
void vapi_done ()
507
{
508
  int i;
509
  struct vapi_handler *t = vapi_handler;
510 293 markom
 
511 304 markom
  for (i = 0; i < nfds; i++)
512
    if (fds[i].fd)
513 306 markom
      close (fds[i].fd);
514 304 markom
  server_fd = 0;
515 551 markom
  runtime.vapi.enabled = 0;
516 304 markom
  serverIP = 0;
517
  free (fds);
518
  fds = 0;
519 361 markom
  if (runtime.vapi.vapi_file) {
520
    /* Mark end of simulation */
521 442 erez
    vapi_write_log_file (VAPI_COMMAND_END, 0, 0);
522 361 markom
    fclose (runtime.vapi.vapi_file);
523
  }
524 355 markom
 
525 304 markom
  while (vapi_handler) {
526
    t = vapi_handler;
527
    vapi_handler = vapi_handler->next;
528
    free (t);
529
  }
530 293 markom
}
531
 
532 477 erez
/* Installs a vapi handler for one VAPI id */
533 336 markom
void vapi_install_handler (unsigned long id, void (*read_func) (unsigned long, unsigned long))
534 304 markom
{
535 477 erez
  vapi_install_multi_handler (id, 1, read_func);
536
}
537
 
538
/* Installs a vapi handler for many VAPI id */
539
void vapi_install_multi_handler (unsigned long base_id, unsigned long num_ids, void (*read_func) (unsigned long, unsigned long))
540
{
541 293 markom
  struct vapi_handler *tt;
542 355 markom
 
543 477 erez
  debug(4, "vapi_install_handler %08x, %u, %08x\n", base_id, num_ids, read_func);
544 304 markom
  if (read_func == NULL) {
545
    struct vapi_handler **t = &vapi_handler;
546 477 erez
    while ((*t) && !handler_fits_id (*t, base_id))
547 293 markom
      t = &(*t)->next;
548
    if (!t) {
549 477 erez
      fprintf (stderr, "Cannot uninstall VAPI read handler from id %x\n", base_id);
550 293 markom
      exit (1);
551
    }
552
    tt = *t;
553
    (*t) = (*t)->next;
554
    free (tt);
555 304 markom
    nhandlers--;
556 293 markom
  } else {
557 477 erez
    tt = find_handler (base_id);
558 355 markom
    if (!tt) {
559 477 erez
      tt = add_handler (base_id, num_ids);
560 355 markom
      tt->read_func = read_func;
561
    } else {
562
      tt->read_func = read_func;
563
      rebuild_fds ();
564
    }
565 293 markom
  }
566
}
567
 
568 304 markom
/* Returns number of unconnected handles.  */
569 336 markom
int vapi_num_unconnected (int printout)
570 304 markom
{
571
  struct vapi_handler *t = vapi_handler;
572
  int numu = 0;
573 336 markom
  for (; t; t = t->next) {
574
    if (!t->fd) {
575
      numu++;
576 477 erez
      if (printout) {
577
        if ( t->num_ids == 1 )
578
          printf (" 0x%x", t->base_id);
579
        else
580
          printf (" 0x%x..0x%x", t->base_id, t->base_id + t->num_ids - 1);
581
      }
582 336 markom
    }
583
  }
584 304 markom
  return numu;
585
}
586
 
587 305 markom
/* Sends a packet to specified test */
588
int vapi_send (unsigned long id, unsigned long data)
589
{
590 355 markom
  debug (4, "vapi_send [%08x %08x]\n", id, data);
591 442 erez
  vapi_write_log_file (VAPI_COMMAND_SEND, id, data);
592 305 markom
  write_packet (id, data);
593
}
594
 
595
/*
596 304 markom
int main ()
597
{
598 551 markom
  runtime.vapi.enabled = 1;
599 304 markom
  config.vapi.server_port = 9999;
600 293 markom
  vapi_init ();
601
  while (1) {
602
    vapi_check();
603 304 markom
    usleep(1);
604 293 markom
  }
605
  vapi_done ();
606 335 markom
}*/

powered by: WebSVN 2.1.0

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