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

Subversion Repositories or1k

[/] [or1k/] [branches/] [stable_0_2_x/] [or1ksim/] [vapi/] [vapi.c] - Blame information for rev 442

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

powered by: WebSVN 2.1.0

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