Commit | Line | Data |
---|---|---|
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 | ||
42 | SS_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 | ||
56 | int 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 | /*}}}*/ | |
120 | int 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 | /*}}}*/ | |
153 | int 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 | ||
187 | int 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 | /*}}}*/ | |
228 | int 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 | ||
310 | int 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 | ||
319 | int 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 | ||
328 | int SS_PliSocket::flush()/*{{{*/ | |
329 | { | |
330 | if (write_file) | |
331 | return fflush(write_file); | |
332 | else | |
333 | return 0; | |
334 | } | |
335 | /*}}}*/ | |
336 | int 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 | ||
375 | uint8_t SS_PliSocket::get8( uint_t ofs )/*{{{*/ | |
376 | { | |
377 | return buffer[ofs]; | |
378 | } | |
379 | /*}}}*/ | |
380 | uint16_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 | /*}}}*/ | |
386 | uint32_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 | /*}}}*/ | |
394 | uint64_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 | /*}}}*/ | |
402 | uint64_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 | /*}}}*/ | |
410 | uint64_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 |