* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: rstf.c
* 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 ============================================
#pragma ident "@(#) rstf.c 1.3: 03/05/03 16:59:47 @(#)"
// This is C code, not C++
#include <stdarg.h> // ??
#include <stdio.h> // fopen()
#include <string.h> // strncmp()
#include <stdlib.h> // putenv()
#include <sys/types.h> // time_t
#include <sys/stat.h> // struct stat
#include <time.h> // time_t
static int numbad
= 0; // number of bad RST recs
// static int dummy = RSTF_ATRACE_NO_PC;
#define print_type_size(out,type) \
check(out, #type, sizeof(type), want);
static int streq (const char* a
, const char* b
) {
return (strcmp(a
, b
) == 0);
static int endsWith (const char* str
, const char* suffix
) {
int sufflen
= strlen(suffix
);
return (sufflen
<= slen
) &&
(strncmp(str
+slen
-sufflen
, suffix
, sufflen
) == 0);
// Set of triples (AA,BB,CC), where
// Versions in the range [AA,BB) are compatiable.
// Versions with the same CC value are considered semi-compatible.
// Versions with different CC values are incompatible.
// The last entry should have AA = BB = CC = -1 .
// 1.00 vs. 1.04 => compatible.
// 1.04 vs. 1.06 => semi-compatible.
// 1.07 vs. 1.09 => semi-compatible.
// 1.10 vs. 2.02 => compatible.
double rst_vequivtab
[][3] = {
static double rstver2double (const char * str
) {
int ni
= sscanf(str
, "%d.%d", &x
, &y
);
const char* ct_str
, const char* rt_str
, double vt
[][3], const char* modname
double ct_ver
= rstver2double(ct_str
);
double rt_ver
= rstver2double(rt_str
);
return ver_check_dbl(ct_ver
, rt_ver
, vt
, modname
);
int rstf_version_check_fn (const char* ct_version
) {
const char* rt_str
= RSTF_VERSION_STR
;
return rst_verCheck(ct_version
, rt_str
, rst_vequivtab
, "RST");
} /* rstf_version_check_fn */
int rstf_checkheader (const char* compile_time_ver
, rstf_headerT
*rec
) {
double ct_ver
= rstver2double(compile_time_ver
);
if (rec
->rtype
== RSTHEADER_T
) {
double trace_ver
= (100 * rec
->majorVer
) + rec
->minorVer
;
if (rec
->percent
!= '%') {
fprintf(stderr
, "Non-compliant RST header: compile-on=%% got=%c\n",
return ver_check_dbl(ct_ver
, trace_ver
, rst_vequivtab
, "RST trace");
static int nfileinfo
= 0;
static fileinfo_t fileinfo
[64];
for (i
=0; i
<nfileinfo
; i
++) {
fileinfo_t
* pp
= & fileinfo
[i
];
"[%d]->f=0x%0x iscompressed=%d\n", i
, pp
->f
, pp
->isCompressed
);
FILE * openRST (const char* filename
) {
endsWith(filename
, ".rsz") ||
endsWith(filename
, ".rz.gz") ||
endsWith(filename
, ".rsz.gz") ||
endsWith(filename
, ".rzgz");
int decompress2
= endsWith(filename
, ".rz2.gz");
putenv("PATH=/import/archperf/bin:/usr/bin:/bin");
sprintf(command
, "rstzip -d -gz %s", filename
);
} else if (decompress2
) {
putenv("PATH=/import/archperf/bin:/usr/bin:/bin");
sprintf(command
, "rstunzip2 %s", filename
);
f
= fopen(filename
, "r");
fileinfo
[nfileinfo
].f
= f
;
fileinfo
[nfileinfo
].isCompressed
= decompress
|| decompress2
;
void closeRST (FILE* f
) {
for (i
=0; i
<nfileinfo
; i
++) {
fileinfo_t
* pp
= & fileinfo
[i
];
f
= NULL
; /* we found it */
*pp
= fileinfo
[nfileinfo
-1];
/* guess the type of the file */
ftype
= "pipe from popen";
fprintf(stderr
, "closeRST(f=%x), guessed f is %s\n", f
, ftype
);
int isPipeRST (FILE* f
) {
return ((statbuf
.st_mode
& S_IFIFO
) == S_IFIFO
);
int isCompressedRSZ (char * buff
, int bufflen
) {
// from running "od -x trace.rz.gz"
0x1f, 0x8b, 0x08, 0x00, -1, -1, -1, -1
for (i
=0; i
<sizeof(want
)/sizeof(want
[0]) ; i
++) {
if (buff
[i
] != want
[i
] && want
[i
] != -1) {
void check (FILE* out
, const char* type
, int tsize
, int want
) {
fprintf(out
, "sizeof(%18s) = %4d\n", type
, tsize
);
fprintf(out
, "ERROR on (%s) field.\n", type
, sizeof(type
));
static void initrec (void* ptr
, uint8_t rtype
) {
#define INIT_RST_REC_DBG(rstf_ptr,rtype_val) \
rstf_uint64T * p = (rstf_uint64T*) (rstf_ptr); \
p->arr64[0] = (rtype_val); \
p->arr64[0] <<= (64-8); \
int want
= sizeof(rstf_unionT
);
print_type_size(out
,rstf_unionT
);
print_type_size(out
,rstf_protoT
);
print_type_size(out
,rstf_whatT
);
print_type_size(out
,rstf_instrT
);
print_type_size(out
,rstf_tlbT
);
print_type_size(out
,rstf_threadT
);
print_type_size(out
,rstf_processT
);
print_type_size(out
,rstf_pregT
);
print_type_size(out
,rstf_trapT
);
print_type_size(out
,rstf_cpuT
);
print_type_size(out
,rstf_trapT
);
print_type_size(out
,rstf_stringT
);
print_type_size(out
,rstf_physaddrT
);
print_type_size(out
,rstf_pavadiffT
);
print_type_size(out
,rstf_memval64T
);
print_type_size(out
,rstf_memval128T
);
print_type_size(out
,rstf_bustraceT
);
print_type_size(out
,rstf_filemarkerT
);
print_type_size(out
,rstf_recnumT
);
print_type_size(out
,rstf_hwinfoT
);
print_type_size(out
,rstf_statusT
);
print_type_size(out
,rstf_patchT
);
print_type_size(out
,rstf_dmaT
);
printf("================\n");
print_type_size(out
,rstf_uint8T
);
print_type_size(out
,rstf_uint16T
);
print_type_size(out
,rstf_uint32T
);
print_type_size(out
,rstf_uint64T
);
fprintf(out
, "Good. All records in rstf are the same size.\n");
fprintf(out
, "OK rtype=%d want=%d\n", rec
.rtype
, INSTR_T
); fflush(out
);
fprintf(out
, "OK rtype=%d want=%d\n", rec
.rtype
, TLB_T
); fflush(out
);
// INIT_RST_REC_DBG( p , INSTR_T);
// fprintf(out, "OK rtype=%d want=%d\n", rec.rtype, INSTR_T); fflush(out);
INIT_RST_REC( p
, INSTR_T
);
fprintf(out
, "OK rtype=%d want=%d\n", rec
.rtype
, INSTR_T
); fflush(out
);
static void strcopy (char* dest
, const char* src
, int destsize
) {
strncpy(dest
, src
, destsize
);
int rstf_strncpy (void * dest_rstp
, const char *str
) {
rstf_unionT
* up
= (rstf_unionT
*) dest_rstp
;
rstf_headerT
* hp
= &(up
->header
);
switch (up
->string
.rtype
) {
strncpy(hp
->header_str
, str
, sizeof(hp
->header_str
));
// initialize a header record with the current RST major/minor number.
int init_rstf_header (rstf_headerT
* hp
) {
INIT_RST_REC(hp
, RSTHEADER_T
);
hp
->majorVer
= RSTF_MAJOR_VERSION
;
hp
->minorVer
= RSTF_MINOR_VERSION
;
sprintf(buff
, "%s v%s", RSTF_MAGIC
, RSTF_VERSION_STR
);
int init_rstf_traceinfo_level (rstf_traceinfo_levelT
* ti
, int level
) {
INIT_RST_REC(ti
, TRACEINFO_T
);
ti
->rtype2
= RSTT2_NLEVEL_T
;
ti
->time64
= (uint64_t) time(NULL
);
int init_rstf_string (rstf_stringT
* strp
, const char *str
) {
int len
= strlen(str
) + 1; // null char adds 1
int recsize
= sizeof(strp
->string
);
INIT_RST_REC(strp
, STRDESC_T
);
strncpy(strp
->string
, str
, recsize
);
strncpy(strp
->string
, str
, recsize
-1);
strp
->string
[recsize
-1] = '\0';
const char* get_rstf_longstr (const rstf_stringT
* p
, int nrec
, int *nrread
) {
const int strcontsize
= sizeof(p
->string
);
const rstf_stringT
* strp
= & (p
[nr
]);
int rem
= buff
+ sizeof(buff
) - end
; // remaining room
if (strp
->rtype
== STRCONT_T
) {
strncpy(end
, strp
->string
, strcontsize
);
} else if (strp
->rtype
== STRDESC_T
) {
strcpy(end
, strp
->string
);
end
+= strlen(strp
->string
);
} /* get_rstf_long_string */
#define min(x,y) ((x)<(y) ? (x) : (y))
// Initialize upto MAXREC records with the string STR, using
// STRDESC_T and STRCONT_T records. Handles strings of any length.
// Returns the number of RST records used.
int init_rstf_strbuff (rstf_stringT
* strp
, const char *str
, int maxrec
) {
int len
= strlen(str
) + 1; // null char adds 1
int recsize
= sizeof(strp
->string
);
int nrneeded
= ((len
) + (recsize
-1))/ recsize
;
int canuse
= min(maxrec
, nrneeded
); // RST records we can use
for (i
=0; i
<canuse
; i
++) {
init_rstf_string( &strp
[i
], ss
);
strp
[i
].rtype
= STRCONT_T
;
strncpy(strp
[i
].string
, ss
, recsize
);
} /* init_rstf_strbuff */
// Convenience fn to generate a RST_STRDESC record.
int rstf_sprintf (rstf_stringT
* strp
, const char* fmt
, ...) {
vsnprintf(buff
, BUFFLEN
, fmt
, ap
);
init_rstf_string(strp
, buff
);
// Convenience fn to generate a RST_STRDESC record.
int rstf_snprintf (rstf_stringT
* strp
, int maxrec
, const char* fmt
, ...) {
vsnprintf(buff
, 8192, fmt
, ap
);
nr
= init_rstf_strbuff(strp
, buff
, maxrec
);
void printIfBadAddr (uint64_t xaddr
) {
if (RSTF_IS_BADADDR(xaddr
)) {
printf("Addr 0x%08llx is a known bad RST addr\n", xaddr
);
uint64_t x
= RSTF_ATRACE_NO_PC
;
char* unixcommand (const char * command
, int nl
, int * statusptr
) {
static char charbuff
[RCBUFFSIZE
];
FILE *ptr
= popen(command
, "r");
while (fgets(buf
, RCBUFFSIZE
- (buf
-charbuff
), ptr
) != NULL
) {
if (buf
[len
-1] == '\n') {
// remove '\n', terminate string, in case last line of input
buf
[len
-1] = '\0'; // discard last newline
static void genTestTrace (const char* str
) {
rstf_stringT
* buff
= & (uuu
[1].string
); // [1] == skip past header
char* now
= unixcommand("date", 1, NULL
);
init_rstf_header(& uuu
[0].header
);
rstf_sprintf(buff
, "BEGIN it is %s", now
);
nr
= rstf_snprintf(buff
+1, 88, "it is now %s", now
);
df
= unixcommand("df -lk", 44, NULL
);
nr2
= rstf_snprintf(buff
+1+nr
, 88, "Local mounted disks %s", df
);
rstf_sprintf(buff
+1+nr
+nr2
, "END. argv[0]=(%s)", str
);
fwrite(&uuu
, sizeof(buff
[0]), 3+nr
+nr2
, stdout
);
static void usage (char* argv0
) {
printf("usage: %s [-tvf]\n", argv0
);
printf(" -f FILE = read 16K recs from FILE openRST(), send to stdout\n");
printf(" -t = generate a test trace to stdout\n");
printf(" -v = run version check code\n");
printf(" Eg. %s -t | trconv\n", argv0
);
static void checkVer () {
{ "1.00", "1.4", "1.7", "1.8", "1.10", "2.0", "2.02", "4.8" };
int len
= sizeof(strArr
) / sizeof(strArr
[0]);
const char * ct
= strArr
[i
];
const char * rt
= strArr
[j
];
int status
= generic_verCheck(ct
, rt
, rst_vequivtab
, "XYZ");
int status2
= rst_verCheck(ct
, rt
, rst_vequivtab
, "RST");
printf("%d = verCheck(%s, %s)\n", status
, ct
, rt
);
printf("%d = rst_verCheck(%s, %s)\n", status2
, ct
, rt
);
int main (int argc
, char* argv
[]) {
if ( streq(argv
[1], "-f") ) {
FILE * f
= openRST(argv
[i
]);
while ((nr
=fread(ru
, sizeof(ru
[0]), 128, f
)) > 0) {
fwrite(ru
, sizeof(ru
[0]), nr
, stdout
);
} else if ( streq(argv
[1], "-v") ) {
} else if ( streq(argv
[1], "-v") ) {
} else if ( streq(argv
[1], "-t") ) {