/*  pdtstats.c          eej    8/93  */
/*                      rev   12/93  */
/*                                   */
/*  histograms characteristics of    */
/*  a PDATS trace                    */

#include <stdio.h>

unsigned int CurrentAddr[8],NextAddr,CurrentTS,NextTS;
long addroff,tsoff;
long offsets[8][8], repeats[256][8], ts[4][8];

main()
{
    int c;

    if(getchar()!=0xff) {
	fprintf(stderr, "pdt2din: file not in PDATS format\n");
	exit(-1);
    }
    initial();
    switch (c=getchar()) {
      case 3:         /* time stamps, w/repeats  */
      case 2:         /* time stamps, no repeats */
      case 1:         /* no time stamps, w/repeats  */
      case 0:         /* no time stamps, no repeats */
	histTR();
	break;
      default:
	fprintf(stderr, "pdt2din: unrecognized format\n");
	exit(-2);
    }
    print_results();
}

/**************************************************************/

histTR()    /* TYPE, ADDRESS, and TIME STAMPS */
{
    int i, c, type, tscode, addrcode, NumRep;

    while((c=getchar())!=EOF){
	type= c & 7;
	tscode = (c & 0x18) >>3;
	addrcode = (c & 0x60) >>5;
	if(c & 0x80)         /*** repeated ***/
	  NumRep = getchar();
	else
	  NumRep=1;

	if(addrcode==0)
	  addroff=4;
	else if(addrcode==1 || addrcode==2) {
	    addroff=0;
	    for(i=addrcode;i>0;i--)
	      addroff |= getchar() << ((i-1) << 3);
	}
	else fread((char *) &addroff, 4, 1, stdin);
	if (negnum(addroff,addrcode)) addrcode = 3 - addrcode;
	else addrcode += 4;

	if (tscode < 2) tsoff = tscode;
	else{
	    tsoff = 0;
	    for(i=tscode-1;i>0;i--)
	      tsoff |= getchar() << ((i-1) << 3);
	}
	offsets[addrcode][type] += NumRep;
	repeats[NumRep-1][type]++;
	ts[tscode][type] += NumRep;
    }
}

/**************************************************************/

print_results()
{
    int i, j, nonzero;
    long count = 0, type_used[8];
    double ratio, temp;

    printf("\nRef Type    Count\n");
    for (i=0; i<8; i++) {
	printf("%4d    ", i);
	type_used[i] = ts[0][i] + ts[1][i] + ts[2][i] + ts[3][i];
	printf("%10ld\n", type_used[i]);
	count += type_used[i];
    }
    printf("Total   %10ld\n\n", count);

    printf("\t\tAddress offset code histogram (row = ref type):\n");
    printf("Type\t-3\t-2\t-1\t-0\t0\t1\t2\t3\n");
    for (i=0; i<8; i++) 
      if (type_used[i]) {
	  printf("%3d   ", i);
	  for (j=0; j<8; j++) 
	    printf("%8.4lf", ratio = (double) offsets[j][i] / type_used[i]);
	  printf("\n");
      }
    printf("Avg   ");
    for (j=0; j<8; j++) {
      temp = 0.0;
      for (i=0; i<8; i++) temp += offsets[j][i];
      printf("%8.4lf", ratio = temp / count);
    }

    printf("\n\n\t\tRepeat counts histogram (column = ref type):\n");
    printf("Repeats");
    for (i=0; i<8; i++) printf("%9d", i);
    printf("\n");
    for (j=0; j<256; j++) {
	nonzero = 0;
	for (i=0; i<8; i++) nonzero += repeats[j][i];
	if (nonzero) {
	    printf("%4d   ", j);
	    for (i=0; i<8; i++) {
		if (repeats[j][i]) printf("%9ld", repeats[j][i]);
		else printf("         ");
	    }
	    printf("\n");
	}
    }

    printf("\n\t\tTime stamp code histogram (column = ref type):\n");
    printf("TS Code");
    for (i=0; i<8; i++) printf("%9d", i);
    printf("\n");
    for (j=0; j<4; j++) {
	printf("%4d   ", j);
	for (i=0; i<8; i++) {
	    if (ts[j][i]) printf("%9ld", ts[j][i]);
	    else printf("         ");
	}
	printf("\n");
    }
}

/********************************************************************/
initial()
{
    int i, j;

    for(i=0;i<=7;i++)
      CurrentAddr[i]=0;
    CurrentTS=0;

    for (j=0; j<8; j++) {
	for (i=0; i<8; i++) offsets[i][j] = 0;
	for (i=0; i<256; i++) repeats[i][j] = 0;
	for (i=0; i<4; i++) ts[i][j] = 0;
    }
}
/*********************************************************************/
negnum(num,size)
unsigned long num;
int size;
{
    if (size == 0) return 0;
    else if(size==1) return (num & 0x80);
    else if(size==2) return (num & 0x8000);
    else if(size==3) return (num & 0x80000000);
    else{
	fprintf(stderr, "\npdtstats:  illegal size (%d) passed to negnum\n",
		size);
	print_results();
	exit(-1);
    } 
}
