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 1147

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

powered by: WebSVN 2.1.0

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