1 /******************************************************************************
2  * DESCRIPTION: Dinotrace source: CCLI tempest trace reading
3  *
4  * This file is part of Dinotrace.
5  *
6  * Author: Wilson Snyder <wsnyder@wsnyder.org>
7  *
8  * Code available from: http://www.veripool.org/dinotrace
9  *
10  ******************************************************************************
11  *
12  * Some of the code in this file was originally developed for Digital
13  * Semiconductor, a division of Digital Equipment Corporation.  They
14  * gratefuly have agreed to share it, and thus the bas version has been
15  * released to the public with the following provisions:
16  *
17  *
18  * This software is provided 'AS IS'.
19  *
20  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THE INFORMATION
21  * (INCLUDING ANY SOFTWARE) PROVIDED, INCLUDING ALL IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE, AND
23  * NON-INFRINGEMENT. DIGITAL NEITHER WARRANTS NOR REPRESENTS THAT THE USE
24  * OF ANY SOURCE, OR ANY DERIVATIVE WORK THEREOF, WILL BE UNINTERRUPTED OR
25  * ERROR FREE.  In no event shall DIGITAL be liable for any damages
26  * whatsoever, and in particular DIGITAL shall not be liable for special,
27  * indirect, consequential, or incidental damages, or damages for lost
28  * profits, loss of revenue, or loss of use, arising out of or related to
29  * any use of this software or the information contained in it, whether
30  * such damages arise in contract, tort, negligence, under statute, in
31  * equity, at law or otherwise. This Software is made available solely for
32  * use by end users for information and non-commercial or personal use
33  * only.  Any reproduction for sale of this Software is expressly
34  * prohibited. Any rights not expressly granted herein are reserved.
35  *
36  ******************************************************************************
37  *
38  * Changes made over the basic version are covered by the GNU public licence.
39  *
40  * Dinotrace is free software; you can redistribute it and/or modify
41  * it under the terms of the GNU General Public License as published by
42  * the Free Software Foundation; either version 3, or (at your option)
43  * any later version.
44  *
45  * Dinotrace is distributed in the hope that it will be useful,
46  * but WITHOUT ANY WARRANTY; without even the implied warranty of
47  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
48  * GNU General Public License for more details.
49  *
50  * You should have received a copy of the GNU General Public License
51  * along with Dinotrace; see the file COPYING.  If not, write to
52  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
53  * Boston, MA 02111-1307, USA.
54  *
55  *****************************************************************************/
56 
57 #include "dinotrace.h"
58 #include <errno.h>
59 
60 #include "functions.h"
61 #include "bintradef.h"
62 
63 /**********************************************************************/
64 
65 #ifdef VMS
66 #define TRA$W_NODNAMLEN tra$r_data.tra$$r_nnr_data.tra$r_fill_11.tra$r_fill_12.tra$w_nodnamlen
67 #define TRA$T_NODNAMSTR tra$r_data.tra$$r_nnr_data.tra$r_fill_11.tra$r_fill_12.tra$t_nodnamstr
68 #define TRA$B_DATTYP tra$r_data.tra$$r_nfd_data.tra$b_dattyp
69 #define TRA$W_BITLEN tra$r_data.tra$$r_nfd_data.tra$w_bitlen
70 #define TRA$L_BITPOS tra$r_data.tra$$r_nfd_data.tra$l_bitpos
71 #define TRA$L_TIME_LO tra$r_data.tra$$r_nsr_data.tra$r_fill_13.tra$r_fill_14.tra$l_time_lo
72 #define TRA$L_TIME_HI tra$r_data.tra$$r_nsr_data.tra$r_fill_13.tra$r_fill_14.tra$l_time_hi
73 #endif /* VMS */
74 
75 /* Extract 1 bit or 2 bits from bit position POS in the buffer */
76 /* Type casting to long is important to prevent bit 7 & 8 from separating */
77 /* Note that pos is used twice, no ++'s! */
78 #define EXTRACT_2STATE(buf,pos)	((int)(((*((unsigned long *)(((unsigned long)(buf)) + ((pos)>>3)))) >> ((pos) & 7)) & 1))
79 #define EXTRACT_4STATE(buf,pos)	((int)(((*((unsigned long *)(((unsigned long)(buf)) + ((pos)>>3)))) >> ((pos) & 7)) & 3))
80 
81 #if 0
82 int	EXTRACT_2STATE (
83      uint_t pos,
84      const ulong_t *buf)
85 {
86     register uint_t bitcnt, bit_pos;
87     register uint_t bit_mask;
88     register uint_t bit_pos_in_lw;
89     register uint_t *lw_ptr;
90     register uint_t data;
91     uint_t bit_data;
92 
93     return (((*((ulong_t *)(((ulong_t)(buf)) + ((pos)>>3)))) >> ((pos) & 7)) & 1);
94 
95     if (DTPRINT_FILE) printf ("extr2st buf %x pos %x temp %x ", buf, pos);
96 
97     /*
98       (( ( *((((ulong_t *)_buf_) + ((_pos_)>>5))) ) >> ((_pos_) & 0x1F) )&1)
99       */
100 
101     lw_ptr = buf + ( pos >> 5 );
102     data = *lw_ptr;
103     /* bit_mask = 0x1F - ( pos & 0x1F); */
104     bit_mask = (pos) & 0x1F;
105     bit_data = ( data >> bit_mask ) & 1;
106 
107     if (DTPRINT_FILE) printf (" Data %x >> Mask %x = %d Bit %d\n", data, bit_mask, data>>bit_mask,bit_data);
108     /*
109     for (bit_mask=0; bit_mask<32; bit_mask++) {
110       printf ("%d=%x  ", bit_mask, data>>bit_mask);
111       }
112       printf ("\n");
113       */
114     return (bit_data);
115 }
116 #endif
117 
118 #ifdef VMS
119 #pragma inline (read_4state_to_value)
120 #endif
read_4state_to_value(const Signal_t * sig_ptr,const char * buf,Value_t * value_ptr)121 static void	read_4state_to_value (
122     const Signal_t	*sig_ptr,
123     const char	*buf,
124     Value_t	*value_ptr)
125 {
126     register int bitcnt, bit_pos;
127     int bitval;
128     int bitval_and, bitval_or;
129 
130     /* Preset the state to be based upon first bit (to speed things up) */
131     bitval = EXTRACT_4STATE (buf, sig_ptr->file_pos);
132     if (bitval & 2) bitval ^= 1;	/* decsim 2=Z which is STATE_Z=3 */
133     bitval_and = bitval_or = bitval;
134 
135     /* Extract the values, HIGH 32 BITS */
136     bit_pos = sig_ptr->file_pos;
137     for (bitcnt=96; bitcnt < (MIN (128, sig_ptr->bits)); bitcnt++, bit_pos+=2) {
138 	bitval = EXTRACT_4STATE (buf, bit_pos);
139 	if (bitval & 2) bitval ^= 1;	/* decsim 2=Z which is STATE_Z=3 */
140 	bitval_and &= bitval; bitval_or |= bitval;
141 	value_ptr->number[3] = (value_ptr->number[3]<<1) | (bitval&1);
142 	value_ptr->number[7] = (value_ptr->number[7]<<1) | ((bitval>>1)&1);
143     }
144 
145     /* Extract the values, UPPER MID 32 BITS */
146     bit_pos = sig_ptr->file_pos;
147     for (bitcnt=64; bitcnt < (MIN (96, sig_ptr->bits)); bitcnt++, bit_pos+=2) {
148 	bitval = EXTRACT_4STATE (buf, bit_pos);
149 	if (bitval & 2) bitval ^= 1;	/* decsim 2=Z which is STATE_Z=3 */
150 	bitval_and &= bitval; bitval_or |= bitval;
151 	value_ptr->number[2] = (value_ptr->number[2]<<1) | (bitval&1);
152 	value_ptr->number[6] = (value_ptr->number[6]<<1) | ((bitval>>1)&1);
153     }
154 
155     /* Extract the values LOWER MID 32 BITS */
156     for (bitcnt=32; bitcnt < (MIN (64, sig_ptr->bits)); bitcnt++, bit_pos+=2) {
157 	bitval = EXTRACT_4STATE (buf, bit_pos);
158 	if (bitval & 2) bitval ^= 1;	/* decsim 2=Z which is STATE_Z=3 */
159 	bitval_and &= bitval; bitval_or |= bitval;
160 	value_ptr->number[1] = (value_ptr->number[1]<<1) | (bitval&1);
161 	value_ptr->number[5] = (value_ptr->number[5]<<1) | ((bitval>>1)&1);
162     }
163 
164     /* Extract the values LOW 32 BITS */
165     for (bitcnt=0; bitcnt < (MIN (32, sig_ptr->bits)); bitcnt++, bit_pos+=2) {
166 	bitval = EXTRACT_4STATE (buf, bit_pos);
167 	if (bitval & 2) bitval ^= 1;	/* decsim 2=Z which is STATE_Z=3 */
168 	bitval_and &= bitval; bitval_or |= bitval;
169 	value_ptr->number[0] = (value_ptr->number[0]<<1) | (bitval&1);
170 	value_ptr->number[4] = (value_ptr->number[4]<<1) | ((bitval>>1)&1);
171     }
172 
173     if (bitval_and == bitval_or) {
174 	/* All bits the same */
175 	switch (bitval) {
176 	case STATE_1:
177 	    value_ptr->siglw.stbits.state = sig_ptr->type;
178 	    value_ptr->siglw.stbits.allhigh = TRUE;
179 	    break;
180 	default: value_ptr->siglw.stbits.state = bitval; break;
181 	}
182     } else {
183 	val_minimize (value_ptr, NULL);
184     }
185 }
186 
187 #ifdef VMS
188 #pragma inline (read_2state_to_value)
189 #endif
read_2state_to_value(const Signal_t * sig_ptr,const char * buf,Value_t * value_ptr)190 static void	read_2state_to_value (
191     const Signal_t *sig_ptr,
192     const char	*buf,
193     Value_t	*value_ptr)
194 {
195     register int bitcnt, bit_pos;
196     int bitval;
197     int bitval_and;
198 
199     /* Preset the state to be based upon first bit (to speed things up) */
200     bitval = EXTRACT_2STATE (buf, sig_ptr->file_pos);
201     bitval_and = bitval;
202 
203     /* Extract the values, HIGH 32 BITS */
204     bit_pos = sig_ptr->file_pos;
205     for (bitcnt=96; bitcnt < (MIN (128, sig_ptr->bits)); bitcnt++, bit_pos++) {
206 	bitval = EXTRACT_2STATE (buf, bit_pos);
207 	value_ptr->number[3] = (value_ptr->number[3]<<1) | bitval;
208     }
209 
210     /* Extract the values, UPPER MID 32 BITS */
211     for (bitcnt=64; bitcnt < (MIN (96, sig_ptr->bits)); bitcnt++, bit_pos++) {
212 	bitval = EXTRACT_2STATE (buf, bit_pos);
213 	value_ptr->number[2] = (value_ptr->number[2]<<1) | bitval;
214     }
215 
216     /* Extract the values LOWER MID 32 BITS */
217     for (bitcnt=32; bitcnt < (MIN (64, sig_ptr->bits)); bitcnt++, bit_pos++) {
218 	bitval = EXTRACT_2STATE (buf, bit_pos);
219 	value_ptr->number[1] = (value_ptr->number[1]<<1) | bitval;
220     }
221 
222     /* Extract the values LOW 32 BITS */
223     for (bitcnt=0; bitcnt < (MIN (32, sig_ptr->bits)); bitcnt++, bit_pos++) {
224 	bitval = EXTRACT_2STATE (buf, bit_pos);
225 	value_ptr->number[0] = (value_ptr->number[0]<<1) | bitval;
226     }
227 
228     if (value_ptr->number[0] | value_ptr->number[1] | value_ptr->number[2] | value_ptr->number[3]) {
229 	value_ptr->siglw.stbits.state = sig_ptr->type;
230 	if (bitval_and) value_ptr->siglw.stbits.allhigh = TRUE;
231     } else {
232 	value_ptr->siglw.stbits.state = STATE_0;
233     }
234 }
235 
236 #ifdef VMS
237 #pragma inline (fil_decsim_binary_add_cptr)
238 #endif
fil_decsim_binary_add_cptr(Signal_t * sig_ptr,const char * buf,DTime_t time,Boolean_t nocheck)239 static void	fil_decsim_binary_add_cptr (
240     /* Add a cptr corresponding to the decsim value for this signal */
241     Signal_t	*sig_ptr,
242     const char	*buf,
243     DTime_t	time,
244     Boolean_t	nocheck)		/* don't compare against previous data */
245 {
246     register	int		state;
247     Value_t	value;
248 
249     /* zero the value */
250     val_zero (&value);
251 
252     if (sig_ptr->bits < 2) {
253 	/* Single bit signal */
254 	if (sig_ptr->file_type.flag.four_state == 0)
255 	    state = EXTRACT_2STATE (buf, sig_ptr->file_pos)?STATE_1:STATE_0;
256 	else {
257 	    /*
258 	    if (DTDEBUG &&
259 		(EXTRACT_4STATE (buf, sig_ptr->file_pos) !=
260 		 ((EXTRACT_2STATE (buf, sig_ptr->file_pos+1) * 2) +
261 		  EXTRACT_2STATE (buf, sig_ptr->file_pos))))
262 		printf ("Mismatch@%d %s: %d!=%d,%d,%d\n",
263 			sig_ptr->file_pos,
264 			sig_ptr->signame,
265 			EXTRACT_4STATE (buf, sig_ptr->file_pos),
266 			EXTRACT_2STATE (buf, sig_ptr->file_pos + 1),
267 			EXTRACT_2STATE (buf, sig_ptr->file_pos),
268 			EXTRACT_2STATE (buf, sig_ptr->file_pos - 1));
269 			*/
270 
271 	    state = EXTRACT_4STATE (buf, sig_ptr->file_pos);
272 	    if (state & 2) state ^= 1;	/* decsim 2=Z which is STATE_Z=3 */
273 	}
274     }
275     else {
276 	/* Multibit signal */
277 	if (sig_ptr->file_type.flag.four_state == 0)
278 	    read_2state_to_value (sig_ptr, buf, &value);
279 	else read_4state_to_value (sig_ptr, buf, &value);
280     }
281 
282     value.time = time;
283     fil_add_cptr (sig_ptr, &value, nocheck);
284 }
285 
286 #ifndef VMS
never_just_to_avoid_unused(void)287 void never_just_to_avoid_unused (void) {
288     fil_decsim_binary_add_cptr (NULL, NULL, 0, 0);
289 }
290 #endif
291 
292 #ifdef VMS
decsim_read_binary(Trace_t * trace,int read_fd)293 void decsim_read_binary (
294     Trace_t	*trace,
295     int		read_fd)
296 {
297     static struct bintrarec *buf, *last_buf;
298     static struct bintrarec bufa;
299     static struct bintrarec bufb;
300     int 	first_data=TRUE;	/* True till first data is loaded */
301     int		len;
302     int		next_different_lw_pos;	/* LW pos with different value than last time slice */
303     int		time;
304     Signal_t	*sig_ptr,*last_sig_ptr;
305     int		max_lw_pos=0;		/* Maximum position in buf that has trace data */
306     DTime_t	time_divisor;
307 
308     time_divisor = time_units_to_multiplier (global->time_precision);
309 
310     /* Signal description data */
311     last_sig_ptr = NULL;
312     trace->firstsig = NULL;
313 
314     /* setup data buffers */
315     buf = &bufa;
316     last_buf = &bufb;
317 
318     for (;;) {
319 	/* Alternate between buffers so that we have the data from the last time slice */
320 	if (last_buf == &bufb) {
321 	    buf = &bufb;
322 	    last_buf = &bufa;
323 	}
324 	else {
325 	    buf = &bufa;
326 	    last_buf = &bufb;
327 	}
328 
329 	if (read (read_fd, buf, sizeof (struct bintrarec)) == 0) {
330 	    break;
331 	}
332 
333 	switch (buf->tra$b_class) {
334 	    /***** CLASS: Header *****/
335 	  case tra$k_mhr:
336 	    switch (buf->tra$b_type) {
337 	      case tra$k_mmh:
338 	      case tra$k_mdr:
339 		break;
340 	      default:
341 		if (DTPRINT) printf ( "%%E, Unknown header type %d\n", buf->tra$b_type);
342 	    }
343 	    break;
344 
345 	    /***** CLASS: Signal *****/
346 	  case tra$k_sir:
347 	    switch (buf->tra$b_type) {
348 		/**** TYPE: Begin Of Signal Section ****/
349 	      case tra$k_nns:
350 		break;
351 
352 		/**** TYPE: End Of Signal Section ****/
353 	      case tra$k_nss:
354 		fil_make_busses (trace, TRUE);
355 		break;
356 
357 		/**** TYPE: Unknown ****/
358 	      default:
359 		if (DTPRINT) printf ("%%E, Unknown section identifier type %d\n", buf->tra$b_type);
360 	    }
361 	    break;
362 
363 	    /***** CLASS: Data records *****/
364 	  case tra$k_dr:
365 	    switch (buf->tra$b_type) {
366 
367 		/**** TYPE: Node format data ****/
368 	      case tra$k_nfd:
369 		/* This should be rewritten to use signal_new_file */
370 		error_needs_rewrite_to_use_signal_new_file__contact_wsnyder; /* Comment this out, and it might work though!*/
371 		sig_ptr = DNewCalloc (Signal_t);
372 		sig_ptr->trace = trace;
373 		sig_ptr->dfile = &(trace->dfile);
374 		sig_ptr->radix = global->radixs[0];
375 		sig_ptr->file_pos = buf->TRA$L_BITPOS;
376 		/* if (DTPRINT_FILE) printf ("Reading signal format data, ptr=%d\n", sig_ptr); */
377 
378 		sig_ptr->file_type.flags = 0;
379 		sig_ptr->file_type.flag.four_state = ! (buf->TRA$B_DATTYP == tra$k_twosta);
380 
381 		/* Save the maximum position in the trace */
382 		if ((sig_ptr->file_pos >> 5) > max_lw_pos) {
383 		    max_lw_pos = ( (sig_ptr->file_pos + (sig_ptr->file_type.flag.four_state ? 2:1)
384 			       * sig_ptr->bits ) >> 5) + 1 /* so over estimate */;
385 		}
386 
387 		/* initialize all the pointers that aren't NULL */
388 		if (last_sig_ptr) last_sig_ptr->forward = sig_ptr;
389 		sig_ptr->backward = last_sig_ptr;
390 		if (trace->firstsig==NULL) trace->firstsig = sig_ptr;
391 		trace->lastsig = sig_ptr;
392 		break;
393 
394 		/**** TYPE: Node signal name data ****/
395 	      case tra$k_nnr:
396 		/* if (DTPRINT_FILE) printf ("Reading signal name data, ptr=%d\n", sig_ptr); */
397 		len = buf->TRA$W_NODNAMLEN;
398 		sig_ptr->signame = (char *)XtMalloc(16+len);	/* allow extra space in case becomes vector */
399 		strncpy (sig_ptr->signame, buf->TRA$T_NODNAMSTR, (size_t) len);
400 		sig_ptr->signame[len] = '\0';
401 
402 		last_sig_ptr = sig_ptr;
403 		break;
404 
405 		/**** TYPE: Node state data ****/
406 	      case tra$k_nsr:
407 		time = ((buf->TRA$L_TIME_LO>>1)&0x3FFFFFFF) / time_divisor +
408 		    ((buf->TRA$L_TIME_HI)&0x3FFFFFFF) * (0x40000000 / time_divisor);
409 
410 		/* save start/ end time */
411 		if (first_data) {
412 		    trace->start_time = time;
413 		}
414 		trace->end_time = time;
415 
416 		/* Compute first LW that has a different value in it */
417 		next_different_lw_pos = trace->firstsig->file_pos >> 5;	/* Grab first pos in LWs */
418 		while ( next_different_lw_pos <= max_lw_pos
419 		       && ( ((long *)buf)[next_different_lw_pos]
420 			   == ((long *)last_buf)[next_different_lw_pos] )) {
421 		    next_different_lw_pos++;
422 		}
423 		/*
424 		printf ("ST %d-%d %c%c%c%c%c: ", next_different_lw_pos, max_lw_pos,
425 			( ((long *)buf)[5] == ((long *)last_buf)[5])?'-':'5',
426 			( ((long *)buf)[6] == ((long *)last_buf)[6])?'-':'6',
427 			( ((long *)buf)[7] == ((long *)last_buf)[7])?'-':'7',
428 			( ((long *)buf)[8] == ((long *)last_buf)[8])?'-':'8',
429 			( ((long *)buf)[9] == ((long *)last_buf)[9])?'-':'9'
430 			);
431 			*/
432 
433 		/* save data for each signal */
434 		for (sig_ptr = trace->firstsig; sig_ptr; sig_ptr = sig_ptr->forward) {
435 		    if (( next_different_lw_pos <= (sig_ptr->file_end_pos >> 5)) || first_data) {
436 			/* A bit in this signal's range has changed.  Decode the value.
437 			   This signal itself may not have changed though, since there could
438 			   be 31 of 32 signals in this LW that were not changed.  */
439 
440 			fil_decsim_binary_add_cptr (sig_ptr, buf, time, first_data);
441 
442 			/* Compute next different lw */
443 			if (((sig_ptr->file_end_pos + 1) >> 5) > next_different_lw_pos) {
444 			    /* This signal completely used the different lw, find another */
445 			    /* (else there are other signals later also using this lw) */
446 			    next_different_lw_pos = (sig_ptr->file_end_pos+1) >> 5;	/* Cvt to LW position */
447 			    while ( next_different_lw_pos <= max_lw_pos
448 				   && ( ((long *)buf)[next_different_lw_pos]
449 				       == ((long *)last_buf)[next_different_lw_pos] )) {
450 				next_different_lw_pos++;
451 			    }
452 			    /* printf ("%d ", next_different_lw_pos); */
453 			}
454 		    }
455 
456 		    /* else signal couldn't have changed in this time slice.
457 		       This speed bypass saves an enourmous amount of time */
458 		    else {
459 			/* For debugging, Accumulate statistics on how often we skipped this signal */
460 			/* sig_ptr->color ++; */
461 		    }
462 		}
463 		/* printf ("\n"); */
464 
465 		first_data = FALSE;
466 		break;
467 
468 		/**** TYPE: Unknown ****/
469 	      default:
470 		if (DTDEBUG) printf ("Unknown data record type %d\n", buf->tra$b_type);
471 	    }
472 	    break;
473 
474 	    /**** CLASS: EOF ****/
475 	  case tra$k_mtr:
476 	    break;
477 
478 	    /**** CLASS: Unknown ****/
479 	  default:
480 	    if (DTPRINT_FILE) printf ("Unknown record class %d, assuming ASCII\n", buf->tra$b_class);
481 	    ascii_read (trace, read_fd, NULL);
482 	    return;
483 	}
484     }
485 
486     if (DTPRINT_FILE) printf ("Times = %d to %d\n", trace->start_time, trace->end_time);
487 
488     /* Print skipping statistics * /
489     for (sig_ptr = trace->firstsig; sig_ptr; sig_ptr = sig_ptr->forward) {
490 	printf ("%d\tLW %d-%d\tSig %s\n",sig_ptr->color,
491 		sig_ptr->file_pos >> 5, sig_ptr->file_end_pos >> 5, sig_ptr->signame);
492 	sig_ptr->color = 0;
493 	}
494 	*/
495 }
496 #endif /* VMS */
497 
498 
499 #ifdef VMS
500 #pragma inline (fil_tempest_binary_add_cptr)
501 #endif
fil_tempest_binary_add_cptr(Signal_t * sig_ptr,const uint_t * buf,DTime_t time,Boolean_t nocheck)502 static void	fil_tempest_binary_add_cptr (
503     /* Add a cptr corresponding to the text at value_strg */
504     Signal_t	*sig_ptr,
505     const uint_t *buf,
506     DTime_t	time,
507     Boolean_t	nocheck)		/* don't compare against previous data */
508 {
509     register int state=STATE_U, bit;
510     register uint_t value_index;
511     register uint_t data_index;
512     register uint_t data_mask;
513     Value_t	value;
514 
515     /* zero the value */
516     val_zero (&value);
517 
518     /* determine starting index and bit mask */
519     if (sig_ptr->bits < 2) {
520 	/* Single bit signal */
521 	if (sig_ptr->file_type.flag.four_state == 0) {
522 	    data_index = (sig_ptr->file_pos >> 5);
523 	    data_mask = 1 << ((sig_ptr->file_pos) & 0x1F);
524 
525 	    state = (buf[data_index] & data_mask)?STATE_1:STATE_0;
526 	}
527 
528 	else { /* Single bit four state (not really supported) */
529 	    data_index = (sig_ptr->file_pos >> 5);
530 	    data_mask = 1 << ((sig_ptr->file_pos) & 0x1F);
531 
532 	    value_index = (buf[data_index] & data_mask);	/* Used as temp */
533 	    if (!(data_mask = data_mask << 1)) {
534 		data_mask = 1;
535 		data_index++;
536 	    }
537 	    /* Note STATE_ encodings map directly to the 4 state values */
538 	    state = (value_index << 1) + (buf[data_index] & data_mask);
539 	}
540     }
541     else {
542 	/* Multibit signal */
543 	if (sig_ptr->file_type.flag.four_state == 0) {
544 	    buf += (sig_ptr->file_pos >> 5);	/* Point to LSB's LW */
545 	    bit = (sig_ptr->file_pos & 0x1f);	/* Point to LSB's bit position in LW */
546 
547 	    /* We want to take the data and move it so that the LSB of the data to be extracted is
548 	       now in value[0].  This is effectively a shift right of "bit" bits.  The fun comes in
549 	       because we want more than one LW of accuracy.  (Give me a 128 bit architecture!)
550 	       This method runs fast because it can execute in parallel and has no branches. */
551 
552 	    value.number[0] = (((buf[0] >> bit) & sig_ptr->pos_mask)
553 				    | ((buf[1] << (32-bit)) & (~sig_ptr->pos_mask)))
554 		& sig_ptr->value_mask[0];
555 	    value.number[1] = (((buf[1] >> bit) & sig_ptr->pos_mask)
556 				    | ((buf[2] << (32-bit)) & (~sig_ptr->pos_mask)))
557 		& sig_ptr->value_mask[1];
558 	    value.number[2] = (((buf[2] >> bit) & sig_ptr->pos_mask)
559 				    | ((buf[3] << (32-bit)) & (~sig_ptr->pos_mask)))
560 		& sig_ptr->value_mask[2];
561 	    value.number[3] = (((buf[3] >> bit) & sig_ptr->pos_mask)
562 				    | ((buf[4] << (32-bit)) & (~sig_ptr->pos_mask)))
563 		& sig_ptr->value_mask[3];
564 	    if (value.number[0] | value.number[1] | value.number[2] | value.number[3]) {
565 		if (( value.number[0] == sig_ptr->value_mask[0])
566 		    & (value.number[1] == sig_ptr->value_mask[1])
567 		    & (value.number[2] == sig_ptr->value_mask[2])
568 		    & (value.number[3] == sig_ptr->value_mask[3])) {
569 		    value.siglw.stbits.allhigh = TRUE;
570 		}
571 		state = sig_ptr->type;
572 	    } else {
573 		state = STATE_0;
574 	    }
575 	}
576 	else {
577 	    state = STATE_U;
578 	}
579     }
580 
581     value.siglw.stbits.state = state;
582     value.time = time;
583     fil_add_cptr (sig_ptr, &value, nocheck);
584 
585     /*if (DTPRINT_FILE) printf ("Sig %s  State %d  Value %d\n", sig_ptr->signame, value.siglw.stbits.state,
586       value.number[0]);*/
587 }
588 
bin_read(int fd,void * buf,size_t size)589 static int bin_read (int fd, void *buf, size_t size)
590 {
591     size_t got_tot = 0;
592     size_t remaining = size;
593     char* bufc = (char*)buf;
594     if (size <= 0) return 0;
595     do {
596 	int got_this = read (fd, bufc, remaining);
597 	if (got_this>0) {
598 	    got_tot += got_this;
599 	    bufc += got_this;
600             remaining -= got_this;
601 	} else if (got_this < 0) {
602 	    if (errno != EAGAIN && errno != EINTR) {
603 		/* read failed, presume error */
604                 printf("Read failed in bin_read (%i, -, %i)\n", fd,  (int)size);
605                 perror("dinotrace");
606 		break;
607 	    } else {
608                 got_this = 0;
609             }
610 	} else {
611 	    /* end-of-file */
612 	    break;
613         }
614     } while (got_tot < size);
615     return (got_tot);
616 }
617 
bin_read_little_uint_t32(int read_fd)618 static uint_t bin_read_little_uint_t32 (int read_fd)
619     /* Read a little endian 32 bit uint_t, correct to internal representation */
620 {
621     uint_t	status;
622     uint_t	littledata;
623     uint_t	naturaldata;
624 
625     status = bin_read (read_fd, &littledata, 4);
626     if (status) {} // UNUSED
627     /* Actually it's ANTILITTLE, but it's a symetric function */
628     naturaldata = LITTLEENDIANIZE32 (littledata);
629     return (naturaldata);
630 }
631 
tempest_read(Trace_t * trace,int read_fd)632 void tempest_read (
633     Trace_t	*trace,
634     int		read_fd)
635 {
636     uint_t	status;
637     uint_t	numBytes,numRows,numBitsRow,numBitsRowPad;
638     uint_t	*data;
639     uint_t	*data_xor;
640     Boolean_t	first_data;
641     Boolean_t	have_phase = FALSE;
642     uint_t	i,j;
643     uint_t	pad_len;
644     uint_t	time, last_time=EOT;
645     Signal_t	*sig_ptr=NULL;
646     Boolean_t	verilator_xor_format;
647     char	chardata[4096];
648 
649     /* Read the file identification block */
650     status = bin_read (read_fd, chardata, 4);
651     chardata[4]='\0';
652     verilator_xor_format = !strncmp (chardata,"BX",2);
653     if (!status || (!strncmp (chardata,"BT",2) && !strncmp (chardata,"BX",2) )) {
654 	sprintf (message, "Bad File Format (=%s)\n", chardata);
655 	dino_error_ack(trace, message);
656 	return;
657     }
658 
659     numBytes      = bin_read_little_uint_t32 (read_fd);
660     trace->numsig = bin_read_little_uint_t32 (read_fd);
661     numRows       = bin_read_little_uint_t32 (read_fd);
662     numBitsRow    = bin_read_little_uint_t32 (read_fd);
663     numBitsRowPad = bin_read_little_uint_t32 (read_fd);
664 
665     if (DTPRINT_FILE) {
666 	if (verilator_xor_format) printf ("This is Verilator Compressed XOR format.\n");
667 	printf ("File Sig=%s Bytes=%d Signals=%d Rows=%d Bits/Row=%d Bits/Row(pad)=%d\n",
668 		chardata,numBytes,trace->numsig,numRows,numBitsRow,numBitsRowPad);
669     }
670 
671     /** Read the signal description data - a signal description block is
672      ** created for each signal describing the signal and containing ptrs
673      ** for the trace data, current trace location, etc.
674      */
675     trace->firstsig=NULL;
676     for (i=0;i<trace->numsig;i++) {
677 	union sig_file_type_u file_type;
678 	uint_t	sigChars,sigFlags,sigOffset,sigWidth;
679 
680 	sigFlags  = bin_read_little_uint_t32 (read_fd);
681 	sigOffset = bin_read_little_uint_t32 (read_fd);
682 	sigWidth  = bin_read_little_uint_t32 (read_fd);
683 	sigChars  = bin_read_little_uint_t32 (read_fd);
684 	if (sigChars >= sizeof(chardata)) {
685  	    sprintf (message, "Signal name too long (=%d): Trace may be corrupt.\n", sigChars);
686  	    dino_error_ack(trace, message);
687  	    return;
688 	}
689 
690 	status = bin_read (read_fd, chardata, sigChars);
691 	chardata[sigChars] = '\0';
692 
693 	if (DTPRINT_FILE) {
694 	    printf ("sigFlags=%x sigOffset=%d sigWidth=%d sigChars=%d sigName=%s\n",
695 		   sigFlags,sigOffset,sigWidth,sigChars,chardata);
696 	}
697 
698 	/* These could be simplified as they map 1:1, but safer not to */
699 	file_type.flags = 0;
700 	file_type.flag.pin_input  = ((sigFlags & 1) != 0);
701 	file_type.flag.pin_output = ((sigFlags & 2) != 0);
702 	file_type.flag.pin_psudo  = ((sigFlags & 4) != 0);
703 	file_type.flag.pin_timestamp = ((sigFlags & 8) != 0);
704 	file_type.flag.four_state = ((sigFlags & 16) != 0);
705 
706 	sig_new_file (trace, chardata,
707 		      sigOffset, 0,
708 		      sigWidth, -1/*msb*/, -1/*lsb*/,
709 		      file_type);
710 
711 	/* Detect phase signal -- not completely reliable */
712 	/* This prevents a bug when a trace starts on phase b */
713 	if (sigOffset < 64
714 	    && (0==strcmp ("Phase", chardata+sigChars-5)
715 		|| 0==strcmp ("phase", chardata+sigChars-5))) {
716 	    if (DTPRINT_FILE) printf ("Have Phase indication\n");
717 	    have_phase = TRUE;
718 	}
719 
720 	/* Checks */
721 	if (file_type.flag.four_state != 0) {
722 	    sprintf (message,"Four state tempest not supported.\nSignal %s will be wrong.",chardata);
723 	    dino_warning_ack (trace, message);
724 	}
725 
726 	/* Read the pad bits */
727 	pad_len = (sigChars%8) ? 8 - (sigChars%8) : 0;
728 	status = bin_read (read_fd, chardata, pad_len);
729     }
730 
731     /* Make the busses */
732     fil_make_busses (trace, FALSE);
733 
734     /* Make storage space, with some overhead */
735     data     = (uint_t *)XtCalloc (32 + numBitsRowPad/32, sizeof(uint_t));
736     data_xor = (uint_t *)XtCalloc (32 + numBitsRowPad/32, sizeof(uint_t));
737 
738     /* Read the signal trace data
739      * Pass 0-(numRows-1) reads the data, pass numRows processes last line */
740     first_data = TRUE;
741 
742     /* Don't use numRows as it is written when CCLI exits, and may be incorrect
743        if CCLI was CTL-Ced */
744 
745     while (1) {
746 	/* Read a row of data */
747 	if (verilator_xor_format) {
748 	    status = bin_read (read_fd, data_xor, numBitsRowPad/8);
749 	    if (status < numBitsRowPad/8) break;	/* End of data */
750 
751 	    /* Un-exor the data */
752 	    /* Correct endianization */
753 	    for (j = 0; j <= (numBitsRowPad/(sizeof(uint_t)*8)); j++) {
754 		uint_t littledata = data_xor[j];
755 		/* cppcheck-suppress selfAssignment */
756 		littledata = LITTLEENDIANIZE32 (littledata);
757 		data[j] ^= littledata;
758 	    }
759 	}
760 	else {
761 	    /* Regular format */
762 	    status = bin_read (read_fd, data, numBitsRowPad/8);
763 	    if (status < numBitsRowPad/8) break;	/* End of data */
764 
765 	    /* Correct endianization */
766 #if WORDS_BIGENDIAN	/* If little, make sure whole loop goes away */
767 	    for (j = 0; j <= (numBitsRowPad/(sizeof(uint_t)*8)); j++) {
768 		uint_t littledata = data[j];
769 		data[j] = LITTLEENDIANIZE32 (littledata);
770 	    }
771 #endif
772 	}
773 
774 	/** Extract the phase - this will be used as a 'time' value and
775 	 ** is multiplied by 100 to make the trace easier to read
776 	 */
777 
778 	time = data[0] * global->tempest_time_mult;
779 	if (time == last_time) time+= MAX(1,global->tempest_time_mult/2);
780 	last_time = time;
781 	if (first_data && have_phase) {
782 	    int phase = data[1] & 1;
783 	    if (phase) time += MAX(1,global->tempest_time_mult/2);
784 	    if (DTPRINT_FILE) printf ("Initial phase detected: %d  Adjust 1|%d\n", phase, global->tempest_time_mult/2);
785 	}
786 
787 #if 0
788 	if (DTPRINT_FILE) {
789 	    printf ("read: time=%d  status %d data=%08x [time %d] %08x\n", time,
790 		    status, data[0], data[0], data[1]);
791 	}
792 #endif
793 
794 	/*
795 	 ** If this is the first row, save the starting and initial
796 	 ** time, else eventually the end time will be saved.
797 	 */
798 	if (first_data)
799 	    trace->start_time = time;
800 	else trace->end_time = time;
801 
802 	/* Fortunately, Tempest and Decsim have identical binary packed formats. */
803 	/* Perhaps it's because both were written by Digital's SEG CAD. */
804 	for (sig_ptr = trace->firstsig; sig_ptr; sig_ptr = sig_ptr->forward) {
805 	    fil_tempest_binary_add_cptr (sig_ptr, data, time, first_data);
806 	}
807 
808 	first_data = FALSE;
809     }/* end for */
810 
811     DFree (data);
812 }
813 
814