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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_47/] [or1ksim/] [vapi/] [vapi.c] - Blame information for rev 440

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

powered by: WebSVN 2.1.0

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