summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/ccdrv/devtime.c2
-rwxr-xr-xutil/cscope-find.py38
-rw-r--r--util/m5/Makefile3
-rw-r--r--util/m5/m5.c17
-rw-r--r--util/m5/m5op.S21
-rw-r--r--util/m5/m5op.h5
-rwxr-xr-xutil/oprofile-top.py3
-rwxr-xr-xutil/qdo6
-rwxr-xr-xutil/regress90
-rwxr-xr-xutil/rundiff5
-rw-r--r--util/statetrace/Makefile37
-rw-r--r--util/statetrace/arch/tracechild_i386.cc120
-rw-r--r--util/statetrace/arch/tracechild_i386.hh105
-rw-r--r--util/statetrace/arch/tracechild_sparc.cc342
-rw-r--r--util/statetrace/arch/tracechild_sparc.hh125
-rw-r--r--util/statetrace/printer.cc290
-rw-r--r--util/statetrace/printer.hh109
-rw-r--r--util/statetrace/refcnt.hh125
-rw-r--r--util/statetrace/regstate.hh58
-rw-r--r--util/statetrace/statetrace.cc189
-rw-r--r--util/statetrace/tracechild.cc145
-rw-r--r--util/statetrace/tracechild.hh65
-rw-r--r--util/statetrace/tracechild_arch.cc54
-rw-r--r--util/statetrace/x86.format6
-rw-r--r--util/stats/db.py99
-rw-r--r--util/stats/dbinit.py37
-rw-r--r--util/stats/display.py2
-rw-r--r--util/stats/info.py7
-rw-r--r--util/stats/orderdict.py2
-rw-r--r--util/stats/output.py22
-rw-r--r--util/stats/print.py2
-rw-r--r--util/stats/profile.py2
-rwxr-xr-xutil/stats/stats.py36
-rw-r--r--util/tap/tap.cc2
-rwxr-xr-xutil/tracediff8
35 files changed, 1927 insertions, 252 deletions
diff --git a/util/ccdrv/devtime.c b/util/ccdrv/devtime.c
index 62b0e2592..d8be97bb4 100644
--- a/util/ccdrv/devtime.c
+++ b/util/ccdrv/devtime.c
@@ -24,6 +24,8 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
*/
#include <linux/module.h>
diff --git a/util/cscope-find.py b/util/cscope-find.py
new file mode 100755
index 000000000..1775f1864
--- /dev/null
+++ b/util/cscope-find.py
@@ -0,0 +1,38 @@
+#! /usr/bin/python
+
+# Generate list of files to index with cscope.
+
+# From the m5 directory, run:
+# util/cscope-find.py > cscope.files
+# cscope -b
+
+import os
+
+# absolute paths to skip
+skipdirs = [ 'src/unittest', 'src/doxygen' ]
+
+# suffixes of files to index
+suffixes = [ '.cc', '.hh', '.c', '.h' ]
+
+def oksuffix(f):
+ for s in suffixes:
+ if f.endswith(s):
+ return True
+ return False
+
+for dirpath,subdirs,files in os.walk('src'):
+ # filter out undesirable subdirectories
+ for i,dir in enumerate(subdirs):
+ if dir == 'SCCS':
+ del subdirs[i]
+ break
+
+ # filter out undesriable absolute paths
+ if dirpath in skipdirs:
+ del subdirs[:]
+ continue
+
+ # find C/C++ sources
+ okfiles = [f for f in files if oksuffix(f)]
+ if okfiles:
+ print '\n'.join([os.path.join(dirpath, f) for f in okfiles])
diff --git a/util/m5/Makefile b/util/m5/Makefile
index 518542322..a98092e47 100644
--- a/util/m5/Makefile
+++ b/util/m5/Makefile
@@ -23,6 +23,9 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+# Ali Saidi
### If we are not compiling on an alpha, we must use cross tools ###
ifneq ($(shell uname -m), alpha)
diff --git a/util/m5/m5.c b/util/m5/m5.c
index fa9be96e8..23401aea5 100644
--- a/util/m5/m5.c
+++ b/util/m5/m5.c
@@ -24,6 +24,8 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
*/
#include <inttypes.h>
@@ -48,6 +50,7 @@ usage()
" m5 dumpstats [delay [period]]\n"
" m5 dumpresetstats [delay [period]]\n"
" m5 checkpoint [delay [period]]\n"
+ " m5 readfile\n"
"\n"
"All times in nanoseconds!\n");
exit(1);
@@ -202,6 +205,20 @@ main(int argc, char *argv[])
if (COMPARE("loadsymbol")) {
m5_loadsymbol(arg1);
return 0;
+ if (COMPARE("readfile")) {
+ char buf[256*1024];
+ int offset = 0;
+ int len;
+
+ if (argc != 2)
+ usage();
+
+ while ((len = m5_readfile(buf, sizeof(buf), offset)) > 0) {
+ write(STDOUT_FILENO, buf, len);
+ offset += len;
+ }
+
+ return 0;
}
usage();
diff --git a/util/m5/m5op.S b/util/m5/m5op.S
index 97eb9238d..a19113e62 100644
--- a/util/m5/m5op.S
+++ b/util/m5/m5op.S
@@ -24,6 +24,9 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ * Ali Saidi
*/
#define m5_op 0x01
@@ -48,6 +51,8 @@
#define switchcpu_func 0x52
#define addsymbol_func 0x53
#define panic_func 0x54
+#define anbegin_func 0x55
+#define anwait_func 0x56
#define INST(op, ra, rb, func) \
.long (((op) << 26) | ((ra) << 21) | ((rb) << 16) | (func))
@@ -83,6 +88,8 @@ func:
#define SWITCHCPU INST(m5_op, 0, 0, switchcpu_func)
#define ADDSYMBOL(r1,r2) INST(m5_op, r1, r2, addsymbol_func)
#define PANIC INST(m5_op, 0, 0, panic_func)
+#define AN_BEGIN(r1) INST(m5_op, r1, 0, anbegin_func)
+#define AN_WAIT(r1,r2) INST(m5_op, r1, r2, anwait_func)
.set noreorder
@@ -202,3 +209,17 @@ LEAF(m5_panic)
END(m5_panic)
+ .align 4
+LEAF(m5_anbegin)
+ AN_BEGIN(16)
+ RET
+END(m5_anbegin)
+
+
+ .align 4
+LEAF(m5_anwait)
+ AN_WAIT(16,17)
+ RET
+END(m5_anwait)
+
+
diff --git a/util/m5/m5op.h b/util/m5/m5op.h
index 34ac7760d..eab4e7fd5 100644
--- a/util/m5/m5op.h
+++ b/util/m5/m5op.h
@@ -24,6 +24,9 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ * Ali Saidi
*/
#ifndef __M5OP_H__
@@ -50,5 +53,7 @@ void m5_debugbreak(void);
void m5_switchcpu(void);
void m5_addsymbol(uint64_t addr, char *symbol);
void m5_panic(void);
+void m5_anbegin(uint64_t s);
+void m5_anwait(uint64_t s, uint64_t w);
#endif // __M5OP_H__
diff --git a/util/oprofile-top.py b/util/oprofile-top.py
index c6e35344c..aea9dfadd 100755
--- a/util/oprofile-top.py
+++ b/util/oprofile-top.py
@@ -25,6 +25,9 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Ali Saidi
+# Nathan Binkert
# Parse sampled function profile output (quick hack).
diff --git a/util/qdo b/util/qdo
index 135cce4ef..92e4605b1 100755
--- a/util/qdo
+++ b/util/qdo
@@ -25,6 +25,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Steve Reinhardt
import sys
import os
@@ -179,10 +181,10 @@ try:
if output_dir:
secs_waited = 0
- while not shell.dir_exists(output_dir) and secs_waited < 45:
+ while not shell.dir_exists(output_dir) and secs_waited < 90:
time.sleep(5)
secs_waited += 5
- if secs_waited > 10:
+ if secs_waited > 30:
print "waited", secs_waited, "seconds for", output_dir
# run command
diff --git a/util/regress b/util/regress
index 067f9f092..8e60b6fee 100755
--- a/util/regress
+++ b/util/regress
@@ -1,5 +1,5 @@
#! /usr/bin/env python
-# Copyright (c) 2005 The Regents of The University of Michigan
+# Copyright (c) 2005-2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -32,39 +32,22 @@ import os
import optparse
import datetime
-#
-# Regression invocation:
-#
-# regress \
-# --workdir poolfs \
-# --scons-opts 'BATCH=yes USE_MYSQL=no -j 30 -Q' \
-# --recurse
-
progname = os.path.basename(sys.argv[0])
optparser = optparse.OptionParser()
optparser.add_option('-v', '--verbose', dest='verbose', action='store_true',
default=False,
help='echo commands before executing')
-optparser.add_option('--scratch', dest='scratch', action='store_true',
- default=False,
- help='rebuld from scratch')
optparser.add_option('--builds', dest='builds',
- default='ALPHA_SE,ALPHA_FS,ALPHA_FS_TL',
- help='comma-separated list of builds to test')
+ default='ALPHA_SE,ALPHA_FS,MIPS_SE,SPARC_SE',
+ help='comma-separated list of build targets to test '
+ " (default: '%default')" )
optparser.add_option('--variants', dest='variants',
default='opt',
- help='comma-separated list of build variants to test')
-optparser.add_option('--workdir', dest='workdir',
- help='directory for checked-out source trees')
+ help='comma-separated list of build variants to test '
+ " (default: '%default')" )
optparser.add_option('--scons-opts', dest='scons_opts', default='',
- help='scons options')
-optparser.add_option('--no-pull', dest='pull', action='store_false',
- default=True,
- help="don't pull changes from repository")
-optparser.add_option('--recurse', dest='recurse', action='store_true',
- default=False,
- help='call recursively to get summary up front')
+ help='scons options', metavar='OPTS')
(options, tests) = optparser.parse_args()
@@ -73,9 +56,6 @@ optparser.add_option('--recurse', dest='recurse', action='store_true',
builds = options.builds.split(',')
variants = options.variants.split(',')
-# Repositories to clone/update
-repos = ['m5', 'm5-test', 'ext']
-
# Call os.system() and raise exception if return status is non-zero
def system(cmd):
if options.verbose:
@@ -93,58 +73,20 @@ def shellquote(s):
s = "'%s'" % s
return s
-# The '--recurse' option invokes scons once to perform any necessary
-# rebuilds/test runs with the (possibly verbose) output placed in a
-# log file, then (if the buld was successful) returns scons to print a
-# summary of the results.
-if options.recurse:
- sys.argv.remove('--recurse') # avoid infinite recursion...
- timestr = datetime.datetime.now().isoformat('-')[:19]
- logfile = '%s-%s' % (progname, timestr)
- # quote args for shell
- qargs = [shellquote(a) for a in sys.argv]
- # always run the sub-job in verbose mode
- qargs.append('-v')
- cmd = '%s > %s 2>&1' % (' '.join(qargs), logfile)
- try:
- system(cmd)
- except OSError, exc:
- print "Error: recursive invocation failed, aborting."
- print exc
- print "======================="
- os.system('cat %s' % logfile)
- sys.exit(1)
- # recursive call succeeded... re-run to generate summary
- # don't *re*-build from scratch now
- options.scratch = False
- # no need to re-pull since the recursive call shoudl have done that
- options.pull = False
- print "Recursive invocation successful, see %s for output." % logfile
-
try:
- if options.workdir:
- if options.verbose:
- print 'cd', options.workdir
- os.chdir(options.workdir)
-
- if options.scratch:
- for dir in repos:
- system('rm -rf %s' % dir)
- system('bk clone /bk/%s' % dir)
- elif options.pull:
- for dir in repos:
- system('cd %s; bk pull' % dir)
-
if not tests:
print "No tests specified."
sys.exit(1)
- if options.verbose:
- print 'cd m5/build'
- os.chdir('m5/build')
-
- targets = ['%s/test/%s/%s' % (build, variant, test)
- for build in builds for variant in variants for test in tests]
+ if 'all' in tests:
+ targets = ['build/%s/tests/%s' % (build, variant)
+ for build in builds
+ for variant in variants]
+ else:
+ targets = ['build/%s/tests/%s/%s' % (build, variant, test)
+ for build in builds
+ for variant in variants
+ for test in tests]
system('scons %s %s' % (options.scons_opts, ' '.join(targets)))
diff --git a/util/rundiff b/util/rundiff
index 9376e4b9e..c34bb53a3 100755
--- a/util/rundiff
+++ b/util/rundiff
@@ -25,6 +25,9 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+# Steve Reinhardt
# Diff two streams.
#
@@ -36,7 +39,7 @@
# "filename" is a pipe (|). Thus to compare the instruction traces
# from two versions of m5 (m5a and m5b), you can do this:
#
-# rundiff 'm5a --trace:flags=InstExec |' 'm5b --trace:flags=InstExec |'
+# rundiff 'm5a --traceflags=InstExec |' 'm5b --traceflags=InstExec |'
#
use strict;
diff --git a/util/statetrace/Makefile b/util/statetrace/Makefile
new file mode 100644
index 000000000..c59748163
--- /dev/null
+++ b/util/statetrace/Makefile
@@ -0,0 +1,37 @@
+# Copyright (c) 2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+.PHONY: statetrace
+
+statetrace: statetrace-native
+
+statetrace-native: statetrace.cc tracechild.cc tracechild_arch.cc printer.cc printer.hh refcnt.hh regstate.hh tracechild.hh
+ g++ statetrace.cc tracechild.cc tracechild_arch.cc printer.cc -I ./ -I ./arch/ -O3 --static -o statetrace
+
+statetrace-sparc: statetrace.cc tracechild.cc tracechild_arch.cc printer.cc printer.hh refcnt.hh regstate.hh tracechild.hh
+ sparc64-unknown-linux-gnu-g++ statetrace.cc tracechild.cc tracechild_arch.cc printer.cc -I ./ -I ./arch/ -O3 --static -o statetrace
diff --git a/util/statetrace/arch/tracechild_i386.cc b/util/statetrace/arch/tracechild_i386.cc
new file mode 100644
index 000000000..14c22c7f0
--- /dev/null
+++ b/util/statetrace/arch/tracechild_i386.cc
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include <iostream>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <stdint.h>
+
+#include "tracechild_i386.hh"
+
+using namespace std;
+
+char * I386TraceChild::regNames[numregs] = {
+ //GPRs
+ "eax", "ebx", "ecx", "edx",
+ //Index registers
+ "esi", "edi",
+ //Base pointer and stack pointer
+ "ebp", "esp",
+ //Segmentation registers
+ "cs", "ds", "es", "fs", "gs", "ss",
+ //PC
+ "eip"};
+
+int64_t I386TraceChild::getRegs(user_regs_struct & myregs, int num)
+{
+ assert(num < numregs && num >= 0);
+ switch(num)
+ {
+ //GPRs
+ case EAX: return myregs.eax;
+ case EBX: return myregs.ebx;
+ case ECX: return myregs.ecx;
+ case EDX: return myregs.edx;
+ //Index registers
+ case ESI: return myregs.esi;
+ case EDI: return myregs.edi;
+ //Base pointer and stack pointer
+ case EBP: return myregs.ebp;
+ case ESP: return myregs.esp;
+ //Segmentation registers
+ case CS: return myregs.cs;
+ case DS: return myregs.ds;
+ case ES: return myregs.es;
+ case FS: return myregs.fs;
+ case GS: return myregs.gs;
+ case SS: return myregs.ss;
+ //PC
+ case EIP: return myregs.eip;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+bool I386TraceChild::update(int pid)
+{
+ oldregs = regs;
+ if(ptrace(PTRACE_GETREGS, pid, 0, &regs) != 0)
+ return false;
+ for(unsigned int x = 0; x < numregs; x++)
+ {
+ regDiffSinceUpdate[x] =
+ (getRegVal(x) != getOldRegVal(x));
+ }
+}
+
+I386TraceChild::I386TraceChild()
+{
+ for(unsigned int x = 0; x < numregs; x++)
+ regDiffSinceUpdate[x] = false;
+}
+
+int64_t I386TraceChild::getRegVal(int num)
+{
+ return getRegs(regs, num);
+}
+
+int64_t I386TraceChild::getOldRegVal(int num)
+{
+ return getRegs(oldregs, num);
+}
+
+char * I386TraceChild::printReg(int num)
+{
+ sprintf(printBuffer, "0x%08X", getRegVal(num));
+ return printBuffer;
+}
+
+TraceChild * genTraceChild()
+{
+ return new I386TraceChild;
+}
diff --git a/util/statetrace/arch/tracechild_i386.hh b/util/statetrace/arch/tracechild_i386.hh
new file mode 100644
index 000000000..f8c68c770
--- /dev/null
+++ b/util/statetrace/arch/tracechild_i386.hh
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef REGSTATE_I386_HH
+#define REGSTATE_I386_HH
+
+#include <linux/user.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <assert.h>
+#include <string>
+
+#include "tracechild.hh"
+
+class I386TraceChild : public TraceChild
+{
+public:
+ enum RegNum
+ {
+ //GPRs
+ EAX, EBX, ECX, EDX,
+ //Index registers
+ ESI, EDI,
+ //Base pointer and stack pointer
+ EBP, ESP,
+ //Segmentation registers
+ CS, DS, ES, FS, GS, SS,
+ //PC
+ EIP,
+ numregs
+ };
+private:
+ char printBuffer [256];
+ static char * regNames[numregs];
+ int64_t getRegs(user_regs_struct & myregs, int num);
+ user_regs_struct regs;
+ user_regs_struct oldregs;
+ bool regDiffSinceUpdate[numregs];
+
+protected:
+ bool update(int pid);
+
+public:
+
+ I386TraceChild();
+
+ int getNumRegs()
+ {
+ return numregs;
+ }
+
+ bool diffSinceUpdate(int num)
+ {
+ assert(num < numregs && num >= 0);
+ return regDiffSinceUpdate[num];
+ }
+
+ std::string getRegName(int num)
+ {
+ assert(num < numregs && num >= 0);
+ return regNames[num];
+ }
+
+ int64_t getRegVal(int num);
+ int64_t getOldRegVal(int num);
+ uint64_t getPC() {return getRegVal(EIP);}
+ uint64_t getSP() {return getRegVal(ESP);}
+ std::ostream & outputStartState(std::ostream & output)
+ {
+ output << "Printing i386 initial state not yet implemented"
+ << std::endl;
+ return output;
+ }
+
+ char * printReg(int num);
+};
+
+#endif
diff --git a/util/statetrace/arch/tracechild_sparc.cc b/util/statetrace/arch/tracechild_sparc.cc
new file mode 100644
index 000000000..378de0865
--- /dev/null
+++ b/util/statetrace/arch/tracechild_sparc.cc
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include <iostream>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <stdint.h>
+
+#include "tracechild_sparc.hh"
+
+using namespace std;
+
+string SparcTraceChild::regNames[numregs] = {
+ //Global registers
+ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
+ //Output registers
+ "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
+ //Local registers
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
+ //Input registers
+ "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
+ //Floating point
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ //Miscelaneous
+ "fsr", "fprs", "pc", "npc", "y", "cwp", "pstate", "asi", "ccr"};
+
+int64_t getRegs(regs & myregs, fpu & myfpu,
+ int64_t * locals, int64_t * inputs, int num)
+{
+ assert(num < SparcTraceChild::numregs && num >= 0);
+ switch(num)
+ {
+ //Global registers
+ case SparcTraceChild::G0: return 0;
+ case SparcTraceChild::G1: return myregs.r_g1;
+ case SparcTraceChild::G2: return myregs.r_g2;
+ case SparcTraceChild::G3: return myregs.r_g3;
+ case SparcTraceChild::G4: return myregs.r_g4;
+ case SparcTraceChild::G5: return myregs.r_g5;
+ case SparcTraceChild::G6: return myregs.r_g6;
+ case SparcTraceChild::G7: return myregs.r_g7;
+ //Output registers
+ case SparcTraceChild::O0: return myregs.r_o0;
+ case SparcTraceChild::O1: return myregs.r_o1;
+ case SparcTraceChild::O2: return myregs.r_o2;
+ case SparcTraceChild::O3: return myregs.r_o3;
+ case SparcTraceChild::O4: return myregs.r_o4;
+ case SparcTraceChild::O5: return myregs.r_o5;
+ case SparcTraceChild::O6: return myregs.r_o6;
+ case SparcTraceChild::O7: return myregs.r_o7;
+ //Local registers
+ case SparcTraceChild::L0: return locals[0];
+ case SparcTraceChild::L1: return locals[1];
+ case SparcTraceChild::L2: return locals[2];
+ case SparcTraceChild::L3: return locals[3];
+ case SparcTraceChild::L4: return locals[4];
+ case SparcTraceChild::L5: return locals[5];
+ case SparcTraceChild::L6: return locals[6];
+ case SparcTraceChild::L7: return locals[7];
+ //Input registers
+ case SparcTraceChild::I0: return inputs[0];
+ case SparcTraceChild::I1: return inputs[1];
+ case SparcTraceChild::I2: return inputs[2];
+ case SparcTraceChild::I3: return inputs[3];
+ case SparcTraceChild::I4: return inputs[4];
+ case SparcTraceChild::I5: return inputs[5];
+ case SparcTraceChild::I6: return inputs[6];
+ case SparcTraceChild::I7: return inputs[7];
+ //Floating point
+ case SparcTraceChild::F0: return myfpu.f_fpstatus.fpu_fr[0];
+ case SparcTraceChild::F1: return myfpu.f_fpstatus.fpu_fr[1];
+ case SparcTraceChild::F2: return myfpu.f_fpstatus.fpu_fr[2];
+ case SparcTraceChild::F3: return myfpu.f_fpstatus.fpu_fr[3];
+ case SparcTraceChild::F4: return myfpu.f_fpstatus.fpu_fr[4];
+ case SparcTraceChild::F5: return myfpu.f_fpstatus.fpu_fr[5];
+ case SparcTraceChild::F6: return myfpu.f_fpstatus.fpu_fr[6];
+ case SparcTraceChild::F7: return myfpu.f_fpstatus.fpu_fr[7];
+ case SparcTraceChild::F8: return myfpu.f_fpstatus.fpu_fr[8];
+ case SparcTraceChild::F9: return myfpu.f_fpstatus.fpu_fr[9];
+ case SparcTraceChild::F10: return myfpu.f_fpstatus.fpu_fr[10];
+ case SparcTraceChild::F11: return myfpu.f_fpstatus.fpu_fr[11];
+ case SparcTraceChild::F12: return myfpu.f_fpstatus.fpu_fr[12];
+ case SparcTraceChild::F13: return myfpu.f_fpstatus.fpu_fr[13];
+ case SparcTraceChild::F14: return myfpu.f_fpstatus.fpu_fr[14];
+ case SparcTraceChild::F15: return myfpu.f_fpstatus.fpu_fr[15];
+ case SparcTraceChild::F16: return myfpu.f_fpstatus.fpu_fr[16];
+ case SparcTraceChild::F17: return myfpu.f_fpstatus.fpu_fr[17];
+ case SparcTraceChild::F18: return myfpu.f_fpstatus.fpu_fr[18];
+ case SparcTraceChild::F19: return myfpu.f_fpstatus.fpu_fr[19];
+ case SparcTraceChild::F20: return myfpu.f_fpstatus.fpu_fr[20];
+ case SparcTraceChild::F21: return myfpu.f_fpstatus.fpu_fr[21];
+ case SparcTraceChild::F22: return myfpu.f_fpstatus.fpu_fr[22];
+ case SparcTraceChild::F23: return myfpu.f_fpstatus.fpu_fr[23];
+ case SparcTraceChild::F24: return myfpu.f_fpstatus.fpu_fr[24];
+ case SparcTraceChild::F25: return myfpu.f_fpstatus.fpu_fr[25];
+ case SparcTraceChild::F26: return myfpu.f_fpstatus.fpu_fr[26];
+ case SparcTraceChild::F27: return myfpu.f_fpstatus.fpu_fr[27];
+ case SparcTraceChild::F28: return myfpu.f_fpstatus.fpu_fr[28];
+ case SparcTraceChild::F29: return myfpu.f_fpstatus.fpu_fr[29];
+ case SparcTraceChild::F30: return myfpu.f_fpstatus.fpu_fr[30];
+ case SparcTraceChild::F31: return myfpu.f_fpstatus.fpu_fr[31];
+ //Miscelaneous
+ case SparcTraceChild::FSR: return myfpu.f_fpstatus.Fpu_fsr;
+ case SparcTraceChild::FPRS: return myregs.r_fprs;
+ case SparcTraceChild::PC: return myregs.r_tpc;
+ case SparcTraceChild::NPC: return myregs.r_tnpc;
+ case SparcTraceChild::Y: return myregs.r_y;
+ case SparcTraceChild::CWP:
+ return (myregs.r_tstate >> 0) & ((1 << 5) - 1);
+ case SparcTraceChild::PSTATE:
+ return (myregs.r_tstate >> 8) & ((1 << 13) - 1);
+ case SparcTraceChild::ASI:
+ return (myregs.r_tstate >> 24) & ((1 << 8) - 1);
+ case SparcTraceChild::CCR:
+ return (myregs.r_tstate >> 32) & ((1 << 8) - 1);
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+bool SparcTraceChild::update(int pid)
+{
+ static const int stackBias = 2047;
+ memcpy(&oldregs, &theregs, sizeof(regs));
+ memcpy(&oldfpregs, &thefpregs, sizeof(fpu));
+ memcpy(oldLocals, locals, 8 * sizeof(uint64_t));
+ memcpy(oldInputs, inputs, 8 * sizeof(uint64_t));
+ if(ptrace(PTRACE_GETREGS, pid, &theregs, 0) != 0)
+ {
+ cerr << "Update failed" << endl;
+ return false;
+ }
+ uint64_t StackPointer = getRegVal(O6);
+ for(unsigned int x = 0; x < 8; x++)
+ {
+ locals[x] = ptrace(PTRACE_PEEKTEXT, pid,
+ StackPointer + stackBias + x * 8, 0);
+ inputs[x] = ptrace(PTRACE_PEEKTEXT, pid,
+ StackPointer + stackBias + x * 8 + (8 * 8), 0);
+ }
+ if(ptrace(PTRACE_GETFPREGS, pid, &thefpregs, 0) != 0)
+ return false;
+ for(unsigned int x = 0; x < numregs; x++)
+ regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
+ return true;
+}
+
+SparcTraceChild::SparcTraceChild()
+{
+ for(unsigned int x = 0; x < numregs; x++)
+ regDiffSinceUpdate[x] = false;
+}
+
+bool SparcTraceChild::step()
+{
+ //Two important considerations are that the address of the instruction
+ //being breakpointed should be word (64bit) aligned, and that both the
+ //next instruction and the instruction after that need to be breakpointed
+ //so that annulled branches will still stop as well.
+ const static uint64_t breakInst = 0x91d02001;
+ const static uint64_t breakWord = breakInst | (breakInst << 32);
+ const static uint64_t lowMask = (uint64_t)(0xFFFFFFFF);
+ const static uint64_t highMask = lowMask << 32;
+ uint64_t originalInst, originalAnnulInst;
+ uint64_t nextPC = getRegVal(NPC);
+ bool unaligned = nextPC & 7;
+ uint64_t alignedPC = nextPC & (~7);
+ originalInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC, 0);
+ if(unaligned)
+ {
+ originalAnnulInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC+8, 0);
+ }
+ uint64_t newInst;
+ if(unaligned)
+ {
+ newInst = (originalInst & highMask) | (breakInst << 0);
+ if(ptrace(PTRACE_POKETEXT, pid, alignedPC, newInst) != 0)
+ cerr << "Poke failed" << endl;
+ newInst = (originalAnnulInst & lowMask) | (breakInst << 32);
+ if(ptrace(PTRACE_POKETEXT, pid, alignedPC+8, newInst) != 0)
+ cerr << "Poke failed" << endl;
+ }
+ else
+ {
+ if(ptrace(PTRACE_POKETEXT, pid, alignedPC, breakWord) != 0)
+ cerr << "Poke failed" << endl;
+ }
+ //Note that the "addr" parameter is supposed to be ignored, but in at
+ //least one version of the kernel, it must be 1 or it will set what
+ //pc to continue from
+ if(ptrace(PTRACE_CONT, pid, /*nextPC - 4*/ 1, 0) != 0)
+ cerr << "Cont failed" << endl;
+ doWait();
+ update(pid);
+ if(ptrace(PTRACE_POKETEXT, pid, alignedPC, originalInst) != 0)
+ cerr << "Repoke failed" << endl;
+ if(unaligned)
+ {
+ if(ptrace(PTRACE_POKETEXT, pid, alignedPC+8, originalAnnulInst) != 0)
+ cerr << "Repoke failed" << endl;
+ }
+ return true;
+}
+
+int64_t SparcTraceChild::getRegVal(int num)
+{
+ return getRegs(theregs, thefpregs, locals, inputs, num);
+}
+
+int64_t SparcTraceChild::getOldRegVal(int num)
+{
+ return getRegs(oldregs, oldfpregs, oldLocals, oldInputs, num);
+}
+
+char * SparcTraceChild::printReg(int num)
+{
+ sprintf(printBuffer, "0x%016llx", getRegVal(num));
+ return printBuffer;
+}
+
+ostream & SparcTraceChild::outputStartState(ostream & os)
+{
+ uint64_t sp = getSP();
+ uint64_t pc = getPC();
+ char obuf[1024];
+ sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
+ os << obuf;
+ sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
+ os << obuf;
+ //Take out the stack bias
+ sp += 2047;
+ //Output the window save area
+ for(unsigned int x = 0; x < 16; x++)
+ {
+ uint64_t regspot = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sprintf(obuf, "0x%016llx: Window save %d = 0x%016llx\n",
+ sp, x+1, regspot);
+ os << obuf;
+ sp += 8;
+ }
+ //Output the argument count
+ uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
+ os << obuf;
+ sp += 8;
+ //Output argv pointers
+ int argCount = 0;
+ uint64_t cargv;
+ do
+ {
+ cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
+ sp, argCount++, cargv);
+ os << obuf;
+ sp += 8;
+ } while(cargv);
+ //Output the envp pointers
+ int envCount = 0;
+ uint64_t cenvp;
+ do
+ {
+ cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
+ sp, envCount++, cenvp);
+ os << obuf;
+ sp += 8;
+ } while(cenvp);
+ uint64_t auxType, auxVal;
+ do
+ {
+ auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sp += 8;
+ auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sp += 8;
+ sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
+ sp - 16, auxType, auxVal);
+ os << obuf;
+ } while(auxType != 0 || auxVal != 0);
+ //Print out the argument strings, environment strings, and file name.
+ string current;
+ uint64_t buf;
+ uint64_t currentStart = sp;
+ bool clearedInitialPadding = false;
+ do
+ {
+ buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ char * cbuf = (char *)&buf;
+ for(int x = 0; x < sizeof(uint64_t); x++)
+ {
+ if(cbuf[x])
+ current += cbuf[x];
+ else
+ {
+ sprintf(obuf, "0x%016llx: \"%s\"\n",
+ currentStart, current.c_str());
+ os << obuf;
+ current = "";
+ currentStart = sp + x + 1;
+ }
+ }
+ sp += 8;
+ clearedInitialPadding = clearedInitialPadding || buf != 0;
+ } while(!clearedInitialPadding || buf != 0);
+ return os;
+}
+
+TraceChild * genTraceChild()
+{
+ return new SparcTraceChild;
+}
+
diff --git a/util/statetrace/arch/tracechild_sparc.hh b/util/statetrace/arch/tracechild_sparc.hh
new file mode 100644
index 000000000..d177d5941
--- /dev/null
+++ b/util/statetrace/arch/tracechild_sparc.hh
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef TRACECHILD_SPARC_HH
+#define TRACECHILD_SPARC_HH
+
+#include <asm-sparc64/reg.h>
+#include <assert.h>
+#include <ostream>
+#include <stdint.h>
+#include <string>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+
+#include "tracechild.hh"
+
+struct regs;
+
+class SparcTraceChild : public TraceChild
+{
+public:
+ enum RegNum
+ {
+ //Global registers
+ G0, G1, G2, G3, G4, G5, G6, G7,
+ //Output registers
+ O0, O1, O2, O3, O4, O5, O6, O7,
+ //Local registers
+ L0, L1, L2, L3, L4, L5, L6, L7,
+ //Input registers
+ I0, I1, I2, I3, I4, I5, I6, I7,
+ //Floating point
+ F0, F1, F2, F3, F4, F5, F6, F7,
+ F8, F9, F10, F11, F12, F13, F14, F15,
+ F16, F17, F18, F19, F20, F21, F22, F23,
+ F24, F25, F26, F27, F28, F29, F30, F31,
+ //Miscelaneous
+ FSR, FPRS, PC, NPC, Y, CWP, PSTATE, ASI, CCR,
+ numregs
+ };
+private:
+ char printBuffer[256];
+ static std::string regNames[numregs];
+ regs theregs;
+ regs oldregs;
+ fpu thefpregs;
+ fpu oldfpregs;
+ int64_t locals[8];
+ int64_t oldLocals[8];
+ int64_t inputs[8];
+ int64_t oldInputs[8];
+ bool regDiffSinceUpdate[numregs];
+
+protected:
+ bool update(int pid);
+
+public:
+ SparcTraceChild();
+
+ int getNumRegs()
+ {
+ return numregs;
+ }
+
+ bool diffSinceUpdate(int num)
+ {
+ assert(num < numregs && num >= 0);
+ return regDiffSinceUpdate[num];
+ }
+
+ std::string getRegName(int num)
+ {
+ assert(num < numregs && num >= 0);
+ return regNames[num];
+ }
+
+ int64_t getRegVal(int num);
+
+ int64_t getOldRegVal(int num);
+
+ bool step();
+
+ uint64_t getPC()
+ {
+ return getRegVal(PC);
+ }
+
+ uint64_t getSP()
+ {
+ return getRegVal(O6);
+ }
+
+ char * printReg(int num);
+
+ std::ostream & outputStartState(std::ostream & os);
+};
+
+#endif
diff --git a/util/statetrace/printer.cc b/util/statetrace/printer.cc
new file mode 100644
index 000000000..b14671f2c
--- /dev/null
+++ b/util/statetrace/printer.cc
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "tracechild.hh"
+#include "printer.hh"
+
+using namespace std;
+
+//Types of printers. If none is found, or there is an error in the input,
+//there are psuedo types to return.
+enum PrinterType {PRINTER_NONE, PRINTER_ERROR, PRINTER_NESTING, PRINTER_REG};
+
+int findEndOfRegPrinter(string, int);
+int findEndOfNestingPrinter(string, int);
+PrinterType findSub(string, int &, int &);
+
+//This is pretty easy. Just find the closing parenthesis.
+int findEndOfRegPrinter(string config, int startPos)
+{
+ int pos = config.find(")", startPos);
+ if(pos == string::npos)
+ {
+ cerr << "Couldn't find the closing parenthesis for a reg printer" << endl;
+ return 0;
+ }
+ return pos;
+}
+
+//This is a little harder. We need to make sure we don't
+//grab an ending parenthesis that belongs to the nesting printer.
+int findEndOfNestingPrinter(string config, int startPos)
+{
+ int length = config.length();
+ int pos = startPos;
+ int endPos = length;
+ int parenPos = config.find(")", pos);
+ //If we didn't find an ending parenthesis at all, we're in trouble
+ if(parenPos == string::npos)
+ {
+ cerr << "Couldn't find the closing parenthesis for a nesting printer on the first try" << endl;
+ return 0;
+ }
+ //Keep pulling out embedded stuff until we can't any more
+ //we need to make sure we aren't skipping over the parenthesis
+ //that ends -this- printer.
+ PrinterType type = findSub(config, pos, endPos);
+ if(type == PRINTER_ERROR)
+ return 0;
+ while(type != PRINTER_NONE && endPos >= parenPos)
+ {
+ //Find the next closest ending parenthesis since we passed
+ //up the last one
+ parenPos = config.find(")", endPos + 1);
+ //If we didn't find one, we're in trouble
+ if(parenPos == string::npos)
+ {
+ cerr << "Couldn't find the closing parenthesis for a nested printer on later tries" << endl;
+ return 0;
+ }
+ //Start looking for the end of this printer and embedded
+ //stuff past the one we just found
+ pos = endPos + 1;
+ //Reset endPos so we search to the end of config
+ endPos = length;
+ type = findSub(config, pos, endPos);
+ if(type == PRINTER_ERROR)
+ return 0;
+ }
+ //We ran out of embedded items, and we didn't pass up our last
+ //closing paren. This must be the end of this printer.
+ return parenPos;
+}
+
+//Find a sub printer. This looks for things which have a type defining
+//character and then an opening parenthesis. The type is returned, and
+//startPos and endPos are set to the beginning and end of the sub printer
+//On entry, the search starts at index startPos and ends at either index
+//endPos or a closing parenthesis, whichever comes first
+PrinterType findSub(string config, int & startPos, int & endPos)
+{
+ int length = config.length();
+ //Figure out where the different types of sub printers may start
+ int regPos = config.find("%(", startPos);
+ int nestingPos = config.find("~(", startPos);
+ //If a type of printer wasn't found, say it was found too far away.
+ //This simplifies things later
+ if(regPos == string::npos)
+ regPos = endPos;
+ if(nestingPos == string::npos)
+ nestingPos = endPos;
+ //If we find a closing paren, that marks the
+ //end of the region we're searching.
+ int closingPos = config.find(")", startPos);
+ if(closingPos != string::npos &&
+ closingPos < regPos &&
+ closingPos < nestingPos)
+ return PRINTER_NONE;
+ //If we didn't find anything close enough, say so.
+ if(regPos >= endPos && nestingPos >= endPos)
+ return PRINTER_NONE;
+ //At this point, we know that one of the options starts legally
+ //We need to find which one is first and return that
+ if(regPos < nestingPos)
+ {
+ int regEnd = findEndOfRegPrinter(config, regPos + 2);
+ //If we couldn't find the end...
+ if(!regEnd)
+ {
+ cerr << "Couldn't find the end of the reg printer" << endl;
+ return PRINTER_ERROR;
+ }
+ //Report the sub printer's vitals.
+ startPos = regPos;
+ endPos = regEnd;
+ return PRINTER_REG;
+ }
+ else
+ {
+ int nestingEnd = findEndOfNestingPrinter(config, nestingPos + 2);
+ //If we couldn't find the end...
+ if(!nestingEnd)
+ {
+ cerr << "Couldn't find the end of the nesting printer" << endl;
+ return PRINTER_ERROR;
+ }
+ //Report the sub printer's vitals.
+ startPos = nestingPos;
+ endPos = nestingEnd;
+ return PRINTER_NESTING;
+ }
+ return PRINTER_NONE;
+}
+
+//Set up a nesting printer. This printer can contain sub printers
+bool NestingPrinter::configure(string config)
+{
+ //Clear out any old stuff
+ constStrings.clear();
+ numPrinters = 0;
+ printers.clear();
+ int length = config.length();
+ int startPos = 0, endPos = length;
+ int lastEndPos = -1;
+ //Try to find a sub printer
+ PrinterType type = findSub(config, startPos, endPos);
+ if(type == PRINTER_ERROR)
+ {
+ cerr << "Problem finding first sub printer" << endl;
+ return false;
+ }
+ while(type != PRINTER_NONE)
+ {
+ string prefix = config.substr(lastEndPos + 1, startPos - lastEndPos - 1);
+ lastEndPos = endPos;
+ constStrings.push_back(prefix);
+ string subConfig, subString;
+ int commaPos, lastCommaPos, childSwitchVar;
+ switch(type)
+ {
+ //If we found a plain register printer
+ case PRINTER_REG:
+ numPrinters++;
+ //Get the register name
+ subConfig = config.substr(startPos + 2, endPos - startPos - 2);
+ //Set up the register printer
+ RegPrinter * regPrinter = new RegPrinter(child);
+ if(!regPrinter->configure(subConfig))
+ {
+ delete regPrinter;
+ cerr << "Error configuring reg printer" << endl;
+ return false;
+ }
+ printers.push_back(regPrinter);
+ break;
+ //If we found an embedded nesting printer
+ case PRINTER_NESTING:
+ numPrinters++;
+ //Punt on reading in all the parameters of the nesting printer
+ NestingPrinter * nestingPrinter = new NestingPrinter(child);
+ subConfig = config.substr(startPos + 2, endPos - startPos - 2);
+ lastCommaPos = string::npos;
+ commaPos = subConfig.find(",");
+ if(commaPos == string::npos)
+ return false;
+ childSwitchVar = child->getRegNum(subConfig.substr(0, commaPos));
+ if(childSwitchVar == -1)
+ {
+ cerr << "Couldn't configure switching variable!" << endl;
+ return false;
+ }
+ //Eat up remaining arguments
+ while(commaPos != string::npos)
+ {
+ lastCommaPos = commaPos;
+ commaPos = subConfig.find(",", commaPos + 1);
+ }
+ if(lastCommaPos != string::npos)
+ {
+ subConfig = subConfig.substr(lastCommaPos + 1, subConfig.length() - lastCommaPos - 1);
+ }
+ if(!nestingPrinter->configure(subConfig))
+ {
+ delete nestingPrinter;
+ cerr << "Error configuring nesting printer" << endl;
+ return false;
+ }
+ nestingPrinter->switchVar = childSwitchVar;
+ printers.push_back(nestingPrinter);
+ break;
+ default:
+ cerr << "Unrecognized printer type" << endl;
+ return false;
+ }
+ //Move down past what we just parsed
+ startPos = endPos + 1;
+ endPos = length;
+ type = findSub(config, startPos, endPos);
+ if(type == PRINTER_ERROR)
+ {
+ cerr << "Unable to find subprinters on later tries" << endl;
+ return false;
+ }
+ }
+ //Put in the trailing stuff
+ string trailer = config.substr(startPos, length - startPos);
+ constStrings.push_back(trailer);
+ return true;
+}
+
+bool RegPrinter::configure(string config)
+{
+ //Figure out what our register number is based on the name we're given
+ int num = child->getRegNum(config);
+ if(num == -1)
+ {
+ cerr << "Couldn't find register " << config << endl;
+ return false;
+ }
+ regNum(num);
+ return true;
+}
+
+ostream & NestingPrinter::writeOut(ostream & os)
+{
+ if(switchVar == -1 || child->diffSinceUpdate(switchVar))
+ {
+ int x;
+ for(x = 0; x < numPrinters; x++)
+ {
+ os << constStrings[x];
+ os << printers[x];
+ }
+ os << constStrings[x];
+ }
+ return os;
+}
+
+ostream & RegPrinter::writeOut(ostream & os)
+{
+ os << child->printReg(intRegNum);
+ return os;
+}
+
diff --git a/util/statetrace/printer.hh b/util/statetrace/printer.hh
new file mode 100644
index 000000000..db3b8c1b8
--- /dev/null
+++ b/util/statetrace/printer.hh
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef PRINTER_HH
+#define PRINTER_HH
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "refcnt.hh"
+
+class TraceChild;
+class PrinterObject;
+
+typedef RefCountingPtr<PrinterObject> PrinterPointer;
+
+class PrinterObject : public RefCounted
+{
+ protected:
+ TraceChild * child;
+ public:
+ PrinterObject(TraceChild * newChild) : child(newChild)
+ {;}
+ virtual std::ostream & writeOut(std::ostream & os) = 0;
+ virtual bool configure(std::string) = 0;
+};
+
+class NestingPrinter : public PrinterObject
+{
+ private:
+ std::vector<std::string> constStrings;
+ std::vector<PrinterPointer> printers;
+ int switchVar;
+ int numPrinters;
+ public:
+ NestingPrinter(TraceChild * newChild) :
+ PrinterObject(newChild), numPrinters(0), switchVar(-1)
+ {;}
+
+ bool configure(std::string);
+
+ std::ostream & writeOut(std::ostream & os);
+};
+
+class RegPrinter : public PrinterObject
+{
+ private:
+ int intRegNum;
+ public:
+ RegPrinter(TraceChild * newChild, int num = 0) :
+ PrinterObject(newChild), intRegNum(num)
+ {;}
+
+ void regNum(int num)
+ {
+ intRegNum = num;
+ }
+
+ int regNum()
+ {
+ return intRegNum;
+ }
+
+ bool configure(std::string);
+
+ std::ostream & writeOut(std::ostream & os);
+};
+
+static inline std::ostream & operator << (std::ostream & os,
+ PrinterObject & printer)
+{
+ return printer.writeOut(os);
+}
+
+static inline std::ostream & operator << (std::ostream & os,
+ PrinterPointer & printer)
+{
+ return printer->writeOut(os);
+}
+
+#endif
diff --git a/util/statetrace/refcnt.hh b/util/statetrace/refcnt.hh
new file mode 100644
index 000000000..6672d4a5f
--- /dev/null
+++ b/util/statetrace/refcnt.hh
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#ifndef __REFCNT_HH__
+#define __REFCNT_HH__
+
+#include <stddef.h> //For the NULL macro definition
+
+class RefCounted
+{
+ private:
+ int count;
+
+ private:
+ RefCounted(const RefCounted &);
+
+ public:
+ RefCounted() : count(0) {}
+ virtual ~RefCounted() {}
+
+ void incref() { ++count; }
+ void decref() { if (--count <= 0) delete this; }
+};
+
+template <class T>
+class RefCountingPtr
+{
+ protected:
+ T *data;
+
+ void copy(T *d)
+ {
+ data = d;
+ if (data)
+ data->incref();
+ }
+ void del()
+ {
+ if (data)
+ data->decref();
+ }
+ void set(T *d)
+ {
+ if (data == d)
+ return;
+
+ del();
+ copy(d);
+ }
+
+
+ public:
+ RefCountingPtr() : data(NULL) {}
+ RefCountingPtr(T *data) { copy(data); }
+ RefCountingPtr(const RefCountingPtr &r) { copy(r.data); }
+ ~RefCountingPtr() { del(); }
+
+ T *operator->() { return data; }
+ T &operator*() { return *data; }
+ T *get() { return data; }
+
+ const T *operator->() const { return data; }
+ const T &operator*() const { return *data; }
+ const T *get() const { return data; }
+
+ RefCountingPtr &operator=(T *p) { set(p); return *this; }
+ RefCountingPtr &operator=(const RefCountingPtr &r)
+ { return operator=(r.data); }
+
+ bool operator!() const { return data == 0; }
+ operator bool() const { return data != 0; }
+};
+
+template<class T>
+bool operator==(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
+{ return l.get() == r.get(); }
+
+template<class T>
+bool operator==(const RefCountingPtr<T> &l, const T *r)
+{ return l.get() == r; }
+
+template<class T>
+bool operator==(const T &l, const RefCountingPtr<T> &r)
+{ return l == r.get(); }
+
+template<class T>
+bool operator!=(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
+{ return l.get() != r.get(); }
+
+template<class T>
+bool operator!=(const RefCountingPtr<T> &l, const T *r)
+{ return l.get() != r; }
+
+template<class T>
+bool operator!=(const T &l, const RefCountingPtr<T> &r)
+{ return l != r.get(); }
+
+#endif // __REFCNT_HH__
diff --git a/util/statetrace/regstate.hh b/util/statetrace/regstate.hh
new file mode 100644
index 000000000..e97d535a3
--- /dev/null
+++ b/util/statetrace/regstate.hh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef REGSTATE_H
+#define REGSTATE_H
+
+#include <string>
+#include <stdint.h>
+
+class RegState
+{
+protected:
+ virtual bool update(int pid) = 0;
+public:
+ virtual int getNumRegs() = 0;
+ virtual bool diffSinceUpdate(int num) = 0;
+ virtual std::string getRegName(int num) = 0;
+ virtual int getRegNum(std::string name)
+ {
+ int numregs = getNumRegs();
+ for(unsigned int x = 0; x < numregs; x++)
+ if(getRegName(x) == name)
+ return x;
+ return -1;
+ }
+ virtual int64_t getRegVal(int num) = 0;
+ virtual int64_t getOldRegVal(int num) = 0;
+ virtual char * printReg(int num) = 0;
+};
+
+#endif
diff --git a/util/statetrace/statetrace.cc b/util/statetrace/statetrace.cc
new file mode 100644
index 000000000..78fdf9393
--- /dev/null
+++ b/util/statetrace/statetrace.cc
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+#include <unistd.h>
+
+#include "tracechild.hh"
+#include "printer.hh"
+
+using namespace std;
+
+void printUsage(const char * execName)
+{
+ cout << execName << " -f <output format file> | -h | -r -- <command> <arguments>" << endl;
+}
+
+int main(int argc, char * argv[], char * envp[])
+{
+ TraceChild * child = genTraceChild();
+ NestingPrinter printer(child);
+ string args;
+ int startProgramArgs;
+
+ //Parse the command line arguments
+ bool formatStringSet = false;
+ bool printInitial = false;
+ bool printTrace = true;
+ string format;
+ for(int x = 1; x < argc; x++)
+ {
+ if(!strcmp(argv[x], "-f"))
+ {
+ if(formatStringSet)
+ {
+ cerr << "Attempted to set format twice!"
+ << endl;
+ printUsage(argv[0]);
+ return 1;
+ }
+ formatStringSet = true;
+ x++;
+ if(x >= argc)
+ {
+ cerr << "Incorrect usage.\n" << endl;
+ printUsage(argv[0]);
+ return 1;
+ }
+ ifstream formatFile(argv[x]);
+ if(!formatFile)
+ {
+ cerr << "Problem opening file "
+ << argv[x] << "." << endl;
+ return 1;
+ }
+ format = "";
+ while(formatFile)
+ {
+ string line;
+ getline(formatFile, line);
+ if(formatFile.eof())
+ {
+ format += line;
+ break;
+ }
+ if(!formatFile)
+ {
+ cerr << "Problem reading from file "
+ << argv[x] << "." << endl;
+ return 1;
+ }
+ format += line + '\n';
+ }
+ }
+ else if(!strcmp(argv[x], "-h"))
+ {
+ printUsage(argv[0]);
+ return 0;
+ }
+ else if(!strcmp(argv[x], "-r"))
+ {
+ cout << "Legal register names:" << endl;
+ int numRegs = child->getNumRegs();
+ for(unsigned int x = 0; x < numRegs; x++)
+ {
+ cout << "\t" << child->getRegName(x) << endl;
+ }
+ return 0;
+ }
+ else if(!strcmp(argv[x], "-i"))
+ {
+ printInitial = true;
+ }
+ else if(!strcmp(argv[x], "-nt"))
+ {
+ printTrace = false;
+ }
+ else if(!strcmp(argv[x], "--"))
+ {
+ x++;
+ if(x >= argc)
+ {
+ cerr << "Incorrect usage.\n" << endl;
+ printUsage(argv[0]);
+ return 1;
+ }
+ startProgramArgs = x;
+ break;
+ }
+ else
+ {
+ cerr << "Incorrect usage.\n" << endl;
+ printUsage(argv[0]);
+ return 1;
+ }
+ }
+ for(unsigned int x = startProgramArgs; x < argc; x++)
+ args += argv[x];
+ if(!child->startTracing(argv[startProgramArgs], args.c_str()))
+ {
+ cerr << "Couldn't start target program" << endl;
+ return 1;
+ }
+ if(printInitial)
+ {
+ child->outputStartState(cout);
+ }
+ if(printTrace)
+ {
+ if(!formatStringSet)
+ {
+ cerr << "No output format set!" << endl;
+ child->stopTracing();
+ printUsage(argv[0]);
+ return 1;
+ }
+ if(!printer.configure(format))
+ {
+ cerr << "Problem in the output format" << endl;
+ child->stopTracing();
+ return 1;
+ }
+ child->step();
+ while(child->isTracing())
+ {
+ cout << printer;
+ child->step();
+ }
+ cout << printer;
+ }
+ if(!child->stopTracing())
+ {
+ cerr << "Couldn't stop child" << endl;
+ return 1;
+ }
+ return 0;
+}
+
diff --git a/util/statetrace/tracechild.cc b/util/statetrace/tracechild.cc
new file mode 100644
index 000000000..292c45658
--- /dev/null
+++ b/util/statetrace/tracechild.cc
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "tracechild.hh"
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+#include <iostream>
+#include <errno.h>
+
+using namespace std;
+
+bool TraceChild::startTracing(const char * pathToFile, const char * arg)
+{
+ pid = fork();
+ if(pid == -1)
+ {
+ cout << "fork failed" << endl;
+ return false;
+ }
+ else if(pid == 0)
+ {
+ //We're the child. Get things ready and then exec the
+ //program to trace.
+
+ //Let our parent trace us
+ ptrace(PTRACE_TRACEME, 0, 0, 0);
+
+ //Start the program to trace
+ execl(pathToFile, arg);
+
+ //We should never get here, so this is an error!
+ return false;
+ }
+
+ //From this point forward, we know we're in the parent process.
+ if(!doWait())
+ {
+ cout << "Didn't wait successfully" << endl;
+ return false;
+ }
+ tracing = true;
+ if(!update(pid))
+ {
+ cout << "Didn't update successfully!" << endl;
+ return false;
+ }
+ return true;
+}
+
+bool TraceChild::stopTracing()
+{
+ if(ptrace(PTRACE_KILL, pid, 0, 0) != 0)
+ return false;
+ tracing = false;
+ return true;
+}
+
+bool TraceChild::step()
+{
+ ptraceSingleStep();
+}
+
+bool TraceChild::ptraceSingleStep()
+{
+ if(!tracing)
+ {
+ cout << "Not tracing!" << endl;
+ return false;
+ }
+ if(ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0)
+ {
+ switch(errno)
+ {
+ case EBUSY: cout << "EBUSY" << endl; break;
+ case EFAULT: cout << "EFAULT" << endl; break;
+ case EIO: cout << "EIO" << endl; break;
+ case EPERM: cout << "EPERM" << endl; break;
+ case ESRCH: cout << "ESRCH" << endl; break;
+ default: cout << "Unknown error" << endl; break;
+ }
+ cout << "Not able to single step!" << endl;
+ tracing == false;
+ return false;
+ }
+ doWait();
+ update(pid);
+}
+
+bool TraceChild::doWait()
+{
+ int wait_val;
+ wait(&wait_val);
+ if(WIFEXITED(wait_val))
+ {
+ cerr << "Program exited! Exit status is "
+ << WEXITSTATUS(wait_val) << endl;
+ tracing = false;
+ return false;
+ }
+ if(WIFSIGNALED(wait_val))
+ {
+ if(WTERMSIG(wait_val))
+ cerr << "Program terminated by signal "
+ << WTERMSIG(wait_val) << endl;
+ if(WCOREDUMP(wait_val))
+ cerr << "Program core dumped!" << endl;
+ tracing = false;
+ return false;
+ }
+ if(WIFSTOPPED(wait_val) && WSTOPSIG(wait_val) != SIGTRAP)
+ {
+ cerr << "Program stopped by signal "
+ << WSTOPSIG(wait_val) << endl;
+ tracing = false;
+ return false;
+ }
+ return true;
+}
diff --git a/util/statetrace/tracechild.hh b/util/statetrace/tracechild.hh
new file mode 100644
index 000000000..f9c23b781
--- /dev/null
+++ b/util/statetrace/tracechild.hh
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef TRACECHILD_HH
+#define TRACECHILD_HH
+
+#include "regstate.hh"
+
+class TraceChild : public RegState
+{
+protected:
+ int pid;
+ bool tracing;
+public:
+ TraceChild() : tracing(false)
+ {;}
+ virtual bool startTracing(const char * pathToFile, const char * arg);
+ virtual bool stopTracing();
+ virtual bool step();
+ virtual uint64_t getPC() = 0;
+ virtual uint64_t getSP() = 0;
+ virtual std::ostream & outputStartState(std::ostream & os) = 0;
+ int getPid()
+ {
+ return pid;
+ }
+ bool isTracing()
+ {
+ return tracing;
+ }
+protected:
+ bool ptraceSingleStep();
+ bool doWait();
+};
+
+TraceChild * genTraceChild();
+
+#endif
diff --git a/util/statetrace/tracechild_arch.cc b/util/statetrace/tracechild_arch.cc
new file mode 100644
index 000000000..603ccb12c
--- /dev/null
+++ b/util/statetrace/tracechild_arch.cc
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#if defined __alpha__
+ #error "Alpha architecture not implemented"
+#elif defined __amd64__
+ #error "AMD64 architecture not implemented"
+#elif defined __hppa__
+ #error "Hppa architecture not implemented"
+#elif defined __i386__ || defined __i486__ || \
+ defined __i586__ || defined __i686
+ #include "arch/tracechild_i386.cc"
+#elif defined __ia64__
+ #error "IA64 architecture not implemented"
+#elif defined __mips__
+ #error "Mips architecture not implemented"
+#elif defined __powerpc__
+ #error "PowerPC architecture not implemented"
+#elif defined __sparc__
+ #include "arch/tracechild_sparc.cc"
+#elif defined __sh__
+ #include "SuperH architecture not implemented"
+#elif defined __s390__
+ #include "System/390 architecture not implemented"
+#else
+ #error "Couldn't determine architecture"
+#endif
diff --git a/util/statetrace/x86.format b/util/statetrace/x86.format
new file mode 100644
index 000000000..03035ee29
--- /dev/null
+++ b/util/statetrace/x86.format
@@ -0,0 +1,6 @@
+######################
+EIP = %(eip)
+EAX = %(eax), EBX = %(ebx), ECX = %(ecx), EDX = %(edx)
+EDI = %(edi), ESI = %(esi)
+EBP = %(ebp), ESP = %(esp)
+CS = %(cs), DS = %(ds), ES = %(es), FS = %(fs), GS = %(gs), SS = %(ss)
diff --git a/util/stats/db.py b/util/stats/db.py
index c0e7796eb..e1198d438 100644
--- a/util/stats/db.py
+++ b/util/stats/db.py
@@ -23,6 +23,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
import MySQLdb, re, string
@@ -135,10 +137,6 @@ class Database(object):
self.allRunIds = {}
self.allRunNames = {}
- self.allBins = []
- self.allBinIds = {}
- self.allBinNames = {}
-
self.allFormulas = {}
self.stattop = {}
@@ -147,7 +145,6 @@ class Database(object):
self.mode = 'sum';
self.runs = None
- self.bins = None
self.ticks = None
self.method = 'sum'
self._method = type(self).sum
@@ -218,11 +215,6 @@ class Database(object):
self.allRunIds[run.run] = run
self.allRunNames[run.name] = run
- self.query('select * from bins')
- for id,name in self.cursor.fetchall():
- self.allBinIds[int(id)] = name
- self.allBinNames[name] = int(id)
-
self.query('select sd_stat,sd_x,sd_y,sd_name,sd_descr from subdata')
for result in self.cursor.fetchall():
subdata = SubData(result)
@@ -245,18 +237,6 @@ class Database(object):
self.allStatIds[stat.stat] = stat
self.allStatNames[stat.name] = stat
- # Name: listbins
- # Desc: Prints all bins matching regex argument, if no argument
- # is given all bins are returned
- def listBins(self, regex='.*'):
- print '%-50s %-10s' % ('bin name', 'id')
- print '-' * 61
- names = self.allBinNames.keys()
- names.sort()
- for name in names:
- id = self.allBinNames[name]
- print '%-50s %-10d' % (name, id)
-
# Name: listruns
# Desc: Prints all runs matching a given user, if no argument
# is given all runs are returned
@@ -360,39 +340,10 @@ class Database(object):
ret.append(stat)
return ret
- def getBin(self, bins):
- if type(bins) is not list:
- bins = [ bins ]
-
- ret = []
- for bin in bins:
- if type(bin) is int:
- ret.append(bin)
- elif type(bin) is str:
- ret.append(self.allBinNames[bin])
- else:
- for name,id in self.allBinNames.items():
- if bin.match(name):
- ret.append(id)
-
- return ret
-
- def getNotBin(self, bin):
- map = {}
- for bin in getBin(bin):
- map[bin] = 1
-
- ret = []
- for bin in self.allBinIds.keys():
- if not map.has_key(bin):
- ret.append(bin)
-
- return ret
-
#########################################
# get the data
#
- def inner(self, op, stat, bins, ticks, group=False):
+ def query(self, op, stat, ticks, group=False):
sql = 'select '
sql += 'dt_stat as stat, '
sql += 'dt_run as run, '
@@ -414,10 +365,6 @@ class Database(object):
val = ' or '.join([ 'dt_run=%d' % r for r in self.runs ])
sql += ' and (%s)' % val
- if bins != None and len(bins):
- val = ' or '.join([ 'dt_bin=%d' % b for b in bins ])
- sql += ' and (%s)' % val
-
if ticks != None and len(ticks):
val = ' or '.join([ 'dt_tick=%d' % s for s in ticks ])
sql += ' and (%s)' % val
@@ -427,35 +374,21 @@ class Database(object):
sql += ',dt_tick'
return sql
- def outer(self, op_out, op_in, stat, bins, ticks):
- sql = self.inner(op_in, stat, bins, ticks, True)
- sql = 'select stat,run,x,y,%s(data) from (%s) as tb ' % (op_out, sql)
- sql += 'group by stat,run,x,y'
- return sql
-
# Name: sum
- # Desc: given a run, a stat and an array of samples and bins,
- # sum all the bins and then get the standard deviation of the
- # samples for non-binned runs. This will just return the average
- # of samples, however a bin array still must be passed
- def sum(self, stat, bins, ticks):
- return self.inner('sum', stat, bins, ticks)
+ # Desc: given a run, a stat and an array of samples, total the samples
+ def sum(self, *args, **kwargs):
+ return self.query('sum', *args, **kwargs)
# Name: avg
- # Desc: given a run, a stat and an array of samples and bins,
- # sum all the bins and then average the samples for non-binned
- # runs this will just return the average of samples, however
- # a bin array still must be passed
- def avg(self, stat, bins, ticks):
- return self.outer('avg', 'sum', stat, bins, ticks)
+ # Desc: given a run, a stat and an array of samples, average the samples
+ def avg(self, stat, ticks):
+ return self.query('avg', *args, **kwargs)
# Name: stdev
- # Desc: given a run, a stat and an array of samples and bins,
- # sum all the bins and then get the standard deviation of the
- # samples for non-binned runs. This will just return the average
- # of samples, however a bin array still must be passed
- def stdev(self, stat, bins, ticks):
- return self.outer('stddev', 'sum', stat, bins, ticks)
+ # Desc: given a run, a stat and an array of samples, get the standard
+ # deviation
+ def stdev(self, stat, ticks):
+ return self.query('stddev', *args, **kwargs)
def __setattr__(self, attr, value):
super(Database, self).__setattr__(attr, value)
@@ -471,12 +404,10 @@ class Database(object):
else:
raise AttributeError, "can only set get to: sum | avg | stdev"
- def data(self, stat, bins=None, ticks=None):
- if bins is None:
- bins = self.bins
+ def data(self, stat, ticks=None):
if ticks is None:
ticks = self.ticks
- sql = self._method(self, stat, bins, ticks)
+ sql = self._method(self, stat, ticks)
self.query(sql)
runs = {}
diff --git a/util/stats/dbinit.py b/util/stats/dbinit.py
index ffae88cdb..036941675 100644
--- a/util/stats/dbinit.py
+++ b/util/stats/dbinit.py
@@ -23,6 +23,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
import MySQLdb
@@ -98,28 +100,6 @@ class MyDB(object):
) TYPE=InnoDB''')
#
- # We keep the bin names separate so that the data table doesn't get
- # huge since bin names are frequently repeated.
- #
- # COLUMNS:
- # 'id' is the unique bin identifer.
- # 'name' is the string name for the bin.
- #
- # INDEXES:
- # 'bin' is indexed to get the name of a bin when data is retrieved
- # via the data table.
- # 'name' is indexed to get the bin id for a named bin when you want
- # to search the data table based on a specific bin.
- #
- self.query('''
- CREATE TABLE bins(
- bn_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
- bn_name VARCHAR(255) NOT NULL,
- PRIMARY KEY(bn_id),
- UNIQUE (bn_name)
- ) TYPE=InnoDB''')
-
- #
# The stat table gives us all of the data for a particular stat.
#
# COLUMNS:
@@ -220,14 +200,12 @@ class MyDB(object):
# 'run' is the run that the data was generated from. Details up in
# the run table
# 'tick' is a timestamp generated by the simulator.
- # 'bin' is the name of the bin that the data was generated in, if
- # any.
# 'data' is the actual stat value.
#
# INDEXES:
# 'stat' is indexed so that a user can find all of the data for a
# particular stat. It is not unique, because that specific stat
- # can be found in many runs, bins, and samples, in addition to
+ # can be found in many runs and samples, in addition to
# having entries for the mulidimensional cases.
# 'run' is indexed to allow a user to remove all of the data for a
# particular execution run. It can also be used to allow the
@@ -240,11 +218,10 @@ class MyDB(object):
dt_y SMALLINT NOT NULL,
dt_run SMALLINT UNSIGNED NOT NULL,
dt_tick BIGINT UNSIGNED NOT NULL,
- dt_bin SMALLINT UNSIGNED NOT NULL,
dt_data DOUBLE NOT NULL,
INDEX (dt_stat),
INDEX (dt_run),
- UNIQUE (dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_bin)
+ UNIQUE (dt_stat,dt_x,dt_y,dt_run,dt_tick)
) TYPE=InnoDB;''')
#
@@ -396,12 +373,6 @@ class MyDB(object):
WHERE dt_stat IS NULL''')
self.query('''
- DELETE bins
- FROM bins
- LEFT JOIN data ON bn_id=dt_bin
- WHERE dt_bin IS NULL''')
-
- self.query('''
DELETE events
FROM events
LEFT JOIN runs ON ev_run=rn_id
diff --git a/util/stats/display.py b/util/stats/display.py
index fbcff5c70..cb825f493 100644
--- a/util/stats/display.py
+++ b/util/stats/display.py
@@ -23,6 +23,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
class Value:
def __init__(self, value, precision, percent = False):
diff --git a/util/stats/info.py b/util/stats/info.py
index 4cb55f564..193159b4c 100644
--- a/util/stats/info.py
+++ b/util/stats/info.py
@@ -23,6 +23,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
from __future__ import division
import operator, re, types
@@ -174,7 +176,7 @@ def WrapValue(value):
class Statistic(object):
def __getattr__(self, attr):
if attr in ('data', 'x', 'y'):
- result = self.source.data(self, self.bins, self.ticks)
+ result = self.source.data(self, self.ticks)
self.data = result.data
self.x = result.x
self.y = result.y
@@ -183,7 +185,7 @@ class Statistic(object):
def __setattr__(self, attr, value):
if attr == 'stat':
raise AttributeError, '%s is read only' % stat
- if attr in ('source', 'bins', 'ticks'):
+ if attr in ('source', 'ticks'):
if getattr(self, attr) != value:
if hasattr(self, 'data'):
delattr(self, 'data')
@@ -759,7 +761,6 @@ def NewStat(source, data):
stat = Formula()
stat.__dict__['source'] = source
- stat.__dict__['bins'] = None
stat.__dict__['ticks'] = None
stat.__dict__.update(data.__dict__)
diff --git a/util/stats/orderdict.py b/util/stats/orderdict.py
index 816355ae2..3f755d299 100644
--- a/util/stats/orderdict.py
+++ b/util/stats/orderdict.py
@@ -23,6 +23,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
__all__ = [ 'orderdict' ]
diff --git a/util/stats/output.py b/util/stats/output.py
index abfb8d901..03c100edc 100644
--- a/util/stats/output.py
+++ b/util/stats/output.py
@@ -29,24 +29,16 @@
from chart import ChartOptions
class StatOutput(ChartOptions):
- def __init__(self, jobfile, info, stat=None, binstats=None):
+ def __init__(self, jobfile, info, stat=None):
super(StatOutput, self).__init__()
self.jobfile = jobfile
self.stat = stat
- self.binstats = None
self.invert = False
self.info = info
- def printdata(self, name, bin = None, printmode = 'G'):
+ def display(self, name, printmode = 'G'):
import info
- if bin:
- print '%s %s stats' % (name, bin)
-
- if self.binstats:
- for stat in self.binstats:
- stat.bins = bin
-
if printmode == 'G':
valformat = '%g'
elif printmode != 'F' and value > 1e6:
@@ -70,16 +62,6 @@ class StatOutput(ChartOptions):
valstring = ', '.join([ valformat % val for val in value ])
print '%-50s %s' % (job.name + ':', valstring)
- def display(self, name, binned = False, printmode = 'G'):
- if binned and self.binstats:
- self.printdata(name, 'kernel', printmode)
- self.printdata(name, 'idle', printmode)
- self.printdata(name, 'user', printmode)
- self.printdata(name, 'interrupt', printmode)
-
- print '%s total stats' % name
- self.printdata(name, printmode=printmode)
-
def graph(self, name, graphdir, proxy=None):
from os.path import expanduser, isdir, join as joinpath
from barchart import BarChart
diff --git a/util/stats/print.py b/util/stats/print.py
index 2572fd4e7..1c83fa87d 100644
--- a/util/stats/print.py
+++ b/util/stats/print.py
@@ -23,6 +23,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
all = False
descriptions = False
diff --git a/util/stats/profile.py b/util/stats/profile.py
index f28c5867c..6959e0e34 100644
--- a/util/stats/profile.py
+++ b/util/stats/profile.py
@@ -23,6 +23,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
from orderdict import orderdict
import output
diff --git a/util/stats/stats.py b/util/stats/stats.py
index 08281287f..2aa0d4e0b 100755
--- a/util/stats/stats.py
+++ b/util/stats/stats.py
@@ -25,6 +25,8 @@
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
from __future__ import division
import re, sys, math
@@ -37,7 +39,6 @@ Usage: %s [-E] [-F] [ -G <get> ] [-d <db> ] [-g <graphdir> ] [-h <host>] [-p]
commands extra parameters description
----------- ------------------ ---------------------------------------
- bins [regex] List bins (only matching regex)
formula <formula> Evaluated formula specified
formulas [regex] List formulas (only matching regex)
runs none List all runs in database
@@ -140,16 +141,6 @@ def commands(options, command, args):
return
- if command == 'bins':
- if len(args) == 0:
- source.listBins()
- elif len(args) == 1:
- source.listBins(args[0])
- else:
- raise CommandException
-
- return
-
if command == 'formulas':
if len(args) == 0:
source.listFormulas()
@@ -279,7 +270,7 @@ def commands(options, command, args):
if options.graph:
output.graph(stat.name, options.graphdir)
else:
- output.display(stat.name, options.binned, options.printmode)
+ output.display(stat.name, options.printmode)
return
@@ -299,22 +290,10 @@ def commands(options, command, args):
if options.graph:
output.graph(command, options.graphdir, proxy)
else:
- output.display(command, options.binned, options.printmode)
-
- if command == 'usertime':
- import copy
- user = copy.copy(system.run0.numCycles)
- user.bins = 'user'
-
- output.stat = user / system.run0.numCycles
- output.ylabel = 'User Fraction'
-
- display()
- return
+ output.display(command, options.printmode)
if command == 'ticks':
output.stat = system.run0.numCycles
- output.binstats = [ system.run0.numCycles ]
display()
return
@@ -401,7 +380,6 @@ def commands(options, command, args):
if command == 'mpkb':
output.stat = misses / (bytes / 1024)
- output.binstats = [ misses ]
output.ylabel = 'Misses / KB'
display()
return
@@ -409,7 +387,6 @@ def commands(options, command, args):
if command == 'ipkb':
interrupts = system.run0.kern.faults[4]
output.stat = interrupts / kbytes
- output.binstats = [ interrupts ]
output.ylabel = 'Interrupts / KB'
display()
return
@@ -446,7 +423,6 @@ if __name__ == '__main__':
options.runs = None
options.system = 'client'
options.method = None
- options.binned = False
options.graph = False
options.ticks = False
options.printmode = 'G'
@@ -454,10 +430,8 @@ if __name__ == '__main__':
options.jobfile = None
options.all = False
- opts, args = getopts(sys.argv[1:], '-BEFJad:g:h:j:m:pr:s:u:T:')
+ opts, args = getopts(sys.argv[1:], '-EFJad:g:h:j:m:pr:s:u:T:')
for o,a in opts:
- if o == '-B':
- options.binned = True
if o == '-E':
options.printmode = 'E'
if o == '-F':
diff --git a/util/tap/tap.cc b/util/tap/tap.cc
index f4d0aadf2..b026e0220 100644
--- a/util/tap/tap.cc
+++ b/util/tap/tap.cc
@@ -24,6 +24,8 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
*/
extern "C" {
diff --git a/util/tracediff b/util/tracediff
index f11431293..f2377a999 100755
--- a/util/tracediff
+++ b/util/tracediff
@@ -1,5 +1,5 @@
#! /usr/bin/env perl
-# Copyright (c) 2003-2005 The Regents of The University of Michigan
+# Copyright (c) 2003-2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,7 @@
# If you want to pass different arguments to the two instances of m5,
# you can embed them in the simulator arguments like this:
#
-# % tracediff "m5.opt --foo.bar=1" "m5.opt --foo.bar=2" [common args]
+# % tracediff "m5.opt --option1" "m5.opt --option2" [common args]
#
if (@ARGV < 2) {
@@ -58,8 +58,8 @@ $dir2 = "tracediff-$$-2";
mkdir($dir1) or die "Can't create dir $dir1\n";
mkdir($dir2) or die "Can't create dir $dir2\n";
-$cmd1 = "$sim1 $simargs -d $dir1 2>&1 |";
-$cmd2 = "$sim2 $simargs -d $dir2 2>&1 |";
+$cmd1 = "$sim1 -d $dir1 $simargs 2>&1 |";
+$cmd2 = "$sim2 -d $dir2 $simargs 2>&1 |";
# This only works if you have rundiff in your path. I just edit it
# with an explicit path if necessary.