Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / common / pli / socket / c / src / socket.c
CommitLineData
86530b38
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: socket.c
5* Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
6* 4150 Network Circle, Santa Clara, California 95054, U.S.A.
7*
8* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9*
10* This program is free software; you can redistribute it and/or modify
11* it under the terms of the GNU General Public License as published by
12* the Free Software Foundation; version 2 of the License.
13*
14* This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details.
18*
19* You should have received a copy of the GNU General Public License
20* along with this program; if not, write to the Free Software
21* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22*
23* For the avoidance of doubt, and except that if any non-GPL license
24* choice is available it will apply instead, Sun elects to use only
25* the General Public License version 2 (GPLv2) at this time for any
26* software where a choice of GPL license versions is made
27* available with the language indicating that GPLv2 or any later version
28* may be used, or where a choice of which version of the GPL is applied is
29* otherwise unspecified.
30*
31* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
32* CA 95054 USA or visit www.sun.com if you need additional information or
33* have any questions.
34*
35*
36* ========== Copyright Header End ============================================
37*/
38#include <sys/types.h>
39#include <sys/socket.h>
40#include <sys/stat.h>
41#include <errno.h>
42#include <fcntl.h>
43#include <netinet/in.h>
44#include <arpa/inet.h>
45#include <stdlib.h>
46#include <sys/time.h>
47#include <string.h>
48#include <strings.h>
49#include <unistd.h>
50#include "vcsuser.h"
51#include "acc_user.h"
52#include <regex.h>
53#include "monitor.h"
54
55#define CMD_BUFSIZE 10240
56#define RCV_BUFSIZE 102400
57#define SEND_MAX 10240
58#define NODE_SIZE 1024
59//simics comands
60#define PLI_QUIT 0x01 /* None */
61#define PLI_SSTEP 0x02 /* %1 th id */
62#define PLI_READ_TH_REG 0x03 /* %1 th id, %2 win num, %3 reg num */
63#define PLI_READ_TH_CTL_REG 0x04 /* %1 th id, %2 reg num */
64#define PLI_READ_TH_FP_REG_I 0x05 /* %1 th id, %2 reg num */
65#define PLI_READ_TH_FP_REG_X 0x06 /* %1 th id, %2 reg num */
66#define PLI_RTL_DATA 0x07 /* 436 bytes rtl data */
67#define PLI_RTL_CYCLE 0x08
68#define PLI_WRITE_TH_XCC_REG 0x09
69#define PLI_WRITE_TH_REG_HI 10
70#define PLI_RETRY 0x0f
71#define PLI_IHWTW 0x11 /* %1=tid %2=itlb-write-time
72 %3=VA %4=entry# */
73#define PLI_DHWTW 0x12 /* %1=tid %2=dtlb-write-time
74 %3=VA %4=ASI# %5=entry# */
75#define PLI_ITLBREAD 0x13 /* %1=tid %2=itlb-read-time */
76#define PLI_DTLBREAD 0x14 /* %1=tid %2=dtlb-read-time */
77#define PLI_ITLBWRITE 0x15 /* %1=tid %2=itlb-write-time
78 %3=entry# */
79#define PLI_DTLBWRITE 0x16 /* %1=tid %2=dtlb-write-time
80 %3=entry# */
81#define PLI_ITLBPROBE 0x17 /* %1=tid %2=itlbprobe-time */
82
83/* %0=cmd(1) for every command. (N) - N bytes */
84/* %1=tid(1),%2=pa(5),%3=data(8),%4=size_vec(1),%5=itype(1),%6=time(4) */
85#define PLI_MEM_ST_ISSUE 0x20
86/* %1=tid(1),%2=pa(5),%3=size_vec(1),%4=inv_vec(2),%5=time(4) */
87#define PLI_MEM_ST_L2_COMMIT 0x21
88/* %1=cid(1),%2=src_tid(1),%3=pa(5),%4=time(4) */
89#define PLI_MEM_ST_INV 0x22
90/* %1=cid(1),%2=pa(5),%3=time(4) */
91#define PLI_MEM_ST_UPDATE 0x23
92/* %1=cid(1),%2=rmo(1),%3=time(4) */
93#define PLI_MEM_ST_ACK 0x24
94/* %1=tid(1),%2=ld_id(4),%3=pa(5),%4=size(1),%5=itype(1),%6=cache(1),%7=time(4)
95 * */
96#define PLI_MEM_LD_ISSUE 0x25
97/* %1=tid(1),%2=ld_id(4),%3=pa(5),%4=size(1),%5=data_src(1),%6=cache(1),%7=time(4)
98 * */
99#define PLI_MEM_LD_DATA 0x26
100/* %1=cid(1),%2=ld_id(4),%3=pa(5),%4=time(4) */
101#define PLI_MEM_LD_FILL 0x27
102/* %1=pa(5),%2=set(4),%3=way(1),%4=inv_vec(4),%5=time(4) */
103#define PLI_MEM_EVICT 0x28
104/* %1=cid(1),%2=src_bankid(1),%3=set(4),%4=way(1),%5=time(4) */
105#define PLI_MEM_EVICT_INV 0x29
106
107/* %1=tid(1),%2=tt(1) */
108#define PLI_INT_INTP 0x40
109
110/* %1=tid(1),%2=asr(1),%3=value(8) */
111#define PLI_ASR_WRITE 0x41
112
113/* %1=tid(1),%2=asi(1),%3=va(8),%4=value(8) */
114#define PLI_ASI_WRITE 0x42
115
116/* %1=tid(1) %2=asi(1) %3=va(1) %4=value(8) */
117#define PLI_ASI_READ 0x43
118
119/* %1=va(1) %2=value(8) */
120#define PLI_CMP_WRITE 0x44
121
122/* %1=tid(1),%2=asr(1),%3=value(8) */
123#define PLI_ASR_READ 0x45
124
125
126#define INTR_RECEIVE 106
127#define VER 88
128#define TICK_CMPR 41
129#define FPSR 36
130#define CCR 35
131#define TPC 52
132#define TNPC 62
133#define HINTP 120
134#define MID 122
135#define END_INSTR 999
136#include "queue.h"
137
138
139//list node for socket buffer
140typedef struct buf_node{
141 int start, count, thrid;
142 char data[NODE_SIZE];
143 struct buf_node *next;
144} *buf_node_ptr;
145
146typedef struct buf_head_node{
147 buf_node_ptr head_ptr, tail_ptr;
148 int vld[32];
149}*buf_head_ptr;
150
151//socket head
152typedef struct sock_handle{
153 fd_set fd_rd, fd_wr;
154 int sockfd;
155 struct timeval tv;
156 char data[RCV_BUFSIZE+1];
157 char rerv[CMD_BUFSIZE];
158 int len;
159 int num, read;
160 int max_count, max_recv;
161 buf_head_ptr active, heap;
162 int max;
163 int step;
164 char sent;
165} *sockPtr;
166
167static sockPtr sock;
168
169int debug_socket, use_flush, send_count;
170
171// Execution string REGEX
172static char *sim_instr_ere
173 = "([0-9]+):.+swvp([0-9]+).th([0-9]+).+<v:([0-9A-fa-f]+)>.+<p:([0-9A-Fa-f]+)>(.*)\n";
174static regex_t regex;
175/*
176static char* symbolic [] = {
177"PC",
178"NPC",
179"Y",
180"CCR",
181"FPRS",
182"FSR",
183"ASI",
184"TICK",
185"GSR",
186"TICK_CMPR",
187"STICK",
188"STICK_CMPR",
189"PSTATE",
190"TL",
191"PIL",
192"TPC1",
193"TPC2",
194"TPC3",
195"TPC4",
196"TPC5",
197"TPC6", "", "", "", "",
198"TNPC1",
199"TNPC2",
200"TNPC3",
201"TNPC4",
202"TNPC5",
203"TNPC6", "", "", "", "",
204"TSTATE1",
205"TSTATE2",
206"TSTATE3",
207"TSTATE4",
208"TSTATE5",
209"TSTATE6","", "", "", "",
210"TT1",
211"TT2",
212"TT3",
213"TT4",
214"TT5",
215"TT6", "", "", "", "",
216"TBA",
217"VER",
218"CWP",
219"CANSAVE",
220"CANRESTORE",
221"OTHERWIN",
222"WSTATE",
223"CLEANWIN",
224"SOFTINT",
225"ECACHE_ERROR_ENABLE",
226"ASYNCHRONOUS_FAULT_STATUS",
227"ASYNCHRONOUS_FAULT_ADDRESS",
228"OUT_INTR_DATA0",
229"OUT_INTR_DATA1",
230"OUT_INTR_DATA2",
231"INTR_DISPATCH_STATUS",
232"IN_INTR_DATA0",
233"IN_INTR_DATA1",
234"IN_INTR_DATA2",
235"INTR_RECEIVE",
236"GL",
237"HPSTATE",
238"HTSTATE1",
239"HTSTATE2",
240"HTSTATE3",
241"HTSTATE4",
242"HTSTATE5",
243"HTSTATE6",
244"HTSTATE7",
245"HTSTATE8",
246"HTSTATE9",
247"HTSTATE10",
248"HTBA",
249"HINTP",
250"HSTICK_CMPR",
251"MID"
252};
253*/
254
255int send_socket_nfd(char* send_buf, int len);
256
257/*----------------------------------------------------------------------------
258open tcp socket
259-----------------------------------------------------------------------------*/
260int socket_init_call()
261{
262 struct sockaddr_in sin;
263 int csocket, sockfd, status;
264 char *pargs;
265 int sockbufsize = 0;
266 int size = sizeof(int);
267 int err;
268
269 sock = (sockPtr)malloc(sizeof(struct sock_handle));
270 pargs = mc_scan_plusargs ("csocket=");
271 csocket = atoi(pargs);
272 if(csocket == 0){
273 cDispmon("socket", MON_ERR, "Socket Not Found");
274 tf_dofinish();
275 }
276 if((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0){
277 cDispmon("socket", MON_ERR, "Can't open stream socket");
278 tf_dofinish();
279 }
280 bzero ((char *) &sin, sizeof (sin));
281 sin.sin_family = AF_INET;
282 sin.sin_addr.s_addr = htonl (INADDR_ANY);
283 sin.sin_port = htons (csocket);
284 if(connect (sockfd, (struct sockaddr *) &sin, sizeof (sin)) < 0){
285 cDispmon("socket", MON_ERR, "Can't connect to in server");
286 tf_dofinish();
287 }
288 status = fcntl(sockfd, F_GETFL, 0);
289 status |= O_NONBLOCK;
290 fcntl(sockfd, F_SETFL, status);
291 sock->sockfd = sockfd;
292 sock->tv.tv_sec = 0;
293 sock->tv.tv_usec = 0;
294 sock->len = 0;
295 sock->data[0] = '\0';
296 sock->num = 0;
297 sock->read = 0;
298 sock->max_count = 0;
299 sock->sent = 0;
300
301 //print socket size :
302 sockbufsize = RCV_BUFSIZE;
303 err = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize,
304 (int)sizeof(sockbufsize));
305
306 err = getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize,&size);
307
308 if(debug_socket)
309 cDispmon("socket", MON_INFO, "Socket Rcv Buffer size is %d bytes", sockbufsize);
310
311 sockbufsize = 0;
312 err = getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize,&size);
313 cDispmon("socket", MON_INFO, "Socket Snd Buffer size is %d bytes", sockbufsize);
314
315 //get the debug flag
316
317 pargs = mc_scan_plusargs ("max_count=");
318 if(pargs != (char *) 0) {
319 sock->max = atoi (pargs);
320 }
321 else sock->max = 0;
322 sock->active = (buf_head_ptr)malloc(sizeof(struct buf_head_node));
323 sock->heap = (buf_head_ptr)malloc(sizeof(struct buf_head_node));
324 sock->active->head_ptr = 0;
325 sock->active->tail_ptr = 0;
326 sock->heap->head_ptr = 0;
327 sock->heap->tail_ptr = 0;
328 sock->step = 0;
329 sock->max_recv = 0;
330
331 cDispmon ("socket", MON_NORMAL, "Initialized socket %d.", csocket);
332 // Initialize the Pattern matching strings
333 // Compile the ERE ..
334
335 if (regcomp(&regex, sim_instr_ere, REG_EXTENDED) != 0) {
336 cDispmon ("socket", MON_ERR, "Regex compilation problem in Regcomp()");
337 tf_dofinish();
338 }
339
340 // Initialize the Instruction sequence Queue
341
342 q_instr = init_q(q_instr);
343 cDispmon ("socket", MON_NORMAL, "Initialized Sequence Queue\n");
344
345 if(mc_scan_plusargs ("debug_socket") ) {
346 debug_socket = 1;
347 } else {
348 debug_socket = 0;
349 }
350 if(mc_scan_plusargs ("socket_use_flush") ) {
351 use_flush = 1;
352 send_count = 0;
353 cDispmon ("socket", MON_NORMAL, "Socket in flush mode\n");
354 } else {
355 use_flush = 0;
356 send_count = 0;
357 }
358 if(mc_scan_plusargs ("debug_queue") ) {
359 debug_queue = 1;
360 } else {
361 debug_queue = 0;
362 }
363 if(mc_scan_plusargs ("quiet") ) {
364 quiet = 1;
365 } else {
366 quiet = 0;
367 }
368 if(mc_scan_plusargs ("nas_trace") ) {
369#ifndef USE_FPRINTF
370 if((nas_fd = open("nas.trace", O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP))==-1) {
371#else
372 nas_fd = fopen("nas.trace", "w");
373 if (nas_fd == NULL) {
374#endif
375 cDispmon ("socket", MON_ERR, "Could not open \"nas.trace\" for writing!");
376 } else {
377 nas_trace = 1;
378 cDispmon ("socket", MON_NORMAL, "Nas trace dump enabled\n");
379 }
380 } else {
381 nas_trace = 0;
382 }
383 show_instr_pa = 0;
384 if(!(mc_scan_plusargs ("show_pa") == NULL)) {
385 show_instr_pa = 1;
386 cDispmon ("socket", MON_NORMAL, "Enabled PA display\n");
387 }
388 return 0;
389}
390/*----------------------------------------------------------------------------
391 do the fron operation on the buffer list.
392-----------------------------------------------------------------------------*/
393buf_node_ptr buf_pop(buf_head_ptr handle)
394{
395 buf_node_ptr tmp_ptr;
396
397 tmp_ptr = handle->head_ptr;
398 handle->head_ptr = tmp_ptr->next;
399 return tmp_ptr;
400}
401/*----------------------------------------------------------------------------
402 push a node on the buffer list.
403-----------------------------------------------------------------------------*/
404void buf_push(buf_head_ptr handle, buf_node_ptr* item)
405{
406 (*item)->next = 0;//indicates the last record.
407 if(handle->head_ptr == 0)
408 handle->head_ptr = *item;
409 else
410 handle->tail_ptr->next = *item;
411 handle->tail_ptr = *item;
412}
413/*----------------------------------------------------------------------------
414 remove leading space or tab.
415 if found carriage return, return -1 to indicate anenpty string.
416-----------------------------------------------------------------------------*/
417int rm_leading_space(char* buf, int index, int max){
418 while((index < max) && (buf[index] == ' ' ||
419 buf[index] == '\t' ||
420 buf[index] == ',' ))index++;
421 return buf[index] == '\n' || buf[index] == '\0' ? -1 : index;
422}
423/*----------------------------------------------------------------------------
424 Convert hex string to 64 bit value
425-----------------------------------------------------------------------------*/
426unsigned long long str2hex64(char* buf) {
427 unsigned long long val = 0;
428 int i;
429
430 for (i = 0; i<strlen (buf); i++) {
431 val <<= 4;
432 val |= buf[i] > '9' ? ((buf[i] & 0xf) + 9) : buf[i] & 0xf;
433 }
434 return val;
435}
436/*----------------------------------------------------------------------------
437 Extract the instruction strings and insert into instr queue
438 Return 0 if valid match found, non-zero otherwise ..
439
440 Formats are :
441 216: [swvp0.th00] <v:fffffffff0080350> <p:000000fff0080350> nop
442 \d+: [swvp\d.th\d+] <v:val64> <p:val64> INSTRUCTION STRING
443-----------------------------------------------------------------------------*/
444int extract_instr_info(char *buf) {
445 int i, ret, len;
446 regmatch_t *submatch;
447 int coreid, tid;
448 char *substrings[10];
449 t_instr_item_ptr item;
450
451
452 // Allocate submatch arrays
453 submatch = (regmatch_t *)malloc(sizeof(regmatch_t)*(regex.re_nsub+1));
454 if (submatch == NULL) {
455 cDispmon ("socket", MON_ERR, "Error in Allocating for Subexpressions");
456 }
457
458 // Do the match ..
459
460 if ((ret = regexec (&regex, buf, regex.re_nsub+1, submatch, 0)) ==0) {
461 // Populate the submatch variables ..
462 for (i = 1; i<=regex.re_nsub; i++) {
463 if (submatch[i].rm_so != -1) {
464 len = submatch[i].rm_eo-submatch[i].rm_so;
465 substrings[i] = (char *)malloc(sizeof(char)*(len+1));
466 strncpy(substrings[i], buf+submatch[i].rm_so, len);
467 substrings[i][len] = NULL;
468 } else {
469 substrings[i] = NULL;
470 }
471 }
472 // Now assign the values and push into Queue
473
474
475 item = (t_instr_item_ptr)malloc(sizeof(struct t_instr_item));
476 if (item == NULL) {
477 cDispmon ("socket", MON_ERR, "Malloc Error Instr queue (%d)");
478 tf_dofinish();
479 }
480
481 item->num = atoi(substrings[1]);
482 coreid = atoi(substrings[2]);
483 tid = atoi(substrings[3]);
484 item->va = str2hex64(substrings[4]) & 0xffffffffffffULL; // Only 48 bits
485 item->pa = str2hex64(substrings[5]) & 0xffffffffffffULL;
486
487 item->instruction = (char*)malloc(sizeof(char)*strlen(substrings[6])+1);
488 strcpy (item->instruction, substrings[6]);
489
490
491 if (! push_q (q_instr, coreid*NUMCORE+tid, item)) {
492 cDispmon ("socket", MON_ERR, "Error pushing values to queue (%d)",
493 coreid*NUMCORE+tid);
494 tf_dofinish();
495 }
496 for (i = 1; i<=regex.re_nsub; i++) {
497 free (substrings[i]);
498 }
499 free (submatch);
500 } else {
501 if (ret != REG_NOMATCH) {
502 cDispmon ("socket", MON_ERR, "Error in Regexec()\n");
503 } else {
504 free (submatch);
505 return ret;
506 }
507 }
508 return 0;
509}
510/*----------------------------------------------------------------------------
511 Extract the updated data from simics and put into Expected queue ..
512
513 Formats are :
514 STEP: <tid> G <gl> <num> <val64>
515 STEP: <tid> W <win> <num> <val64>
516 STEP: <tid> F <num> <val32>
517 STEP: <tid> C <num> <val64>
518 Assumption - A carriage return will delimit instruction boundary
519-----------------------------------------------------------------------------*/
520void extract_step_info(mt_list_ptr queue, char *buf)
521{
522 char buf1[RCV_BUFSIZE], buf2[256], type;
523 char *strseq;
524 unsigned long long value;
525 int currlen;
526 int tid, regnum, win=0, level=0;
527 t_check_item_ptr item; // Individual record items
528
529 //time = tf_gettime();
530 // io_printf("socket > InFo:(%d), %s\n", time, buf);
531
532 strcpy(buf1, buf);
533
534 // Break String into 'STEP: ..' Sequences
535
536 currlen = 0;
537 strseq = strtok(buf1, "STEP:");
538 while (strseq != NULL) {
539 currlen = currlen+strlen(strseq)+5;
540 //printf ("Found string %s (%d)\n", strseq, currlen); fflush (NULL);
541 // First is TID
542 strcpy (buf2, strseq);
543 tid = atoi (strtok(buf2, " "));
544 // printf("\tTID = %d\n", tid);
545 // Second is Type
546 type = (strtok(NULL, " "))[0];
547 // printf("\tTYPE = %c\n", type);
548 switch (type) {
549 case 'G' : // Global Register
550 level = atoi(strtok(NULL, " "));
551 // printf("\tLevel = %d\n", level);
552 break;
553 case 'W' : // Window Register
554 win = atoi(strtok(NULL, " "));
555 // printf("\tWin = %d\n", win);
556 break;
557 }
558 // Next is register number
559 regnum = atoi(strtok(NULL, " "));
560 // printf("\tNum = %d\n", regnum);
561 // Last is value - 64 bits
562 value = str2hex64(strtok(NULL, " "));
563 // printf("\tval = %llx\n", value);
564
565 // OK Lets save this in queue # tid ..
566
567 // Build item ..
568 //
569 item = (t_check_item_ptr)malloc(sizeof(struct t_check_item));
570 if (item == NULL) {
571 cDispmon ("socket", MON_ERR, "Malloc Error pushing values to queue (%d)",
572 tid);
573 tf_dofinish();
574 }
575
576 item->time = 0;
577 item->type = type;
578 item->level = level;
579 item->win = win;
580 item->reg_num = regnum;
581 item->value = value;
582
583 // Push into queue
584
585
586 if (! push_q (queue, tid, item)) {
587 cDispmon ("socket", MON_ERR, "Error pushing values to queue (%d)",
588 tid);
589 tf_dofinish();
590 }
591
592 // Get next STEP: entry ..
593
594 strcpy(buf1, buf+currlen);
595 strseq = strtok(buf1, "STEP:");
596 }
597
598 // Push a END_INSTR into the queue for instruction delimitation .
599 //
600 item = (t_check_item_ptr)malloc(sizeof(struct t_check_item));
601 if (item == NULL) {
602 cDispmon ("socket", MON_ERR, "Malloc Error pushing values to queue (%d)",
603 tid);
604 tf_dofinish();
605 }
606
607 item->time = 0;
608 item->type = 'X';
609 item->level = 0;
610 item->win = 0;
611 item->reg_num = END_INSTR;
612 item->value = 0;
613
614 // Push into queue
615
616
617 if (! push_q (queue, tid, item)) {
618 cDispmon ("socket", MON_ERR, "Error pushing values to queue (%d)",
619 tid);
620 tf_dofinish();
621 }
622
623}
624/*-----------------------------------------------------------------------------
625 Process the receiving data from simics.
626-----------------------------------------------------------------------------*/
627int parse_data(mt_list_ptr queue)
628{
629 int num=0, found;
630 char tmp_buf[1024];
631
632 if(debug_socket)
633 cDispmon ("socket", MON_DEBUG, "parse_data(%d) [%s]\n", sock->len, sock->data);
634 found = 0;
635 while(sock->len > num){
636 tmp_buf[num] = sock->data[num];
637 if(tmp_buf[num] == '\n'){
638 tmp_buf[++num] = '\0';
639 sock->len -= num;
640 // Check for SAS Error
641 if(strncmp (tmp_buf, "ERROR:", 6) == 0){
642 cDispmon ("socket", MON_WARN, " %s ", tmp_buf);
643 strcpy(sock->data, sock->data + num);
644 num = 0;
645 continue;
646 }
647 // Check for STEP return
648 if(strncmp (tmp_buf, "STEP: ", 6) == 0){
649 strcpy(sock->data, sock->data + num);
650 extract_step_info(queue, tmp_buf);
651 num = 0;
652 found = 1;
653 continue;
654 }
655 // Check for Instruction string
656 if (extract_instr_info(tmp_buf) != 0) {
657 // Check for Regval
658 if(strncmp (tmp_buf, "regval", 6) != 0){
659 cDispmon ("socket", MON_NORMAL, "%s", tmp_buf);
660 strcpy(sock->data, sock->data + num);
661 num = 0;
662 continue;
663 }
664 } else {
665 strcpy(sock->data, sock->data + num);
666 num = 0;
667 continue;
668 }
669 }
670 num++;
671 }
672 return found;
673}
674/*----------------------------------------------------------------------------
675 Get data from socket.
676-----------------------------------------------------------------------------*/
677int read_socket_nfd()
678{
679 char read_buf[RCV_BUFSIZE+1];
680 int len;
681
682 // io_printf("socket > Starting to read socket ..\n");
683 // fflush(NULL);
684 len = RCV_BUFSIZE - sock->len;
685 if (debug_socket) cWritemon ("socket", MON_INFO, "Starting read of (%d) bytes [%d]", len, sock->len);
686 len = read(sock->sockfd, read_buf, len);
687 if (debug_socket) cDispmon ("socket", MON_INFO, ".. read (%d) bytes", len);
688 if(len == -1){
689 if (errno != EAGAIN && errno != EINTR) {
690 cDispmon ("socket", MON_ERR, "Socket read error");
691 read_buf[0] = PLI_QUIT;
692 send_socket_nfd(read_buf, 1);
693 tf_dofinish();
694 }
695 return 0;
696 }
697 if (len == (RCV_BUFSIZE - sock->len)) {
698 sock->max_recv = 1;
699 } else {
700 sock->max_recv = 0;
701 }
702 sock->len += len;
703 read_buf[len] = '\0';
704 sock->max_count = 0;
705 strcat(sock->data, read_buf);
706 if(debug_socket && len){
707 read_buf[len - 1] != '\n' ? cDispmon ("socket", MON_DEBUG, "[%s:]", read_buf) :
708 cWritemon ("socket", MON_DEBUG, "[%s]", read_buf);
709 }
710 // io_printf("socket > Just read %d from socket (Q=%d)\n", len,sock->len);
711 return len;
712}
713/*----------------------------------------------------------------------------
714 Receiving data from server.
715 Return back an information on which threads are in Recd queue
716 Arguments : 1. 'Expected' Queue handle
717 2. Conditional 2nd Queue hanlde for oldest tid
718 3. Conditional Sent back oldest tid info for 1nd queue
719 Returned : 64 bit queue status array
720 Conditional oldest (integer)
721-----------------------------------------------------------------------------*/
722
723#ifdef NCV
724int sim_recv_call()
725#else
726unsigned long long sim_recv_call()
727#endif
728
729{
730 int temp, i, j, k, l;
731 mt_list_ptr exp_queue, act_queue;
732 unsigned long long status;
733
734 // Get handle for Expected queue
735
736 exp_queue = (mt_list_ptr) tf_getp (1);
737 if (tf_nump() > 1) {
738 act_queue = (mt_list_ptr) tf_getp (2);
739 }
740
741
742 temp = 0;
743
744 // Read Socket and parse if data available ..
745
746
747 if (debug_socket)
748 cDispmon ("socket", MON_DEBUG, "Checking socket for incoming ..");
749 sock->read = 0;
750 while(read_socket_nfd() && sock->len) {
751 temp = parse_data(exp_queue);
752 if (!sock->max_recv) break;
753 }
754
755 // Get Expected queue status - 64 bits
756
757 status = status_q(exp_queue);
758 if (tf_nump() == 3) {
759 tf_putp(3, oldest_t(act_queue));
760 }
761
762 if (debug_socket)
763 cDispmon ("socket", MON_DEBUG, "Recd & parsed data with status = %llx", status);
764 // Return values
765
766 tf_putlongp(0, status, status >> 32);
767
768 if(debug_queue) {
769 j=0;k=0;l=0;
770 for (i = NUMCORE*NUMTHREAD-1; i >= 0; i--) {
771 j = j+size_q (exp_queue, i);
772 k = k+size_q (act_queue, i);
773 l = l+size_q (q_instr, i);
774 }
775 cDispmon ("queue", MON_INFO, "[sim_recv_call] Exp Q = %d Act Q = %d Inst Q = %d ", j, k, l);
776 }
777 return 0;
778}
779
780/*----------------------------------------------------------------------------
781 Send Socket request.
782-----------------------------------------------------------------------------*/
783int send_socket_nfd(char* send_buf, int len)
784{
785 int slen, counter, i;
786 static int tot_slen;
787
788 slen = send(sock->sockfd, send_buf, len, 0);
789 send_count++;
790 if (debug_socket) {
791 tot_slen = tot_slen + slen;
792 cDispmon("socket", MON_INFO, ".. Sent %d of %d bytes (%d total)", slen, len, tot_slen);
793 }
794 if(slen == -1){
795 switch(errno) {
796 case (EINTR): cDispmon ("socket", MON_DEBUG, "Err=EINTR"); break;
797 case (EMSGSIZE): cDispmon ("socket", MON_DEBUG, "Err=EMSGSIZE"); break;
798 case (ENOMEM): cDispmon ("socket", MON_DEBUG, "Err=ENOMEM"); break;
799 case (ENOSR): cDispmon ("socket", MON_DEBUG, "Err=ENOSR"); break;
800 case (EWOULDBLOCK): cDispmon ("socket", MON_DEBUG, "Err=EWOULDBLOCK");
801 return 0;
802 case (EINVAL): cDispmon ("socket", MON_DEBUG, "Err=EINVAL"); break;
803 case (EPIPE): cDispmon ("socket", MON_DEBUG, "Err=EPIPE"); break;
804 default : cDispmon ("socket", MON_DEBUG, "Err=%d", errno);
805 }
806 cDispmon ("socket", MON_NORMAL, "Trying, but can't send data. Length(%d)", len);
807 }
808 else if(slen == len){
809 sock->num = 0;
810 sock->sent= 1;
811 return 1;
812 }
813 else if(slen < len){
814 counter = 0;
815 for(i = slen; i < len;i++)send_buf[counter++] = send_buf[i];
816 sock->num -= slen;
817 sock->sent= 1;
818 }
819 return 0;
820}
821
822/*----------------------------------------------------------------------------
823 Copy data to socket send buffer.
824-----------------------------------------------------------------------------*/
825void copyPacket(char* buf, int num)
826{
827 int idx;
828
829 for(idx = 0; idx < num; idx++)sock->rerv[sock->num++] = buf[idx];
830}
831/*----------------------------------------------------------------------------
832 shift data in list to reserved buffer of send.
833-----------------------------------------------------------------------------*/
834int packed()
835{
836 int available, num;
837 buf_node_ptr node;
838
839 available = CMD_BUFSIZE - sock->num;
840 while(sock->active->head_ptr && available){
841 node = sock->active->head_ptr;
842 num = node->count;
843 if(num <= available){//move whole junk.
844 node = (buf_node_ptr) buf_pop(sock->active);
845 copyPacket(node->data+node->start, num);
846 buf_push(sock->heap, &node);
847 }
848 else {
849 num = available;
850 copyPacket(node->data+node->start, num);
851 node->start += num;
852 node->count -= num;
853 }
854 available -= num;
855 }
856 return 0;
857}
858/*----------------------------------------------------------------------------
859 add the new data to the end of send list.
860-----------------------------------------------------------------------------*/
861void add_node(char* buf, int index, int num)
862{
863 int idx, nidx, available;
864 buf_node_ptr node;
865
866 if(sock->active->head_ptr){//fill the last node if space is available.
867 node = sock->active->tail_ptr;
868 nidx = node->start + node->count;
869 available = NODE_SIZE - nidx;
870 if(available){
871 available = available > num ? num : available;
872 num -= available;
873 node->count += available;
874 for(idx = nidx; idx < (nidx + available);idx++)node->data[idx] = buf[index++];
875 }
876 }
877 while(num){
878 if(sock->heap->head_ptr)node = buf_pop(sock->heap);
879 else node = (buf_node_ptr)malloc(sizeof(struct buf_node));
880 node->start = 0;
881 available = NODE_SIZE > num ? num : NODE_SIZE;
882 for(idx = 0; idx < available; idx++)node->data[idx] = buf[index++];
883 node->count = available;
884 num -= available;
885 buf_push(sock->active, &node);
886 }
887}
888/*----------------------------------------------------------------------------
889 Make the reusable buffer for socket send.
890-----------------------------------------------------------------------------*/
891void handle_buf(char *cmd_buf, int num)
892{
893 int available, idx, send_max;
894
895 if (use_flush) {
896 send_max = SEND_MAX;
897 } else {
898 send_max = 1;
899 }
900
901 available = sock->num + num;
902 if((cmd_buf[0] != PLI_RETRY) &&
903 (cmd_buf[0] != PLI_QUIT) &&
904 (available < send_max)){//not reach the minimum number to be sent.
905 copyPacket(cmd_buf, num);
906 sock->sent = 0;
907 return;
908 }
909 if(debug_socket && cmd_buf[0] == PLI_QUIT) {
910 cDispmon("socket", MON_ALWAYS, "Socket Send Count Was %d", send_count);
911 }
912 //send data to simcs.
913 available = CMD_BUFSIZE - sock->num;
914 available = available > num ? num : available;
915 copyPacket(cmd_buf, available);
916 send_socket_nfd(sock->rerv, sock->num);
917 num -= available;
918 idx = available;
919 //check list buffer
920 if(sock->active->head_ptr)packed();
921 available = CMD_BUFSIZE - sock->num;
922 if(available && num && (sock->active->head_ptr == 0)){
923 //move data on the send buffer if avaiable.
924 available = available > num ? num : available;
925 copyPacket(cmd_buf+idx, available);
926 num -= available;
927 idx += available;
928 }
929 if(num)add_node(cmd_buf, idx, num);
930}
931/*----------------------------------------------------------------------------
932flush buffer NOW
933-----------------------------------------------------------------------------*/
934int sim_flush_call()
935{
936 if (debug_socket) {
937 cDispmon ("socket", MON_INFO, "Flush Send Buffer (%d)\n", sock->num);
938 }
939 if (use_flush && ( sock->num >0))
940 send_socket_nfd(sock->rerv, sock->num);
941
942 return 0;
943}
944/*----------------------------------------------------------------------------
945send a command to simics
946-----------------------------------------------------------------------------*/
947
948#ifdef NCV
949int sim_send_call()
950#else
951unsigned long long sim_send_call()
952#endif
953
954{
955 unsigned int word;
956 unsigned long long longword;
957 char cmd_buf[2024];
958 int groups, ind, num, size, hword, i;
959 s_tfnodeinfo node_info;
960
961
962 // Need to format params in a byte stream ..
963 // 1st two are <command> <tid>, which will fit in bytes.
964 // Others need to be formatted into bytes ..
965
966 ind = 0; // ind tracks bytes in message
967 // num tracks current parameter ..
968 cmd_buf[ind] = tf_getp(1);
969 ind++;
970#ifndef USE_FPRINTF
971 if (nas_trace) write(nas_fd, &cmd_buf[0], 1);
972#else
973 if (nas_trace) fprintf(nas_fd, "%02x", cmd_buf[0]);
974#endif
975 if (debug_socket)
976 switch(cmd_buf[0]){ // {{{ Debug Dispmons ..
977 case(PLI_QUIT) :
978 cWritemon ("socket", MON_INFO, "Sending quit\n");
979 break;
980 case(PLI_SSTEP) :
981 sock->step++;
982 cWritemon ("socket", MON_INFO, "Sending step(%d) ", sock->step);
983 break;
984 case(PLI_READ_TH_REG) :
985 cWritemon ("socket", MON_INFO, "Sending read ");
986 break;
987 case(PLI_READ_TH_CTL_REG) :
988 cWritemon ("socket", MON_INFO, "Sending read-special ");
989 break;
990 case(PLI_READ_TH_FP_REG_I) :
991 cWritemon ("socket", MON_INFO, "Sending float-32 ");
992 break;
993 case(PLI_READ_TH_FP_REG_X) :
994 cWritemon ("socket", MON_INFO, "Sending float-64 ");
995 break;
996 case(PLI_RTL_DATA) : cWritemon ("socket", MON_INFO, "Sending rtl-data") ;
997 break;
998 case(PLI_WRITE_TH_XCC_REG) :
999 cWritemon ("socket", MON_INFO, "Sending PLI_WRITE_TH_XCC_REG ");
1000 break;
1001 case(PLI_WRITE_TH_REG_HI) :
1002 cWritemon ("socket", MON_INFO, "Sending PLI_WRITE_TH_REG ");
1003 break;
1004 case(PLI_RETRY) :
1005 cWritemon ("socket", MON_INFO, "Sending ReTry remained-data(%0d)\n", sock->num);
1006 break;
1007 case(PLI_IHWTW) : cWritemon ("socket", MON_INFO, "Sending IHWTW ");
1008 break;
1009 case(PLI_DHWTW) : cWritemon ("socket", MON_INFO, "Sending DHWTW ");
1010 break;
1011 case(PLI_ITLBREAD) : cWritemon ("socket", MON_INFO, "Sending ITLBREAD ");
1012 break;
1013 case(PLI_DTLBREAD) : cWritemon ("socket", MON_INFO, "Sending DTLBREAD ");
1014 break;
1015 case(PLI_ITLBWRITE) : cWritemon ("socket", MON_INFO, "Sending ITLBWRITE ");
1016 break;
1017 case(PLI_DTLBWRITE) : cWritemon ("socket", MON_INFO, "Sending DTLBWRITE ");
1018 break;
1019 case(PLI_ITLBPROBE) : cWritemon ("socket", MON_INFO, "Sending ITLBPROBE ");
1020 break;
1021 case(PLI_MEM_ST_ISSUE):
1022 cWritemon ("socket", MON_INFO, "Sending PLI_MEM_ST_ISSUE "); break;
1023 case(PLI_MEM_ST_L2_COMMIT):
1024 cWritemon ("socket", MON_INFO, "Sending PLI_MEM_ST_L2_COMMIT "); break;
1025 case(PLI_MEM_ST_INV):
1026 cWritemon ("socket", MON_INFO, "Sending PLI_MEM_ST_INV "); break;
1027 case(PLI_MEM_ST_UPDATE):
1028 cWritemon ("socket", MON_INFO, "Sending PLI_MEM_ST_UPDATE "); break;
1029 case(PLI_MEM_ST_ACK):
1030 cWritemon ("socket", MON_INFO, "Sending PLI_MEM_ST_ACK "); break;
1031 case(PLI_MEM_LD_ISSUE):
1032 cWritemon ("socket", MON_INFO, "Sending PLI_MEM_LD_ISSUE "); break;
1033 case(PLI_MEM_LD_DATA):
1034 cWritemon ("socket", MON_INFO, "Sending PLI_MEM_LD_DATA "); break;
1035 case(PLI_MEM_LD_FILL):
1036 cWritemon ("socket", MON_INFO, "Sending PLI_MEM_LD_FILL "); break;
1037 case(PLI_MEM_EVICT):
1038 cWritemon ("socket", MON_INFO, "Sending PLI_MEM_EVICT "); break;
1039 case(PLI_MEM_EVICT_INV):
1040 cWritemon ("socket", MON_INFO, "Sending PLI_MEM_EVICT_INV "); break;
1041 case(PLI_INT_INTP):
1042 cWritemon ("socket", MON_INFO, "Sending PLI_INT_INTP "); break;
1043 case(PLI_ASR_WRITE):
1044 cWritemon ("socket", MON_INFO, "Sending PLI_ASR_WRITE "); break;
1045 case(PLI_ASI_WRITE):
1046 cWritemon ("socket", MON_INFO, "Sending PLI_ASI_WRITE "); break;
1047 case(PLI_ASI_READ):
1048 cWritemon ("socket", MON_INFO, "Sending PLI_ASI_READ "); break;
1049 case(PLI_CMP_WRITE):
1050 cWritemon ("socket", MON_INFO, "Sending PLI_CMP_WRITE "); break;
1051 case(PLI_ASR_READ):
1052 cWritemon ("socket", MON_INFO, "Sending PLI_ASR_READ "); break;
1053 default: cDispmon ("socket", MON_INFO, "Unknown message %x\n", cmd_buf[0]);
1054 } // }}}
1055
1056 for(num = 1; num < tf_nump(); num++) {
1057 size = tf_sizep(num+1);
1058 groups = (size+7)/8;
1059 if (debug_socket)
1060 cWritemon ("socket", MON_DEBUG, " Parm(%d)[%db=%dB] = ",
1061 num, size,groups);
1062 if (size > 32) {
1063 word = tf_getlongp(&hword, num+1);
1064 longword = hword; longword <<= 32; longword |= word;
1065 for (i=groups; i>0;i--) {
1066 cmd_buf[ind] = (longword >> ((i-1)*8)) & 0xff;
1067 if (debug_socket)
1068 cWritemon ("socket", MON_DEBUG, "%02x", (unsigned char)cmd_buf[ind]);
1069#ifndef USE_FPRINTF
1070 if (nas_trace) write(nas_fd, &cmd_buf[ind], 1);
1071#else
1072 if (nas_trace) fprintf(nas_fd, "%02x", (unsigned char) cmd_buf[ind]);
1073#endif
1074 ind++;
1075 }
1076 } else {
1077 word = tf_getp(num+1);
1078 for (i=groups; i>0;i--) {
1079 cmd_buf[ind] = (word >> ((i-1)*8)) & 0xff;
1080 if (debug_socket)
1081 cWritemon ("socket", MON_DEBUG, "%02x", (unsigned char)cmd_buf[ind]);
1082#ifndef USE_FPRINTF
1083 if (nas_trace) write(nas_fd, &cmd_buf[ind], 1);
1084#else
1085 if (nas_trace) fprintf(nas_fd, "%02x", (unsigned char) cmd_buf[ind]);
1086#endif
1087 ind++;
1088 }
1089 }
1090
1091 }
1092 if (debug_socket) cWritemon ("socket", MON_DEBUG, "\n");
1093
1094
1095 if(cmd_buf[0] == PLI_RTL_CYCLE){//send rtl cycle
1096 num = tf_getp(2);
1097 for(ind = 0; ind < num;ind++)cmd_buf[ind] = PLI_RTL_CYCLE;
1098 }
1099 if(cmd_buf[0] == PLI_RTL_DATA){
1100 tf_nodeinfo(2, &node_info);
1101 ind = 1;
1102 for(groups = (node_info.node_ngroups - 1); groups >= 0; groups--){
1103 word = node_info.node_value.vecval_p[groups].avalbits;
1104 cmd_buf[ind] = (word >> 24) & 0xff;
1105 cmd_buf[ind+1] = (word >> 16) & 0xff;
1106 cmd_buf[ind+2] = (word >> 8) & 0xff;
1107 cmd_buf[ind+3] = word & 0xff;
1108 ind += 4;
1109 }
1110 }
1111 if(cmd_buf[0] == PLI_RETRY)ind = 0;
1112 if(cmd_buf[0] == PLI_QUIT){
1113 sock->num = 0;
1114 if(sock->active->head_ptr)sock->active->head_ptr = 0;
1115#ifndef USE_FPRINTF
1116 if (nas_trace) close(nas_fd);
1117#else
1118 if (nas_trace) fclose(nas_fd);
1119#endif
1120 }
1121 handle_buf(cmd_buf, ind);
1122 return 0;
1123}
1124