Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / pli / src / SS_PliSocket.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: SS_PliSocket.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21
22#include <strings.h>
23#include <stdio.h>
24#include <errno.h>
25#include <unistd.h>
26#include <time.h>
27#include <fcntl.h>
28#include <sys/stat.h>
29#include <sys/socket.h>
30#include "SS_PliSocket.h"
31
32// debug_level : 0 - silent
33// 1 - trap
34// 2 - trap + instr <=== cosim default
35// 3 - trap + instr + delta + pli
36// 4 - trap + instr + delta + pli + pli byte-by-byte
37
38// in interactive mode (i.e., NASENV=pfe), set -sas_run_args=-DPLI_DEBUG=0,
39// or not specify it at all. Otherwise the output (to sas.log) generated here
40// can interfere with pfe output
41
42SS_PliSocket::SS_PliSocket()/*{{{*/
43 :
44 replay(false),
45 debug_level(0),
46 reg_comp(1),
47 write_file(0),
48 read_file(0),
49 read_file_gz(0),
50 record_input(0),
51 record_output(0),
52 pliok(true)
53{}
54/*}}}*/
55
56int SS_PliSocket::open_cosim( int socket_no )/*{{{*/
57{
58 int socket_fd;
59 int fd;
60 time_t clock;
61 struct sockaddr_in cli_addr, serv_addr;
62
63 if ((fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
64 {
65 perror("PLI: ERROR: Can't open stream socket");
66 exit(1);
67 }
68
69 bzero((char*)&serv_addr,sizeof(serv_addr));
70 serv_addr.sin_family = AF_INET;
71 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
72 serv_addr.sin_port = htons(socket_no);
73
74 if (bind(fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
75 {
76 perror ("PLI: ERROR: Can't bind local address");
77 exit(1);
78 }
79
80 if (listen(fd,5) < 0)
81 {
82 perror ("PLI: ERROR: listen error");
83 exit(1);
84 }
85
86 FILE* opened = fopen("pli-socket-opened","w");
87 time(&clock);
88 fprintf(opened,"%s\n",ctime(&clock));
89 fclose(opened);
90
91 int accept_retry = 0;
92 int clilen = sizeof(cli_addr);
93
94 while ((socket_fd = accept(fd,(struct sockaddr*)&cli_addr,&clilen)) < 0)
95 {
96 if (accept_retry++ >= 2000)
97 {
98 fprintf(stdout,"PLI: ERROR: accept timeout\n");
99 exit(1);
100 }
101 }
102
103 if ((write_file = fdopen(socket_fd,"wb")) == 0)
104 {
105 perror("PLI: ERROR: Can't fdopen output socket");
106 exit(1);
107 }
108
109 socket_fd = dup(socket_fd);
110
111 if ((read_file = fdopen(socket_fd,"rb")) == 0)
112 {
113 perror("PLI: ERROR: Can't fdopen input socket");
114 exit(1);
115 }
116
117 return 0;
118}
119/*}}}*/
120int SS_PliSocket::open_record( const std::string& record_fn )/*{{{*/
121{
122 std::string inp;
123 std::string out;
124
125 if (record_fn.size() == 0)
126 {
127 inp = "dut";
128 out = "dut";
129 }
130 else
131 {
132 inp = record_fn;
133 out = record_fn;
134 }
135
136 inp += ".inp.gz";
137 out += ".out.gz";
138
139 if ((record_input = gzopen(inp.data(),"w")) == 0)
140 {
141 perror("PLI: ERROR: Cannot create record input cmd file for writing");
142 exit(-1);
143 }
144 if ((record_output = gzopen(out.data(),"w")) == 0)
145 {
146 perror("PLI: ERROR: Cannot create record output cmp file for writing");
147 exit(-1);
148 }
149
150 return 0;
151}
152/*}}}*/
153int SS_PliSocket::open_replay( const std::string& replay_fn )/*{{{*/
154{
155 std::string inp;
156 std::string out;
157
158 if (replay_fn.size() == 0)
159 {
160 inp = "ref";
161 out = "ref";
162 }
163 else
164 {
165 inp = replay_fn;
166 out = replay_fn;
167 }
168
169 inp += ".inp.gz";
170 out += ".out.gz";
171
172 replay = true;
173 if ((read_file_gz = gzopen(inp.data(),"r")) == 0)
174 {
175 perror("PLI: ERROR: Cannot open replay input file for reading");
176 exit(-1);
177 }
178 if ((check_file = gzopen(out.data(),"r")) == 0)
179 {
180 perror("PLI: ERROR: Cannot open replay output file for reading");
181 exit(-1);
182 }
183 return 0;
184}
185/*}}}*/
186
187int SS_PliSocket::read( uint_t length )/*{{{*/
188{
189 uint8_t* buf = buffer;
190 uint_t len = length;
191
192 while (1)
193 {
194 size_t n;
195
196 if (read_file)
197 n = fread(buf,1,len,read_file);
198 else
199 n = gzread(read_file_gz,buf,len);
200
201 if (n == 0)
202 {
203 if (replay)
204 perror( "PLI: Replay read 0 bytes");
205 else
206 perror("PLI: Socket read 0 bytes");
207 return 0;
208 }
209
210 len -= n;
211 if (len == 0)
212 {
213 if (debug() >= 4)
214 {
215 fprintf(stdout,"PLI:");
216 for (int i = 0; i < length; i++)
217 fprintf(stdout," %02x",buffer[i]);
218 fprintf(stdout,"\n");
219 }
220 if (record_input)
221 gzwrite(record_input,buffer,length);
222 return length;
223 }
224 buf += n;
225 }
226}
227/*}}}*/
228int SS_PliSocket::write( const char* s )/*{{{*/
229{
230 const size_t SIZE=256;
231
232 size_t length = strlen(s);
233
234 if (check_file)
235 {
236 char bfr[SIZE];
237 char* buf = bfr;
238 size_t len = length;
239
240 assert (len < SIZE);
241 while (len && !gzeof(check_file))
242 {
243 size_t n = gzread(check_file,buf,len);
244 buf += n;
245 len -= n;
246 }
247
248 *buf = '\0'; // properly zero terminate the reference string
249
250 // if reg_comp==1, then report any miscompare (during replay)
251 if ((reg_comp == 1) && (strncmp(s,bfr,length) != 0))
252 {
253 // This is a temporary fix for end of line versus
254 // space followed by end of line miscompare. It
255 // is caused by a misunderstanding of the format
256 // if the data send back to rtl. The old reference
257 // has onle newline while new dut expects space
258 // and newline.
259
260 if (strncmp(s,bfr,length) != 0)
261 {
262 fprintf(stdout,"ERROR: regession failed\n",s);
263 fprintf(stdout,"ref: %s\n",bfr);
264 fprintf(stdout,"dut: %s\n",s);
265 exit(-1);
266 }
267 }
268 }
269 else if (write_file)
270 fprintf(write_file,"%s",s);
271
272 if (record_output)
273 gzprintf(record_output,"%s",s);
274
275 // instr & delta in sas.log, do it here so that it is consistent with what
276 // we send over to testbench.
277 if (debug() >= 2)
278 {
279 if (strstr(s, ": [swvp"))
280 {
281 // instr, has \n at the end of the string
282 // 4: [swvp0,th00] <v:fffffffff000002c> <p:000000fff000002c> [8410a020] or %g2, 0x20, %g2
283 //===> 4: T0 <v:fffffffff000002c> <p:000000fff000002c> [8410a020] or %g2, 0x20, %g2
284 char* s1 = strchr((char*)s, ':');
285 char* s2 = strchr((char*)s, ']');
286 // strand-id
287 char nn[8];
288 strncpy(nn, (char*)(s1+11), (s2-s1-11));
289 // make syre the string is terminated properly
290 nn[s2-s1-11] = '\0';
291 sprintf(nn, " T%d", atoi(nn));
292 // re-arrange string
293 char ss[SIZE];
294 ss[0] = '\0';
295 strncat(ss, s, (s1-s));
296 strcat(ss, nn);
297 strcat(ss, (char*)(s2+1));
298 fprintf(stdout,"#%s", ss);
299 }
300 else if (strstr(s, "STEP: ") && (debug() >= 3))
301 {
302 fprintf(stdout, "\t%s\n", s);
303 }
304 }
305
306 return length;
307}
308/* }}}*/
309
310int SS_PliSocket::write_err( const char* s )/*{{{*/
311{
312 if (write_file)
313 return fprintf(write_file,"%s",s);
314 else
315 return 0;
316}
317/* }}}*/
318
319int SS_PliSocket::write_err( char* format, va_list args )/*{{{*/
320{
321 if (write_file)
322 return vfprintf(write_file, format, args);
323 else
324 return 0;
325}
326/* }}}*/
327
328int SS_PliSocket::flush()/*{{{*/
329{
330 if (write_file)
331 return fflush(write_file);
332 else
333 return 0;
334}
335/*}}}*/
336int SS_PliSocket::close()/*{{{*/
337{
338 if (replay)
339 {
340 replay = false;
341 gzclose(read_file);
342 }
343 else
344 {
345 fclose(write_file);
346 fclose(read_file);
347 }
348
349 read_file = 0;
350 read_file_gz = 0;
351 write_file = 0;
352
353 if (record_input)
354 {
355 gzclose(record_input);
356 record_input = 0;
357 }
358
359 if (record_output)
360 {
361 gzclose(record_output);
362 record_output = 0;
363 }
364
365 if (check_file)
366 {
367 gzclose(check_file);
368 check_file = 0;
369 }
370
371 return 0;
372}
373/*}}}*/
374
375uint8_t SS_PliSocket::get8( uint_t ofs )/*{{{*/
376{
377 return buffer[ofs];
378}
379/*}}}*/
380uint16_t SS_PliSocket::get16( uint_t ofs )/*{{{*/
381{
382 uint16_t val = (uint16_t(buffer[ofs]) << 8) | buffer[ofs + 1];
383 return val;
384}
385/*}}}*/
386uint32_t SS_PliSocket::get32( uint_t ofs )/*{{{*/
387{
388 uint32_t val = 0;
389 for (int n=4; n--; ofs++)
390 val = (val << 8) | buffer[ofs];
391 return val;
392}
393/*}}}*/
394uint64_t SS_PliSocket::get40( uint_t ofs )/*{{{*/
395{
396 uint64_t val = 0;
397 for (int n=5; n--; ofs++)
398 val = (val << 8) | buffer[ofs];
399 return val;
400}
401/*}}}*/
402uint64_t SS_PliSocket::get48( uint_t ofs )/*{{{*/
403{
404 uint64_t val = 0;
405 for (int n=6; n--; ofs++)
406 val = (val << 8) | buffer[ofs];
407 return val;
408}
409/*}}}*/
410uint64_t SS_PliSocket::get64( uint_t ofs )/*{{{*/
411{
412 uint64_t val = 0;
413 for (int n=8; n--; ofs++)
414 val = (val << 8) | buffer[ofs];
415 return val;
416}
417/*}}}*/
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432