// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: SS_PliSocket.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// ========== Copyright Header End ============================================
#include "SS_PliSocket.h"
// debug_level : 0 - silent
// 2 - trap + instr <=== cosim default
// 3 - trap + instr + delta + pli
// 4 - trap + instr + delta + pli + pli byte-by-byte
// in interactive mode (i.e., NASENV=pfe), set -sas_run_args=-DPLI_DEBUG=0,
// or not specify it at all. Otherwise the output (to sas.log) generated here
// can interfere with pfe output
SS_PliSocket::SS_PliSocket()/*{{{*/
int SS_PliSocket::open_cosim( int socket_no
)/*{{{*/
struct sockaddr_in cli_addr
, serv_addr
;
if ((fd
= socket(AF_INET
,SOCK_STREAM
,0)) < 0)
perror("PLI: ERROR: Can't open stream socket");
bzero((char*)&serv_addr
,sizeof(serv_addr
));
serv_addr
.sin_family
= AF_INET
;
serv_addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
serv_addr
.sin_port
= htons(socket_no
);
if (bind(fd
,(struct sockaddr
*)&serv_addr
,sizeof(serv_addr
)) < 0)
perror ("PLI: ERROR: Can't bind local address");
perror ("PLI: ERROR: listen error");
FILE* opened
= fopen("pli-socket-opened","w");
fprintf(opened
,"%s\n",ctime(&clock
));
int clilen
= sizeof(cli_addr
);
while ((socket_fd
= accept(fd
,(struct sockaddr
*)&cli_addr
,&clilen
)) < 0)
if (accept_retry
++ >= 2000)
fprintf(stdout
,"PLI: ERROR: accept timeout\n");
if ((write_file
= fdopen(socket_fd
,"wb")) == 0)
perror("PLI: ERROR: Can't fdopen output socket");
socket_fd
= dup(socket_fd
);
if ((read_file
= fdopen(socket_fd
,"rb")) == 0)
perror("PLI: ERROR: Can't fdopen input socket");
int SS_PliSocket::open_record( const std::string
& record_fn
)/*{{{*/
if (record_fn
.size() == 0)
if ((record_input
= gzopen(inp
.data(),"w")) == 0)
perror("PLI: ERROR: Cannot create record input cmd file for writing");
if ((record_output
= gzopen(out
.data(),"w")) == 0)
perror("PLI: ERROR: Cannot create record output cmp file for writing");
int SS_PliSocket::open_replay( const std::string
& replay_fn
)/*{{{*/
if (replay_fn
.size() == 0)
if ((read_file_gz
= gzopen(inp
.data(),"r")) == 0)
perror("PLI: ERROR: Cannot open replay input file for reading");
if ((check_file
= gzopen(out
.data(),"r")) == 0)
perror("PLI: ERROR: Cannot open replay output file for reading");
int SS_PliSocket::read( uint_t length
)/*{{{*/
n
= fread(buf
,1,len
,read_file
);
n
= gzread(read_file_gz
,buf
,len
);
perror( "PLI: Replay read 0 bytes");
perror("PLI: Socket read 0 bytes");
for (int i
= 0; i
< length
; i
++)
fprintf(stdout
," %02x",buffer
[i
]);
gzwrite(record_input
,buffer
,length
);
int SS_PliSocket::write( const char* s
)/*{{{*/
size_t length
= strlen(s
);
while (len
&& !gzeof(check_file
))
size_t n
= gzread(check_file
,buf
,len
);
*buf
= '\0'; // properly zero terminate the reference string
// if reg_comp==1, then report any miscompare (during replay)
if ((reg_comp
== 1) && (strncmp(s
,bfr
,length
) != 0))
// This is a temporary fix for end of line versus
// space followed by end of line miscompare. It
// is caused by a misunderstanding of the format
// if the data send back to rtl. The old reference
// has onle newline while new dut expects space
if (strncmp(s
,bfr
,length
) != 0)
fprintf(stdout
,"ERROR: regession failed\n",s
);
fprintf(stdout
,"ref: %s\n",bfr
);
fprintf(stdout
,"dut: %s\n",s
);
fprintf(write_file
,"%s",s
);
gzprintf(record_output
,"%s",s
);
// instr & delta in sas.log, do it here so that it is consistent with what
// we send over to testbench.
if (strstr(s
, ": [swvp"))
// instr, has \n at the end of the string
// 4: [swvp0,th00] <v:fffffffff000002c> <p:000000fff000002c> [8410a020] or %g2, 0x20, %g2
//===> 4: T0 <v:fffffffff000002c> <p:000000fff000002c> [8410a020] or %g2, 0x20, %g2
char* s1
= strchr((char*)s
, ':');
char* s2
= strchr((char*)s
, ']');
strncpy(nn
, (char*)(s1
+11), (s2
-s1
-11));
// make syre the string is terminated properly
sprintf(nn
, " T%d", atoi(nn
));
strcat(ss
, (char*)(s2
+1));
fprintf(stdout
,"#%s", ss
);
else if (strstr(s
, "STEP: ") && (debug() >= 3))
fprintf(stdout
, "\t%s\n", s
);
int SS_PliSocket::write_err( const char* s
)/*{{{*/
return fprintf(write_file
,"%s",s
);
int SS_PliSocket::write_err( char* format
, va_list args
)/*{{{*/
return vfprintf(write_file
, format
, args
);
int SS_PliSocket::flush()/*{{{*/
return fflush(write_file
);
int SS_PliSocket::close()/*{{{*/
uint8_t SS_PliSocket::get8( uint_t ofs
)/*{{{*/
uint16_t SS_PliSocket::get16( uint_t ofs
)/*{{{*/
uint16_t val
= (uint16_t(buffer
[ofs
]) << 8) | buffer
[ofs
+ 1];
uint32_t SS_PliSocket::get32( uint_t ofs
)/*{{{*/
for (int n
=4; n
--; ofs
++)
val
= (val
<< 8) | buffer
[ofs
];
uint64_t SS_PliSocket::get40( uint_t ofs
)/*{{{*/
for (int n
=5; n
--; ofs
++)
val
= (val
<< 8) | buffer
[ofs
];
uint64_t SS_PliSocket::get48( uint_t ofs
)/*{{{*/
for (int n
=6; n
--; ofs
++)
val
= (val
<< 8) | buffer
[ofs
];
uint64_t SS_PliSocket::get64( uint_t ofs
)/*{{{*/
for (int n
=8; n
--; ofs
++)
val
= (val
<< 8) | buffer
[ofs
];