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 867

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 397 julius
#define RSP_SERVER_PORT 50002
184 40 julius
 
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 397 julius
    case 0xd :
401
      printf("  detach\n");
402
      break;
403
    case 0xe :
404
      printf("  WB read 8\n");
405
      break;
406 40 julius
    }
407
}
408
 
409
// See if there's anything on the FIFO for us
410
 
411
void check_for_command(char *userdata){
412
 
413
  vpiHandle systfref, args_iter, argh;
414
 
415
  struct t_vpi_value argval;
416
 
417
  int value,i;
418
 
419
  int n;
420
 
421
  unsigned char data;
422
 
423 46 julius
  //if(DBG_JP_VPI) printf("check_for_command\n");
424 40 julius
 
425
  //n = read(rsp_to_vpi_pipe[0], &data, 1);
426
 
427
  n = read(command_pipe[0], &data, 1);
428
 
429
  if ( ((n < 0) && (errno == EAGAIN)) || (n==0) )
430
    {
431
      // Nothing in the fifo this time, let's return
432
      return;
433
    }
434
  else if (n < 0)
435
    {
436
      // some sort of error
437
      perror("check_for_command");
438
 
439
      exit(1);
440
    }
441
 
442 46 julius
  if (DBG_JP_VPI)
443 40 julius
  {
444
    printf("jp_vpi: c = %x:",data);
445
    print_command_string(data);
446
    fflush(stdout);
447
  }
448
 
449
  // Return the command to the sim
450
 
451
  // Obtain a handle to the argument list
452
  systfref = vpi_handle(vpiSysTfCall, NULL);
453
 
454
  // Now call iterate with the vpiArgument parameter
455
  args_iter = vpi_iterate(vpiArgument, systfref);
456
 
457
  // get a handle on the variable passed to the function
458
  argh = vpi_scan(args_iter);
459
 
460
  // now store the command value back in the sim
461
  argval.format = vpiIntVal;
462
 
463
  // Now set the command value
464
  vpi_get_value(argh, &argval);
465
 
466 46 julius
  argval.value.integer = (uint32_t) data;
467 40 julius
 
468
  // And vpi_put_value() it back into the sim
469
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
470
 
471
  // Cleanup and return
472
  vpi_free_object(args_iter);
473
 
474
  n = write(vpi_to_rsp_pipe[1],&data,1);
475 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: r");
476 40 julius
 
477 46 julius
  if (DBG_JP_VPI) printf("\n");
478 40 julius
 
479
  return;
480
}
481
 
482
void get_command_address(char *userdata){
483
 
484
  vpiHandle systfref, args_iter, argh;
485
 
486
  struct t_vpi_value argval;
487
 
488
  int value,i;
489
 
490
  int n;
491
 
492 46 julius
  uint32_t data;
493 40 julius
 
494
  char* recv_buf;
495
 
496
  recv_buf = (char *) &data; // cast data as our receive char buffer
497
 
498
  n = read(rsp_to_vpi_pipe[0],recv_buf,4);
499
  if (n<0)
500
    {
501
      //client has closed connection
502
      //attempt to close and return gracefully
503
      return;
504
    }
505
 
506 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: get_command_address adr=0x%.8x\n",data);
507 40 julius
 
508
  // now put the address into the argument passed to the task
509
 
510
  // Obtain a handle to the argument list
511
  systfref = vpi_handle(vpiSysTfCall, NULL);
512
 
513
  // Now call iterate with the vpiArgument parameter
514
  args_iter = vpi_iterate(vpiArgument, systfref);
515
 
516
  // get a handle on the variable passed to the function
517
  argh = vpi_scan(args_iter);
518
 
519
  // now store the command value back in the sim
520
  argval.format = vpiIntVal;
521
 
522
  // Now set the address value
523
  vpi_get_value(argh, &argval);
524 46 julius
  argval.value.integer = (uint32_t) data;
525 40 julius
 
526
  // And vpi_put_value() it back into the sim
527
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
528
 
529
  // Cleanup and return
530
  vpi_free_object(args_iter);
531
 
532
   return;
533
 
534
}
535
 
536
void get_command_data(char *userdata){
537
 
538
  vpiHandle systfref, args_iter, argh;
539
 
540
  struct t_vpi_value argval;
541
 
542
  int value,i;
543
 
544
  int n = 0;
545
 
546 46 julius
  uint32_t data;
547 40 julius
 
548
  char* recv_buf;
549
 
550
  recv_buf = (char *) &data; // cast data as our receive char buffer
551
 
552
 read_command_data_again:
553
  n = read(rsp_to_vpi_pipe[0],recv_buf,4);
554
 
555
  if ((n < 4) && errno==EAGAIN)
556
    goto read_command_data_again;
557
  else if (n < 4)
558
    {
559
      printf("jp_vpi: get_command_data errno: %d\n",errno);
560
      perror("jp_vpi: get_command_data read failed");
561
    }
562 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: get_command_data = 0x%.8x\n",data);
563 40 julius
 
564
  // Obtain a handle to the argument list
565
  systfref = vpi_handle(vpiSysTfCall, NULL);
566
 
567
  // Now call iterate with the vpiArgument parameter
568
  args_iter = vpi_iterate(vpiArgument, systfref);
569
 
570
  // get a handle on the variable passed to the function
571
  argh = vpi_scan(args_iter);
572
 
573
  // now store the command value back in the sim
574
  argval.format = vpiIntVal;
575
 
576
  // Now set the data value
577
  vpi_get_value(argh, &argval);
578 46 julius
  argval.value.integer = (uint32_t) data;
579 40 julius
 
580
  // And vpi_put_value() it back into the sim
581
  vpi_put_value(argh, &argval, NULL, vpiNoDelay);
582
 
583
  // Cleanup and return
584
  vpi_free_object(args_iter);
585
 
586
   return;
587
 
588
}
589
 
590
 
591
void get_command_block_data(){ // $get_command_block_data(length, mem_array)
592
 
593
  vpiHandle systfref, args_iter, argh;
594
 
595
  struct t_vpi_value argval;
596
 
597
  int value,i;
598
 
599
  int n;
600
 
601 46 julius
  uint32_t data;
602
  uint32_t length;
603 40 julius
 
604
  char* recv_buf;
605
 
606
  // Now setup the handles to verilog objects and check things
607
  // Obtain a handle to the argument list
608
  systfref = vpi_handle(vpiSysTfCall, NULL);
609
 
610
  // Now call iterate with the vpiArgument parameter
611
  args_iter = vpi_iterate(vpiArgument, systfref);
612
 
613
  // get a handle on the length variable
614
  argh = vpi_scan(args_iter);
615
 
616
  argval.format = vpiIntVal;
617
 
618
  // get the value for the length object
619
  vpi_get_value(argh, &argval);
620
 
621
  // now set length
622
  length = argval.value.integer;
623
 
624
  int num_words = length/4;
625 46 julius
 
626
  //if((length % 4) != 0) vpi_printf("length of %d bytes is not exactly word-aligned\n",length);
627 40 julius
  // If non-word aligned we throw away remainder
628
  int throw_away_bytes = length %4;
629
 
630
  int loaded_words = 0;
631
 
632 46 julius
  if(DBG_JP_VPI)printf("jp_vpi: get_command_block_data: length=%d, num_words=%d\n",length,num_words);
633 40 julius
 
634
  // now get a handle on the next object (memory array)
635
  argh = vpi_scan(args_iter);
636
 
637
  // check we got passed a memory (array of regs)
638 397 julius
  if (!((vpi_get(vpiType, argh) == vpiMemory)
639
#ifdef MODELSIM_VPI
640
        || (vpi_get(vpiType, argh) == vpiRegArray)
641
#endif
642
        ))
643 40 julius
    {
644
      vpi_printf("jp_vpi: ERROR: did not pass a memory to get_command_block_data\n");
645 397 julius
      vpi_printf("jp_vpi: ERROR: was passed type %d\n", (int)vpi_get(vpiType, argh));
646 40 julius
      return;
647
    }
648
 
649
  // check the memory we're writing into is big enough
650
  if (vpi_get(vpiSize, argh) < num_words )
651
    {
652
      vpi_printf("jp_vpi: ERROR: buffer passed to get_command_block_data too small. size is %d words, needs to be %d\n",
653
                 vpi_get(vpiSize, argh), num_words);
654
      return;
655
    }
656
 
657
  vpiHandle array_word;
658
 
659
  // Loop to load the words
660
  while (loaded_words < num_words) {
661
 
662
    recv_buf = (char *) &data;
663
 
664
    // blocking receive for data block
665
    n = read(rsp_to_vpi_pipe[0],recv_buf,4);
666
 
667
    // now get a handle on the current word we want in the array that was passed to us
668
    array_word = vpi_handle_by_index(argh, loaded_words);
669
 
670
    if (array_word != NULL)
671
      {
672 46 julius
        argval.value.integer = (uint32_t) data;
673 40 julius
 
674
        // And vpi_put_value() it back into the sim
675
        vpi_put_value(array_word, &argval, NULL, vpiNoDelay);
676
      }
677
    else
678
      return;
679
 
680
    loaded_words++;
681
  }
682
  // TODO: This is a quick fix, should be delt with properly!!
683
  if (throw_away_bytes)
684
    {
685
      //printf("reading off %d extra data bytes\n",throw_away_bytes);
686
      n = read(rsp_to_vpi_pipe[0],&data,throw_away_bytes);
687
      //printf("read off %d bytes \n",n);
688
    }
689
 
690
  // Cleanup and return
691
  vpi_free_object(args_iter);
692
 
693
  return;
694
 
695
}
696
 
697
void return_command_data(char *userdata){
698
 
699
  vpiHandle systfref, args_iter, argh;
700
 
701
  struct t_vpi_value argval;
702
 
703
  int value,i;
704
 
705 397 julius
  int n, length;
706 40 julius
 
707
  uint32_t data;
708
 
709
  char* send_buf;
710
 
711
  // Obtain a handle to the argument list
712
  systfref = vpi_handle(vpiSysTfCall, NULL);
713
 
714
  // Now call iterate with the vpiArgument parameter
715
  args_iter = vpi_iterate(vpiArgument, systfref);
716
 
717 397 julius
  // get a handle on the length variable
718
  argh = vpi_scan(args_iter);
719
 
720
  argval.format = vpiIntVal;
721
 
722
  // get the value for the length object
723
  vpi_get_value(argh, &argval);
724
 
725
  // now set length
726
  length = argval.value.integer;
727
 
728 40 julius
  // get a handle on the object passed to the function
729
  argh = vpi_scan(args_iter);
730
 
731
  // now store the command value back in the sim
732
  argval.format = vpiIntVal;
733
 
734
  // Now set the data value
735
  vpi_get_value(argh, &argval);
736
 
737 46 julius
  data = (uint32_t) argval.value.integer;
738 40 julius
 
739
  // Cleanup and return
740
  vpi_free_object(args_iter);
741
 
742 397 julius
  if (DBG_JP_VPI) printf("jp_vpi: return_command_data %d bytes, 0x%.8x\n",length,data);
743 40 julius
 
744
  send_buf = (char *) &data; //cast our long as a char buf
745
 
746
  // write the data back
747 397 julius
  n = write(vpi_to_rsp_pipe[1],send_buf,length);
748 40 julius
 
749
  return;
750
 
751
}
752
 
753
void return_command_block_data(){
754
 
755
  vpiHandle systfref, args_iter, argh;
756
 
757
  struct t_vpi_value argval;
758
 
759
  int value,i;
760
 
761
  int n;
762
 
763 46 julius
  uint32_t data;
764
  uint32_t length;
765 40 julius
 
766 46 julius
  char *block_data_buf;
767
  uint32_t *block_word_data_buf_ptr;
768 40 julius
 
769 46 julius
  int num_words;
770
  int sent_words = 0;
771
 
772
  vpiHandle array_word;
773
 
774 40 julius
  // Now setup the handles to verilog objects and check things
775
  // Obtain a handle to the argument list
776
  systfref = vpi_handle(vpiSysTfCall, NULL);
777
 
778
  // Now call iterate with the vpiArgument parameter
779
  args_iter = vpi_iterate(vpiArgument, systfref);
780
 
781
  // get a handle on the length variable
782
  argh = vpi_scan(args_iter);
783
 
784
  argval.format = vpiIntVal;
785
 
786
  // get the value for the length object
787
  vpi_get_value(argh, &argval);
788
 
789
  // now set length
790
  length = argval.value.integer;
791
 
792
  // now get a handle on the next object (memory array)
793
  argh = vpi_scan(args_iter);
794
 
795 397 julius
  // check we got passed a memory (array of regs) (modelsim passes back a vpiRegArray, so check for that too)
796
  if (!((vpi_get(vpiType, argh) == vpiMemory)
797
#ifdef MODELSIM_VPI
798
        || (vpi_get(vpiType, argh) == vpiRegArray)
799
#endif
800
      ))
801 40 julius
    {
802
      vpi_printf("jp_vpi: ERROR: did not pass a memory to return_command_block_data\n");
803 397 julius
      vpi_printf("jp_vpi: ERROR: was passed type %d\n", (int)vpi_get(vpiType, argh));
804 40 julius
      return;
805
    }
806
 
807 46 julius
  // We have to alloc memory here for lengths > 4
808
  if (length > 4);
809
  {
810
    block_data_buf = (char*) malloc(length * sizeof(char));
811
    if (block_data_buf == NULL)
812
      {
813
        vpi_printf("jp_vpi: return_command_block_data: Error. Could not allocate memory\n");
814
        // Cleanup and return
815
        vpi_free_object(args_iter);
816
        return;
817
      }
818
 
819
    // Now cast it as a uint32_t array
820
    block_word_data_buf_ptr = (uint32_t *) block_data_buf;
821
  }
822
 
823
  num_words = length / 4; // We're always going to be dealing with whole words here
824 40 julius
 
825 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: return_command_block_data: num_words %d\n",
826
                         num_words);
827
 
828
    // Loop to load the words
829 40 julius
  while (sent_words < num_words) {
830
 
831 46 julius
    // Get a handle on the current word we want in the array that was passed to us
832 40 julius
    array_word = vpi_handle_by_index(argh, sent_words);
833
 
834
    if (array_word != NULL)
835
      {
836
        vpi_get_value(array_word, &argval);
837
 
838 46 julius
        data = (uint32_t) argval.value.integer;
839
 
840
        block_word_data_buf_ptr[sent_words] = data;
841 40 julius
      }
842
    else
843
      return;
844
 
845 46 julius
    if (DBG_JP_VPI) printf ( "jp_vpi: return_command_block_data: word %d 0x%.8x\n",
846
                             sent_words, data);
847 40 julius
    sent_words++;
848
  }
849
 
850 46 julius
  if (!(length > 4))
851
    {
852
      block_data_buf = (char *) &data;
853
    }
854
 
855
  n = write(vpi_to_rsp_pipe[1],block_data_buf,length);
856
 
857
 
858
  if (length > 4)
859
    {
860
      // Free the array
861
      free(block_data_buf);
862
    }
863
 
864
 
865 40 julius
  // Cleanup and return
866
  vpi_free_object(args_iter);
867 46 julius
 
868 40 julius
  return;
869
 
870
}
871
 
872
 
873
 
874
void return_response(char *userdata){
875
 
876
  int n;
877
 
878
  char resp = 0;
879
 
880
  // send a response byte
881
  n = write(vpi_to_rsp_pipe[1],&resp,1);
882
 
883 46 julius
  if (DBG_JP_VPI) printf("jp_vpi: ret\n\n");
884 40 julius
 
885
  return;
886
 
887
}
888
 
889
void register_check_for_command() {
890
  s_vpi_systf_data data = {vpiSysTask,
891
                           0,
892
                           "$check_for_command",
893
                           (void *)check_for_command,
894
                           0,
895
                           0,
896
                           0};
897
 
898
  vpi_register_systf(&data);
899
 
900
  return;
901
}
902
 
903
void register_get_command_address() {
904
  s_vpi_systf_data data = {vpiSysTask,
905
                           0,
906
                           "$get_command_address",
907
                           (void *)get_command_address,
908
                           0,
909
                           0,
910
                           0};
911
 
912
  vpi_register_systf(&data);
913
 
914
  return;
915
}
916
 
917
void register_get_command_data() {
918
  s_vpi_systf_data data = {vpiSysTask,
919
                           0,
920
                           "$get_command_data",
921
                           (void *)get_command_data,
922
                           0,
923
                           0,
924
                           0};
925
 
926
  vpi_register_systf(&data);
927
 
928
  return;
929
}
930
 
931
void register_get_command_block_data() {
932
  s_vpi_systf_data data = {vpiSysTask,
933
                           0,
934
                           "$get_command_block_data",
935
                           (void *)get_command_block_data,
936
                           0,
937
                           0,
938
                           0};
939
 
940
  vpi_register_systf(&data);
941
 
942
  return;
943
}
944
 
945
 
946
void register_return_command_block_data() {
947
  s_vpi_systf_data data = {vpiSysTask,
948
                           0,
949
                           "$return_command_block_data",
950
                           (void *)return_command_block_data,
951
                           0,
952
                           0,
953
                           0};
954
 
955
  vpi_register_systf(&data);
956
 
957
  return;
958
}
959
 
960
void register_return_command_data() {
961
  s_vpi_systf_data data = {vpiSysTask,
962
                           0,
963
                           "$return_command_data",
964
                           (void *)return_command_data,
965
                           0,
966
                           0,
967
                           0};
968
 
969
  vpi_register_systf(&data);
970
 
971
  return;
972
}
973
 
974
void register_return_response() {
975
  s_vpi_systf_data data = {vpiSysTask,
976
                           0,
977
                           "$return_response",
978
                           (void *)return_response,
979
                           0,
980
                           0,
981
                           0};
982
 
983
  vpi_register_systf(&data);
984
 
985
  return;
986
}
987
 
988
 
989
void setup_reset_callbacks()
990
{
991
 
992
  // here we setup and install callbacks for 
993
  // the setup and management of connections to
994
  // the simulator upon simulation start and 
995
  // reset
996
 
997
  static s_vpi_time time_s = {vpiScaledRealTime};
998
  static s_vpi_value value_s = {vpiBinStrVal};
999
  static s_cb_data cb_data_s =
1000
    {
1001
      cbEndOfReset, // or start of simulation - initing socket fds etc
1002
      (void *)sim_reset_callback,
1003
      NULL,
1004
      &time_s,
1005
      &value_s
1006
    };
1007
 
1008
  cb_data_s.obj = NULL;  /* trigger object */
1009
 
1010
  cb_data_s.user_data = NULL;
1011
 
1012
  // actual call to register the callback
1013
  vpi_register_cb(&cb_data_s);
1014
 
1015
}
1016
 
1017
void sim_reset_callback()
1018
{
1019
 
1020
  // nothing to do!
1021
 
1022
  return;
1023
 
1024
}
1025
 
1026
void setup_endofcompile_callbacks()
1027
{
1028
 
1029
  // here we setup and install callbacks for 
1030
  // simulation finish
1031
 
1032
  static s_vpi_time time_s = {vpiScaledRealTime};
1033
  static s_vpi_value value_s = {vpiBinStrVal};
1034
  static s_cb_data cb_data_s =
1035
    {
1036
      cbEndOfCompile, // end of compile
1037
      (void *)sim_endofcompile_callback,
1038
      NULL,
1039
      &time_s,
1040
      &value_s
1041
    };
1042
 
1043
  cb_data_s.obj = NULL;  /* trigger object */
1044
 
1045
  cb_data_s.user_data = NULL;
1046
 
1047
  // actual call to register the callback
1048
  vpi_register_cb(&cb_data_s);
1049
 
1050
}
1051
 
1052
void sim_endofcompile_callback()
1053
{
1054
  // Init the RSP server
1055
  init_rsp_server(); // Start the RSP server from here!
1056
 
1057
}
1058
 
1059
 
1060
void setup_finish_callbacks()
1061
{
1062
 
1063
  // here we setup and install callbacks for 
1064
  // simulation finish
1065
 
1066
  static s_vpi_time time_s = {vpiScaledRealTime};
1067
  static s_vpi_value value_s = {vpiBinStrVal};
1068
  static s_cb_data cb_data_s =
1069
    {
1070
      cbEndOfSimulation, // end of simulation
1071
      (void *)sim_finish_callback,
1072
      NULL,
1073
      &time_s,
1074
      &value_s
1075
    };
1076
 
1077
  cb_data_s.obj = NULL;  /* trigger object */
1078
 
1079
  cb_data_s.user_data = NULL;
1080
 
1081
  // actual call to register the callback
1082
  vpi_register_cb(&cb_data_s);
1083
 
1084
}
1085
 
1086
void sim_finish_callback()
1087
{
1088
  printf("Closing RSP server\n");
1089
  // Close down the child process, if it hasn't already
1090
  kill(rsp_server_child_pid,SIGTERM);
1091
}
1092
 
1093
 
1094
 
1095
// Register the new system task here
1096
void (*vlog_startup_routines[ ] ) () = {
1097
  register_init_rsp_server_functions,
1098
#ifdef CDS_VPI
1099
  // this installs a callback on simulator reset - something which 
1100
  // icarus does not do, so we only do it for cadence currently
1101
  setup_reset_callbacks,
1102
#endif
1103
  setup_endofcompile_callbacks,
1104
  setup_finish_callbacks,
1105
  register_check_for_command,
1106
  register_get_command_address,
1107
  register_get_command_data,
1108
  register_get_command_block_data,
1109
  register_return_command_data,
1110
  register_return_command_block_data,
1111
  register_return_response,
1112
 
1113
};
1114
 
1115
 
1116
 
1117
// Entry point for testing development of the vpi functions
1118
int main(int argc, char *argv[])
1119
{
1120
 
1121
  return 0;
1122
 
1123
}
1124
 
1125
 
1126
 

powered by: WebSVN 2.1.0

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