Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / util / fileutil.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: fileutil.cc
// 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 ============================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> // gid_t
#include <sys/stat.h> // gid_t
#include <unistd.h> // getuid
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdarg.h>
#include "types.h"
#include "fileutil.h"
#pragma ident "@(#)1.12 06/05/22 fileutil.cc"
static char buff[256];
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef void (*sigfunc_t)(int);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/*
* This routine is used to perform a waitpid() call that will work.
* It disables the SIGCHLD signal handler (used by window command)
* before the waitpid() and then restores it.
*/
int
fw_waitpid(pid_t pid, int* statusp, int options)
{
pid_t w;
/* static void (*sigchld_func)(int); */
sigfunc_t sigchld_func;
/*
* Set handling of sigchld to default (ignored) -- needed because we
* call waitpid() below.
*/
sigchld_func = signal(SIGCHLD, SIG_DFL);
/* Wait for child to die. */
w = waitpid(pid, statusp, options);
/* Restore sigchld handling. */
signal(SIGCHLD, sigchld_func);
return w;
}
/* A safe interface for the wait() routine. */
int
fw_wait(int* statusp)
{
pid_t w;
/* void (*sigchld_func)(int); */
sigfunc_t sigchld_func;
/* Set handling of sigchld to default (ignored) -- needed because we
* call waitpid() below.
*/
sigchld_func = signal(SIGCHLD, SIG_DFL);
/* Wait for child to die. */
w = wait(statusp);
/* Restore sigchld handling. */
signal(SIGCHLD, sigchld_func);
return w;
}
/*
* This routine executes the specified UNIX command and examines the status.
* If the command passed, 0 is returned, otherwise 1.
*/
int
system_command(char* cmd)
{
int status;
pid_t pid;
pid_t w;
#if 0
int tty_flags;
#endif
/*
* Put the tty into blocking mode. This also stops the simulator from
* handling SIGIO signals until it gets back into non-blocking
* mode.
*/
#if 0 //////// TODO
tty_flags = sigio_make_tty_blocking();
#endif
if ((pid = fork()) == 0) {
(void) execl("/bin/sh", "sh", "-c", cmd, NULL);
_exit(127);
}
if (pid == -1) {
#if 0 //// TODO
/* Restore the tty mode. */
sigio_set_tty_flags(tty_flags);
#endif
printf("Fork for UNIX command %s failed.\n", cmd);
perror("fork");
return 1;
}
/* Wait for child to die. */
w = fw_waitpid(pid, &status, 0);
#if 0 ///// TODO
/* Restore the tty mode. */
sigio_set_tty_flags(tty_flags);
#endif
if (w == -1) {
if (errno == ECHILD) {
printf("Child did not exist for UNIX command %s.\n", cmd);
}
perror("waitpid");
return 1;
}
if (WIFSTOPPED(status)) {
printf("UNIX command %s stopped by signal %d.\n",
cmd, WSTOPSIG(status));
printf("May not be enough memory.\n");
return 1;
}
if (WIFSIGNALED(status)) {
printf("UNIX command %s terminated by signal %d.\n",
cmd, WTERMSIG(status));
return 1;
}
if (WIFEXITED(status)) {
if (WEXITSTATUS(status)) {
return 1;
}
return 0;
}
/* Command didn't call exit() so assume it failed. */
return 1;
}
FILE *fopen_dir_path(const char *dir, const char *a, const char *b,
const char *mode)
{
if (b != NULL) {
sprintf(buff, "%s%s%s", dir, a, b);
} else {
sprintf(buff, "%s%s", dir, a);
}
{
FILE *f = fopen(buff, mode);
if (f == NULL) {
perror(buff);
}
return f;
}
} /* fopen_dir_path */
FILE *fopen_as_uid(const char *filename, const char *mode)
{
int uid = getuid();
FILE *fp = fopen(filename, mode);
if (fp == NULL) {
perror(filename);
} else {
if (*mode == 'w') { // change owner if writing a file
int fd = fileno(fp);
fchown(fd, uid, -1); // change owner to the actual user
}
}
return fp;
}
// just a template for defining other fns
static int statTest(const char *dirname)
{
struct stat statbuf;
int status = stat(dirname, &statbuf);
if (status == 0) {
int reg = (S_ISREG(statbuf.st_mode));
int fifo = (S_ISFIFO(statbuf.st_mode));
int chr = (S_ISCHR(statbuf.st_mode));
int dir = (S_ISDIR(statbuf.st_mode));
int blk = (S_ISBLK(statbuf.st_mode));
int lnk = (S_ISLNK(statbuf.st_mode));
}
return 0;
} /* statTest */
int isDir(const char *dirname)
{
struct stat statbuf;
int status = stat(dirname, &statbuf);
if (status == 0) {
int dir = (S_ISDIR(statbuf.st_mode));
return dir;
}
return 0;
}
int isFile(const char *filename)
{
struct stat statbuf;
int status = stat(filename, &statbuf);
if (status == 0) {
int reg = (S_ISREG(statbuf.st_mode));
return reg;
}
return 0;
}
int fileExists(const char *filename)
{
struct stat statbuf;
int status = stat(filename, &statbuf);
return (status == 0) || (errno != ENOENT);
} /* fileExists */
/////////////////////////////////////////////////////////////////
void write_double (FILE *fp, const char * name, double v)
{
fprintf (fp, "%s %f\n", name, v);
}
void write_scalar_64 (FILE *fp, const char * name, uint64_t v)
{
fprintf (fp, "%s 0x%llx\n", name, v);
}
void write_scalar_2_64 (FILE *fp, const char * name, uint64_t v1, uint64_t v2)
{
fprintf (fp, "%s 2\n", name);
fprintf (fp, " 0x%llx\n ", v1);
fprintf (fp, " 0x%llx\n", v2);
}
void write_scalar_32 (FILE *fp, const char * name, uint32_t v)
{
fprintf (fp, "%s 0x%x\n", name, v);
}
void write_scalar_8 (FILE *fp, const char * name, uint8_t v)
{
fprintf (fp, "%s 0x%x\n", name, v);
}
void write_string (FILE *fp, const char * name, char *s)
{
fprintf (fp, "%s \"%s\"\n", name, s);
}
void write_vector_64 (FILE *fp, const char * name, int n, uint64_t *v)
{
int i;
fprintf (fp, "%s %d\n", name, n);
for (i = 0; i < n; i++) {
fprintf (fp, " 0x%llx\n", v[i]);
}
}
void write_vector_32 (FILE *fp, const char * name, int n, uint32_t *v)
{
int i;
fprintf (fp, "%s %d\n", name, n);
for (i = 0; i < n; i++) {
fprintf (fp, " 0x%x\n", v[i]);
}
}
///////////////////
void dump_uint32(FILE * fp, uint32_t val)
{
fwrite(&val, sizeof(uint32_t), 1, fp);
}
void dump_uint64(FILE * fp, uint64_t val)
{
fwrite(&val, sizeof(uint64_t), 1, fp);
}
uint64_t restore_uint64(FILE * fp)
{
uint64_t val;
fread((void*)&val, sizeof(val), 1, fp);
return val;
}
bool_t read_double (FILE *fp, const char * name, double *v)
{
char s[128], sn[128];
float ff;
if (fgets (s, 128, fp) == NULL) {
return FALSE;
}
if (sscanf (s, "%s %f", sn, &ff) != 2) {
return FALSE;
}
*v = ff;
if (strcmp(sn, name) != NULL) {
return FALSE;
}
return TRUE;
}
bool_t read_scalar_64 (FILE *fp, const char * name, uint64_t *v)
{
char s[128], sn[128];
if (fgets (s, 128, fp) == NULL) {
return FALSE;
}
if (sscanf (s, "%s %lli", sn, v) != 2) {
return FALSE;
}
if (strcmp(sn, name) != NULL) {
return FALSE;
}
return TRUE;
}
bool_t read_scalar_32 (FILE *fp, const char * name, uint32_t *v)
{
char s[128], sn[128];
if (fgets (s, 128, fp) == NULL) {
return FALSE;
}
if (sscanf (s, "%s %i", sn, v) != 2) {
return FALSE;
}
if (strcmp(sn, name) != NULL) {
return FALSE;
}
return TRUE;
}
bool_t read_scalar_8 (FILE *fp, const char * name, Byte *v)
{
int i;
char s[128], sn[128];
if (fgets (s, 128, fp) == NULL) {
return FALSE;
}
if (sscanf (s, "%s %i", sn, &i) != 2) {
return FALSE;
}
if (strcmp(sn, name) != NULL) {
return FALSE;
}
*v = (Byte)i;
return TRUE;
}
bool_t read_scalar_2_64 (FILE *fp, const char * name, uint64_t *v1, uint64_t *v2)
{
int i;
char s[128], sn[128];
if (fgets (s, 128, fp) == NULL) {
return FALSE;
}
if (sscanf (s, "%s %i", sn, &i) != 2) {
return FALSE;
}
if (strcmp(sn, name) != NULL) {
return FALSE;
}
if (fgets (s, 128, fp) == NULL) {
return FALSE;
}
if (sscanf (s, "%lli", v1) != 1) {
return FALSE;
}
if (fgets (s, 128, fp) == NULL) {
return FALSE;
}
if (sscanf (s, "%lli", v2) != 1) {
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////
char * read_string (FILE *fp, const char * name, int n, char *ss)
{
int i = 0;
char s[128], sn[128];
char *ps = ss, *ps1, *ps2;
if (fgets (s, 128, fp) == NULL)
return NULL;
if (sscanf (s, "%s", sn) != 1) {
return NULL;
}
if (strcmp(sn, name) != NULL) {
fprintf (stderr, "restore err S = <%s>; pattern <%s>, %d\n", s, name, n);
return NULL;
}
ps1 = strchr (s, '"');
ps2 = strrchr (s, '"');
if ((ps1 == NULL) || (ps2 == NULL)) {
fprintf (stderr, "restore err <%s> \n", s);
return NULL;
}
++ps1;
for (;ps1 != ps2; ps1++, i++) {
if (i >= n)
break;
*ps++ = *ps1;
}
*ps = '\0';
return ps;
}
char * read_string_2 (FILE *fp, const char * name, const char * alt_name, int n, char *ss)
{
int i = 0;
char s[128], sn[128];
char *ps = ss, *ps1, *ps2;
if (fgets (s, 128, fp) == NULL)
return NULL;
if (sscanf (s, "%s", sn) != 1) {
return NULL;
}
if ((strcmp(sn, name) != NULL) && (strcmp(sn, alt_name) != NULL)) {
fprintf (stderr, "restore err S = <%s>; pattern <%s>, %d\n", s, name, n);
return NULL;
}
ps1 = strchr (s, '"');
ps2 = strrchr (s, '"');
if ((ps1 == NULL) || (ps2 == NULL)) {
fprintf (stderr, "restore err <%s> \n", s);
return NULL;
}
++ps1;
for (;ps1 != ps2; ps1++, i++) {
if (i >= n)
break;
*ps++ = *ps1;
}
*ps = '\0';
return ps;
}
bool_t read_vector_64 (FILE *fp, const char * name, int n, uint64_t *v)
{
int i;
char s[128], sn[128];
if (fgets (s, 128, fp) == NULL)
return FALSE;
if (sscanf (s, "%s %d", sn, &i) != 2) {
return FALSE;
}
if ((i != n) || (strcmp(sn, name) != NULL)) {
fprintf (stderr, "restore err S = <%s>; pattern <%s>, %d\n", s, name, n);
return FALSE;
}
for (i = 0; i < n; i++) {
if (fgets (s, 128, fp) == NULL)
return FALSE;
if (sscanf (s, "%lli", &v[i]) != 1) {
return FALSE;
}
}
return TRUE;
}
bool_t read_vector_32 (FILE *fp, const char * name, int n, uint32_t *v)
{
int i;
char s[128], sn[128];
if (fgets (s, 128, fp) == NULL)
return FALSE;
if (sscanf (s, "%s %d", sn, &i) != 2) {
return FALSE;
}
if ((i != n) || (strcmp(sn, name) != NULL)) {
fprintf (stderr, "restore err S = <%s>; pattern <%s>, %d\n", s, name, n);
return FALSE;
}
for (i = 0; i < n; i++) {
if (fgets (s, 128, fp) == NULL)
return FALSE;
if (sscanf (s, "%i", &v[i]) != 1) {
return FALSE;
}
}
return TRUE;
}
///////////////////////////////////////////
// Thw following routines borrowed
// form BLAZE V3 without modifocation
//
/*
* This routine converts a pointer into an array into its equivalent integer
* index and then writes it to a file. It handles null pointers.
* Returns 1 on error, 0 no error.
* Borrowed from Blaze v3 without changes
*
*/
int dump_array_ptr (
FILE* fp,
char* array_base,
u_int element_size,
char* ptr
)
{
char is_ptr_null = 0;
u_int index = 0;
if (ptr == NULL) {
is_ptr_null = 1;
} else {
if (ptr < array_base) {
/* Address of pointer is less than the base. */
return 1;
}
index = ((u_int) (ptr - array_base)) / element_size;
if (ptr != array_base + index * element_size) {
/*
* If reconstructing the address from the index
* doesn't give the original pointer value, return
* with and error. This can happen when the pointer
* doesn't point to the start of an element.
*/
return 1;
}
}
/* Write out flag that indicates if pointer is null. */
if (fwrite((char*)&is_ptr_null, sizeof(is_ptr_null), 1, fp) != 1) {
return 1;
}
/* Write out index (even if pointer is null). */
if (fwrite((char*)&index, sizeof(index), 1, fp) != 1) {
return 1;
}
return 0;
}
int restore_array_ptr (
FILE* fp,
char* array_base,
u_int element_size,
char** ptr
)
{
char is_ptr_null = 0;
u_int index = 0;
/* Read in flag that indicates if pointer is null. */
if (fread((char*)&is_ptr_null, sizeof(is_ptr_null), 1, fp) != 1) {
return 1;
}
/* Read in index (even if pointer is null). */
if (fread((char*)&index, sizeof(index), 1, fp) != 1) {
return 1;
}
if (is_ptr_null) {
*ptr = NULL;
} else {
*ptr = array_base + index * element_size;
}
return 0;
}
/*
* Remove directory tree recursively by calling "rm -rf <dirname>".
* It cannot return status since rm -f doesn't set it.
*/
void rm_rf_directory (char* dir_name)
{
char buf[FILENAME_MAX];
sprintf(buf, "rm -rf %s", dir_name);
system_command(buf);
}
//
// 32 vs 64 bit stuff
//
void print_addr (FILE *f, void *vp) {
#if HOST32BIT == 1
fprintf (f, "0x%08x", vp);
#elif HOST64BIT == 1
fprintf (f, "0x%016llx", vp);
#else
printf ("Print_addr error: neither HOST32BIT nor HOST64BIT defined\n");
#endif
}
//
// DUMP FUNCTIONS
//
void dumpStructAddr (FILE *f, char *addr, const char *name, int size, int arrlen) {
fprintf (f, "StructAddr %d %d ", size, arrlen);
print_addr (f, addr);
fprintf (f, " %s\n", name);
}
void dumpDynArrDelm (FILE *f, const char *name, int idx, int total) {
fprintf (f, "DynArrDelm %d %d %s\n", idx, total, name);
}
void dumpScalar (FILE *f, const char *name, char *data, size_t size) {
int i;
fprintf (f, "%s %d 0x", name, size);
for (i = 0; i < size; i++) {
fprintf (f, "%02x", *(data + i) & 0xff);
}
fprintf (f, "\n");
fflush(f);
}
void dumpArr (FILE *f, const char *name, unsigned char *data, size_t num, size_t size) {
int i, j;
for (i = 0; i < num; i++) {
fprintf (f, "%s[%d] %d 0x", name, i, size);
for (j = 0; j < size; j++) {
fprintf (f, "%02x", *(data + size*i + j) & 0xff);
}
fprintf (f, "\n");
}
}
///////////////////////////////////////////////
char *get_substr_until (char *src, char *tgt, char stop_symbol)
{
char *ps = src, *pt = tgt;
*pt = '\0';
while (*ps == ' ')
ps++;
if (*ps == '\0')
return NULL;
if (*ps == 0xA)
return NULL;
if ((*ps == '#') || (*ps == '!'))
return NULL;
while ((*ps != stop_symbol) && (*ps != ' ')) {
*pt++ = *ps;
++ps;
}
*pt = '\0';
if (*ps == stop_symbol) {
return ps + 1;
}
else {
while ((*ps != stop_symbol) && (*ps != '\0')) {
++ps;
}
if (*ps == '\0')
return ps;
else
return ps + 1;
}
}
///////////////////////////////////////////////
char * get_quoted_substr (char *src, char *tgt)
{
char *ps = src, *pt = tgt;
while (*ps == ' ')
ps++;
if (*ps == '\0')
return NULL;
if (*ps == 0xA)
return NULL;
if ((*ps == '#') || (*ps == '!'))
return NULL;
if (*ps == '\"') {
*pt = '\0';
}
else {
return NULL;
}
++ps;
while (*ps != '\"') {
*pt++ = *ps++;
if (*ps == '\0')
return NULL;
}
*pt = '\0';
return ps + 1;
}
///////////////////////////////////////////////
//
// Microsecs --> cycles
//
uint64_t usec2cycles (uint64_t usecs, uint64_t sfreq, uint32_t loopticks)
{
double tau = ((double)(1000000.0) / (double) sfreq) / (double) loopticks ;
return (uint64_t) ((double) usecs / tau);
}
///////////////////////////////////////////////
#define NNN 16
AddrPair * eval_mem_image (FILE *fp, int *ret_size)
{
int index = -1, len = NNN;
char s[512 + 4], *ps;
uint64_t v[4], pa;
AddrPair *ppp = (AddrPair*) calloc (NNN, sizeof(AddrPair));
if (ppp == NULL) {
return NULL;
}
*ret_size = 0;
while (fgets (s, 512, fp)) {
if (s[0] == '\0') {
continue;
}
if (s[0] == '@') { /// address
ps = &s[1];
int ret = sscanf (ps, "%llx", &pa);
if (ret != 1) {
goto error;
}
index++;
ppp[index].addr = pa;
ppp[index].size = 0;
if (index >= len - 1) {
len <<= 1;
ppp = (AddrPair*)realloc (ppp, sizeof(AddrPair) * len);
}
}
else {
int ret = sscanf (s, "%llx %llx %llx %llx", &v[0], &v[1], &v[2], &v[3]);
if (ret != 4) {
ret = sscanf (s, "%llx %llx %llx", &v[0], &v[1], &v[2]);
if (ret != 3) {
ret = sscanf (s, "%llx %llx", &v[0], &v[1]);
if (ret != 2) {
ret = sscanf (s, "%llx", &v[0]);
if (ret != 1) {
continue;
}
}
}
}
ppp[index].size += (ret<<3);
}
}
*ret_size = index + 1;
return ppp;
error:
free ((char*) ppp);
return NULL;
}