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 282

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 46 julius
uint32_t vpi_to_rsp_pipe[2]; // [0] - read, [1] - write
221
uint32_t rsp_to_vpi_pipe[2]; // [0] - read, [1] - write
222
uint32_t command_pipe[2]; // RSP end writes, VPI end reads ONLY
223 40 julius
 
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 46 julius
  if(DBG_JP_VPI) printf("jp_vpi: init_rsp_server\n");
286 40 julius
 
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 46 julius
      printf("  WB write\n");
384 40 julius
      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 46 julius
  //if(DBG_JP_VPI) printf("check_for_command\n");
418 40 julius
 
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 46 julius
  if (DBG_JP_VPI)
437 40 julius
  {
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 46 julius
  argval.value.integer = (uint32_t) data;
461 40 julius
 
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 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: r");
470 40 julius
 
471 46 julius
  if (DBG_JP_VPI) printf("\n");
472 40 julius
 
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 46 julius
  uint32_t data;
487 40 julius
 
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 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: get_command_address adr=0x%.8x\n",data);
501 40 julius
 
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 46 julius
  argval.value.integer = (uint32_t) data;
519 40 julius
 
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 46 julius
  uint32_t data;
541 40 julius
 
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 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: get_command_data = 0x%.8x\n",data);
557 40 julius
 
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 46 julius
  argval.value.integer = (uint32_t) data;
573 40 julius
 
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 46 julius
  uint32_t data;
596
  uint32_t length;
597 40 julius
 
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 46 julius
 
620
  //if((length % 4) != 0) vpi_printf("length of %d bytes is not exactly word-aligned\n",length);
621 40 julius
  // If non-word aligned we throw away remainder
622
  int throw_away_bytes = length %4;
623
 
624
  int loaded_words = 0;
625
 
626 46 julius
  if(DBG_JP_VPI)printf("jp_vpi: get_command_block_data: length=%d, num_words=%d\n",length,num_words);
627 40 julius
 
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 46 julius
        argval.value.integer = (uint32_t) data;
662 40 julius
 
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 46 julius
  data = (uint32_t) argval.value.integer;
716 40 julius
 
717
  // Cleanup and return
718
  vpi_free_object(args_iter);
719
 
720 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: return_command_data 0x%.8x\n",data);
721 40 julius
 
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 46 julius
  uint32_t data;
742
  uint32_t length;
743 40 julius
 
744 46 julius
  char *block_data_buf;
745
  uint32_t *block_word_data_buf_ptr;
746 40 julius
 
747 46 julius
  int num_words;
748
  int sent_words = 0;
749
 
750
  vpiHandle array_word;
751
 
752 40 julius
  // Now setup the handles to verilog objects and check things
753
  // Obtain a handle to the argument list
754
  systfref = vpi_handle(vpiSysTfCall, NULL);
755
 
756
  // Now call iterate with the vpiArgument parameter
757
  args_iter = vpi_iterate(vpiArgument, systfref);
758
 
759
  // get a handle on the length variable
760
  argh = vpi_scan(args_iter);
761
 
762
  argval.format = vpiIntVal;
763
 
764
  // get the value for the length object
765
  vpi_get_value(argh, &argval);
766
 
767
  // now set length
768
  length = argval.value.integer;
769
 
770
  // now get a handle on the next object (memory array)
771
  argh = vpi_scan(args_iter);
772
 
773
  // check we got passed a memory (array of regs)
774
  if (vpi_get(vpiType, argh) != vpiMemory)
775
    {
776
      vpi_printf("jp_vpi: ERROR: did not pass a memory to return_command_block_data\n");
777
      return;
778
    }
779
 
780 46 julius
  // We have to alloc memory here for lengths > 4
781
  if (length > 4);
782
  {
783
    block_data_buf = (char*) malloc(length * sizeof(char));
784
    if (block_data_buf == NULL)
785
      {
786
        vpi_printf("jp_vpi: return_command_block_data: Error. Could not allocate memory\n");
787
        // Cleanup and return
788
        vpi_free_object(args_iter);
789
        return;
790
      }
791
 
792
    // Now cast it as a uint32_t array
793
    block_word_data_buf_ptr = (uint32_t *) block_data_buf;
794
  }
795
 
796
  num_words = length / 4; // We're always going to be dealing with whole words here
797 40 julius
 
798 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: return_command_block_data: num_words %d\n",
799
                         num_words);
800
 
801
    // Loop to load the words
802 40 julius
  while (sent_words < num_words) {
803
 
804 46 julius
    // Get a handle on the current word we want in the array that was passed to us
805 40 julius
    array_word = vpi_handle_by_index(argh, sent_words);
806
 
807
    if (array_word != NULL)
808
      {
809
        vpi_get_value(array_word, &argval);
810
 
811 46 julius
        data = (uint32_t) argval.value.integer;
812
 
813
        block_word_data_buf_ptr[sent_words] = data;
814 40 julius
      }
815
    else
816
      return;
817
 
818 46 julius
    if (DBG_JP_VPI) printf ( "jp_vpi: return_command_block_data: word %d 0x%.8x\n",
819
                             sent_words, data);
820 40 julius
    sent_words++;
821
  }
822
 
823 46 julius
  if (!(length > 4))
824
    {
825
      block_data_buf = (char *) &data;
826
    }
827
 
828
  n = write(vpi_to_rsp_pipe[1],block_data_buf,length);
829
 
830
 
831
  if (length > 4)
832
    {
833
      // Free the array
834
      free(block_data_buf);
835
    }
836
 
837
 
838 40 julius
  // Cleanup and return
839
  vpi_free_object(args_iter);
840 46 julius
 
841 40 julius
  return;
842
 
843
}
844
 
845
 
846
 
847
void return_response(char *userdata){
848
 
849
  int n;
850
 
851
  char resp = 0;
852
 
853
  // send a response byte
854
  n = write(vpi_to_rsp_pipe[1],&resp,1);
855
 
856 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: ret\n\n");
857 40 julius
 
858
  return;
859
 
860
}
861
 
862
void register_check_for_command() {
863
  s_vpi_systf_data data = {vpiSysTask,
864
                           0,
865
                           "$check_for_command",
866
                           (void *)check_for_command,
867
                           0,
868
                           0,
869
                           0};
870
 
871
  vpi_register_systf(&data);
872
 
873
  return;
874
}
875
 
876
void register_get_command_address() {
877
  s_vpi_systf_data data = {vpiSysTask,
878
                           0,
879
                           "$get_command_address",
880
                           (void *)get_command_address,
881
                           0,
882
                           0,
883
                           0};
884
 
885
  vpi_register_systf(&data);
886
 
887
  return;
888
}
889
 
890
void register_get_command_data() {
891
  s_vpi_systf_data data = {vpiSysTask,
892
                           0,
893
                           "$get_command_data",
894
                           (void *)get_command_data,
895
                           0,
896
                           0,
897
                           0};
898
 
899
  vpi_register_systf(&data);
900
 
901
  return;
902
}
903
 
904
void register_get_command_block_data() {
905
  s_vpi_systf_data data = {vpiSysTask,
906
                           0,
907
                           "$get_command_block_data",
908
                           (void *)get_command_block_data,
909
                           0,
910
                           0,
911
                           0};
912
 
913
  vpi_register_systf(&data);
914
 
915
  return;
916
}
917
 
918
 
919
void register_return_command_block_data() {
920
  s_vpi_systf_data data = {vpiSysTask,
921
                           0,
922
                           "$return_command_block_data",
923
                           (void *)return_command_block_data,
924
                           0,
925
                           0,
926
                           0};
927
 
928
  vpi_register_systf(&data);
929
 
930
  return;
931
}
932
 
933
void register_return_command_data() {
934
  s_vpi_systf_data data = {vpiSysTask,
935
                           0,
936
                           "$return_command_data",
937
                           (void *)return_command_data,
938
                           0,
939
                           0,
940
                           0};
941
 
942
  vpi_register_systf(&data);
943
 
944
  return;
945
}
946
 
947
void register_return_response() {
948
  s_vpi_systf_data data = {vpiSysTask,
949
                           0,
950
                           "$return_response",
951
                           (void *)return_response,
952
                           0,
953
                           0,
954
                           0};
955
 
956
  vpi_register_systf(&data);
957
 
958
  return;
959
}
960
 
961
 
962
void setup_reset_callbacks()
963
{
964
 
965
  // here we setup and install callbacks for 
966
  // the setup and management of connections to
967
  // the simulator upon simulation start and 
968
  // reset
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
      cbEndOfReset, // or start of simulation - initing socket fds etc
975
      (void *)sim_reset_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_reset_callback()
991
{
992
 
993
  // nothing to do!
994
 
995
  return;
996
 
997
}
998
 
999
void setup_endofcompile_callbacks()
1000
{
1001
 
1002
  // here we setup and install callbacks for 
1003
  // simulation finish
1004
 
1005
  static s_vpi_time time_s = {vpiScaledRealTime};
1006
  static s_vpi_value value_s = {vpiBinStrVal};
1007
  static s_cb_data cb_data_s =
1008
    {
1009
      cbEndOfCompile, // end of compile
1010
      (void *)sim_endofcompile_callback,
1011
      NULL,
1012
      &time_s,
1013
      &value_s
1014
    };
1015
 
1016
  cb_data_s.obj = NULL;  /* trigger object */
1017
 
1018
  cb_data_s.user_data = NULL;
1019
 
1020
  // actual call to register the callback
1021
  vpi_register_cb(&cb_data_s);
1022
 
1023
}
1024
 
1025
void sim_endofcompile_callback()
1026
{
1027
  // Init the RSP server
1028
  init_rsp_server(); // Start the RSP server from here!
1029
 
1030
}
1031
 
1032
 
1033
void setup_finish_callbacks()
1034
{
1035
 
1036
  // here we setup and install callbacks for 
1037
  // simulation finish
1038
 
1039
  static s_vpi_time time_s = {vpiScaledRealTime};
1040
  static s_vpi_value value_s = {vpiBinStrVal};
1041
  static s_cb_data cb_data_s =
1042
    {
1043
      cbEndOfSimulation, // end of simulation
1044
      (void *)sim_finish_callback,
1045
      NULL,
1046
      &time_s,
1047
      &value_s
1048
    };
1049
 
1050
  cb_data_s.obj = NULL;  /* trigger object */
1051
 
1052
  cb_data_s.user_data = NULL;
1053
 
1054
  // actual call to register the callback
1055
  vpi_register_cb(&cb_data_s);
1056
 
1057
}
1058
 
1059
void sim_finish_callback()
1060
{
1061
  printf("Closing RSP server\n");
1062
  // Close down the child process, if it hasn't already
1063
  kill(rsp_server_child_pid,SIGTERM);
1064
}
1065
 
1066
 
1067
 
1068
// Register the new system task here
1069
void (*vlog_startup_routines[ ] ) () = {
1070
  register_init_rsp_server_functions,
1071
#ifdef CDS_VPI
1072
  // this installs a callback on simulator reset - something which 
1073
  // icarus does not do, so we only do it for cadence currently
1074
  setup_reset_callbacks,
1075
#endif
1076
  setup_endofcompile_callbacks,
1077
  setup_finish_callbacks,
1078
  register_check_for_command,
1079
  register_get_command_address,
1080
  register_get_command_data,
1081
  register_get_command_block_data,
1082
  register_return_command_data,
1083
  register_return_command_block_data,
1084
  register_return_response,
1085
 
1086
};
1087
 
1088
 
1089
 
1090
// Entry point for testing development of the vpi functions
1091
int main(int argc, char *argv[])
1092
{
1093
 
1094
  return 0;
1095
 
1096
}
1097
 
1098
 
1099
 

powered by: WebSVN 2.1.0

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