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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_52/] [or1ksim/] [vapi/] [vapi.c] - Blame information for rev 335

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

powered by: WebSVN 2.1.0

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