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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [verilog/] [vpi/] [c/] [jp_vpi.c] - Blame information for rev 40

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 40 julius
/*$$HEADER*/
2
/******************************************************************************/
3
/*                                                                            */
4
/*                    H E A D E R   I N F O R M A T I O N                     */
5
/*                                                                            */
6
/******************************************************************************/
7
 
8
// Project Name                   : ORPSoCv2
9
// File Name                      : jp_vpi.c
10
// Prepared By                    : jb, jb@orsoc.se
11
// Project Start                  : 2009-05-01
12
 
13
/*$$COPYRIGHT NOTICE*/
14
/******************************************************************************/
15
/*                                                                            */
16
/*                      C O P Y R I G H T   N O T I C E                       */
17
/*                                                                            */
18
/******************************************************************************/
19
/*
20
  This library is free software; you can redistribute it and/or
21
  modify it under the terms of the GNU Lesser General Public
22
  License as published by the Free Software Foundation;
23
  version 2.1 of the License, a copy of which is available from
24
  http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
25
 
26
  This library is distributed in the hope that it will be useful,
27
  but WITHOUT ANY WARRANTY; without even the implied warranty of
28
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29
  Lesser General Public License for more details.
30
 
31
  You should have received a copy of the GNU Lesser General Public
32
  License along with this library; if not, write to the Free Software
33
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
34
*/
35
 
36
/*$$DESCRIPTION*/
37
/******************************************************************************/
38
/*                                                                            */
39
/*                           D E S C R I P T I O N                            */
40
/*                                                                            */
41
/******************************************************************************/
42
//
43
// Implements communication between verilog simulator and RSP server
44
//
45
//
46
/*
47
Functions used via the Verilog Procedural Interface (VPI), in a verilog
48
simulation of an OpenRISC processor, providing a means of communication to the
49
simulatin for a GDB stub.
50
 
51
The communication between the GDB stub and this module is via a "custom"
52
protocol, which is decoded into the verilog debug task module and the
53
appropriate transactions are performed with the debug interface inside the
54
OpenRISC design.
55
 
56
Operation:
57
See the verilog file containing the calls to the VPI tasks  we outline in this
58
file for exact details of how they are  used (debug_vpi_module.v), but
59
following is a brief outline of how it is meant to work.
60
 
61
The RSP GDB stub is initialised after compile via a VPI callback
62
(cbEndOfCompile). A process is forked off to run the RSP server, and IPC is via
63
pipes. Note: This is probably an extremely ineffecient way to do this as the
64
fork() creates a copy of the program, including it's ~200MB memory space, so
65
maybe a different method should be worked out for massive sims, but for smaller
66
OpenRISC designs on a power machine this is not a problem.
67
 
68
The verilog debug module polls for incoming commands from the GDB stub at a
69
#delay rate set in the verilog code.
70
 
71
The port which the GDB server runs on is #define'd in this file by
72
RSP_SERVER_PORT.
73
 
74
When a GDB connection is established, the state of the processor is downloaded
75
by GDB, so expect a slight delay after connection.
76
 
77
To close down the simulation gracefully, issue a "detach" command from GDB.
78
This will close the connection with the stub and will also send a message to
79
$finish the simulation.
80
 
81
Note: Simulation reset is untested, but should probably work OK.
82
 
83
Note: Reading uninitialised memory which returns Xs will break things.
84
Specifically, the CRC generation breaks, and then many other things. So to help
85
avoid hours of X tracing, ensure you're reading initialised space from GDB.
86
 
87
To Do:
88
* Comment this better! Sorry, it's a little lacking in this area.
89
* Block transfers (ie. what happens when "load"ing from GDB) ignore any bytes
90
  over the word boundary at the end of a transfer. Currently a warning printf
91
  will appear.
92
* Make the RSP server process not be a complete copy of the vvp image - ie.
93
  don't fork() in the sim, maybe compile and exec() a separate app for this.
94
 
95
*/
96
 
97
 
98
/* EXAMPLE
99
// Associate C Function with a New System Task
100
voi
101
d registerHelloSystfs() {
102
  s_vpi_systf_data task_data_s;
103
  p_vpi_systf_data task_data_p = &task_data_s;
104
  task_data_p->type = vpiSysTask;
105
  task_data_p->tfname = "$hello";
106
  task_data_p->calltf = hello;
107
  task_data_p->compiletf = 0;
108
 
109
  vpi_register_systf(task_data_p);
110
}
111
 
112
*/
113
 
114
 
115
/*
116
To associate your C function with a system task, create a
117
data structure of type s_vpi_systf_data and a pointer to
118
that structure. The vpi_systf_data data type is defined in
119
the vpi_user.h include file. Below is the data structure
120
of s_vpi_systf_data.
121
 
122
 typedef struct t_vpi_systf_data {
123
   PLI_INT32 type;     // vpiSysTask, vpiSysFunc - task not return val, Func does
124
   PLI_INT32 sysfunctype; // vpiSysTask, vpi[Int,Real,Time,Sized, SizedSigned]Func - if it's a func, this is the typ of return
125
   PLI_BYTE8 *tfname;  // First character must be `$'
126
   PLI_INT32 (*calltf)(PLI_BYTE8 *); //pointer to the function
127
   PLI_INT32 (*compiletf)(PLI_BYTE8 *); // pointer to a function that the simulator calls
128
                                        // when it's compiled - can be NULL
129
   PLI_INT32 (*sizetf)(PLI_BYTE8 *); // For sized function callbacks only, This field is a
130
                                     // pointer to a routine that returns the size, in bits,
131
                                     // of the value that the system task or function returns.
132
   PLI_BYTE8 *user_data; --optional extra data?
133
 } s_vpi_systf_data, *p_vpi_systf_data;
134
*/
135
 
136
 
137
 
138
/*$$CHANGE HISTORY*/
139
/******************************************************************************/
140
/*                                                                            */
141
/*                         C H A N G E  H I S T O R Y                         */
142
/*                                                                            */
143
/******************************************************************************/
144
// Date         Version Description
145
//------------------------------------------------------------------------
146
// 090501               Imported code from "jp" VPI project             jb
147
//                      Changed to use pipes instead of sockets         jb
148
 
149
 
150
 
151
 
152
#include <stdio.h>
153
#include <stdlib.h>
154
#include <errno.h>
155
#include <unistd.h>
156
#include <sys/types.h>
157
#include <sys/wait.h>
158
#include <sys/select.h>
159
#include <sys/poll.h>
160
#include <sys/stat.h>
161
#include <fcntl.h>
162
#include <ctype.h>
163
#include <string.h>
164
#include <stdarg.h>
165
#include <stdint.h>
166
#include <signal.h>
167
#include <inttypes.h>
168
 
169
// VPI includes
170
#include <vpi_user.h>
171
 
172
#ifdef CDS_VPI
173
// Cadence ncverilog specific include
174
#include <vpi_user_cds.h>
175
#endif
176
 
177
// Includes for the RSP server side of things
178
#include "gdb.h"
179
#include "rsp-rtl_sim.h"
180
#include "rsp-vpi.h"
181
 
182
// Define the port we open the RSP server on
183
#define RSP_SERVER_PORT 5555
184
 
185
//Function to register the function which sets up the sockets interface
186
void register_init_rsp_server_functions() ;
187
// Function which sets up the socket interface
188
void init_rsp_server();
189
//install a callback on simulation reset which calls setup
190
void setup_reset_callbacks();
191
//install a callback on simulation compilation finish
192
void setup_endofcompile_callbacks();
193
//install a callback on simulation finish
194
void setup_finish_callbacks();
195
//callback function which closes and clears the socket file descriptors
196
// on simulation reset
197
void sim_reset_callback();
198
void sim_endofcompile_callback();
199
void sim_finish_callback();
200
 
201
void register_check_for_command();
202
void register_get_command_address();
203
void register_get_command_data();
204
void register_return_command_block_data();
205
void register_return_command_data();
206
void register_get_command_block_data();
207
void register_return_response();
208
 
209
void check_for_command();
210
void get_command_address();
211
void get_command_data();
212
void get_command_block_data();
213
void return_command_data();
214
void return_command_block_data();
215
void return_response();
216
 
217
 
218
#include <time.h>
219
 
220
int vpi_to_rsp_pipe[2]; // [0] - read, [1] - write
221
int rsp_to_vpi_pipe[2]; // [0] - read, [1] - write
222
int command_pipe[2]; // RSP end writes, VPI end reads ONLY
223
 
224
/* Global static to store the child rsp server PID if we want to kill it */
225
static pid_t rsp_server_child_pid = (pid_t) 0; // pid_t is just a signed int
226
 
227
 
228
/********************************************************************/
229
/* init_rsp_server
230
 *
231
 * Fork off the rsp server process
232
 *                                                                   /
233
/********************************************************************/
234
void init_rsp_server(){
235
 
236
 
237
  // First get the port number to start the RSP server on
238
 
239
  vpiHandle systfref, args_iter, argh;
240
 
241
  struct t_vpi_value argval;
242
 
243
  int value,i;
244
 
245
  int n;
246
 
247
  int portNum;
248
 
249
  char* send_buf;
250
 
251
  /*
252
 
253
  // Currently removed - ability to call $rsp_init_server() with a
254
  // port number as parameter. Hardcoded allows us to run this as
255
  // a callback after compiile (cbEndOfCompile)
256
 
257
  // Obtain a handle to the argument list
258
  systfref = vpi_handle(vpiSysTfCall, NULL);
259
 
260
  // Now call iterate with the vpiArgument parameter
261
  args_iter = vpi_iterate(vpiArgument, systfref);
262
 
263
  // get a handle on the object passed to the function
264
  argh = vpi_scan(args_iter);
265
 
266
  // now store the command value back in the sim
267
  argval.format = vpiIntVal;
268
 
269
  // Now set the data value
270
  vpi_get_value(argh, &argval);
271
 
272
  portNum = (int) argval.value.integer;
273
 
274
  // Cleanup and return
275
  vpi_free_object(args_iter);
276
 
277
  // We should now have our port number.
278
 
279
  */
280
 
281
  // Fork. Let the child run the RSP server
282
  pid_t pid;
283
  int rv;
284
 
285
  if(DBG_ON) printf("jp_vpi: init_rsp_server\n");
286
 
287
  // Setup pipes
288
  if(pipe(vpi_to_rsp_pipe) == -1)
289
    {
290
      perror("jp_vpi: init_rsp_server pipes");
291
      exit(1);
292
    }
293
  if(pipe(rsp_to_vpi_pipe) == -1)
294
    {
295
      perror("jp_vpi: init_rsp_server pipes");
296
      exit(1);
297
    }
298
  if(pipe(command_pipe) == -1)
299
    {
300
      perror("jp_vpi: init_rsp_server pipes");
301
      exit(1);
302
    }
303
 
304
  // Set command pipe to be non-blocking
305
#if defined (STRIDE) || (defined (pfa) && defined (HAVE_PTYS)) || defined (AIX)
306
  {
307
    int one = 1;
308
    ioctl (command_pipe[0], FIONBIO, &one);
309
  }
310
#endif
311
 
312
#ifdef O_NONBLOCK /* The POSIX way */
313
  fcntl (command_pipe[0], F_SETFL, O_NONBLOCK);
314
#elif defined (O_NDELAY)
315
  fcntl (command_pipe[0], F_SETFL, O_NDELAY);
316
#endif /* O_NONBLOCK */
317
 
318
  // Check on the child process. If it has not been started it will
319
  // be 0, else it will be something else and we'll just return
320
  if ((int) rsp_server_child_pid > 0)
321
    return;
322
 
323
  switch(pid=fork())
324
    {
325
    case -1:
326
      perror("fork");
327
      exit(1);
328
      break;
329
    case 0: // Child
330
      run_rsp_server(RSP_SERVER_PORT);
331
      // exit if it ever returns, which it shouldn't
332
      exit(0);
333
      break;
334
    default:
335
      //  We're the parent process, so continue on.
336
      rsp_server_child_pid = pid;
337
      break;
338
    }
339
 
340
  // Parent will only ever get this far...
341
 
342
  return;
343
 
344
}
345
 
346
void register_init_rsp_server_functions() {
347
  s_vpi_systf_data data = {vpiSysTask,
348
                           0,
349
                           "$init_rsp_server",
350
                           (void *)init_rsp_server,
351
                           0,
352
                           0,
353
                           0};
354
 
355
  vpi_register_systf(&data);
356
 
357
  return;
358
}
359
 
360
void print_command_string(unsigned char cmd)
361
{
362
  switch(cmd)
363
    {
364
    case 0x1 :
365
      printf("  TAP instruction register set\n");
366
      break;
367
    case 0x2 :
368
      printf("  set debug chain\n");
369
      break;
370
    case 0x3 :
371
      printf("  CPU control (stall/reset) reg write\n");
372
      break;
373
    case 0x4 :
374
      printf("  CPU control (stall/reset) reg read\n");
375
      break;
376
    case 0x5 :
377
      printf("  CPU reg write\n");
378
      break;
379
    case 0x6 :
380
      printf("  CPU reg read\n");
381
      break;
382
    case 0x7 :
383
      printf("  WB write 32\n");
384
      break;
385
    case 0x8 :
386
      printf("  WB read 32\n");
387
      break;
388
    case 0x9 :
389
      printf("  WB block write 32\n");
390
      break;
391
    case 0xa :
392
      printf("  WB block read 32\n");
393
      break;
394
    case 0xb :
395
      printf("  reset\n");
396
      break;
397
    case 0xc :
398
      printf("  read jtag id\n");
399
      break;
400
    }
401
}
402
 
403
// See if there's anything on the FIFO for us
404
 
405
void check_for_command(char *userdata){
406
 
407
  vpiHandle systfref, args_iter, argh;
408
 
409
  struct t_vpi_value argval;
410
 
411
  int value,i;
412
 
413
  int n;
414
 
415
  unsigned char data;
416
 
417
  //if(DBG_ON) printf("check_for_command\n");
418
 
419
  //n = read(rsp_to_vpi_pipe[0], &data, 1);
420
 
421
  n = read(command_pipe[0], &data, 1);
422
 
423
  if ( ((n < 0) && (errno == EAGAIN)) || (n==0) )
424
    {
425
      // Nothing in the fifo this time, let's return
426
      return;
427
    }
428
  else if (n < 0)
429
    {
430
      // some sort of error
431
      perror("check_for_command");
432
 
433
      exit(1);
434
    }
435
 
436
  if (DBG_ON)
437
  {
438
    printf("jp_vpi: c = %x:",data);
439
    print_command_string(data);
440
    fflush(stdout);
441
  }
442
 
443
  // Return the command to the sim
444
 
445
  // Obtain a handle to the argument list
446
  systfref = vpi_handle(vpiSysTfCall, NULL);
447
 
448
  // Now call iterate with the vpiArgument parameter
449
  args_iter = vpi_iterate(vpiArgument, systfref);
450
 
451
  // get a handle on the variable passed to the function
452
  argh = vpi_scan(args_iter);
453
 
454
  // now store the command value back in the sim
455
  argval.format = vpiIntVal;
456
 
457
  // Now set the command value
458
  vpi_get_value(argh, &argval);
459
 
460
  argval.value.integer = (unsigned int) data;
461
 
462
  // And vpi_put_value() it back into the sim
463
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
464
 
465
  // Cleanup and return
466
  vpi_free_object(args_iter);
467
 
468
  n = write(vpi_to_rsp_pipe[1],&data,1);
469
  if (DBG_ON) printf("jp_vpi: r");
470
 
471
  if (DBG_ON) printf("\n");
472
 
473
  return;
474
}
475
 
476
void get_command_address(char *userdata){
477
 
478
  vpiHandle systfref, args_iter, argh;
479
 
480
  struct t_vpi_value argval;
481
 
482
  int value,i;
483
 
484
  int n;
485
 
486
  unsigned int data;
487
 
488
  char* recv_buf;
489
 
490
  recv_buf = (char *) &data; // cast data as our receive char buffer
491
 
492
  n = read(rsp_to_vpi_pipe[0],recv_buf,4);
493
  if (n<0)
494
    {
495
      //client has closed connection
496
      //attempt to close and return gracefully
497
      return;
498
    }
499
 
500
  if (DBG_ON) printf("jp_vpi: get_command_address adr=0x%.8x\n",data);
501
 
502
  // now put the address into the argument passed to the task
503
 
504
  // Obtain a handle to the argument list
505
  systfref = vpi_handle(vpiSysTfCall, NULL);
506
 
507
  // Now call iterate with the vpiArgument parameter
508
  args_iter = vpi_iterate(vpiArgument, systfref);
509
 
510
  // get a handle on the variable passed to the function
511
  argh = vpi_scan(args_iter);
512
 
513
  // now store the command value back in the sim
514
  argval.format = vpiIntVal;
515
 
516
  // Now set the address value
517
  vpi_get_value(argh, &argval);
518
  argval.value.integer = (unsigned int) data;
519
 
520
  // And vpi_put_value() it back into the sim
521
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
522
 
523
  // Cleanup and return
524
  vpi_free_object(args_iter);
525
 
526
   return;
527
 
528
}
529
 
530
void get_command_data(char *userdata){
531
 
532
  vpiHandle systfref, args_iter, argh;
533
 
534
  struct t_vpi_value argval;
535
 
536
  int value,i;
537
 
538
  int n = 0;
539
 
540
  unsigned int data;
541
 
542
  char* recv_buf;
543
 
544
  recv_buf = (char *) &data; // cast data as our receive char buffer
545
 
546
 read_command_data_again:
547
  n = read(rsp_to_vpi_pipe[0],recv_buf,4);
548
 
549
  if ((n < 4) && errno==EAGAIN)
550
    goto read_command_data_again;
551
  else if (n < 4)
552
    {
553
      printf("jp_vpi: get_command_data errno: %d\n",errno);
554
      perror("jp_vpi: get_command_data read failed");
555
    }
556
  if (DBG_ON) printf("jp_vpi: get_command_data = 0x%.8x\n",data);
557
 
558
  // Obtain a handle to the argument list
559
  systfref = vpi_handle(vpiSysTfCall, NULL);
560
 
561
  // Now call iterate with the vpiArgument parameter
562
  args_iter = vpi_iterate(vpiArgument, systfref);
563
 
564
  // get a handle on the variable passed to the function
565
  argh = vpi_scan(args_iter);
566
 
567
  // now store the command value back in the sim
568
  argval.format = vpiIntVal;
569
 
570
  // Now set the data value
571
  vpi_get_value(argh, &argval);
572
  argval.value.integer = (unsigned int) data;
573
 
574
  // And vpi_put_value() it back into the sim
575
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
576
 
577
  // Cleanup and return
578
  vpi_free_object(args_iter);
579
 
580
   return;
581
 
582
}
583
 
584
 
585
void get_command_block_data(){ // $get_command_block_data(length, mem_array)
586
 
587
  vpiHandle systfref, args_iter, argh;
588
 
589
  struct t_vpi_value argval;
590
 
591
  int value,i;
592
 
593
  int n;
594
 
595
  unsigned int data;
596
  unsigned int length;
597
 
598
  char* recv_buf;
599
 
600
  // Now setup the handles to verilog objects and check things
601
  // Obtain a handle to the argument list
602
  systfref = vpi_handle(vpiSysTfCall, NULL);
603
 
604
  // Now call iterate with the vpiArgument parameter
605
  args_iter = vpi_iterate(vpiArgument, systfref);
606
 
607
  // get a handle on the length variable
608
  argh = vpi_scan(args_iter);
609
 
610
  argval.format = vpiIntVal;
611
 
612
  // get the value for the length object
613
  vpi_get_value(argh, &argval);
614
 
615
  // now set length
616
  length = argval.value.integer;
617
 
618
  int num_words = length/4;
619
 
620
  if((length % 4) != 0) vpi_printf("length of %d bytes is not exactly word-aligned\n",length);
621
  // If non-word aligned we throw away remainder
622
  int throw_away_bytes = length %4;
623
 
624
  int loaded_words = 0;
625
 
626
  if(DBG_ON)printf("jp_vpi: get_command_block_data: length=%d, num_words=%d\n",length,num_words);
627
 
628
  // now get a handle on the next object (memory array)
629
  argh = vpi_scan(args_iter);
630
 
631
  // check we got passed a memory (array of regs)
632
  if (vpi_get(vpiType, argh) != vpiMemory)
633
    {
634
      vpi_printf("jp_vpi: ERROR: did not pass a memory to get_command_block_data\n");
635
      return;
636
    }
637
 
638
  // check the memory we're writing into is big enough
639
  if (vpi_get(vpiSize, argh) < num_words )
640
    {
641
      vpi_printf("jp_vpi: ERROR: buffer passed to get_command_block_data too small. size is %d words, needs to be %d\n",
642
                 vpi_get(vpiSize, argh), num_words);
643
      return;
644
    }
645
 
646
  vpiHandle array_word;
647
 
648
  // Loop to load the words
649
  while (loaded_words < num_words) {
650
 
651
    recv_buf = (char *) &data;
652
 
653
    // blocking receive for data block
654
    n = read(rsp_to_vpi_pipe[0],recv_buf,4);
655
 
656
    // now get a handle on the current word we want in the array that was passed to us
657
    array_word = vpi_handle_by_index(argh, loaded_words);
658
 
659
    if (array_word != NULL)
660
      {
661
        argval.value.integer = (unsigned int) data;
662
 
663
        // And vpi_put_value() it back into the sim
664
        vpi_put_value(array_word, &argval, NULL, vpiNoDelay);
665
      }
666
    else
667
      return;
668
 
669
    loaded_words++;
670
  }
671
  // TODO: This is a quick fix, should be delt with properly!!
672
  if (throw_away_bytes)
673
    {
674
      //printf("reading off %d extra data bytes\n",throw_away_bytes);
675
      n = read(rsp_to_vpi_pipe[0],&data,throw_away_bytes);
676
      //printf("read off %d bytes \n",n);
677
    }
678
 
679
  // Cleanup and return
680
  vpi_free_object(args_iter);
681
 
682
  return;
683
 
684
}
685
 
686
void return_command_data(char *userdata){
687
 
688
  vpiHandle systfref, args_iter, argh;
689
 
690
  struct t_vpi_value argval;
691
 
692
  int value,i;
693
 
694
  int n;
695
 
696
  uint32_t data;
697
 
698
  char* send_buf;
699
 
700
  // Obtain a handle to the argument list
701
  systfref = vpi_handle(vpiSysTfCall, NULL);
702
 
703
  // Now call iterate with the vpiArgument parameter
704
  args_iter = vpi_iterate(vpiArgument, systfref);
705
 
706
  // get a handle on the object passed to the function
707
  argh = vpi_scan(args_iter);
708
 
709
  // now store the command value back in the sim
710
  argval.format = vpiIntVal;
711
 
712
  // Now set the data value
713
  vpi_get_value(argh, &argval);
714
 
715
  data = (unsigned int) argval.value.integer;
716
 
717
  // Cleanup and return
718
  vpi_free_object(args_iter);
719
 
720
  if (DBG_ON) printf("jp_vpi: return_command_data 0x%.8x\n",data);
721
 
722
  send_buf = (char *) &data; //cast our long as a char buf
723
 
724
  // write the data back
725
  n = write(vpi_to_rsp_pipe[1],send_buf,4);
726
 
727
  return;
728
 
729
}
730
 
731
void return_command_block_data(){
732
 
733
  vpiHandle systfref, args_iter, argh;
734
 
735
  struct t_vpi_value argval;
736
 
737
  int value,i;
738
 
739
  int n;
740
 
741
  unsigned int data;
742
  unsigned int length;
743
 
744
  char* recv_buf;
745
 
746
  // Now setup the handles to verilog objects and check things
747
  // Obtain a handle to the argument list
748
  systfref = vpi_handle(vpiSysTfCall, NULL);
749
 
750
  // Now call iterate with the vpiArgument parameter
751
  args_iter = vpi_iterate(vpiArgument, systfref);
752
 
753
  // get a handle on the length variable
754
  argh = vpi_scan(args_iter);
755
 
756
  argval.format = vpiIntVal;
757
 
758
  // get the value for the length object
759
  vpi_get_value(argh, &argval);
760
 
761
  // now set length
762
  length = argval.value.integer;
763
 
764
  // now get a handle on the next object (memory array)
765
  argh = vpi_scan(args_iter);
766
 
767
  // check we got passed a memory (array of regs)
768
  if (vpi_get(vpiType, argh) != vpiMemory)
769
    {
770
      vpi_printf("jp_vpi: ERROR: did not pass a memory to return_command_block_data\n");
771
      return;
772
    }
773
 
774
  vpiHandle array_word;
775
 
776
  int num_words = length/4;
777
 
778
  int sent_words = 0;
779
 
780
  // Loop to load the words
781
  while (sent_words < num_words) {
782
 
783
    // now get a handle on the current word we want in the array that was passed to us
784
    array_word = vpi_handle_by_index(argh, sent_words);
785
 
786
    if (array_word != NULL)
787
      {
788
        vpi_get_value(array_word, &argval);
789
 
790
        data = (unsigned int) argval.value.integer;
791
      }
792
    else
793
      return;
794
 
795
    recv_buf = (char *) &data;
796
 
797
    n = write(vpi_to_rsp_pipe[1],recv_buf,4);
798
 
799
    sent_words++;
800
 
801
  }
802
 
803
  // Cleanup and return
804
  vpi_free_object(args_iter);
805
 
806
  return;
807
 
808
}
809
 
810
 
811
 
812
void return_response(char *userdata){
813
 
814
  int n;
815
 
816
  char resp = 0;
817
 
818
  // send a response byte
819
  n = write(vpi_to_rsp_pipe[1],&resp,1);
820
 
821
  if (DBG_ON) printf("jp_vpi: ret\n\n");
822
 
823
  return;
824
 
825
}
826
 
827
void register_check_for_command() {
828
  s_vpi_systf_data data = {vpiSysTask,
829
                           0,
830
                           "$check_for_command",
831
                           (void *)check_for_command,
832
                           0,
833
                           0,
834
                           0};
835
 
836
  vpi_register_systf(&data);
837
 
838
  return;
839
}
840
 
841
void register_get_command_address() {
842
  s_vpi_systf_data data = {vpiSysTask,
843
                           0,
844
                           "$get_command_address",
845
                           (void *)get_command_address,
846
                           0,
847
                           0,
848
                           0};
849
 
850
  vpi_register_systf(&data);
851
 
852
  return;
853
}
854
 
855
void register_get_command_data() {
856
  s_vpi_systf_data data = {vpiSysTask,
857
                           0,
858
                           "$get_command_data",
859
                           (void *)get_command_data,
860
                           0,
861
                           0,
862
                           0};
863
 
864
  vpi_register_systf(&data);
865
 
866
  return;
867
}
868
 
869
void register_get_command_block_data() {
870
  s_vpi_systf_data data = {vpiSysTask,
871
                           0,
872
                           "$get_command_block_data",
873
                           (void *)get_command_block_data,
874
                           0,
875
                           0,
876
                           0};
877
 
878
  vpi_register_systf(&data);
879
 
880
  return;
881
}
882
 
883
 
884
void register_return_command_block_data() {
885
  s_vpi_systf_data data = {vpiSysTask,
886
                           0,
887
                           "$return_command_block_data",
888
                           (void *)return_command_block_data,
889
                           0,
890
                           0,
891
                           0};
892
 
893
  vpi_register_systf(&data);
894
 
895
  return;
896
}
897
 
898
void register_return_command_data() {
899
  s_vpi_systf_data data = {vpiSysTask,
900
                           0,
901
                           "$return_command_data",
902
                           (void *)return_command_data,
903
                           0,
904
                           0,
905
                           0};
906
 
907
  vpi_register_systf(&data);
908
 
909
  return;
910
}
911
 
912
void register_return_response() {
913
  s_vpi_systf_data data = {vpiSysTask,
914
                           0,
915
                           "$return_response",
916
                           (void *)return_response,
917
                           0,
918
                           0,
919
                           0};
920
 
921
  vpi_register_systf(&data);
922
 
923
  return;
924
}
925
 
926
 
927
void setup_reset_callbacks()
928
{
929
 
930
  // here we setup and install callbacks for 
931
  // the setup and management of connections to
932
  // the simulator upon simulation start and 
933
  // reset
934
 
935
  static s_vpi_time time_s = {vpiScaledRealTime};
936
  static s_vpi_value value_s = {vpiBinStrVal};
937
  static s_cb_data cb_data_s =
938
    {
939
      cbEndOfReset, // or start of simulation - initing socket fds etc
940
      (void *)sim_reset_callback,
941
      NULL,
942
      &time_s,
943
      &value_s
944
    };
945
 
946
  cb_data_s.obj = NULL;  /* trigger object */
947
 
948
  cb_data_s.user_data = NULL;
949
 
950
  // actual call to register the callback
951
  vpi_register_cb(&cb_data_s);
952
 
953
}
954
 
955
void sim_reset_callback()
956
{
957
 
958
  // nothing to do!
959
 
960
  return;
961
 
962
}
963
 
964
void setup_endofcompile_callbacks()
965
{
966
 
967
  // here we setup and install callbacks for 
968
  // simulation finish
969
 
970
  static s_vpi_time time_s = {vpiScaledRealTime};
971
  static s_vpi_value value_s = {vpiBinStrVal};
972
  static s_cb_data cb_data_s =
973
    {
974
      cbEndOfCompile, // end of compile
975
      (void *)sim_endofcompile_callback,
976
      NULL,
977
      &time_s,
978
      &value_s
979
    };
980
 
981
  cb_data_s.obj = NULL;  /* trigger object */
982
 
983
  cb_data_s.user_data = NULL;
984
 
985
  // actual call to register the callback
986
  vpi_register_cb(&cb_data_s);
987
 
988
}
989
 
990
void sim_endofcompile_callback()
991
{
992
  // Init the RSP server
993
  init_rsp_server(); // Start the RSP server from here!
994
 
995
}
996
 
997
 
998
void setup_finish_callbacks()
999
{
1000
 
1001
  // here we setup and install callbacks for 
1002
  // simulation finish
1003
 
1004
  static s_vpi_time time_s = {vpiScaledRealTime};
1005
  static s_vpi_value value_s = {vpiBinStrVal};
1006
  static s_cb_data cb_data_s =
1007
    {
1008
      cbEndOfSimulation, // end of simulation
1009
      (void *)sim_finish_callback,
1010
      NULL,
1011
      &time_s,
1012
      &value_s
1013
    };
1014
 
1015
  cb_data_s.obj = NULL;  /* trigger object */
1016
 
1017
  cb_data_s.user_data = NULL;
1018
 
1019
  // actual call to register the callback
1020
  vpi_register_cb(&cb_data_s);
1021
 
1022
}
1023
 
1024
void sim_finish_callback()
1025
{
1026
  printf("Closing RSP server\n");
1027
  // Close down the child process, if it hasn't already
1028
  kill(rsp_server_child_pid,SIGTERM);
1029
}
1030
 
1031
 
1032
 
1033
// Register the new system task here
1034
void (*vlog_startup_routines[ ] ) () = {
1035
  register_init_rsp_server_functions,
1036
#ifdef CDS_VPI
1037
  // this installs a callback on simulator reset - something which 
1038
  // icarus does not do, so we only do it for cadence currently
1039
  setup_reset_callbacks,
1040
#endif
1041
  setup_endofcompile_callbacks,
1042
  setup_finish_callbacks,
1043
  register_check_for_command,
1044
  register_get_command_address,
1045
  register_get_command_data,
1046
  register_get_command_block_data,
1047
  register_return_command_data,
1048
  register_return_command_block_data,
1049
  register_return_response,
1050
 
1051
};
1052
 
1053
 
1054
 
1055
// Entry point for testing development of the vpi functions
1056
int main(int argc, char *argv[])
1057
{
1058
 
1059
  return 0;
1060
 
1061
}
1062
 
1063
 
1064
 

powered by: WebSVN 2.1.0

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