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 419

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

powered by: WebSVN 2.1.0

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