diff options
122 files changed, 3569 insertions, 3491 deletions
diff --git a/SConstruct b/SConstruct index afb2a2a6e..0cf15b1f9 100644 --- a/SConstruct +++ b/SConstruct @@ -158,6 +158,12 @@ env = Environment(ENV = os.environ, # inherit user's environment vars env.SConsignFile("sconsign") +# Default duplicate option is to use hard links, but this messes up +# when you use emacs to edit a file in the target dir, as emacs moves +# file to file~ then copies to file, breaking the link. Symbolic +# (soft) links work better. +env.SetOption('duplicate', 'soft-copy') + # I waffle on this setting... it does avoid a few painful but # unnecessary builds, but it also seems to make trivial builds take # noticeably longer. @@ -193,6 +199,19 @@ env.Append(LIBS = py_version_name) if sys.exec_prefix != '/usr': env.Append(LIBPATH = os.path.join(sys.exec_prefix, 'lib')) +# Set up SWIG flags & scanner + +env.Append(SWIGFLAGS=Split('-c++ -python -modern $_CPPINCFLAGS')) + +import SCons.Scanner + +swig_inc_re = '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")' + +swig_scanner = SCons.Scanner.ClassicCPP("SwigScan", ".i", "CPPPATH", + swig_inc_re) + +env.Append(SCANNERS = swig_scanner) + # Other default libraries env.Append(LIBS=['z']) @@ -268,7 +287,6 @@ sticky_opts.AddOptions( BoolOption('USE_SSE2', 'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts', False), - BoolOption('STATS_BINNING', 'Bin statistics by CPU mode', have_mysql), BoolOption('USE_MYSQL', 'Use MySQL for stats output', have_mysql), BoolOption('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv), ('CC', 'C compiler', os.environ.get('CC', env['CC'])), @@ -285,8 +303,7 @@ nonsticky_opts.AddOptions( # These options get exported to #defines in config/*.hh (see m5/SConscript). env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \ - 'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \ - 'STATS_BINNING'] + 'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP'] # Define a handy 'no-op' action def no_action(target, source, env): @@ -469,7 +486,7 @@ for build_path in build_paths: # to the configured options. It returns a list of environments, # one for each variant build (debug, opt, etc.) envList = SConscript('src/SConscript', build_dir = build_path, - exports = 'env', duplicate = False) + exports = 'env') # Set up the regression tests for each build. # for e in envList: diff --git a/configs/test/fs.py b/configs/test/fs.py index fdbf86abe..55e7003a4 100644 --- a/configs/test/fs.py +++ b/configs/test/fs.py @@ -1,7 +1,18 @@ -from m5 import * +import m5 +from m5.objects import * import os from SysPaths import * +parser = optparse.OptionParser(option_list=m5.standardOptions) + +parser.add_option("-t", "--timing", action="store_true") + +(options, args) = parser.parse_args() + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + # Base for tests is directory containing this file. test_base = os.path.dirname(__file__) @@ -181,7 +192,13 @@ class LinuxAlphaSystem(LinuxAlphaSystem): read_only=True) simple_disk = SimpleDisk(disk=Parent.raw_image) intrctrl = IntrControl() - cpu = AtomicSimpleCPU(mem=Parent.magicbus2) + if options.timing: + cpu = TimingSimpleCPU() + else: + cpu = AtomicSimpleCPU() + cpu.mem = Parent.magicbus2 + cpu.itb = AlphaITB() + cpu.dtb = AlphaDTB() sim_console = SimConsole(listener=ConsoleListener(port=3456)) kernel = binary('vmlinux') pal = binary('ts_osfpal') @@ -190,18 +207,15 @@ class LinuxAlphaSystem(LinuxAlphaSystem): # readfile = os.path.join(test_base, 'halt.sh') -BaseCPU.itb = AlphaITB() -BaseCPU.dtb = AlphaDTB() -BaseCPU.system = Parent.any class TsunamiRoot(System): pass -def DualRoot(ClientSystem, ServerSystem): +def DualRoot(clientSystem, serverSystem): self = Root() - self.client = ClientSystem() - self.server = ServerSystem() + self.client = clientSystem + self.server = serverSystem self.etherdump = EtherDump(file='ethertrace') self.etherlink = EtherLink(int1 = Parent.client.tsunami.etherint[0], @@ -210,6 +224,11 @@ def DualRoot(ClientSystem, ServerSystem): self.clock = '5GHz' return self -root = DualRoot(ClientSystem = LinuxAlphaSystem(readfile=script('netperf-stream-nt-client.rcS')), - ServerSystem = LinuxAlphaSystem(readfile=script('netperf-server.rcS'))) +root = DualRoot(LinuxAlphaSystem(readfile=script('netperf-stream-nt-client.rcS')), + LinuxAlphaSystem(readfile=script('netperf-server.rcS'))) + +m5.instantiate(root) + +exit_event = m5.simulate() +print 'Exiting @', m5.curTick(), 'because', exit_event.getCause() diff --git a/configs/test/test.py b/configs/test/test.py index 75e832f5e..8c5b06e6a 100644 --- a/configs/test/test.py +++ b/configs/test/test.py @@ -1,12 +1,50 @@ -from m5 import * +# Simple test script +# +# Alpha: "m5 test.py" +# MIPS: "m5 test.py -a Mips -c hello_mips" -class HelloWorld(AlphaLiveProcess): - executable = '../configs/test/hello' - cmd = 'hello' +import os, optparse, sys +import m5 +from m5.objects import * + +# parse command-line arguments +parser = optparse.OptionParser(option_list=m5.standardOptions) + +parser.add_option("-c", "--cmd", default="hello") +parser.add_option("-t", "--timing", action="store_true") + +(options, args) = parser.parse_args() + +if args: + print "Error: script doesn't take any positional arguments" + sys.exit(1) + +# build configuration +this_dir = os.path.dirname(__file__) + +process = LiveProcess() +process.executable = os.path.join(this_dir, options.cmd) +process.cmd = options.cmd magicbus = Bus() mem = PhysicalMemory() -cpu = AtomicSimpleCPU(workload=HelloWorld(), mem=magicbus) -system = System(physmem=mem, cpu=cpu) -system.c1 = Connector(side_a=mem, side_b=magicbus) -root = Root(system=system) + +if options.timing: + cpu = TimingSimpleCPU() +else: + cpu = AtomicSimpleCPU() +cpu.workload = process +cpu.mem = magicbus + +system = System(physmem = mem, cpu = cpu) +system.c1 = Connector(side_a = mem, side_b = magicbus) +root = Root(system = system) + +# instantiate configuration +m5.instantiate(root) + +# simulate until program terminates +exit_event = m5.simulate() + +print 'Exiting @', m5.curTick(), 'because', exit_event.getCause() + diff --git a/src/SConscript b/src/SConscript index d29ecb7bb..a1c18711c 100644 --- a/src/SConscript +++ b/src/SConscript @@ -109,12 +109,12 @@ base_sources = Split(''' sim/eventq.cc sim/faults.cc sim/main.cc + python/swig/main_wrap.cc sim/param.cc sim/profile.cc sim/root.cc sim/serialize.cc sim/sim_events.cc - sim/sim_exit.cc sim/sim_object.cc sim/startup.cc sim/stat_context.cc @@ -219,7 +219,6 @@ full_system_sources = Split(''' dev/uart.cc dev/uart8250.cc - kern/kernel_binning.cc kern/kernel_stats.cc kern/system_events.cc kern/linux/events.cc @@ -286,14 +285,18 @@ memtest_sources = Split(''' cpu/memtest/memtest.cc ''') +# Include file paths are rooted in this directory. SCons will +# automatically expand '.' to refer to both the source directory and +# the corresponding build directory to pick up generated include +# files. +env.Append(CPPPATH=Dir('.')) + # Add a flag defining what THE_ISA should be for all compilation env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) -arch_sources = SConscript('arch/SConscript', - exports = 'env', duplicate = False) +arch_sources = SConscript('arch/SConscript', exports = 'env') -cpu_sources = SConscript('cpu/SConscript', - exports = 'env', duplicate = False) +cpu_sources = SConscript('cpu/SConscript', exports = 'env') # This is outside of cpu/SConscript since the source directory isn't # underneath 'cpu'. @@ -328,7 +331,7 @@ env.Command(Split('base/traceflags.hh base/traceflags.cc'), 'base/traceflags.py', 'python $SOURCE $TARGET.base') -SConscript('python/SConscript', exports = ['env'], duplicate=0) +SConscript('python/SConscript', exports = ['env']) # This function adds the specified sources to the given build # environment, and returns a list of all the corresponding SCons @@ -351,12 +354,6 @@ def make_objs(sources, env): # ################################################### -# Include file paths are rooted in this directory. SCons will -# automatically expand '.' to refer to both the source directory and -# the corresponding build directory to pick up generated include -# files. -env.Append(CPPPATH='.') - # List of constructed environments to pass back to SConstruct envList = [] diff --git a/src/arch/SConscript b/src/arch/SConscript index dd616174c..ff460dafd 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -28,7 +28,7 @@ # # Authors: Steve Reinhardt -import os.path +import os.path, sys # Import build environment variable from SConstruct. Import('env') @@ -134,7 +134,8 @@ def isa_desc_emitter(target, source, env): return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source) # Pieces are in place, so create the builder. -isa_desc_builder = Builder(action='python2.4 $SOURCES $TARGET.dir $CPU_MODELS', +python = sys.executable # use same Python binary used to run scons +isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS', emitter = isa_desc_emitter) env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) @@ -146,7 +147,6 @@ env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) isa = env['TARGET_ISA'] # someday this may be a list of ISAs # Let the target architecture define what additional sources it needs -sources += SConscript(os.path.join(isa, 'SConscript'), - exports = 'env', duplicate = False) +sources += SConscript(os.path.join(isa, 'SConscript'), exports = 'env') Return('sources') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 247c5f56e..ae3b668ea 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -41,7 +41,7 @@ #include "cpu/thread_context.hh" #include "kern/kernel_stats.hh" #include "sim/debug.hh" -#include "sim/sim_events.hh" +#include "sim/sim_exit.hh" #if FULL_SYSTEM @@ -575,7 +575,7 @@ SimpleThread::simPalCheck(int palFunc) case PAL::halt: halt(); if (--System::numSystemsRunning == 0) - new SimExitEvent("all cpus halted"); + exitSimLoop("all cpus halted"); break; case PAL::bpt: diff --git a/src/arch/alpha/freebsd/system.cc b/src/arch/alpha/freebsd/system.cc index 91f8b5af1..7cf68e0db 100644 --- a/src/arch/alpha/freebsd/system.cc +++ b/src/arch/alpha/freebsd/system.cc @@ -109,10 +109,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) Param<uint64_t> system_type; Param<uint64_t> system_rev; - Param<bool> bin; - VectorParam<string> binned_fns; - Param<bool> bin_int; - END_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) @@ -127,10 +123,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), - INIT_PARAM_DFLT(bin, "is this system to be binned", false), - INIT_PARAM(binned_fns, "functions to be broken down and binned"), - INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true) + INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10) END_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem) @@ -148,9 +141,6 @@ CREATE_SIM_OBJECT(FreebsdAlphaSystem) p->readfile = readfile; p->system_type = system_type; p->system_rev = system_rev; - p->bin = bin; - p->binned_fns = binned_fns; - p->bin_int = bin_int; return new FreebsdAlphaSystem(p); } diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index dd29e47e4..2ecd9f5ad 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -697,7 +697,7 @@ decode OPCODE default Unknown::unknown() { 0x00: decode PALFUNC { format EmulatedCallPal { 0x00: halt ({{ - SimExit(curTick, "halt instruction encountered"); + exitSimLoop(curTick, "halt instruction encountered"); }}, IsNonSpeculative); 0x83: callsys({{ xc->syscall(R0); diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc index 3e061bba8..9fe63c390 100644 --- a/src/arch/alpha/linux/system.cc +++ b/src/arch/alpha/linux/system.cc @@ -137,24 +137,6 @@ LinuxAlphaSystem::LinuxAlphaSystem(Params *p) } else { printThreadEvent = NULL; } - - if (params()->bin_int) { - intStartEvent = addPalFuncEvent<InterruptStartEvent>("sys_int_21"); - if (!intStartEvent) - panic("could not find symbol: sys_int_21\n"); - - intEndEvent = addPalFuncEvent<InterruptEndEvent>("rti_to_kern"); - if (!intEndEvent) - panic("could not find symbol: rti_to_kern\n"); - - intEndEvent2 = addPalFuncEvent<InterruptEndEvent>("rti_to_user"); - if (!intEndEvent2) - panic("could not find symbol: rti_to_user\n"); - - intEndEvent3 = addKernelFuncEvent<InterruptEndEvent>("do_softirq"); - if (!intEndEvent3) - panic("could not find symbol: do_softirq\n"); - } } LinuxAlphaSystem::~LinuxAlphaSystem() @@ -168,9 +150,6 @@ LinuxAlphaSystem::~LinuxAlphaSystem() delete debugPrintkEvent; delete idleStartEvent; delete printThreadEvent; - delete intStartEvent; - delete intEndEvent; - delete intEndEvent2; } @@ -224,10 +203,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem) Param<uint64_t> system_type; Param<uint64_t> system_rev; - Param<bool> bin; - VectorParam<string> binned_fns; - Param<bool> bin_int; - END_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem) @@ -242,10 +217,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem) INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), - INIT_PARAM_DFLT(bin, "is this system to be binned", false), - INIT_PARAM(binned_fns, "functions to be broken down and binned"), - INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true) + INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10) END_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem) @@ -263,9 +235,6 @@ CREATE_SIM_OBJECT(LinuxAlphaSystem) p->readfile = readfile; p->system_type = system_type; p->system_rev = system_rev; - p->bin = bin; - p->binned_fns = binned_fns; - p->bin_int = bin_int; return new LinuxAlphaSystem(p); } diff --git a/src/arch/alpha/linux/system.hh b/src/arch/alpha/linux/system.hh index c03586ac5..6921ba820 100644 --- a/src/arch/alpha/linux/system.hh +++ b/src/arch/alpha/linux/system.hh @@ -45,7 +45,7 @@ using namespace AlphaISA; using namespace Linux; /** - * This class contains linux specific system code (Loading, Events, Binning). + * This class contains linux specific system code (Loading, Events). * It points to objects that are the system binaries to load and patches them * appropriately to work in simulator. */ @@ -124,18 +124,6 @@ class LinuxAlphaSystem : public AlphaSystem */ PrintThreadInfo *printThreadEvent; - /** - * Event to bin Interrupts seperately from kernel code - */ - InterruptStartEvent *intStartEvent; - - /** - * Event to bin Interrupts seperately from kernel code - */ - InterruptEndEvent *intEndEvent; - InterruptEndEvent *intEndEvent2; - InterruptEndEvent *intEndEvent3; - /** Grab the PCBB of the idle process when it starts */ IdleStartEvent *idleStartEvent; diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 4c0c68761..970292cd8 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -31,55 +31,15 @@ #include "arch/alpha/constants.hh" #include "arch/alpha/process.hh" -#include "arch/alpha/linux/process.hh" -#include "arch/alpha/tru64/process.hh" #include "base/loader/object_file.hh" #include "base/misc.hh" #include "cpu/thread_context.hh" -#include "sim/builder.hh" #include "sim/system.hh" using namespace AlphaISA; using namespace std; -AlphaLiveProcess * -AlphaLiveProcess::create(const std::string &nm, System *system, int stdin_fd, - int stdout_fd, int stderr_fd, std::string executable, - std::vector<std::string> &argv, std::vector<std::string> &envp) -{ - AlphaLiveProcess *process = NULL; - - ObjectFile *objFile = createObjectFile(executable); - if (objFile == NULL) { - fatal("Can't load object file %s", executable); - } - - - if (objFile->getArch() != ObjectFile::Alpha) - fatal("Object file does not match architecture."); - switch (objFile->getOpSys()) { - case ObjectFile::Tru64: - process = new AlphaTru64Process(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp); - break; - - case ObjectFile::Linux: - process = new AlphaLinuxProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp); - break; - - default: - fatal("Unknown/unsupported operating system."); - } - - if (process == NULL) - fatal("Unknown error creating process object."); - return process; -} - AlphaLiveProcess::AlphaLiveProcess(const std::string &nm, ObjectFile *objFile, System *_system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp) @@ -111,60 +71,3 @@ AlphaLiveProcess::startup() } - - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaLiveProcess) - - VectorParam<string> cmd; - Param<string> executable; - Param<string> input; - Param<string> output; - VectorParam<string> env; - SimObjectParam<System *> system; - -END_DECLARE_SIM_OBJECT_PARAMS(AlphaLiveProcess) - - -BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaLiveProcess) - - INIT_PARAM(cmd, "command line (executable plus arguments)"), - INIT_PARAM(executable, "executable (overrides cmd[0] if set)"), - INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"), - INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"), - INIT_PARAM(env, "environment settings"), - INIT_PARAM(system, "system") - -END_INIT_SIM_OBJECT_PARAMS(AlphaLiveProcess) - - -CREATE_SIM_OBJECT(AlphaLiveProcess) -{ - string in = input; - string out = output; - - // initialize file descriptors to default: same as simulator - int stdin_fd, stdout_fd, stderr_fd; - - if (in == "stdin" || in == "cin") - stdin_fd = STDIN_FILENO; - else - stdin_fd = Process::openInputFile(input); - - if (out == "stdout" || out == "cout") - stdout_fd = STDOUT_FILENO; - else if (out == "stderr" || out == "cerr") - stdout_fd = STDERR_FILENO; - else - stdout_fd = Process::openOutputFile(out); - - stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; - - return AlphaLiveProcess::create(getInstanceName(), system, - stdin_fd, stdout_fd, stderr_fd, - (string)executable == "" ? cmd[0] : executable, - cmd, env); -} - - -REGISTER_SIM_OBJECT("AlphaLiveProcess", AlphaLiveProcess) - diff --git a/src/arch/alpha/process.hh b/src/arch/alpha/process.hh index 7fa913cad..5d5c9a52e 100644 --- a/src/arch/alpha/process.hh +++ b/src/arch/alpha/process.hh @@ -49,18 +49,6 @@ class AlphaLiveProcess : public LiveProcess std::vector<std::string> &envp); void startup(); - - public: - // this function is used to create the LiveProcess object, since - // we can't tell which subclass of LiveProcess to use until we - // open and look at the object file. - static AlphaLiveProcess *create(const std::string &nm, - System *_system, - int stdin_fd, int stdout_fd, int stderr_fd, - std::string executable, - std::vector<std::string> &argv, - std::vector<std::string> &envp); - }; diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index a68e440b0..3aaba7d58 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -232,10 +232,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem) Param<uint64_t> system_type; Param<uint64_t> system_rev; - Param<bool> bin; - VectorParam<std::string> binned_fns; - Param<bool> bin_int; - END_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem) @@ -250,10 +246,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem) INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), - INIT_PARAM_DFLT(bin, "is this system to be binned", false), - INIT_PARAM(binned_fns, "functions to be broken down and binned"), - INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true) + INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10) END_INIT_SIM_OBJECT_PARAMS(AlphaSystem) @@ -271,9 +264,6 @@ CREATE_SIM_OBJECT(AlphaSystem) p->readfile = readfile; p->system_type = system_type; p->system_rev = system_rev; - p->bin = bin; - p->binned_fns = binned_fns; - p->bin_int = bin_int; return new AlphaSystem(p); } diff --git a/src/arch/alpha/tru64/system.cc b/src/arch/alpha/tru64/system.cc index 8d9a53273..6c0edc1ee 100644 --- a/src/arch/alpha/tru64/system.cc +++ b/src/arch/alpha/tru64/system.cc @@ -107,9 +107,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem) Param<uint64_t> system_type; Param<uint64_t> system_rev; - Param<bool> bin; - VectorParam<string> binned_fns; - END_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem) @@ -124,9 +121,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem) INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 12), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1), - INIT_PARAM_DFLT(bin, "is this system to be binned", false), - INIT_PARAM(binned_fns, "functions to be broken down and binned") + INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1) END_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem) @@ -144,9 +139,6 @@ CREATE_SIM_OBJECT(Tru64AlphaSystem) p->readfile = readfile; p->system_type = system_type; p->system_rev = system_rev; - p->bin = bin; - p->binned_fns = binned_fns; - p->bin_int = false; return new Tru64AlphaSystem(p); } diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index 22baaf98e..4d522e18a 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -25,6 +25,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Authors: Steve Reinhardt +# Korey Sewell import os import sys @@ -1181,6 +1182,11 @@ class IntRegOperand(Operand): if (self.size == self.dflt_size): return '%s = xc->readIntReg(this, %d);\n' % \ (self.base_name, self.src_reg_idx) + elif (self.size > self.dflt_size): + int_reg_val = 'xc->readIntReg(this, %d)' % (self.src_reg_idx) + if (self.is_signed): + int_reg_val = 'sext<%d>(%s)' % (self.dflt_size, int_reg_val) + return '%s = %s;\n' % (self.base_name, int_reg_val) else: return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \ (self.base_name, self.src_reg_idx, self.size-1) diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript index 0365f5373..6295a6c11 100644 --- a/src/arch/mips/SConscript +++ b/src/arch/mips/SConscript @@ -28,6 +28,7 @@ # # Authors: Gabe Black # Steve Reinhardt +# Korey Sewell import os import sys @@ -46,6 +47,7 @@ Import('env') base_sources = Split(''' faults.cc isa_traits.cc + utility.cc ''') # Full-system sources diff --git a/src/arch/mips/isa/base.isa b/src/arch/mips/isa/base.isa index b2a31c018..b733da7da 100644 --- a/src/arch/mips/isa/base.isa +++ b/src/arch/mips/isa/base.isa @@ -1,5 +1,33 @@ // -*- mode:c++ -*- +// 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 +// 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: Korey Sewell + //////////////////////////////////////////////////////////////////// // // Base class for MIPS instructions, and some support functions @@ -18,16 +46,6 @@ output header {{ { protected: - /// Make MipsISA register dependence tags directly visible in - /// this class and derived classes. Maybe these should really - /// live here and not in the MipsISA namespace. - /*enum DependenceTags { - FP_Base_DepTag = MipsISA::FP_Base_DepTag, - Fpcr_DepTag = MipsISA::Fpcr_DepTag, - Uniq_DepTag = MipsISA::Uniq_DepTag, - IPR_Base_DepTag = MipsISA::IPR_Base_DepTag - };*/ - // Constructor MipsStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass) : StaticInst(mnem, _machInst, __opClass) @@ -67,12 +85,12 @@ output decoder {{ } if(_numSrcRegs > 0) { - ss << ","; + ss << ", "; printReg(ss, _srcRegIdx[0]); } if(_numSrcRegs > 1) { - ss << ","; + ss << ", "; printReg(ss, _srcRegIdx[1]); } diff --git a/src/arch/mips/isa/bitfields.isa b/src/arch/mips/isa/bitfields.isa index e1124a591..e8d4578c7 100644 --- a/src/arch/mips/isa/bitfields.isa +++ b/src/arch/mips/isa/bitfields.isa @@ -1,5 +1,33 @@ // -*- mode:c++ -*- +// 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 +// 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: Korey Sewell + //////////////////////////////////////////////////////////////////// // // Bitfield definitions. @@ -17,20 +45,19 @@ def bitfield FUNCTION < 5: 0>; def bitfield FUNCTION_HI < 5: 3>; def bitfield FUNCTION_LO < 2: 0>; -// Integer operate format -def bitfield RT <20:16>; -def bitfield RT_HI <20:19>; -def bitfield RT_LO <18:16>; - def bitfield RS <25:21>; def bitfield RS_MSB <25:25>; def bitfield RS_HI <25:24>; def bitfield RS_LO <23:21>; -def bitfield RS_SRL <25:22>; - +def bitfield RS_SRL <25:22>; +def bitfield RS_RT <25:16>; +def bitfield RT <20:16>; +def bitfield RT_HI <20:19>; +def bitfield RT_LO <18:16>; +def bitfield RT_RD <20:11>; def bitfield RD <15:11>; -def bitfield INTIMM <15: 0>; // integer immediate (literal) +def bitfield INTIMM <15: 0>; // Floating-point operate format def bitfield FMT <25:21>; @@ -67,5 +94,9 @@ def bitfield HINT <10: 6>; def bitfield SYSCALLCODE <25: 6>; def bitfield TRAPCODE <15:13>; +// EXT/INS instructions +def bitfield MSB <15:11>; +def bitfield LSB <10: 6>; + // M5 instructions def bitfield M5FUNC <7:0>; diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index 1454aba39..a64f74c4f 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -1,4 +1,32 @@ - // -*- mode:c++ -*- +// -*- mode:c++ -*- + +// 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 +// 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: Korey Sewell //////////////////////////////////////////////////////////////////// // @@ -6,41 +34,33 @@ // ----------------------------- // The following instructions are specified in the MIPS32 ISA // Specification. Decoding closely follows the style specified -// in the MIPS32 ISAthe specification document starting with Table +// in the MIPS32 ISA specification document starting with Table // A-2 (document available @ www.mips.com) // -//@todo: Distinguish "unknown/future" use insts from "reserved" -// ones decode OPCODE_HI default Unknown::unknown() { - - // Derived From ... Table A-2 MIPS32 ISA Manual + //Table A-2 0x0: decode OPCODE_LO { - 0x0: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { 0x1: decode MOVCI { format BasicOp { - 0: movf({{ if (getFPConditionCode(FCSR, CC) == 0) Rd = Rs}}); - 1: movt({{ if (getFPConditionCode(FCSR, CC) == 1) Rd = Rs}}); + 0: movf({{ Rd = (getCondCode(FCSR, CC) == 0) ? Rd : Rs; }}); + 1: movt({{ Rd = (getCondCode(FCSR, CC) == 1) ? Rd : Rs; }}); } } format BasicOp { - - //Table A-3 Note: "1. Specific encodings of the rt, rd, and sa fields - //are used to distinguish among the SLL, NOP, SSNOP and EHB functions. + //Table A-3 Note: "Specific encodings of the rd, rs, and + //rt fields are used to distinguish SLL, SSNOP, and EHB + //functions 0x0: decode RS { - 0x0: decode RT { //fix Nop traditional vs. Nop converted disassembly later - 0x0: decode RD default Nop::nop(){ - 0x0: decode SA { - 0x1: ssnop({{ ; }}); //really sll r0,r0,1 - 0x3: ehb({{ ; }}); //really sll r0,r0,3 - } - } - - default: sll({{ Rd = Rt.uw << SA; }}); + 0x0: decode RT_RD { + 0x0: decode SA default Nop::nop(){ + 0x1: WarnUnimpl::ssnop(); + 0x3: WarnUnimpl::ehb(); + } + default: sll({{ Rd = Rt.uw << SA; }}); } - } 0x2: decode RS_SRL { @@ -55,7 +75,6 @@ decode OPCODE_HI default Unknown::unknown() { 0x3: decode RS { 0x0: sra({{ uint32_t temp = Rt >> SA; - if ( (Rt & 0x80000000) > 0 ) { uint32_t mask = 0x80000000; for(int i=0; i < SA; i++) { @@ -63,7 +82,6 @@ decode OPCODE_HI default Unknown::unknown() { mask = mask >> 1; } } - Rd = temp; }}); } @@ -96,37 +114,36 @@ decode OPCODE_HI default Unknown::unknown() { } 0x1: decode FUNCTION_LO { - - //Table A-3 Note: "Specific encodings of the hint field are used - //to distinguish JR from JR.HB and JALR from JALR.HB" + //Table A-3 Note: "Specific encodings of the hint field are + //used to distinguish JR from JR.HB and JALR from JALR.HB" format Jump { 0x0: decode HINT { - 0:jr({{ NNPC = Rs & ~1; }},IsReturn); - - 1:jr_hb({{ NNPC = Rs & ~1; clear_exe_inst_hazards(); }},IsReturn); + 0x1: jr_hb({{ NNPC = Rs & ~1; }}, IsReturn, ClearHazards); + default: jr({{ NNPC = Rs & ~1; }}, IsReturn); } 0x1: decode HINT { - 0: jalr({{ Rd = NNPC; NNPC = Rs; }},IsCall,IsReturn); - - 1: jalr_hb({{ Rd = NNPC; NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn); + 0x1: jalr_hb({{ Rd = NNPC; NNPC = Rs; }}, IsCall, Link + , ClearHazards); + default: jalr({{ Rd = NNPC; NNPC = Rs; }}, IsCall, + Link); } } format BasicOp { - 0x2: movz({{ if (Rt == 0) Rd = Rs; }}); - 0x3: movn({{ if (Rt != 0) Rd = Rs; }}); + 0x2: movz({{ Rd = (Rt == 0) ? Rs : Rd; }}); + 0x3: movn({{ Rd = (Rt != 0) ? Rs : Rd; }}); + 0x4: syscall({{ xc->syscall(R2); }}, IsNonSpeculative); + 0x7: sync({{ ; }}, IsMemBarrier); } - format BasicOp { - 0x4: syscall({{ xc->syscall(R2); }},IsNonSpeculative); - 0x5: break({{ panic("Not implemented break yet"); }},IsNonSpeculative); - 0x7: sync({{ panic("Not implemented sync yet"); }},IsNonSpeculative); + format FailUnimpl { + 0x5: break(); } } 0x2: decode FUNCTION_LO { - format BasicOp { + format HiLoMiscOp { 0x0: mfhi({{ Rd = HI; }}); 0x1: mthi({{ HI = Rs; }}); 0x2: mflo({{ Rd = LO; }}); @@ -135,24 +152,16 @@ decode OPCODE_HI default Unknown::unknown() { } 0x3: decode FUNCTION_LO { - format IntOp { - 0x0: mult({{ - int64_t temp1 = Rs.sd * Rt.sd; - HI = temp1<63:32>; - LO = temp1<31:0>; - }}); - - 0x1: multu({{ - uint64_t temp1 = Rs.ud * Rt.ud; - HI = temp1<63:32>; - LO = temp1<31:0>; - }}); + format HiLoOp { + 0x0: mult({{ val = Rs.sd * Rt.sd; }}); + 0x1: multu({{ val = Rs.ud * Rt.ud; }}); + } + format HiLoMiscOp { 0x2: div({{ HI = Rs.sd % Rt.sd; LO = Rs.sd / Rt.sd; }}); - 0x3: divu({{ HI = Rs.ud % Rt.ud; LO = Rs.ud / Rt.ud; @@ -201,11 +210,8 @@ decode OPCODE_HI default Unknown::unknown() { format Branch { 0x0: bltz({{ cond = (Rs.sw < 0); }}); 0x1: bgez({{ cond = (Rs.sw >= 0); }}); - } - - format BranchLikely { - 0x2: bltzl({{ cond = (Rs.sw < 0); }}); - 0x3: bgezl({{ cond = (Rs.sw >= 0); }}); + 0x2: bltzl({{ cond = (Rs.sw < 0); }}, Likely); + 0x3: bgezl({{ cond = (Rs.sw >= 0); }}, Likely); } } @@ -222,13 +228,13 @@ decode OPCODE_HI default Unknown::unknown() { 0x2: decode REGIMM_LO { format Branch { - 0x0: bltzal({{ cond = (Rs.sw < 0); }}, IsCall,IsReturn); - 0x1: bgezal({{ cond = (Rs.sw >= 0); }}, IsCall,IsReturn); - } - - format BranchLikely { - 0x2: bltzall({{ cond = (Rs.sw < 0); }}, IsCall, IsReturn); - 0x3: bgezall({{ cond = (Rs.sw >= 0); }}, IsCall, IsReturn); + 0x0: bltzal({{ cond = (Rs.sw < 0); }}, Link); + 0x1: decode RS { + 0x0: bal ({{ cond = 1; }}, IsCall, Link); + default: bgezal({{ cond = (Rs.sw >= 0); }}, Link); + } + 0x2: bltzall({{ cond = (Rs.sw < 0); }}, Link, Likely); + 0x3: bgezall({{ cond = (Rs.sw >= 0); }}, Link, Likely); } } @@ -241,25 +247,23 @@ decode OPCODE_HI default Unknown::unknown() { format Jump { 0x2: j({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2);}}); - - 0x3: jal({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }},IsCall,IsReturn); + 0x3: jal({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }}, IsCall, + Link); } format Branch { - 0x4: beq({{ cond = (Rs.sw == Rt.sw); }}); - 0x5: bne({{ cond = (Rs.sw != Rt.sw); }}); - 0x6: decode RT { - 0x0: blez({{ cond = (Rs.sw <= 0); }}); - } - - 0x7: decode RT { - 0x0: bgtz({{ cond = (Rs.sw > 0); }}); + 0x4: decode RS_RT { + 0x0: b({{ cond = 1; }}); + default: beq({{ cond = (Rs.sw == Rt.sw); }}); } + 0x5: bne({{ cond = (Rs.sw != Rt.sw); }}); + 0x6: blez({{ cond = (Rs.sw <= 0); }}); + 0x7: bgtz({{ cond = (Rs.sw > 0); }}); } } 0x1: decode OPCODE_LO { - format IntOp { + format IntImmOp { 0x0: addi({{ Rt.sw = Rs.sw + imm; /*Trap If Overflow*/}}); 0x1: addiu({{ Rt.sw = Rs.sw + imm;}}); 0x2: slti({{ Rt.sw = ( Rs.sw < imm) ? 1 : 0 }}); @@ -275,112 +279,47 @@ decode OPCODE_HI default Unknown::unknown() { } 0x2: decode OPCODE_LO { - //Table A-11 MIPS32 COP0 Encoding of rs Field 0x0: decode RS_MSB { 0x0: decode RS { - format System { - 0x0: mfc0({{ - //uint64_t reg_num = Rd.uw; - - Rt = xc->readMiscReg(RD << 5 | SEL); - }}); - - 0x4: mtc0({{ - //uint64_t reg_num = Rd.uw; - - xc->setMiscReg(RD << 5 | SEL,Rt); - }}); - - 0x8: mftr({{ - //The contents of the coprocessor 0 register specified by the - //combination of rd and sel are loaded into general register - //rt. Note that not all coprocessor 0 registers support the - //sel field. In those instances, the sel field must be zero. - - //MT Code Needed Here - - }}); - - 0xC: mttr({{ - //The contents of the coprocessor 0 register specified by the - //combination of rd and sel are loaded into general register - //rt. Note that not all coprocessor 0 registers support the - //sel field. In those instances, the sel field must be zero. - - //MT Code Needed Here - }}); - - - 0xA: rdpgpr({{ - //Accessing Previous Shadow Set Register Number - //uint64_t prev = xc->readMiscReg(SRSCtl)/*[PSS]*/; - //uint64_t reg_num = Rt.uw; - - //Rd = xc->regs.IntRegFile[prev]; - //Rd = xc->shadowIntRegFile[prev][reg_num]; - }}); + format CP0Control { + 0x0: mfc0({{ Rt = xc->readMiscReg(RD << 5 | SEL); }}); + 0x4: mtc0({{ xc->setMiscReg(RD << 5 | SEL, Rt); }}); + } + format MipsMT { + 0x8: mftr(); + 0xC: mttr(); 0xB: decode RD { - 0x0: decode SC { - 0x0: dvpe({{ - Rt.sw = xc->readMiscReg(MVPControl); - xc->setMiscReg(MVPControl,0); - }}); - - 0x1: evpe({{ - Rt.sw = xc->readMiscReg(MVPControl); - xc->setMiscReg(MVPControl,1); - }}); + 0x0: dvpe(); + 0x1: evpe(); } - 0x1: decode SC { - 0x0: dmt({{ - Rt.sw = xc->readMiscReg(VPEControl); - xc->setMiscReg(VPEControl,0); - }}); - - 0x1: emt({{ - Rt.sw = xc->readMiscReg(VPEControl); - xc->setMiscReg(VPEControl,1); - }}); - } - - 0xC: decode SC { - 0x0: di({{ - Rt.sw = xc->readMiscReg(Status); - xc->setMiscReg(Status,0); - }}); - - 0x1: ei({{ - Rt.sw = xc->readMiscReg(Status); - xc->setMiscReg(Status,1); - }}); + 0x0: dmt(); + 0x1: emt(); + 0xC: decode SC { + 0x0: di(); + 0x1: ei(); + } } } + } - 0xE: wrpgpr({{ - //Accessing Previous Shadow Set Register Number - //uint64_t prev = xc->readMiscReg(SRSCtl/*[PSS]*/); - //uint64_t reg_num = Rd.uw; - - //xc->regs.IntRegFile[prev]; - //xc->shadowIntRegFile[prev][reg_num] = Rt; - }}); + format FailUnimpl { + 0xA: rdpgpr(); + 0xE: wrpgpr(); } } //Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO 0x1: decode FUNCTION { - format System { - 0x01: tlbr({{ }}); - 0x02: tlbwi({{ }}); - 0x06: tlbwr({{ }}); - 0x08: tlbp({{ }}); - } + format FailUnimpl { + 0x01: tlbr(); + 0x02: tlbwi(); + 0x06: tlbwr(); + 0x08: tlbp(); - format WarnUnimpl { 0x18: eret(); 0x1F: deret(); 0x20: wait(); @@ -393,18 +332,9 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode RS_HI { 0x0: decode RS_LO { - format FloatOp { + format CP1Control { 0x0: mfc1 ({{ Rt.uw = Fs.uw<31:0>; }}); - 0x3: mfhc1({{ Rt.uw = Fs.ud<63:32>;}}); - 0x4: mtc1 ({{ Fs.uw = Rt.uw; }}); - 0x7: mthc1({{ - uint64_t fs_hi = Rt.uw; - uint64_t fs_lo = Fs.ud & 0x0000FFFF; - Fs.ud = fs_hi << 32 | fs_lo; - }}); - } - format System { 0x2: cfc1({{ switch (FS) { @@ -424,11 +354,14 @@ decode OPCODE_HI default Unknown::unknown() { Rt = FCSR; break; default: - panic("FP Control Value (%d) Not Available. Ignoring Access to" - "Floating Control Status Register",FS); + panic("FP Control Value (%d) Not Valid"); } }}); + 0x3: mfhc1({{ Rt.uw = Fs.ud<63:32>;}}); + + 0x4: mtc1 ({{ Fs.uw = Rt.uw; }}); + 0x6: ctc1({{ switch (FS) { @@ -464,21 +397,29 @@ decode OPCODE_HI default Unknown::unknown() { "Floating Control Status Register", FS); } }}); + + 0x7: mthc1({{ + uint64_t fs_hi = Rt.uw; + uint64_t fs_lo = Fs.ud & 0x0FFFFFFFF; + Fs.ud = (fs_hi << 32) | fs_lo; + }}); + } } 0x1: decode ND { - 0x0: decode TF { - format Branch { - 0x0: bc1f({{ cond = (getFPConditionCode(FCSR,CC) == 0); }}); - 0x1: bc1t({{ cond = (getFPConditionCode(FCSR,CC) == 1); }}); + format Branch { + 0x0: decode TF { + 0x0: bc1f({{ cond = getCondCode(FCSR, BRANCH_CC) == 0; + }}); + 0x1: bc1t({{ cond = getCondCode(FCSR, BRANCH_CC) == 1; + }}); } - } - - 0x1: decode TF { - format BranchLikely { - 0x0: bc1fl({{ cond = (getFPConditionCode(FCSR,CC) == 0); }}); - 0x1: bc1tl({{ cond = (getFPConditionCode(FCSR,CC) == 1); }}); + 0x1: decode TF { + 0x0: bc1fl({{ cond = getCondCode(FCSR, BRANCH_CC) == 0; + }}, Likely); + 0x1: bc1tl({{ cond = getCondCode(FCSR, BRANCH_CC) == 1; + }}, Likely); } } } @@ -486,9 +427,8 @@ decode OPCODE_HI default Unknown::unknown() { 0x1: decode RS_HI { 0x2: decode RS_LO { - //Table A-14 MIPS32 COP1 Encoding of Function Field When rs=S - //(( single-word )) + //(( single-precision floating point)) 0x0: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { format FloatOp { @@ -499,194 +439,102 @@ decode OPCODE_HI default Unknown::unknown() { 0x4: sqrt_s({{ Fd.sf = sqrt(Fs.sf);}}); 0x5: abs_s({{ Fd.sf = fabs(Fs.sf);}}); 0x6: mov_s({{ Fd.sf = Fs.sf;}}); - 0x7: neg_s({{ Fd.sf = -1 * Fs.sf;}}); + 0x7: neg_s({{ Fd.sf = -Fs.sf;}}); } } 0x1: decode FUNCTION_LO { - format Float64Op { - 0x0: round_l_s({{ - Fd.ud = fpConvert(roundFP(Fs.sf,0), SINGLE_TO_LONG); - }}); - - 0x1: trunc_l_s({{ - Fd.ud = fpConvert(truncFP(Fs.sf), SINGLE_TO_LONG); - }}); - - 0x2: ceil_l_s({{ - Fd.ud = fpConvert(ceil(Fs.sf), SINGLE_TO_LONG); - }}); - - 0x3: floor_l_s({{ - Fd.ud = fpConvert(floor(Fs.sf), SINGLE_TO_LONG); - }}); - } - - format FloatOp { - 0x4: round_w_s({{ - Fd.uw = fpConvert(roundFP(Fs.sf,0), SINGLE_TO_WORD); - }}); - - 0x5: trunc_w_s({{ - Fd.uw = fpConvert(truncFP(Fs.sf), SINGLE_TO_WORD); - }}); - - 0x6: ceil_w_s({{ - Fd.uw = fpConvert(ceil(Fs.sf), SINGLE_TO_WORD); - }}); - - 0x7: floor_w_s({{ - Fd.uw = fpConvert(floor(Fs.sf), SINGLE_TO_WORD); - }}); + format FloatConvertOp { + 0x0: round_l_s({{ val = Fs.sf; }}, ToLong, + Round); + 0x1: trunc_l_s({{ val = Fs.sf; }}, ToLong, + Trunc); + 0x2: ceil_l_s({{ val = Fs.sf; }}, ToLong, + Ceil); + 0x3: floor_l_s({{ val = Fs.sf; }}, ToLong, + Floor); + 0x4: round_w_s({{ val = Fs.sf; }}, ToWord, + Round); + 0x5: trunc_w_s({{ val = Fs.sf; }}, ToWord, + Trunc); + 0x6: ceil_w_s({{ val = Fs.sf; }}, ToWord, + Ceil); + 0x7: floor_w_s({{ val = Fs.sf; }}, ToWord, + Floor); } } 0x2: decode FUNCTION_LO { 0x1: decode MOVCF { - format FloatOp { - 0x0: movf_s({{if (getFPConditionCode(FCSR,CC) == 0) Fd = Fs;}}); - 0x1: movt_s({{if (getFPConditionCode(FCSR,CC) == 1) Fd = Fs;}}); + format BasicOp { + 0x0: movf_s({{ Fd = (getCondCode(FCSR,CC) == 0) ? Fs : Fd; }}); + 0x1: movt_s({{ Fd = (getCondCode(FCSR,CC) == 1) ? Fs : Fd; }}); } } + format BasicOp { + 0x2: movz_s({{ Fd = (Rt == 0) ? Fs : Fd; }}); + 0x3: movn_s({{ Fd = (Rt != 0) ? Fs : Fd; }}); + } + format FloatOp { - 0x2: movz_s({{ if (Rt == 0) Fd = Fs; }}); - 0x3: movn_s({{ if (Rt != 0) Fd = Fs; }}); 0x5: recip_s({{ Fd = 1 / Fs; }}); 0x6: rsqrt_s({{ Fd = 1 / sqrt(Fs);}}); } } 0x4: decode FUNCTION_LO { - format FloatConvertOp { - 0x1: cvt_d_s({{ - Fd.ud = fpConvert(Fs.sf, SINGLE_TO_DOUBLE); - }}); - - 0x4: cvt_w_s({{ - Fd.uw = fpConvert(Fs.sf, SINGLE_TO_WORD); - }}); + 0x1: cvt_d_s({{ val = Fs.sf; }}, ToDouble); + 0x4: cvt_w_s({{ val = Fs.sf; }}, ToWord); + 0x5: cvt_l_s({{ val = Fs.sf; }}, ToLong); } - format FloatConvertOp { - 0x5: cvt_l_s({{ - Fd.ud = fpConvert(Fs.sf, SINGLE_TO_LONG); + 0x6: FloatOp::cvt_ps_s({{ + Fd.ud = (uint64_t) Fs.uw << 32 | + (uint64_t) Ft.uw; }}); - - 0x6: cvt_ps_st({{ - Fd.ud = (uint64_t)Fs.uw << 32 | (uint64_t)Ft.uw; - }}); - } } 0x6: decode FUNCTION_LO { format FloatCompareOp { - 0x0: c_f_s({{ cond = 0; }}); - - 0x1: c_un_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 1; - else - cond = 0; - }}); - - 0x2: c_eq_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 0; - else - cond = (Fs.sf == Ft.sf); - }}); - - 0x3: c_ueq_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 1; - else - cond = (Fs.sf == Ft.sf); - }}); - - 0x4: c_olt_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 0; - else - cond = (Fs.sf < Ft.sf); - }}); - - 0x5: c_ult_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 1; - else - cond = (Fs.sf < Ft.sf); - }}); - - 0x6: c_ole_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 0; - else - cond = (Fs.sf <= Ft.sf); - }}); - - 0x7: c_ule_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 1; - else - cond = (Fs.sf <= Ft.sf); - }}); + 0x0: c_f_s({{ cond = 0; }}, SinglePrecision, + UnorderedFalse); + 0x1: c_un_s({{ cond = 0; }}, SinglePrecision, + UnorderedTrue); + 0x2: c_eq_s({{ cond = (Fs.sf == Ft.sf); }}, + UnorderedFalse); + 0x3: c_ueq_s({{ cond = (Fs.sf == Ft.sf); }}, + UnorderedTrue); + 0x4: c_olt_s({{ cond = (Fs.sf < Ft.sf); }}, + UnorderedFalse); + 0x5: c_ult_s({{ cond = (Fs.sf < Ft.sf); }}, + UnorderedTrue); + 0x6: c_ole_s({{ cond = (Fs.sf <= Ft.sf); }}, + UnorderedFalse); + 0x7: c_ule_s({{ cond = (Fs.sf <= Ft.sf); }}, + UnorderedTrue); } } 0x7: decode FUNCTION_LO { - format FloatCompareWithXcptOp { - 0x0: c_sf_s({{ cond = 0; }}); - - 0x1: c_ngle_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 1; - else - cond = 0; - }}); - - 0x2: c_seq_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 0; - else - cond = (Fs.sf == Ft.sf); - }}); - - 0x3: c_ngl_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 1; - else - cond = (Fs.sf == Ft.sf); - }}); - - 0x4: c_lt_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 0; - else - cond = (Fs.sf < Ft.sf); - }}); - - 0x5: c_nge_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 1; - else - cond = (Fs.sf < Ft.sf); - }}); - - 0x6: c_le_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 0; - else - cond = (Fs.sf <= Ft.sf); - }}); - - 0x7: c_ngt_s({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond = 1; - else - cond = (Fs.sf <= Ft.sf); - }}); + format FloatCompareOp { + 0x0: c_sf_s({{ cond = 0; }}, SinglePrecision, + UnorderedFalse, QnanException); + 0x1: c_ngle_s({{ cond = 0; }}, SinglePrecision, + UnorderedTrue, QnanException); + 0x2: c_seq_s({{ cond = (Fs.sf == Ft.sf);}}, + UnorderedFalse, QnanException); + 0x3: c_ngl_s({{ cond = (Fs.sf == Ft.sf); }}, + UnorderedTrue, QnanException); + 0x4: c_lt_s({{ cond = (Fs.sf < Ft.sf); }}, + UnorderedFalse, QnanException); + 0x5: c_nge_s({{ cond = (Fs.sf < Ft.sf); }}, + UnorderedTrue, QnanException); + 0x6: c_le_s({{ cond = (Fs.sf <= Ft.sf); }}, + UnorderedFalse, QnanException); + 0x7: c_ngt_s({{ cond = (Fs.sf <= Ft.sf); }}, + UnorderedTrue, QnanException); } } } @@ -695,197 +543,108 @@ decode OPCODE_HI default Unknown::unknown() { 0x1: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { format FloatOp { - 0x0: add_d({{ Fd.df = Fs.df + Ft.df;}}); - 0x1: sub_d({{ Fd.df = Fs.df - Ft.df;}}); - 0x2: mul_d({{ Fd.df = Fs.df * Ft.df;}}); - 0x3: div_d({{ Fd.df = Fs.df / Ft.df;}}); - 0x4: sqrt_d({{ Fd.df = sqrt(Fs.df);}}); - 0x5: abs_d({{ Fd.df = fabs(Fs.df);}}); - 0x6: mov_d({{ Fd.ud = Fs.ud;}}); - 0x7: neg_d({{ Fd.df = -1 * Fs.df;}}); + 0x0: add_d({{ Fd.df = Fs.df + Ft.df; }}); + 0x1: sub_d({{ Fd.df = Fs.df - Ft.df; }}); + 0x2: mul_d({{ Fd.df = Fs.df * Ft.df; }}); + 0x3: div_d({{ Fd.df = Fs.df / Ft.df; }}); + 0x4: sqrt_d({{ Fd.df = sqrt(Fs.df); }}); + 0x5: abs_d({{ Fd.df = fabs(Fs.df); }}); + 0x6: mov_d({{ Fd.df = Fs.df; }}); + 0x7: neg_d({{ Fd.df = -1 * Fs.df; }}); } } 0x1: decode FUNCTION_LO { - format FloatOp { - 0x0: round_l_d({{ - Fd.ud = fpConvert(roundFP(Fs.df,0), DOUBLE_TO_LONG); - }}); - - 0x1: trunc_l_d({{ - Fd.ud = fpConvert(truncFP(Fs.df), DOUBLE_TO_LONG); - }}); - - 0x2: ceil_l_d({{ - Fd.ud = fpConvert(ceil(Fs.df), DOUBLE_TO_LONG); - }}); - - 0x3: floor_l_d({{ - Fd.ud = fpConvert(floor(Fs.df), DOUBLE_TO_LONG); - }}); - } - - format FloatOp { - 0x4: round_w_d({{ - Fd.uw = fpConvert(roundFP(Fs.df,0), DOUBLE_TO_WORD); - }}); - - 0x5: trunc_w_d({{ - Fd.uw = fpConvert(truncFP(Fs.df), DOUBLE_TO_WORD); - }}); - - 0x6: ceil_w_d({{ - Fd.uw = fpConvert(ceil(Fs.df), DOUBLE_TO_WORD); - }}); - - 0x7: floor_w_d({{ - Fd.uw = fpConvert(floor(Fs.df), DOUBLE_TO_WORD); - }}); + format FloatConvertOp { + 0x0: round_l_d({{ val = Fs.df; }}, ToLong, + Round); + 0x1: trunc_l_d({{ val = Fs.df; }}, ToLong, + Trunc); + 0x2: ceil_l_d({{ val = Fs.df; }}, ToLong, + Ceil); + 0x3: floor_l_d({{ val = Fs.df; }}, ToLong, + Floor); + 0x4: round_w_d({{ val = Fs.df; }}, ToWord, + Round); + 0x5: trunc_w_d({{ val = Fs.df; }}, ToWord, + Trunc); + 0x6: ceil_w_d({{ val = Fs.df; }}, ToWord, + Ceil); + 0x7: floor_w_d({{ val = Fs.df; }}, ToWord, + Floor); } } 0x2: decode FUNCTION_LO { 0x1: decode MOVCF { - format FloatOp { - 0x0: movf_d({{if (getFPConditionCode(FCSR,CC) == 0) Fd.df = Fs.df; }}); - 0x1: movt_d({{if (getFPConditionCode(FCSR,CC) == 1) Fd.df = Fs.df; }}); + format BasicOp { + 0x0: movf_d({{ Fd.df = (getCondCode(FCSR,CC) == 0) ? + Fs.df : Fd.df; + }}); + 0x1: movt_d({{ Fd.df = (getCondCode(FCSR,CC) == 1) ? + Fs.df : Fd.df; + }}); } } format BasicOp { - 0x2: movz_d({{ if (Rt == 0) Fd.df = Fs.df; }}); - 0x3: movn_d({{ if (Rt != 0) Fd.df = Fs.df; }}); + 0x2: movz_d({{ Fd.df = (Rt == 0) ? Fs.df : Fd.df; }}); + 0x3: movn_d({{ Fd.df = (Rt != 0) ? Fs.df : Fd.df; }}); } format FloatOp { - 0x5: recip_d({{ Fd.df = 1 / Fs.df}}); + 0x5: recip_d({{ Fd.df = 1 / Fs.df }}); 0x6: rsqrt_d({{ Fd.df = 1 / sqrt(Fs.df) }}); } } 0x4: decode FUNCTION_LO { - format FloatOp { - 0x0: cvt_s_d({{ - Fd.uw = fpConvert(Fs.df, DOUBLE_TO_SINGLE); - }}); - - 0x4: cvt_w_d({{ - Fd.uw = fpConvert(Fs.df, DOUBLE_TO_WORD); - }}); - - 0x5: cvt_l_d({{ - Fd.ud = fpConvert(Fs.df, DOUBLE_TO_LONG); - }}); + format FloatConvertOp { + 0x0: cvt_s_d({{ val = Fs.df; }}, ToSingle); + 0x4: cvt_w_d({{ val = Fs.df; }}, ToWord); + 0x5: cvt_l_d({{ val = Fs.df; }}, ToLong); } } 0x6: decode FUNCTION_LO { format FloatCompareOp { - 0x0: c_f_d({{ cond = 0; }}); - - 0x1: c_un_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 1; - else - cond = 0; - }}); - - 0x2: c_eq_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 0; - else - cond = (Fs.df == Ft.df); - }}); - - 0x3: c_ueq_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 1; - else - cond = (Fs.df == Ft.df); - }}); - - 0x4: c_olt_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 0; - else - cond = (Fs.df < Ft.df); - }}); - - 0x5: c_ult_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 1; - else - cond = (Fs.df < Ft.df); - }}); - - 0x6: c_ole_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 0; - else - cond = (Fs.df <= Ft.df); - }}); - - 0x7: c_ule_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 1; - else - cond = (Fs.df <= Ft.df); - }}); + 0x0: c_f_d({{ cond = 0; }}, DoublePrecision, + UnorderedFalse); + 0x1: c_un_d({{ cond = 0; }}, DoublePrecision, + UnorderedTrue); + 0x2: c_eq_d({{ cond = (Fs.df == Ft.df); }}, + UnorderedFalse); + 0x3: c_ueq_d({{ cond = (Fs.df == Ft.df); }}, + UnorderedTrue); + 0x4: c_olt_d({{ cond = (Fs.df < Ft.df); }}, + UnorderedFalse); + 0x5: c_ult_d({{ cond = (Fs.df < Ft.df); }}, + UnorderedTrue); + 0x6: c_ole_d({{ cond = (Fs.df <= Ft.df); }}, + UnorderedFalse); + 0x7: c_ule_d({{ cond = (Fs.df <= Ft.df); }}, + UnorderedTrue); } } 0x7: decode FUNCTION_LO { - format FloatCompareWithXcptOp { - 0x0: c_sf_d({{ cond = 0; }}); - - 0x1: c_ngle_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 1; - else - cond = 0; - }}); - - 0x2: c_seq_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 0; - else - cond = (Fs.df == Ft.df); - }}); - - 0x3: c_ngl_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 1; - else - cond = (Fs.df == Ft.df); - }}); - - 0x4: c_lt_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 0; - else - cond = (Fs.df < Ft.df); - }}); - - 0x5: c_nge_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 1; - else - cond = (Fs.df < Ft.df); - }}); - - 0x6: c_le_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 0; - else - cond = (Fs.df <= Ft.df); - }}); - - 0x7: c_ngt_d({{ - if (isnan(Fs.df) || isnan(Ft.df)) - cond = 1; - else - cond = (Fs.df <= Ft.df); - }}); + format FloatCompareOp { + 0x0: c_sf_d({{ cond = 0; }}, DoublePrecision, + UnorderedFalse, QnanException); + 0x1: c_ngle_d({{ cond = 0; }}, DoublePrecision, + UnorderedTrue, QnanException); + 0x2: c_seq_d({{ cond = (Fs.df == Ft.df); }}, + UnorderedFalse, QnanException); + 0x3: c_ngl_d({{ cond = (Fs.df == Ft.df); }}, + UnorderedTrue, QnanException); + 0x4: c_lt_d({{ cond = (Fs.df < Ft.df); }}, + UnorderedFalse, QnanException); + 0x5: c_nge_d({{ cond = (Fs.df < Ft.df); }}, + UnorderedTrue, QnanException); + 0x6: c_le_d({{ cond = (Fs.df <= Ft.df); }}, + UnorderedFalse, QnanException); + 0x7: c_ngt_d({{ cond = (Fs.df <= Ft.df); }}, + UnorderedTrue, QnanException); } } } @@ -893,19 +652,9 @@ decode OPCODE_HI default Unknown::unknown() { //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=W 0x4: decode FUNCTION { format FloatConvertOp { - 0x20: cvt_s_w({{ - Fd.uw = fpConvert(Fs.sf, WORD_TO_SINGLE); - }}); - - 0x21: cvt_d_w({{ - Fd.ud = fpConvert(Fs.sf, WORD_TO_DOUBLE); - }}); - } - - format Float64ConvertOp { - 0x26: cvt_ps_pw({{ - Fd.ud = fpConvert(Fs.ud, WORD_TO_PS); - }}); + 0x20: cvt_s_w({{ val = Fs.uw; }}, ToSingle); + 0x21: cvt_d_w({{ val = Fs.uw; }}, ToDouble); + 0x26: FailUnimpl::cvt_ps_w(); } } @@ -913,18 +662,10 @@ decode OPCODE_HI default Unknown::unknown() { //Note: "1. Format type L is legal only if 64-bit floating point operations //are enabled." 0x5: decode FUNCTION_HI { - format Float64ConvertOp { - 0x20: cvt_s_l({{ - Fd.uw = fpConvert(Fs.ud, LONG_TO_SINGLE); - }}); - - 0x21: cvt_d_l({{ - Fd.ud = fpConvert(Fs.ud, LONG_TO_DOUBLE); - }}); - - 0x26: cvt_ps_l({{ - Fd.ud = fpConvert(Fs.ud, LONG_TO_PS); - }}); + format FloatConvertOp { + 0x20: cvt_s_l({{ val = Fs.ud; }}, ToSingle); + 0x21: cvt_d_l({{ val = Fs.ud; }}, ToDouble); + 0x26: FailUnimpl::cvt_ps_l(); } } @@ -938,30 +679,25 @@ decode OPCODE_HI default Unknown::unknown() { Fd1.sf = Fs1.sf + Ft2.sf; Fd2.sf = Fs2.sf + Ft2.sf; }}); - 0x1: sub_ps({{ Fd1.sf = Fs1.sf - Ft2.sf; Fd2.sf = Fs2.sf - Ft2.sf; }}); - 0x2: mul_ps({{ Fd1.sf = Fs1.sf * Ft2.sf; Fd2.sf = Fs2.sf * Ft2.sf; }}); - 0x5: abs_ps({{ Fd1.sf = fabs(Fs1.sf); Fd2.sf = fabs(Fs2.sf); }}); - 0x6: mov_ps({{ Fd1.sf = Fs1.sf; Fd2.sf = Fs2.sf; }}); - 0x7: neg_ps({{ - Fd1.sf = -1 * Fs1.sf; - Fd2.sf = -1 * Fs2.sf; + Fd1.sf = -(Fs1.sf); + Fd2.sf = -(Fs2.sf); }}); } } @@ -970,236 +706,112 @@ decode OPCODE_HI default Unknown::unknown() { 0x1: decode MOVCF { format Float64Op { 0x0: movf_ps({{ - if (getFPConditionCode(FCSR, CC) == 0) - Fd1 = Fs1; - if (getFPConditionCode(FCSR, CC+1) == 0) - Fd2 = Fs2; + Fd1 = (getCondCode(FCSR, CC) == 0) ? + Fs1 : Fd1; + Fd2 = (getCondCode(FCSR, CC+1) == 0) ? + Fs2 : Fd2; }}); - 0x1: movt_ps({{ - if (getFPConditionCode(FCSR, CC) == 1) - Fd1 = Fs1; - if (getFPConditionCode(FCSR, CC+1) == 1) - Fd2 = Fs2; + Fd2 = (getCondCode(FCSR, CC) == 1) ? + Fs1 : Fd1; + Fd2 = (getCondCode(FCSR, CC+1) == 1) ? + Fs2 : Fd2; }}); } } format Float64Op { 0x2: movz_ps({{ - if (getFPConditionCode(FCSR, CC) == 0) - Fd1 = Fs1; - if (getFPConditionCode(FCSR, CC) == 0) - Fd2 = Fs2; + Fd1 = (getCondCode(FCSR, CC) == 0) ? + Fs1 : Fd1; + Fd2 = (getCondCode(FCSR, CC) == 0) ? + Fs2 : Fd2; }}); - 0x3: movn_ps({{ - if (getFPConditionCode(FCSR, CC) == 1) - Fd1 = Fs1; - if (getFPConditionCode(FCSR, CC) == 1) - Fd2 = Fs2; + Fd1 = (getCondCode(FCSR, CC) == 1) ? + Fs1 : Fd1; + Fd2 = (getCondCode(FCSR, CC) == 1) ? + Fs2 : Fd2; }}); } } 0x4: decode FUNCTION_LO { - 0x0: Float64Op::cvt_s_pu({{ - Fd.uw = fpConvert(Fs2.uw, PU_TO_SINGLE); - }}); + 0x0: FloatOp::cvt_s_pu({{ Fd.sf = Fs2.sf; }}); } 0x5: decode FUNCTION_LO { - format Float64Op { - 0x0: cvt_s_pl({{ - Fd.uw = fpConvert(Fs1.uw, PL_TO_SINGLE); - }}); + 0x0: FloatOp::cvt_s_pl({{ Fd.sf = Fs1.sf; }}); - 0x4: pll({{ Fd.ud = (uint64_t) Fs1.uw << 32 | Ft1.uw; }}); - 0x5: plu({{ Fd.ud = (uint64_t) Fs1.uw << 32 | Ft2.uw; }}); - 0x6: pul({{ Fd.ud = (uint64_t) Fs2.uw << 32 | Ft1.uw; }}); - 0x7: puu({{ Fd.ud = (uint64_t) Fs2.uw << 32 | Ft2.uw; }}); + format Float64Op { + 0x4: pll({{ Fd.ud = (uint64_t) Fs1.uw << 32 | + Ft1.uw; + }}); + 0x5: plu({{ Fd.ud = (uint64_t) Fs1.uw << 32 | + Ft2.uw; + }}); + 0x6: pul({{ Fd.ud = (uint64_t) Fs2.uw << 32 | + Ft1.uw; + }}); + 0x7: puu({{ Fd.ud = (uint64_t) Fs2.uw << 32 | + Ft2.uw; + }}); } } 0x6: decode FUNCTION_LO { format FloatPSCompareOp { - 0x0: c_f_ps({{ cond1 = 0; cond2 = 0; }}); - - 0x1: c_un_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 1; - else - cond1 = 0; - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 1; - else - cond2 = 0; - - }}); - - 0x2: c_eq_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 0; - else - cond1 = (Fs1.sf == Ft1.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 0; - else - cond2 = (Fs2.sf == Ft2.sf); - }}); - - 0x3: c_ueq_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 1; - else - cond1 = (Fs1.sf == Ft1.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 1; - else - cond2 = (Fs2.sf == Ft2.sf); - }}); - - 0x4: c_olt_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 0; - else - cond1 = (Fs1.sf < Ft1.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 0; - else - cond2 = (Fs2.sf < Ft2.sf); - }}); - - 0x5: c_ult_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 1; - else - cond1 = (Fs.sf < Ft.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 1; - else - cond2 = (Fs2.sf < Ft2.sf); - }}); - - 0x6: c_ole_ps({{ - if (isnan(Fs.sf) || isnan(Ft.sf)) - cond1 = 0; - else - cond1 = (Fs.sf <= Ft.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 0; - else - cond2 = (Fs2.sf <= Ft2.sf); - }}); - - 0x7: c_ule_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 1; - else - cond1 = (Fs1.sf <= Ft1.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 1; - else - cond2 = (Fs2.sf <= Ft2.sf); - }}); + 0x0: c_f_ps({{ cond1 = 0; }}, {{ cond2 = 0; }}, + UnorderedFalse); + 0x1: c_un_ps({{ cond1 = 0; }}, {{ cond2 = 0; }}, + UnorderedTrue); + 0x2: c_eq_ps({{ cond1 = (Fs1.sf == Ft1.sf); }}, + {{ cond2 = (Fs2.sf == Ft2.sf); }}, + UnorderedFalse); + 0x3: c_ueq_ps({{ cond1 = (Fs1.sf == Ft1.sf); }}, + {{ cond2 = (Fs2.sf == Ft2.sf); }}, + UnorderedTrue); + 0x4: c_olt_ps({{ cond1 = (Fs1.sf < Ft1.sf); }}, + {{ cond2 = (Fs2.sf < Ft2.sf); }}, + UnorderedFalse); + 0x5: c_ult_ps({{ cond1 = (Fs.sf < Ft.sf); }}, + {{ cond2 = (Fs2.sf < Ft2.sf); }}, + UnorderedTrue); + 0x6: c_ole_ps({{ cond1 = (Fs.sf <= Ft.sf); }}, + {{ cond2 = (Fs2.sf <= Ft2.sf); }}, + UnorderedFalse); + 0x7: c_ule_ps({{ cond1 = (Fs1.sf <= Ft1.sf); }}, + {{ cond2 = (Fs2.sf <= Ft2.sf); }}, + UnorderedTrue); } } 0x7: decode FUNCTION_LO { - format FloatPSCompareWithXcptOp { - 0x0: c_sf_ps({{ cond1 = 0; cond2 = 0; }}); - - 0x1: c_ngle_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 1; - else - cond1 = 0; - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 1; - else - cond2 = 0; - }}); - - 0x2: c_seq_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 0; - else - cond1 = (Fs1.sf == Ft1.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 0; - else - cond2 = (Fs2.sf == Ft2.sf); - }}); - - 0x3: c_ngl_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 1; - else - cond1 = (Fs1.sf == Ft1.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 1; - else - cond2 = (Fs2.sf == Ft2.sf); - }}); - - 0x4: c_lt_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 0; - else - cond1 = (Fs1.sf < Ft1.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 0; - else - cond2 = (Fs2.sf < Ft2.sf); - }}); - - 0x5: c_nge_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 1; - else - cond1 = (Fs1.sf < Ft1.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 1; - else - cond2 = (Fs2.sf < Ft2.sf); - }}); - - 0x6: c_le_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 0; - else - cond1 = (Fs1.sf <= Ft1.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 0; - else - cond2 = (Fs2.sf <= Ft2.sf); - }}); - - 0x7: c_ngt_ps({{ - if (isnan(Fs1.sf) || isnan(Ft1.sf)) - cond1 = 1; - else - cond1 = (Fs1.sf <= Ft1.sf); - - if (isnan(Fs2.sf) || isnan(Ft2.sf)) - cond2 = 1; - else - cond2 = (Fs2.sf <= Ft2.sf); - }}); + format FloatPSCompareOp { + 0x0: c_sf_ps({{ cond1 = 0; }}, {{ cond2 = 0; }}, + UnorderedFalse, QnanException); + 0x1: c_ngle_ps({{ cond1 = 0; }}, + {{ cond2 = 0; }}, + UnorderedTrue, QnanException); + 0x2: c_seq_ps({{ cond1 = (Fs1.sf == Ft1.sf); }}, + {{ cond2 = (Fs2.sf == Ft2.sf); }}, + UnorderedFalse, QnanException); + 0x3: c_ngl_ps({{ cond1 = (Fs1.sf == Ft1.sf); }}, + {{ cond2 = (Fs2.sf == Ft2.sf); }}, + UnorderedTrue, QnanException); + 0x4: c_lt_ps({{ cond1 = (Fs1.sf < Ft1.sf); }}, + {{ cond2 = (Fs2.sf < Ft2.sf); }}, + UnorderedFalse, QnanException); + 0x5: c_nge_ps({{ cond1 = (Fs1.sf < Ft1.sf); }}, + {{ cond2 = (Fs2.sf < Ft2.sf); }}, + UnorderedTrue, QnanException); + 0x6: c_le_ps({{ cond1 = (Fs1.sf <= Ft1.sf); }}, + {{ cond2 = (Fs2.sf <= Ft2.sf); }}, + UnorderedFalse, QnanException); + 0x7: c_ngt_ps({{ cond1 = (Fs1.sf <= Ft1.sf); }}, + {{ cond2 = (Fs2.sf <= Ft2.sf); }}, + UnorderedTrue, QnanException); } } } @@ -1209,9 +821,9 @@ decode OPCODE_HI default Unknown::unknown() { //Table A-19 MIPS32 COP2 Encoding of rs Field 0x2: decode RS_MSB { - 0x0: decode RS_HI { - 0x0: decode RS_LO { - format WarnUnimpl { + format FailUnimpl { + 0x0: decode RS_HI { + 0x0: decode RS_LO { 0x0: mfc2(); 0x2: cfc2(); 0x3: mfhc2(); @@ -1219,18 +831,14 @@ decode OPCODE_HI default Unknown::unknown() { 0x6: ctc2(); 0x7: mftc2(); } - } - 0x1: decode ND { - 0x0: decode TF { - format WarnUnimpl { + 0x1: decode ND { + 0x0: decode TF { 0x0: bc2f(); 0x1: bc2t(); } - } - 0x1: decode TF { - format WarnUnimpl { + 0x1: decode TF { 0x0: bc2fl(); 0x1: bc2tl(); } @@ -1244,441 +852,240 @@ decode OPCODE_HI default Unknown::unknown() { //operations are enabled." 0x3: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { - format LoadFloatMemory { - 0x0: lwxc1({{ Ft.uw = Mem.uw;}}, {{ EA = Rs + Rt; }}); - 0x1: ldxc1({{ Ft.ud = Mem.ud;}}, {{ EA = Rs + Rt; }}); - 0x5: luxc1({{ Ft.uw = Mem.ud;}}, {{ EA = Rs + Rt; }}); + format LoadIndexedMemory { + 0x0: lwxc1({{ Ft.uw = Mem.uw;}}); + 0x1: ldxc1({{ Ft.ud = Mem.ud;}}); + 0x5: luxc1({{ Ft.uw = Mem.ud;}}); } } 0x1: decode FUNCTION_LO { - format StoreFloatMemory { - 0x0: swxc1({{ Mem.uw = Ft.uw;}}, {{ EA = Rs + Rt; }}); - 0x1: sdxc1({{ Mem.ud = Ft.ud;}}, {{ EA = Rs + Rt; }}); - 0x5: suxc1({{ Mem.ud = Ft.ud;}}, {{ EA = Rs + Rt; }}); + format StoreIndexedMemory { + 0x0: swxc1({{ Mem.uw = Ft.uw;}}); + 0x1: sdxc1({{ Mem.ud = Ft.ud;}}); + 0x5: suxc1({{ Mem.ud = Ft.ud;}}); } - 0x7: WarnUnimpl::prefx(); + 0x7: Prefetch::prefx({{ EA = Rs + Rt; }}); } - format FloatOp { - 0x3: WarnUnimpl::alnv_ps(); + 0x3: decode FUNCTION_LO { + 0x6: Float64Op::alnv_ps({{ if (Rs<2:0> == 0) { + Fd.ud = Fs.ud; + } else if (Rs<2:0> == 4) { + #if BYTE_ORDER == BIG_ENDIAN + Fd.ud = Fs.ud<31:0> << 32 | + Ft.ud<63:32>; + #elif BYTE_ORDER == LITTLE_ENDIAN + Fd.ud = Ft.ud<31:0> << 32 | + Fs.ud<63:32>; + #endif + } else { + Fd.ud = Fd.ud; + } + }}); + } - format BasicOp { - 0x4: decode FUNCTION_LO { - 0x0: madd_s({{ Fd.sf = (Fs.sf * Ft.sf) + Fr.sf; }}); - 0x1: madd_d({{ Fd.df = (Fs.df * Ft.df) + Fr.df; }}); - 0x6: madd_ps({{ - Fd1.sf = (Fs1.df * Ft1.df) + Fr1.df; - Fd2.sf = (Fs2.df * Ft2.df) + Fr2.df; - }}); - } + format FloatAccOp { + 0x4: decode FUNCTION_LO { + 0x0: madd_s({{ Fd.sf = (Fs.sf * Ft.sf) + Fr.sf; }}); + 0x1: madd_d({{ Fd.df = (Fs.df * Ft.df) + Fr.df; }}); + 0x6: madd_ps({{ + Fd1.sf = (Fs1.df * Ft1.df) + Fr1.df; + Fd2.sf = (Fs2.df * Ft2.df) + Fr2.df; + }}); + } - 0x5: decode FUNCTION_LO { - 0x0: msub_s({{ Fd.sf = (Fs.sf * Ft.sf) - Fr.sf; }}); - 0x1: msub_d({{ Fd.df = (Fs.df * Ft.df) - Fr.df; }}); - 0x6: msub_ps({{ - Fd1.sf = (Fs1.df * Ft1.df) - Fr1.df; - Fd2.sf = (Fs2.df * Ft2.df) - Fr2.df; - }}); - } + 0x5: decode FUNCTION_LO { + 0x0: msub_s({{ Fd.sf = (Fs.sf * Ft.sf) - Fr.sf; }}); + 0x1: msub_d({{ Fd.df = (Fs.df * Ft.df) - Fr.df; }}); + 0x6: msub_ps({{ + Fd1.sf = (Fs1.df * Ft1.df) - Fr1.df; + Fd2.sf = (Fs2.df * Ft2.df) - Fr2.df; + }}); + } - 0x6: decode FUNCTION_LO { - 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }}); - 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Ft.df) + Fr.df; }}); - 0x6: nmadd_ps({{ - Fd1.sf = -1 * ((Fs1.df * Ft1.df) + Fr1.df); - Fd2.sf = -1 * ((Fs2.df * Ft2.df) + Fr2.df); - }}); - } + 0x6: decode FUNCTION_LO { + 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }}); + 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Ft.df) + Fr.df; }}); + 0x6: nmadd_ps({{ + Fd1.sf = -((Fs1.df * Ft1.df) + Fr1.df); + Fd2.sf = -((Fs2.df * Ft2.df) + Fr2.df); + }}); + } - 0x7: decode FUNCTION_LO { - 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }}); - 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Ft.df) - Fr.df; }}); - 0x6: nmsub_ps({{ - Fd1.sf = -1 * ((Fs1.df * Ft1.df) - Fr1.df); - Fd2.sf = -1 * ((Fs2.df * Ft2.df) - Fr2.df); - }}); - } + 0x7: decode FUNCTION_LO { + 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }}); + 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Ft.df) - Fr.df; }}); + 0x6: nmsub_ps({{ + Fd1.sf = -((Fs1.df * Ft1.df) - Fr1.df); + Fd2.sf = -((Fs2.df * Ft2.df) - Fr2.df); + }}); } + } } - format BranchLikely { - 0x4: beql({{ cond = (Rs.sw == 0); }}); - 0x5: bnel({{ cond = (Rs.sw != 0); }}); - 0x6: blezl({{ cond = (Rs.sw <= 0); }}); - 0x7: bgtzl({{ cond = (Rs.sw > 0); }}); + format Branch { + 0x4: beql({{ cond = (Rs.sw == Rt.sw); }}, Likely); + 0x5: bnel({{ cond = (Rs.sw != Rt.sw); }}, Likely); + 0x6: blezl({{ cond = (Rs.sw <= 0); }}, Likely); + 0x7: bgtzl({{ cond = (Rs.sw > 0); }}, Likely); } } - 0x3: decode OPCODE_LO default FailUnimpl::reserved() { - + 0x3: decode OPCODE_LO { //Table A-5 MIPS32 SPECIAL2 Encoding of Function Field 0x4: decode FUNCTION_HI { - 0x0: decode FUNCTION_LO { - format IntOp { - 0x0: madd({{ - int64_t temp1 = (int64_t) HI << 32 | LO; - temp1 = temp1 + (Rs.sw * Rt.sw); - HI = temp1<63:32>; - LO = temp1<31:0>; - }}); - - 0x1: maddu({{ - int64_t temp1 = (int64_t) HI << 32 | LO; - temp1 = temp1 + (Rs.uw * Rt.uw); - HI = temp1<63:32>; - LO = temp1<31:0>; - }}); - - 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }}); - - 0x4: msub({{ - int64_t temp1 = (int64_t) HI << 32 | LO; - temp1 = temp1 - (Rs.sw * Rt.sw); - HI = temp1<63:32>; - LO = temp1<31:0>; - }}); + 0x2: IntOp::mul({{ int64_t temp1 = Rs.sd * Rt.sd; + Rd.sw = temp1<31:0> + }}); - 0x5: msubu({{ - int64_t temp1 = (int64_t) HI << 32 | LO; - temp1 = temp1 - (Rs.uw * Rt.uw); - HI = temp1<63:32>; - LO = temp1<31:0>; - }}); + format HiLoOp { + 0x0: madd({{ val = ((int64_t) HI << 32 | LO) + + (Rs.sd * Rt.sd); + }}); + 0x1: maddu({{ val = ((uint64_t) HI << 32 | LO) + + (Rs.ud * Rt.ud); + }}); + 0x4: msub({{ val = ((int64_t) HI << 32 | LO) - + (Rs.sd * Rt.sd); + }}); + 0x5: msubu({{ val = ((uint64_t) HI << 32 | LO) - + (Rs.ud * Rt.ud); + }}); } } 0x4: decode FUNCTION_LO { format BasicOp { - 0x0: clz({{ - int cnt = 0; - uint32_t mask = 0x80000000; - for (int i=0; i < 32; i++) { - if( (Rs & mask) == 0) { - cnt++; - } else { - break; - } - } - Rd.uw = cnt; - }}); - - 0x1: clo({{ - int cnt = 0; - uint32_t mask = 0x80000000; - for (int i=0; i < 32; i++) { - if( (Rs & mask) != 0) { - cnt++; - } else { - break; - } - } - Rd.uw = cnt; - }}); + 0x0: clz({{ int cnt = 32; + for (int idx = 31; idx >= 0; idx--) { + if( Rs<idx:idx> == 1) { + cnt = 31 - idx; + break; + } + } + Rd.uw = cnt; + }}); + 0x1: clo({{ int cnt = 32; + for (int idx = 31; idx >= 0; idx--) { + if( Rs<idx:idx> == 0) { + cnt = 31 - idx; + break; + } + } + Rd.uw = cnt; + }}); } } 0x7: decode FUNCTION_LO { - 0x7: WarnUnimpl::sdbbp(); + 0x7: FailUnimpl::sdbbp(); } } - //Table A-6 MIPS32 SPECIAL3 Encoding of Function Field for Release 2 of the Architecture + //Table A-6 MIPS32 SPECIAL3 Encoding of Function Field for Release 2 + //of the Architecture 0x7: decode FUNCTION_HI { - 0x0: decode FUNCTION_LO { - format FailUnimpl { - 0x1: ext(); - 0x4: ins(); + format BasicOp { + 0x1: ext({{ Rt.uw = bits(Rs.uw, MSB+LSB, LSB); }}); + 0x4: ins({{ Rt.uw = bits(Rt.uw, 31, MSB+1) << (MSB+1) | + bits(Rs.uw, MSB-LSB, 0) << LSB | + bits(Rt.uw, LSB-1, 0); + }}); } } 0x1: decode FUNCTION_LO { - format FailUnimpl { + format MipsMT { 0x0: fork(); 0x1: yield(); } } - //Table A-10 MIPS32 BSHFL Encoding of sa Field 0x4: decode SA { - - 0x02: FailUnimpl::wsbh(); - format BasicOp { + 0x02: wsbh({{ Rd.uw = Rt.uw<23:16> << 24 | + Rt.uw<31:24> << 16 | + Rt.uw<7:0> << 8 | + Rt.uw<15:8>; + }}); 0x10: seb({{ Rd.sw = Rt.sw<7:0>}}); 0x18: seh({{ Rd.sw = Rt.sw<15:0>}}); } } 0x6: decode FUNCTION_LO { - 0x7: FailUnimpl::rdhwr();//{{ /*Rt = xc->hwRegs[RD];*/ }} + 0x7: FailUnimpl::rdhwr(); } } } - 0x4: decode OPCODE_LO default FailUnimpl::reserved() { + 0x4: decode OPCODE_LO { format LoadMemory { 0x0: lb({{ Rt.sw = Mem.sb; }}); 0x1: lh({{ Rt.sw = Mem.sh; }}); - - 0x2: lwl({{ - uint32_t mem_word = Mem.uw; - uint32_t unalign_addr = Rs + disp; - uint32_t offset = unalign_addr & 0x00000003; -#if BYTE_ORDER == BIG_ENDIAN - switch(offset) - { - case 0: - Rt = mem_word; - break; - - case 1: - Rt &= 0x000F; - Rt |= (mem_word << 4); - break; - - case 2: - Rt &= 0x00FF; - Rt |= (mem_word << 8); - break; - - case 3: - Rt &= 0x0FFF; - Rt |= (mem_word << 12); - break; - - default: - panic("lwl: bad offset"); - } -#elif BYTE_ORDER == LITTLE_ENDIAN - switch(offset) - { - case 0: - Rt &= 0x0FFF; - Rt |= (mem_word << 12); - break; - - case 1: - Rt &= 0x00FF; - Rt |= (mem_word << 8); - break; - - case 2: - Rt &= 0x000F; - Rt |= (mem_word << 4); - break; - - case 3: - Rt = mem_word; - break; - - default: - panic("lwl: bad offset"); - } -#endif - }}, {{ EA = (Rs + disp) & ~3; }}); - 0x3: lw({{ Rt.sw = Mem.sw; }}); 0x4: lbu({{ Rt.uw = Mem.ub; }}); 0x5: lhu({{ Rt.uw = Mem.uh; }}); - 0x6: lwr({{ - uint32_t mem_word = Mem.uw; - uint32_t unalign_addr = Rs + disp; - uint32_t offset = unalign_addr & 0x00000003; - -#if BYTE_ORDER == BIG_ENDIAN - switch(offset) - { - case 0: Rt &= 0xFFF0; Rt |= (mem_word >> 12); break; - case 1: Rt &= 0xFF00; Rt |= (mem_word >> 8); break; - case 2: Rt &= 0xF000; Rt |= (mem_word >> 4); break; - case 3: Rt = mem_word; break; - default: panic("lwr: bad offset"); - } -#elif BYTE_ORDER == LITTLE_ENDIAN - switch(offset) - { - case 0: Rt = mem_word; break; - case 1: Rt &= 0xF000; Rt |= (mem_word >> 4); break; - case 2: Rt &= 0xFF00; Rt |= (mem_word >> 8); break; - case 3: Rt &= 0xFFF0; Rt |= (mem_word >> 12); break; - default: panic("lwr: bad offset"); - } -#endif - }}, - {{ EA = (Rs + disp) & ~3; }}); + } + + format LoadUnalignedMemory { + 0x2: lwl({{ uint32_t mem_shift = 24 - (8 * byte_offset); + Rt.uw = mem_word << mem_shift | + Rt.uw & mask(mem_shift); + }}); + 0x6: lwr({{ uint32_t mem_shift = 8 * byte_offset; + Rt.uw = Rt.uw & (mask(mem_shift) << (32 - mem_shift)) | + mem_word >> mem_shift; + }}); } } - 0x5: decode OPCODE_LO default FailUnimpl::reserved() { + 0x5: decode OPCODE_LO { format StoreMemory { 0x0: sb({{ Mem.ub = Rt<7:0>; }}); 0x1: sh({{ Mem.uh = Rt<15:0>; }}); - 0x2: swl({{ - uint32_t mem_word = 0; - uint32_t aligned_addr = (Rs + disp) & ~3; - uint32_t unalign_addr = Rs + disp; - uint32_t offset = unalign_addr & 0x00000003; - - DPRINTF(IEW,"Execute: aligned=0x%x unaligned=0x%x\n offset=0x%x", - aligned_addr,unalign_addr,offset); - - fault = xc->read(aligned_addr, (uint32_t&)mem_word, memAccessFlags); - -#if BYTE_ORDER == BIG_ENDIAN - switch(offset) - { - case 0: - Mem = Rt; - break; - - case 1: - mem_word &= 0xF000; - mem_word |= (Rt >> 4); - Mem = mem_word; - break; - - case 2: - mem_word &= 0xFF00; - mem_word |= (Rt >> 8); - Mem = mem_word; - break; - - case 3: - mem_word &= 0xFFF0; - mem_word |= (Rt >> 12); - Mem = mem_word; - break; - - default: - panic("swl: bad offset"); - } -#elif BYTE_ORDER == LITTLE_ENDIAN - switch(offset) - { - case 0: - mem_word &= 0xFFF0; - mem_word |= (Rt >> 12); - Mem = mem_word; - break; - - case 1: - mem_word &= 0xFF00; - mem_word |= (Rt >> 8); - Mem = mem_word; - break; - - case 2: - mem_word &= 0xF000; - mem_word |= (Rt >> 4); - Mem = mem_word; - break; - - case 3: - Mem = Rt; - break; - - default: - panic("swl: bad offset"); - } -#endif - }},{{ EA = (Rs + disp) & ~3; }},mem_flags = NO_ALIGN_FAULT); - 0x3: sw({{ Mem.uw = Rt<31:0>; }}); - - 0x6: swr({{ - uint32_t mem_word = 0; - uint32_t aligned_addr = (Rs + disp) & ~3; - uint32_t unalign_addr = Rs + disp; - uint32_t offset = unalign_addr & 0x00000003; - - fault = xc->read(aligned_addr, (uint32_t&)mem_word, memAccessFlags); - -#if BYTE_ORDER == BIG_ENDIAN - switch(offset) - { - case 0: - mem_word &= 0x0FFF; - mem_word |= (Rt << 12); - Mem = mem_word; - break; - - case 1: - mem_word &= 0x00FF; - mem_word |= (Rt << 8); - Mem = mem_word; - break; - - case 2: - mem_word &= 0x000F; - mem_word |= (Rt << 4); - Mem = mem_word; - break; - - case 3: - Mem = Rt; - break; - - default: - panic("swr: bad offset"); - } -#elif BYTE_ORDER == LITTLE_ENDIAN - switch(offset) - { - case 0: - Mem = Rt; - break; - - case 1: - mem_word &= 0x000F; - mem_word |= (Rt << 4); - Mem = mem_word; - break; - - case 2: - mem_word &= 0x00FF; - mem_word |= (Rt << 8); - Mem = mem_word; - break; - - case 3: - mem_word &= 0x0FFF; - mem_word |= (Rt << 12); - Mem = mem_word; - break; - - default: - panic("swr: bad offset"); - } -#endif - }},{{ EA = (Rs + disp) & ~3;}},mem_flags = NO_ALIGN_FAULT); } - format WarnUnimpl { - 0x7: cache(); + format StoreUnalignedMemory { + 0x2: swl({{ uint32_t reg_shift = 24 - (8 * byte_offset); + uint32_t mem_shift = 32 - reg_shift; + mem_word = mem_word & (mask(reg_shift) << mem_shift) | + Rt.uw >> reg_shift; + }}); + 0x6: swr({{ uint32_t reg_shift = 8 * byte_offset; + mem_word = Rt.uw << reg_shift | + mem_word & (mask(reg_shift)); + }}); } + 0x7: FailUnimpl::cache(); } - 0x6: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: LoadMemory::ll({{Rt.uw = Mem.uw}},mem_flags=LOCKED); - - format LoadFloatMemory { - 0x1: lwc1({{ Ft.uw = Mem.uw; }}); + 0x6: decode OPCODE_LO { + format LoadMemory { + 0x0: ll({{ Rt.uw = Mem.uw; }}, mem_flags=LOCKED); + 0x1: lwc1({{ Ft.uw = Mem.uw; }}); 0x5: ldc1({{ Ft.ud = Mem.ud; }}); } + + 0x3: Prefetch::pref(); } - 0x7: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: StoreMemory::sc({{ Mem.uw = Rt.uw; Rt.uw = 1; }}); + 0x7: decode OPCODE_LO { + 0x0: StoreCond::sc({{ Mem.uw = Rt.uw;}}, + {{ uint64_t tmp = write_result; + Rt.uw = (tmp == 0 || tmp == 1) ? tmp : Rt.uw; + }}, mem_flags=LOCKED); - format StoreFloatMemory { + format StoreMemory { 0x1: swc1({{ Mem.uw = Ft.uw; }}); 0x5: sdc1({{ Mem.ud = Ft.ud; }}); } diff --git a/src/arch/mips/isa/formats/basic.isa b/src/arch/mips/isa/formats/basic.isa index c02af7ddc..35ce09205 100644 --- a/src/arch/mips/isa/formats/basic.isa +++ b/src/arch/mips/isa/formats/basic.isa @@ -1,5 +1,33 @@ // -*- mode:c++ -*- +// 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 +// 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: Korey Sewell + // Declarations for execute() methods. def template BasicExecDeclare {{ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const; @@ -12,11 +40,11 @@ def template BasicDeclare {{ */ class %(class_name)s : public %(base_class)s { - public: + public: /// Constructor. %(class_name)s(MachInst machInst); %(BasicExecDeclare)s - }; + }; }}; // Basic instruction class constructor template. @@ -27,6 +55,7 @@ def template BasicConstructor {{ } }}; + // Basic instruction class execute method template. def template BasicExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const diff --git a/src/arch/mips/isa/formats/branch.isa b/src/arch/mips/isa/formats/branch.isa index ea5af22c0..827e3ccf0 100644 --- a/src/arch/mips/isa/formats/branch.isa +++ b/src/arch/mips/isa/formats/branch.isa @@ -1,5 +1,33 @@ // -*- mode:c++ -*- +// 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 +// 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: Korey Sewell + //////////////////////////////////////////////////////////////////// // // Control transfer instructions @@ -68,29 +96,6 @@ output header {{ }; /** - * Base class for branch likely branches (PC-relative control transfers), - */ - class BranchLikely : public PCDependentDisassembly - { - protected: - /// target address (signed) Displacement . - int32_t disp; - - /// Constructor. - BranchLikely(const char *mnem, MachInst _machInst, OpClass __opClass) - : PCDependentDisassembly(mnem, _machInst, __opClass), - disp(OFFSET << 2) - { - - } - - Addr branchTarget(Addr branchPC) const; - - std::string - generateDisassembly(Addr pc, const SymbolTable *symtab) const; - }; - - /** * Base class for jumps (register-indirect control transfers). In * the Mips ISA, these are always unconditional. */ @@ -126,12 +131,6 @@ output decoder {{ } Addr - BranchLikely::branchTarget(Addr branchPC) const - { - return branchPC + 4 + disp; - } - - Addr Jump::branchTarget(ThreadContext *tc) const { Addr NPC = tc->readPC() + 4; @@ -171,49 +170,12 @@ output decoder {{ // unconditional branches) if (_numSrcRegs == 1) { printReg(ss, _srcRegIdx[0]); - ss << ","; + ss << ", "; } else if(_numSrcRegs == 2) { printReg(ss, _srcRegIdx[0]); - ss << ","; + ss << ", "; printReg(ss, _srcRegIdx[1]); - ss << ","; - } - - Addr target = pc + 4 + disp; - - std::string str; - if (symtab && symtab->findSymbol(target, str)) - ss << str; - else - ccprintf(ss, "0x%x", target); - - string inst_name = mnemonic; - - if (inst_name.substr(inst_name.length()-2,inst_name.length()) == "al"){ - ccprintf(ss, " (r31=0x%x)",pc+8); - } - - return ss.str(); - } - - std::string - BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const - { - std::stringstream ss; - - ccprintf(ss, "%-10s ", mnemonic); - - // There's only one register arg (RA), but it could be - // either a source (the condition for conditional - // branches) or a destination (the link reg for - // unconditional branches) - if (_numSrcRegs > 0) { - printReg(ss, _srcRegIdx[0]); - ss << ","; - } - else if (_numDestRegs > 0) { - printReg(ss, _destRegIdx[0]); - ss << ","; + ss << ", "; } Addr target = pc + 4 + disp; @@ -247,72 +209,64 @@ output decoder {{ printReg(ss, _srcRegIdx[0]); } else if(_numSrcRegs == 2) { printReg(ss, _srcRegIdx[0]); - ss << ","; + ss << ", "; printReg(ss, _srcRegIdx[1]); - } else { - panic(">= 3 Source Registers!!!"); } return ss.str(); } }}; -def format Branch(code,*flags) {{ - #Add Link Code if Link instruction - strlen = len(name) - if name[strlen-2:] == 'al': - code += 'R31 = NNPC;\n' +def format Branch(code,*opt_flags) {{ + not_taken_code = ' NNPC = NNPC;\n' + not_taken_code += '} \n' + + #Build Instruction Flags + #Use Link & Likely Flags to Add Link/Condition Code + inst_flags = ('IsDirectControl', ) + for x in opt_flags: + if x == 'Link': + code += 'R31 = NNPC;\n' + elif x == 'Likely': + not_taken_code = ' NPC = NNPC;\n' + not_taken_code += ' NNPC = NNPC + 4;\n' + not_taken_code += '} \n' + inst_flags = ('IsCondDelaySlot', ) + else: + inst_flags += (x, ) + + if 'cond == 1' in code: + inst_flags += ('IsCondControl', ) + else: + inst_flags += ('IsUncondControl', ) #Condition code code = 'bool cond;\n' + code code += 'if (cond) {\n' code += ' NNPC = NPC + disp;\n' code += '} else {\n' - code += ' NNPC = NNPC;\n' - code += '} \n' - - iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), - ('IsDirectControl', 'IsCondControl')) - - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) -}}; - - -def format BranchLikely(code,*flags) {{ - #Add Link Code if Link instruction - strlen = len(name) - if name[strlen-3:] == 'all': - code += 'R31 = NNPC;\n' - - #Condition code - code = 'bool cond;\n' + code - code += 'if (cond) {' - code += 'NNPC = NPC + disp;\n' - code += '} \n' - - - iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), - ('IsDirectControl', 'IsCondControl','IsCondDelaySlot')) + code += not_taken_code + iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), inst_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; -def format Jump(code,*flags) {{ - #Add Link Code if Link instruction - strlen = len(name) - if strlen > 1 and name[1:] == 'al': +def format Jump(code, *opt_flags) {{ + #Build Instruction Flags + #Use Link Flag to Add Link Code + inst_flags = ('IsIndirectControl', 'IsUncondControl') + for x in opt_flags: + if x == 'Link': code = 'R31 = NNPC;\n' + code + elif x == 'ClearHazards': + code += '/* Code Needed to Clear Execute & Inst Hazards */\n' + else: + inst_flags += (x, ) - - iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\ - ('IsIndirectControl', 'IsUncondControl')) - + iop = InstObjParams(name, Name, 'Jump', CodeBlock(code), inst_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) diff --git a/src/arch/mips/isa/formats/control.isa b/src/arch/mips/isa/formats/control.isa new file mode 100644 index 000000000..509ee7e87 --- /dev/null +++ b/src/arch/mips/isa/formats/control.isa @@ -0,0 +1,156 @@ +// -*- mode:c++ -*- + +// 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 +// 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: Korey Sewell + +//////////////////////////////////////////////////////////////////// +// +// Integer operate instructions +// + +//Outputs to decoder.hh +output header {{ + + class Control : public MipsStaticInst + { + protected: + + /// Constructor + Control(const char *mnem, MachInst _machInst, OpClass __opClass) : + MipsStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + class CP0Control : public Control + { + protected: + + /// Constructor + CP0Control(const char *mnem, MachInst _machInst, OpClass __opClass) : + Control(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + class CP1Control : public Control + { + protected: + + /// Constructor + CP1Control(const char *mnem, MachInst _machInst, OpClass __opClass) : + Control(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + +}}; + +//Outputs to decoder.cc +output decoder {{ + std::string Control::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (mnemonic == "mfc0" || mnemonic == "mtc0") { + ccprintf(ss, "%-10s %d,%d,%d", mnemonic,RT,RD,SEL); + } else { + + // just print the first dest... if there's a second one, + // it's generally implicit + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + } + + ss << ", "; + + // just print the first two source regs... if there's + // a third one, it's a read-modify-write dest (Rc), + // e.g. for CMOVxx + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + + if (_numSrcRegs > 1) { + ss << ", "; + printReg(ss, _srcRegIdx[1]); + } + } + + return ss.str(); + } + + std::string CP0Control::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + ccprintf(ss, "%-10s r%d, r%d, %d", mnemonic, RT, RD, SEL); + return ss.str(); + } + + std::string CP1Control::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + ccprintf(ss, "%-10s r%d, f%d", mnemonic, RT, FS); + return ss.str(); + } + +}}; + +def format System(code, *flags) {{ + iop = InstObjParams(name, Name, 'Control', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format CP0Control(code, *flags) {{ + iop = InstObjParams(name, Name, 'CP0Control', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format CP1Control(code, *flags) {{ + iop = InstObjParams(name, Name, 'CP1Control', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + diff --git a/src/arch/mips/isa/formats/formats.isa b/src/arch/mips/isa/formats/formats.isa index 7d493ffae..4c3eec132 100644 --- a/src/arch/mips/isa/formats/formats.isa +++ b/src/arch/mips/isa/formats/formats.isa @@ -1,5 +1,33 @@ // -*- mode:c++ -*- +// 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 +// 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: Korey Sewell + //Templates from this format are used later //Include the basic format ##include "basic.isa" @@ -10,8 +38,8 @@ //Include utility functions ##include "util.isa" -//Include the cop0 formats -##include "cop0.isa" +//Include the control/cp0/cp1 formats +##include "control.isa" //Include the integer formats ##include "int.isa" @@ -22,6 +50,9 @@ //Include the mem format ##include "mem.isa" +//Include the mem format +##include "mt.isa" + //Include the trap format ##include "trap.isa" diff --git a/src/arch/mips/isa/formats/fp.isa b/src/arch/mips/isa/formats/fp.isa index 9f2c24755..d05b04d0e 100644 --- a/src/arch/mips/isa/formats/fp.isa +++ b/src/arch/mips/isa/formats/fp.isa @@ -1,5 +1,33 @@ // -*- mode:c++ -*- +// 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 +// 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: Korey Sewell + //////////////////////////////////////////////////////////////////// // // Floating Point operate instructions @@ -18,49 +46,264 @@ output header {{ { } - std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + //std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + //needs function to check for fpEnable or not + }; + + class FPCompareOp : public FPOp + { + protected: + FPCompareOp(const char *mnem, MachInst _machInst, OpClass __opClass) : FPOp(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; }}; output decoder {{ - std::string FPOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + std::string FPCompareOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { - return "Disassembly of integer instruction\n"; + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + ccprintf(ss,"%d",CC); + + if(_numSrcRegs > 0) { + ss << ", "; + printReg(ss, _srcRegIdx[0]); + } + + if(_numSrcRegs > 1) { + ss << ", "; + printReg(ss, _srcRegIdx[1]); + } + + return ss.str(); } }}; +output exec {{ -// Primary format for float operate instructions: -def format FloatOp(code, *flags) {{ - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) + //If any operand is Nan return the appropriate QNaN + template <class T> + bool + fpNanOperands(FPOp *inst, %(CPU_exec_context)s *xc, const T &src_type, + Trace::InstRecord *traceData) + { + uint64_t mips_nan = 0; + T src_op = 0; + int size = sizeof(src_op) * 8; + + for (int i = 0; i < inst->numSrcRegs(); i++) { + uint64_t src_bits = xc->readFloatRegBits(inst, 0, size); + + if (isNan(&src_bits, size) ) { + if (isSnan(&src_bits, size)) { + switch (size) + { + case 32: mips_nan = MIPS32_QNAN; break; + case 64: mips_nan = MIPS64_QNAN; break; + default: panic("Unsupported Floating Point Size (%d)", size); + } + } else { + mips_nan = src_bits; + } + + xc->setFloatRegBits(inst, 0, mips_nan, size); + if (traceData) { traceData->setData(mips_nan); } + return true; + } + } + return false; + } + + template <class T> + bool + fpInvalidOp(FPOp *inst, %(CPU_exec_context)s *cpu, const T dest_val, + Trace::InstRecord *traceData) + { + uint64_t mips_nan = 0; + T src_op = dest_val; + int size = sizeof(src_op) * 8; + + if (isNan(&src_op, size)) { + switch (size) + { + case 32: mips_nan = MIPS32_QNAN; break; + case 64: mips_nan = MIPS64_QNAN; break; + default: panic("Unsupported Floating Point Size (%d)", size); + } + + //Set value to QNAN + cpu->setFloatRegBits(inst, 0, mips_nan, size); + + //Read FCSR from FloatRegFile + uint32_t fcsr_bits = cpu->tc->readFloatRegBits(FCSR); + + //Write FCSR from FloatRegFile + cpu->tc->setFloatRegBits(FCSR, genInvalidVector(fcsr_bits)); + + if (traceData) { traceData->setData(mips_nan); } + return true; + } + + return false; + } + + void + fpResetCauseBits(%(CPU_exec_context)s *cpu) + { + //Read FCSR from FloatRegFile + uint32_t fcsr = cpu->tc->readFloatRegBits(FCSR); + + fcsr = bits(fcsr, 31, 18) << 18 | bits(fcsr, 11, 0); + + //Write FCSR from FloatRegFile + cpu->tc->setFloatRegBits(FCSR, fcsr); + } }}; -def format FloatCompareOp(code, *flags) {{ - code = 'bool cond;\n' + code - code += 'FCSR = makeCCVector(FCSR, CC,cond);\n' - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) +def template FloatingPointExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + + //When is the right time to reset cause bits? + //start of every instruction or every cycle? + fpResetCauseBits(xc); + + %(op_decl)s; + %(op_rd)s; + + //Check if any FP operand is a NaN value + if (!fpNanOperands((FPOp*)this, xc, Fd, traceData)) { + %(code)s; + + //Change this code for Full-System/Sycall Emulation + //separation + //---- + //Should Full System-Mode throw a fault here? + //---- + //Check for IEEE 754 FP Exceptions + //fault = fpNanOperands((FPOp*)this, xc, Fd, traceData); + if (!fpInvalidOp((FPOp*)this, xc, Fd, traceData) && + fault == NoFault) + { + %(op_wb)s; + } + } + + return fault; + } }}; -def format FloatCompareWithXcptOp(code, *flags) {{ - code = 'bool cond;\n' + code - code += 'FCSR = makeCCVector(FCSR, CC,cond);\n' - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) +// Primary format for float point operate instructions: +def format FloatOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'FPOp', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) + exec_output = FloatingPointExecute.subst(iop) +}}; + +def format FloatCompareOp(cond_code, *flags) {{ + import sys + + code = 'bool cond;\n' + if '.sf' in cond_code or 'SinglePrecision' in flags: + if 'QnanException' in flags: + code += 'if (isQnan(&Fs.sf, 32) || isQnan(&Ft.sf, 32)) {\n' + code += '\tFCSR = genInvalidVector(FCSR);\n' + code += '\treturn NoFault;' + code += '}\n else ' + code += 'if (isNan(&Fs.sf, 32) || isNan(&Ft.sf, 32)) {\n' + elif '.df' in cond_code or 'DoublePrecision' in flags: + if 'QnanException' in flags: + code += 'if (isQnan(&Fs.df, 64) || isQnan(&Ft.df, 64)) {\n' + code += '\tFCSR = genInvalidVector(FCSR);\n' + code += '\treturn NoFault;' + code += '}\n else ' + code += 'if (isNan(&Fs.df, 64) || isNan(&Ft.df, 64)) {\n' + else: + sys.exit('Decoder Failed: Can\'t Determine Operand Type\n') + + if 'UnorderedTrue' in flags: + code += 'cond = 1;\n' + elif 'UnorderedFalse' in flags: + code += 'cond = 0;\n' + else: + sys.exit('Decoder Failed: Float Compare Instruction Needs A Unordered Flag\n') + + code += '} else {\n' + code += cond_code + '}' + code += 'FCSR = genCCVector(FCSR, CC, cond);\n' + + iop = InstObjParams(name, Name, 'FPCompareOp', CodeBlock(code)) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) }}; def format FloatConvertOp(code, *flags) {{ - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) + import sys + + #Determine Source Type + convert = 'fpConvert(' + if '.sf' in code: + code = 'float ' + code + '\n' + convert += 'SINGLE_TO_' + elif '.df' in code: + code = 'double ' + code + '\n' + convert += 'DOUBLE_TO_' + elif '.uw' in code: + code = 'uint32_t ' + code + '\n' + convert += 'WORD_TO_' + elif '.ud' in code: + code = 'uint64_t ' + code + '\n' + convert += 'LONG_TO_' + else: + sys.exit("Error Determining Source Type for Conversion") + + #Determine Destination Type + if 'ToSingle' in flags: + code += 'Fd.uw = ' + convert + 'SINGLE, ' + elif 'ToDouble' in flags: + code += 'Fd.ud = ' + convert + 'DOUBLE, ' + elif 'ToWord' in flags: + code += 'Fd.uw = ' + convert + 'WORD, ' + elif 'ToLong' in flags: + code += 'Fd.ud = ' + convert + 'LONG, ' + else: + sys.exit("Error Determining Destination Type for Conversion") + + #Figure out how to round value + if 'Ceil' in flags: + code += 'ceil(val)); ' + elif 'Floor' in flags: + code += 'floor(val)); ' + elif 'Round' in flags: + code += 'roundFP(val, 0)); ' + elif 'Trunc' in flags: + code += 'truncFP(val));' + else: + code += 'val); ' + + iop = InstObjParams(name, Name, 'FPOp', CodeBlock(code)) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format FloatAccOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'FPOp', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -76,34 +319,51 @@ def format Float64Op(code, *flags) {{ exec_output = BasicExecute.subst(iop) }}; -def format Float64ConvertOp(code, *flags) {{ - code = 'bool cond;\n' + code - code += 'FCSR = makeCCVector(FCSR, CC,cond);\n' - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) -}}; +def format FloatPSCompareOp(cond_code1, cond_code2, *flags) {{ + import sys -def format FloatPSCompareOp(code, *flags) {{ - code = 'bool cond1;\nbool cond2;\n' + code - code += 'FCSR = makeCCVector(FCSR, CC+1, cond1);\n' - code += 'FCSR = makeCCVector(FCSR, CC, cond2);\n' - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) -}}; + code = 'bool cond1, cond2;\n' + code += 'bool code_block1, code_block2;\n' + code += 'code_block1 = code_block2 = true;\n' -def format FloatPSCompareWithXcptOp(code, *flags) {{ - code = 'bool cond1;\nbool cond2;\n' + code - code += 'FCSR = makeCCVector(FCSR, CC+1, cond1);\n' - code += 'FCSR = makeCCVector(FCSR, CC, cond2);\n' - iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) + if 'QnanException' in flags: + code += 'if (isQnan(&Fs1.sf, 32) || isQnan(&Ft1.sf, 32)) {\n' + code += '\tFCSR = genInvalidVector(FCSR);\n' + code += 'code_block1 = false;' + code += '}\n' + code += 'if (isQnan(&Fs2.sf, 32) || isQnan(&Ft2.sf, 32)) {\n' + code += '\tFCSR = genInvalidVector(FCSR);\n' + code += 'code_block2 = false;' + code += '}\n' + + code += 'if (code_block1) {' + code += '\tif (isNan(&Fs1.sf, 32) || isNan(&Ft1.sf, 32)) {\n' + if 'UnorderedTrue' in flags: + code += 'cond1 = 1;\n' + elif 'UnorderedFalse' in flags: + code += 'cond1 = 0;\n' + else: + sys.exit('Decoder Failed: Float Compare Instruction Needs A Unordered Flag\n') + code += '} else {\n' + code += cond_code1 + code += 'FCSR = genCCVector(FCSR, CC, cond1);}\n}\n' + + code += 'if (code_block2) {' + code += '\tif (isNan(&Fs2.sf, 32) || isNan(&Ft2.sf, 32)) {\n' + if 'UnorderedTrue' in flags: + code += 'cond2 = 1;\n' + elif 'UnorderedFalse' in flags: + code += 'cond2 = 0;\n' + else: + sys.exit('Decoder Failed: Float Compare Instruction Needs A Unordered Flag\n') + code += '} else {\n' + code += cond_code2 + code += 'FCSR = genCCVector(FCSR, CC, cond2);}\n}' + + iop = InstObjParams(name, Name, 'FPCompareOp', CodeBlock(code)) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) }}; + diff --git a/src/arch/mips/isa/formats/int.isa b/src/arch/mips/isa/formats/int.isa index 7d38b9ff5..7b5affb5c 100644 --- a/src/arch/mips/isa/formats/int.isa +++ b/src/arch/mips/isa/formats/int.isa @@ -1,11 +1,37 @@ // -*- mode:c++ -*- +// 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 +// 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: Korey Sewell + //////////////////////////////////////////////////////////////////// // // Integer operate instructions // - -//Outputs to decoder.hh output header {{ #include <iostream> using namespace std; @@ -25,6 +51,34 @@ output header {{ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; + + class HiLoOp: public IntOp + { + protected: + + /// Constructor + HiLoOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + IntOp(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + class HiLoMiscOp: public HiLoOp + { + protected: + + /// Constructor + HiLoMiscOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + HiLoOp(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + class IntImmOp : public MipsStaticInst { protected: @@ -52,6 +106,33 @@ output header {{ }}; +// HiLo<Misc> instruction class execute method template. +// Mainly to get instruction trace data to print out +// correctly +def template HiLoExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if(fault == NoFault) + { + %(op_wb)s; + //If there are 2 Destination Registers then + //concatenate the values for the traceData + if(traceData && _numDestRegs == 2) { + uint64_t hilo_final_val = (uint64_t)HI << 32 | LO; + traceData->setData(hilo_final_val); + } + } + return fault; + } +}}; + //Outputs to decoder.cc output decoder {{ std::string IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const @@ -64,7 +145,7 @@ output decoder {{ // it's generally implicit if (_numDestRegs > 0) { printReg(ss, _destRegIdx[0]); - ss << ","; + ss << ", "; } // just print the first two source regs... if there's @@ -75,13 +156,47 @@ output decoder {{ } if (_numSrcRegs > 1) { - ss << ","; + ss << ", "; + printReg(ss, _srcRegIdx[1]); + } + + return ss.str(); + } + + std::string HiLoOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + //Destination Registers are implicit for HI/LO ops + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + + if (_numSrcRegs > 1) { + ss << ", "; printReg(ss, _srcRegIdx[1]); } return ss.str(); } + std::string HiLoMiscOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numDestRegs > 0 && _destRegIdx[0] < 32) { + printReg(ss, _destRegIdx[0]); + } else if (_numSrcRegs > 0 && _srcRegIdx[0] < 32) { + printReg(ss, _srcRegIdx[0]); + } + + return ss.str(); + } + std::string IntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; @@ -92,15 +207,15 @@ output decoder {{ printReg(ss, _destRegIdx[0]); } - ss << ","; + ss << ", "; if (_numSrcRegs > 0) { printReg(ss, _srcRegIdx[0]); - ss << ","; + ss << ", "; } if( mnemonic == "lui") - ccprintf(ss, "%08p ", sextImm); + ccprintf(ss, "0x%x ", sextImm); else ss << (int) sextImm; @@ -109,23 +224,47 @@ output decoder {{ }}; -//Used by decoder.isa def format IntOp(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - - # Figure out if we are creating a IntImmOp or a IntOp - # by looking at the instruction name - iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags) - strlen = len(name) - if name[strlen-1] == 'i' or name[strlen-2:] == 'iu': - iop = InstObjParams(name, Name, 'IntImmOp', cblk, opt_flags) - - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = OperateNopCheckDecode.subst(iop) - exec_output = BasicExecute.subst(iop) + iop = InstObjParams(name, Name, 'IntOp', CodeBlock(code), opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = OperateNopCheckDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format IntImmOp(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'IntImmOp', CodeBlock(code), opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = OperateNopCheckDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format HiLoOp(code, *opt_flags) {{ + if '.sd' in code: + code = 'int64_t ' + code + elif '.ud' in code: + code = 'uint64_t ' + code + + code += 'HI = val<63:32>;\n' + code += 'LO = val<31:0>;\n' + + iop = InstObjParams(name, Name, 'HiLoOp', CodeBlock(code), opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = OperateNopCheckDecode.subst(iop) + exec_output = HiLoExecute.subst(iop) }}; +def format HiLoMiscOp(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'HiLoMiscOp', CodeBlock(code), opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = OperateNopCheckDecode.subst(iop) + exec_output = HiLoExecute.subst(iop) +}}; + + + diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa index d5436b308..f52247056 100644 --- a/src/arch/mips/isa/formats/mem.isa +++ b/src/arch/mips/isa/formats/mem.isa @@ -31,7 +31,7 @@ //////////////////////////////////////////////////////////////////// // -// Memory-format instructions: LoadAddress, Load, Store +// Memory-format instructions // output header {{ @@ -90,15 +90,6 @@ output decoder {{ }}; -def format LoadAddress(code) {{ - iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code)) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) -}}; - - def template LoadStoreDeclare {{ /** * Static instruction class for "%(mnemonic)s". @@ -426,8 +417,70 @@ def template StoreCompleteAcc {{ } }}; + +def template MiscMemAccExecute {{ + Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (fault == NoFault) { + %(code)s; + } + + return NoFault; + } +}}; + +def template MiscExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + return NoFault; + } +}}; + +def template MiscInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("Misc instruction does not support split access method!"); + return NoFault; + } +}}; + + +def template MiscCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("Misc instruction does not support split access method!"); + + return NoFault; + } +}}; + // load instructions use Rt as dest, so check for -// Rt == 31 to detect nops +// Rt == 0 to detect nops def template LoadNopCheckDecode {{ { MipsStaticInst *i = new %(class_name)s(machInst); @@ -446,7 +499,6 @@ def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, exec_template_base = 'Load') }}; - def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ @@ -454,26 +506,70 @@ def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, exec_template_base = 'Store') }}; -//FP loads are offloaded to these formats for now ... -def format LoadFloatMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, +def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }}, mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, - decode_template = BasicDecode, + decode_template = LoadNopCheckDecode, exec_template_base = 'Load') }}; +def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + exec_template_base = 'Store') +}}; + +def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }}, + mem_flags = [], inst_flags = []) {{ + decl_code = 'uint32_t mem_word = Mem.uw;\n' + decl_code += 'uint32_t unalign_addr = Rs + disp;\n' + decl_code += 'uint32_t byte_offset = unalign_addr & 3;\n' + decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n' + decl_code += '\tbyte_offset ^= 3;\n' + decl_code += '#endif\n' + + memacc_code = decl_code + memacc_code + + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Load') +}}; -def format StoreFloatMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, +def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }}, mem_flags = [], inst_flags = []) {{ + decl_code = 'uint32_t mem_word = 0;\n' + decl_code += 'uint32_t unaligned_addr = Rs + disp;\n' + decl_code += 'uint32_t byte_offset = unaligned_addr & 3;\n' + decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n' + decl_code += '\tbyte_offset ^= 3;\n' + decl_code += '#endif\n' + decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n' + memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n' + (header_output, decoder_output, decode_block, exec_output) = \ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, exec_template_base = 'Store') }}; +def format Prefetch(ea_code = {{ EA = Rs + disp; }}, + mem_flags = [], pf_flags = [], inst_flags = []) {{ + pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT'] + pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad', + 'IsDataPrefetch', 'MemReadOp'] + + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, + 'xc->prefetch(EA, memAccessFlags);', + pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc') + +}}; -def format UnalignedStore(memacc_code, postacc_code, - ea_code = {{ EA = Rb + disp; }}, +def format StoreCond(memacc_code, postacc_code, + ea_code = {{ EA = Rs + disp; }}, mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, diff --git a/src/arch/mips/isa/formats/mt.isa b/src/arch/mips/isa/formats/mt.isa new file mode 100644 index 000000000..521b01123 --- /dev/null +++ b/src/arch/mips/isa/formats/mt.isa @@ -0,0 +1,81 @@ +// -*- mode:c++ -*- + +// 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 +// 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: Korey Sewell + +//////////////////////////////////////////////////////////////////// +// +// MT instructions +// + +output header {{ + /** + * Base class for integer operations. + */ + class MT : public MipsStaticInst + { + protected: + + /// Constructor + MT(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + //Edit This Template When MT is Implemented + std::string MT::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return "Disassembly of MT instruction\n"; + } +}}; + +def template MTExecute {{ + //Edit This Template When MT is Implemented + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + //Write the resulting state to the execution context + %(op_wb)s; + + //Call into the trap handler with the appropriate fault + return No_Fault; + } +}}; + +// Primary format for integer operate instructions: +def format MipsMT() {{ + code = 'panic(\"Mips MT Is Currently Unimplemented.\");\n' + iop = InstObjParams(name, Name, 'MT', CodeBlock(code)) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/src/arch/mips/isa/formats/noop.isa b/src/arch/mips/isa/formats/noop.isa index 2aa4816e3..4fd8235e4 100644 --- a/src/arch/mips/isa/formats/noop.isa +++ b/src/arch/mips/isa/formats/noop.isa @@ -1,5 +1,33 @@ // -*- mode:c++ -*- +// 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 +// 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: Korey Sewell + //////////////////////////////////////////////////////////////////// // // Nop @@ -36,11 +64,7 @@ output decoder {{ std::string Nop::generateDisassembly(Addr pc, const SymbolTable *symtab) const { -#ifdef SS_COMPATIBLE_DISASSEMBLY - return originalDisassembly; -#else - return csprintf("%-10s (%s)", "nop", originalDisassembly); -#endif + return csprintf("%-10s %s", "nop", originalDisassembly); } /// Helper function for decoding nops. Substitute Nop object @@ -89,6 +113,6 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{ }}; def format Nop() {{ - decode_block = 'return new Nop(\"sll r0,r0,0\",machInst);\n' + decode_block = 'return new Nop(\"\",machInst);\n' }}; diff --git a/src/arch/mips/isa/formats/tlbop.isa b/src/arch/mips/isa/formats/tlbop.isa index f5e4076f2..75ab71c48 100644 --- a/src/arch/mips/isa/formats/tlbop.isa +++ b/src/arch/mips/isa/formats/tlbop.isa @@ -1,3 +1,33 @@ +// -*- mode:c++ -*- + +// 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 +// 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: Korey Sewell + //////////////////////////////////////////////////////////////////// // // TlbOp instructions @@ -30,13 +60,10 @@ output decoder {{ def template TlbOpExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { - //Call into the trap handler with the appropriate fault - return No_Fault; - } - //Write the resulting state to the execution context %(op_wb)s; + //Call into the trap handler with the appropriate fault return No_Fault; } }}; diff --git a/src/arch/mips/isa/formats/trap.isa b/src/arch/mips/isa/formats/trap.isa index 6884d4fa8..574b808cc 100644 --- a/src/arch/mips/isa/formats/trap.isa +++ b/src/arch/mips/isa/formats/trap.isa @@ -1,3 +1,33 @@ +// -*- mode:c++ -*- + +// 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 +// 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: Korey Sewell + //////////////////////////////////////////////////////////////////// // // Trap instructions @@ -23,27 +53,26 @@ output header {{ output decoder {{ std::string Trap::generateDisassembly(Addr pc, const SymbolTable *symtab) const { - return "Disassembly of integer instruction\n"; + return "Disassembly of trap instruction\n"; } }}; def template TrapExecute {{ + //Edit This Template When Traps Are Implemented Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { - //Call into the trap handler with the appropriate fault - return No_Fault; - } - //Write the resulting state to the execution context %(op_wb)s; + //Call into the trap handler with the appropriate fault return No_Fault; } }}; -// Primary format for integer operate instructions: def format Trap(code, *flags) {{ - code = 'bool cond;\n' + code; + code = 'panic(\"' + code += 'Trap Exception Handler Is Currently Not Implemented.' + code += '\");' iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/src/arch/mips/isa/formats/unimp.isa b/src/arch/mips/isa/formats/unimp.isa index 8e42da499..e17b5f832 100644 --- a/src/arch/mips/isa/formats/unimp.isa +++ b/src/arch/mips/isa/formats/unimp.isa @@ -1,5 +1,6 @@ // -*- mode:c++ -*- + // Copyright (c) 2003-2005 The Regents of The University of Michigan // All rights reserved. // @@ -103,11 +104,7 @@ output decoder {{ WarnUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab) const { -#ifdef SS_COMPATIBLE_DISASSEMBLY - return csprintf("%-10s", mnemonic); -#else return csprintf("%-10s (unimplemented)", mnemonic); -#endif } }}; @@ -127,7 +124,7 @@ output exec {{ Trace::InstRecord *traceData) const { if (!warned) { - warn("instruction '%s' unimplemented\n", mnemonic); + warn("\tinstruction '%s' unimplemented\n", mnemonic); warned = true; } @@ -146,28 +143,3 @@ def format WarnUnimpl() {{ decode_block = BasicDecodeWithMnemonic.subst(iop) }}; -output header {{ - /** - * Static instruction class for unknown (illegal) instructions. - * These cause simulator termination if they are executed in a - * non-speculative mode. This is a leaf class. - */ - class Unknown : public MipsStaticInst - { - public: - /// Constructor - Unknown(MachInst _machInst) - : MipsStaticInst("unknown", _machInst, No_OpClass) - { - // don't call execute() (which panics) if we're on a - // speculative path - flags[IsNonSpeculative] = true; - } - - %(BasicExecDeclare)s - - std::string - generateDisassembly(Addr pc, const SymbolTable *symtab) const; - }; -}}; - diff --git a/src/arch/mips/isa/formats/unknown.isa b/src/arch/mips/isa/formats/unknown.isa index 7c2275598..41387adca 100644 --- a/src/arch/mips/isa/formats/unknown.isa +++ b/src/arch/mips/isa/formats/unknown.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// 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 @@ -34,28 +34,31 @@ // output header {{ - std::string inst2string(MachInst machInst); -}}; -output decoder {{ - -std::string inst2string(MachInst machInst) -{ - string str = ""; - uint32_t mask = 0x80000000; - - for(int i=0; i < 32; i++) { - if ((machInst & mask) == 0) { - str += "0"; - } else { - str += "1"; + /** + * Static instruction class for unknown (illegal) instructions. + * These cause simulator termination if they are executed in a + * non-speculative mode. This is a leaf class. + */ + class Unknown : public MipsStaticInst + { + public: + /// Constructor + Unknown(MachInst _machInst) + : MipsStaticInst("unknown", _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; } - mask = mask >> 1; - } + %(BasicExecDeclare)s - return str; -} + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; +output decoder {{ std::string Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const { diff --git a/src/arch/mips/isa/formats/util.isa b/src/arch/mips/isa/formats/util.isa index 615160931..b67a02d07 100644 --- a/src/arch/mips/isa/formats/util.isa +++ b/src/arch/mips/isa/formats/util.isa @@ -1,5 +1,34 @@ // -*- mode:c++ -*- +// 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 +// 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: Steve Reinhardt +// Korey Sewell + let {{ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, postacc_code = '', base_class = 'Memory', @@ -90,7 +119,31 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + completeAccTemplate.subst(completeacc_iop)) }}; +output header {{ + std::string inst2string(MachInst machInst); +}}; + +output decoder {{ + +std::string inst2string(MachInst machInst) +{ + string str = ""; + uint32_t mask = 0x80000000; + + for(int i=0; i < 32; i++) { + if ((machInst & mask) == 0) { + str += "0"; + } else { + str += "1"; + } + mask = mask >> 1; + } + + return str; +} + +}}; output exec {{ using namespace MipsISA; @@ -124,6 +177,7 @@ output exec {{ #endif + }}; diff --git a/src/arch/mips/isa/includes.isa b/src/arch/mips/isa/includes.isa index 9c370fbe3..555cec255 100644 --- a/src/arch/mips/isa/includes.isa +++ b/src/arch/mips/isa/includes.isa @@ -1,3 +1,33 @@ +// -*- mode:c++ -*- + +// 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 +// 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: Korey Sewell + //////////////////////////////////////////////////////////////////// // // Output include file directives. @@ -16,9 +46,10 @@ output decoder {{ #include "arch/mips/isa_traits.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" -#include "cpu/exec_context.hh" // for Jump::branchTarget() +#include "cpu/thread_context.hh" #include "arch/mips/faults.hh" #include "arch/mips/isa_traits.hh" +#include "arch/mips/utility.hh" #include <math.h> #if defined(linux) @@ -31,6 +62,8 @@ using namespace MipsISA; output exec {{ #include "arch/mips/faults.hh" #include "arch/mips/isa_traits.hh" +#include "arch/mips/utility.hh" + #include <math.h> #if defined(linux) #include <fenv.h> diff --git a/src/arch/mips/isa/operands.isa b/src/arch/mips/isa/operands.isa index 0f9c74b48..316552ef4 100644 --- a/src/arch/mips/isa/operands.isa +++ b/src/arch/mips/isa/operands.isa @@ -1,3 +1,33 @@ +// -*- mode:c++ -*- + +// 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 +// 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: Korey Sewell + def operand_types {{ 'sb' : ('signed int', 8), 'ub' : ('unsigned int', 8), diff --git a/src/arch/mips/isa_traits.cc b/src/arch/mips/isa_traits.cc index 056c8baff..9f3817a60 100644 --- a/src/arch/mips/isa_traits.cc +++ b/src/arch/mips/isa_traits.cc @@ -42,6 +42,7 @@ using namespace std; void MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest) { + panic("Copy Regs Not Implemented Yet\n"); /*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag); uniq = xc->readMiscReg(MipsISA::Uniq_DepTag); lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag); @@ -55,6 +56,7 @@ MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest) void MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc) { + panic("Copy Misc. Regs Not Implemented Yet\n"); /*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag); uniq = xc->readMiscReg(MipsISA::Uniq_DepTag); lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag); @@ -63,77 +65,6 @@ MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc) #endif*/ } -uint64_t -MipsISA::fpConvert(double fp_val, ConvertType cvt_type) -{ - - switch (cvt_type) - { - case SINGLE_TO_DOUBLE: - double sdouble_val = fp_val; - void *sdouble_ptr = &sdouble_val; - uint64_t sdp_bits = *(uint64_t *) sdouble_ptr; - return sdp_bits; - - case SINGLE_TO_WORD: - int32_t sword_val = (int32_t) fp_val; - void *sword_ptr = &sword_val; - uint64_t sword_bits= *(uint32_t *) sword_ptr; - return sword_bits; - - case WORD_TO_SINGLE: - float wfloat_val = fp_val; - void *wfloat_ptr = &wfloat_val; - uint64_t wfloat_bits = *(uint32_t *) wfloat_ptr; - return wfloat_bits; - - case WORD_TO_DOUBLE: - double wdouble_val = fp_val; - void *wdouble_ptr = &wdouble_val; - uint64_t wdp_bits = *(uint64_t *) wdouble_ptr; - return wdp_bits; - - default: - panic("Invalid Floating Point Conversion Type (%d). See \"types.hh\" for List of Conversions\n",cvt_type); - return 0; - } -} - -double -MipsISA::roundFP(double val, int digits) -{ - double digit_offset = pow(10.0,digits); - val = val * digit_offset; - val = val + 0.5; - val = floor(val); - val = val / digit_offset; - return val; -} - -double -MipsISA::truncFP(double val) -{ - int trunc_val = (int) val; - return (double) trunc_val; -} - -bool -MipsISA::getFPConditionCode(uint32_t fcsr_reg, int cc) -{ - //uint32_t cc_bits = xc->readFloatReg(35); - return false;//regFile.floatRegfile.getConditionCode(cc); -} - -uint32_t -MipsISA::makeCCVector(uint32_t fcsr, int num, bool val) -{ - int shift = (num == 0) ? 22 : num + 23; - - fcsr = fcsr | (val << shift); - - return fcsr; -} - #if FULL_SYSTEM static inline Addr diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index 4a919ac27..17e735527 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -135,7 +135,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 15 */ SyscallDesc("chmod", chmodFunc<MipsLinux>), /* 16 */ SyscallDesc("lchown", chownFunc), - /* 17 */ SyscallDesc("break", obreakFunc), /*obreak*/ + /* 17 */ SyscallDesc("break", obreakFunc), /* 18 */ SyscallDesc("unused#18", unimplementedFunc), /* 19 */ SyscallDesc("lseek", lseekFunc), /* 20 */ SyscallDesc("getpid", getpidFunc), @@ -163,7 +163,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 42 */ SyscallDesc("pipe", unimplementedFunc), /* 43 */ SyscallDesc("times", unimplementedFunc), /* 44 */ SyscallDesc("prof", unimplementedFunc), - /* 45 */ SyscallDesc("brk", obreakFunc),/*openFunc<MipsLinux>*/ + /* 45 */ SyscallDesc("brk", obreakFunc), /* 46 */ SyscallDesc("setgid", unimplementedFunc), /* 47 */ SyscallDesc("getgid", getgidFunc), /* 48 */ SyscallDesc("signal", ignoreFunc), @@ -173,7 +173,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 52 */ SyscallDesc("umount2", unimplementedFunc), /* 53 */ SyscallDesc("lock", unimplementedFunc), /* 54 */ SyscallDesc("ioctl", ioctlFunc<MipsLinux>), - /* 55 */ SyscallDesc("fcntl", unimplementedFunc), + /* 55 */ SyscallDesc("fcntl", fcntlFunc), /* 56 */ SyscallDesc("mpx", unimplementedFunc), /* 57 */ SyscallDesc("setpgid", unimplementedFunc), /* 58 */ SyscallDesc("ulimit", unimplementedFunc), @@ -210,8 +210,8 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 89 */ SyscallDesc("readdir", unimplementedFunc), /* 90 */ SyscallDesc("mmap", mmapFunc<MipsLinux>), /* 91 */ SyscallDesc("munmap",munmapFunc), - /* 92 */ SyscallDesc("truncate", fcntlFunc), - /* 93 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 92 */ SyscallDesc("truncate", truncateFunc), + /* 93 */ SyscallDesc("ftruncate", ftruncateFunc), /* 94 */ SyscallDesc("fchmod", unimplementedFunc), /* 95 */ SyscallDesc("fchown", unimplementedFunc), /* 96 */ SyscallDesc("getpriority", unimplementedFunc), @@ -262,7 +262,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 141 */ SyscallDesc("getdents", unimplementedFunc), /* 142 */ SyscallDesc("newselect", unimplementedFunc), /* 143 */ SyscallDesc("flock", unimplementedFunc), - /* 144 */ SyscallDesc("msync", unimplementedFunc),/*getrlimitFunc<MipsLinux>*/ + /* 144 */ SyscallDesc("msync", unimplementedFunc), /* 145 */ SyscallDesc("readv", unimplementedFunc), /* 146 */ SyscallDesc("writev", writevFunc<MipsLinux>), /* 147 */ SyscallDesc("cacheflush", unimplementedFunc), @@ -338,7 +338,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 217 */ SyscallDesc("mincore", unimplementedFunc), /* 218 */ SyscallDesc("madvise", unimplementedFunc), /* 219 */ SyscallDesc("getdents64", unimplementedFunc), - /* 220 */ SyscallDesc("fcntl64", fcntlFunc), + /* 220 */ SyscallDesc("fcntl64", fcntl64Func), /* 221 */ SyscallDesc("reserved#221", unimplementedFunc), /* 222 */ SyscallDesc("gettid", unimplementedFunc), /* 223 */ SyscallDesc("readahead", unimplementedFunc), @@ -414,9 +414,7 @@ MipsLinuxProcess::MipsLinuxProcess(const std::string &name, : MipsLiveProcess(name, objFile, system, stdin_fd, stdout_fd, stderr_fd, argv, envp), Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) -{ - //init_regs->intRegFile[0] = 0; -} +{ } SyscallDesc* MipsLinuxProcess::getDesc(int callnum) diff --git a/src/arch/mips/linux/process.hh b/src/arch/mips/linux/process.hh index 2c2dadc8b..68da3227b 100644 --- a/src/arch/mips/linux/process.hh +++ b/src/arch/mips/linux/process.hh @@ -24,8 +24,6 @@ * 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: Korey Sewell */ #ifndef __MIPS_LINUX_PROCESS_HH__ diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc index bd7aa394e..7762c2fa0 100644 --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -27,74 +27,38 @@ * * Authors: Gabe Black * Ali Saidi + * Korey Sewell */ #include "arch/mips/isa_traits.hh" #include "arch/mips/process.hh" -#include "arch/mips/linux/process.hh" #include "base/loader/object_file.hh" #include "base/misc.hh" #include "cpu/thread_context.hh" -#include "sim/builder.hh" #include "sim/system.hh" using namespace std; using namespace MipsISA; - -MipsLiveProcess * -MipsLiveProcess::create(const std::string &nm, System *system, int stdin_fd, - int stdout_fd, int stderr_fd, std::string executable, - std::vector<std::string> &argv, std::vector<std::string> &envp) -{ - MipsLiveProcess *process = NULL; - - ObjectFile *objFile = createObjectFile(executable); - if (objFile == NULL) { - fatal("Can't load object file %s", executable); - } - - - if (objFile->getArch() != ObjectFile::Mips) - fatal("Object file does not match architecture."); - switch (objFile->getOpSys()) { - case ObjectFile::Linux: - process = new MipsLinuxProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp); - break; - - default: - fatal("Unknown/unsupported operating system."); - } - - if (process == NULL) - fatal("Unknown error creating process object."); - return process; -} - MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile, System *_system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp) : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd, argv, envp) { + // Set up stack. On MIPS, stack starts at the top of kuseg + // user address space. MIPS stack grows down from here + stack_base = 0x7FFFFFFF; - // XXX all the below need to be updated for SPARC - Ali + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); + + // Set up break point (Top of Heap) brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); brk_point = roundUp(brk_point, VMPageSize); - // Set up stack. On Alpha, stack goes below text section. This - // code should get moved to some architecture-specific spot. - stack_base = objFile->textBase() - (409600+4096); - - // Set up region for mmaps. Tru64 seems to start just above 0 and - // grow up from there. + // Set up region for mmaps. For now, start at bottom of kuseg space. mmap_start = mmap_end = 0x10000; - - // Set pointer for next thread stack. Reserve 8M for main stack. - next_thread_stack_base = stack_base - (8 * 1024 * 1024); - } void @@ -102,63 +66,3 @@ MipsLiveProcess::startup() { argsInit(MachineBytes, VMPageSize); } - - - - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(MipsLiveProcess) - - VectorParam<string> cmd; - Param<string> executable; - Param<string> input; - Param<string> output; - VectorParam<string> env; - SimObjectParam<System *> system; - -END_DECLARE_SIM_OBJECT_PARAMS(MipsLiveProcess) - - -BEGIN_INIT_SIM_OBJECT_PARAMS(MipsLiveProcess) - - INIT_PARAM(cmd, "command line (executable plus arguments)"), - INIT_PARAM(executable, "executable (overrides cmd[0] if set)"), - INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"), - INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"), - INIT_PARAM(env, "environment settings"), - INIT_PARAM(system, "system") - -END_INIT_SIM_OBJECT_PARAMS(MipsLiveProcess) - - -CREATE_SIM_OBJECT(MipsLiveProcess) -{ - string in = input; - string out = output; - - // initialize file descriptors to default: same as simulator - int stdin_fd, stdout_fd, stderr_fd; - - if (in == "stdin" || in == "cin") - stdin_fd = STDIN_FILENO; - else - stdin_fd = Process::openInputFile(input); - - if (out == "stdout" || out == "cout") - stdout_fd = STDOUT_FILENO; - else if (out == "stderr" || out == "cerr") - stdout_fd = STDERR_FILENO; - else - stdout_fd = Process::openOutputFile(out); - - stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; - - return MipsLiveProcess::create(getInstanceName(), system, - stdin_fd, stdout_fd, stderr_fd, - (string)executable == "" ? cmd[0] : executable, - cmd, env); -} - - -REGISTER_SIM_OBJECT("MipsLiveProcess", MipsLiveProcess) - - diff --git a/src/arch/mips/process.hh b/src/arch/mips/process.hh index 45513af46..b0ef20399 100644 --- a/src/arch/mips/process.hh +++ b/src/arch/mips/process.hh @@ -27,6 +27,7 @@ * * Authors: Gabe Black * Ali Saidi + * Korey Sewell */ #ifndef __MIPS_PROCESS_HH__ @@ -49,18 +50,6 @@ class MipsLiveProcess : public LiveProcess std::vector<std::string> &envp); void startup(); - - public: - // this function is used to create the LiveProcess object, since - // we can't tell which subclass of LiveProcess to use until we - // open and look at the object file. - static MipsLiveProcess *create(const std::string &nm, - System *_system, - int stdin_fd, int stdout_fd, int stderr_fd, - std::string executable, - std::vector<std::string> &argv, - std::vector<std::string> &envp); - }; diff --git a/src/arch/mips/regfile/float_regfile.hh b/src/arch/mips/regfile/float_regfile.hh index 013aa01c7..d1a60298a 100644 --- a/src/arch/mips/regfile/float_regfile.hh +++ b/src/arch/mips/regfile/float_regfile.hh @@ -62,13 +62,17 @@ namespace MipsISA switch(width) { case SingleWidth: - void *float_ptr = ®s[floatReg]; - return *(float *) float_ptr; + { + void *float_ptr = ®s[floatReg]; + return *(float *) float_ptr; + } case DoubleWidth: - uint64_t double_val = (FloatReg64)regs[floatReg + 1] << 32 | regs[floatReg]; - void *double_ptr = &double_val; - return *(double *) double_ptr; + { + uint64_t double_val = (FloatReg64)regs[floatReg + 1] << 32 | regs[floatReg]; + void *double_ptr = &double_val; + return *(double *) double_ptr; + } default: panic("Attempted to read a %d bit floating point register!", width); @@ -99,21 +103,24 @@ namespace MipsISA Fault setReg(int floatReg, const FloatReg &val, int width) { - switch(width) { case SingleWidth: - float temp = val; - void *float_ptr = &temp; - regs[floatReg] = *(FloatReg32 *) float_ptr; - break; + { + float temp = val; + void *float_ptr = &temp; + regs[floatReg] = *(FloatReg32 *) float_ptr; + break; + } case DoubleWidth: - const void *double_ptr = &val; - FloatReg64 temp_double = *(FloatReg64 *) double_ptr; - regs[floatReg + 1] = temp_double >> 32; - regs[floatReg] = temp_double; - break; + { + const void *double_ptr = &val; + FloatReg64 temp_double = *(FloatReg64 *) double_ptr; + regs[floatReg + 1] = temp_double >> 32; + regs[floatReg] = 0x0000FFFF & temp_double; + break; + } default: panic("Attempted to read a %d bit floating point register!", width); @@ -148,14 +155,6 @@ namespace MipsISA void unserialize(Checkpoint *cp, const std::string §ion); }; - enum MiscFloatRegNums { - FIR = NumFloatArchRegs, - FCCR, - FEXR, - FENR, - FCSR - }; - } // namespace MipsISA #endif diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc new file mode 100644 index 000000000..e7455fdbf --- /dev/null +++ b/src/arch/mips/utility.cc @@ -0,0 +1,202 @@ +/* + * 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 + * 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: Korey Sewell + */ + +#include "arch/mips/isa_traits.hh" +#include "arch/mips/utility.hh" +#include "config/full_system.hh" +#include "cpu/static_inst.hh" +#include "sim/serialize.hh" +#include "base/bitfield.hh" + +using namespace MipsISA; +using namespace std; + +uint64_t +MipsISA::fpConvert(ConvertType cvt_type, double fp_val) +{ + + switch (cvt_type) + { + case SINGLE_TO_DOUBLE: + { + double sdouble_val = fp_val; + void *sdouble_ptr = &sdouble_val; + uint64_t sdp_bits = *(uint64_t *) sdouble_ptr; + return sdp_bits; + } + + case SINGLE_TO_WORD: + { + int32_t sword_val = (int32_t) fp_val; + void *sword_ptr = &sword_val; + uint64_t sword_bits= *(uint32_t *) sword_ptr; + return sword_bits; + } + + case WORD_TO_SINGLE: + { + float wfloat_val = fp_val; + void *wfloat_ptr = &wfloat_val; + uint64_t wfloat_bits = *(uint32_t *) wfloat_ptr; + return wfloat_bits; + } + + case WORD_TO_DOUBLE: + { + double wdouble_val = fp_val; + void *wdouble_ptr = &wdouble_val; + uint64_t wdp_bits = *(uint64_t *) wdouble_ptr; + return wdp_bits; + } + + default: + panic("Invalid Floating Point Conversion Type (%d). See \"types.hh\" for List of Conversions\n",cvt_type); + return 0; + } +} + +double +MipsISA::roundFP(double val, int digits) +{ + double digit_offset = pow(10.0,digits); + val = val * digit_offset; + val = val + 0.5; + val = floor(val); + val = val / digit_offset; + return val; +} + +double +MipsISA::truncFP(double val) +{ + int trunc_val = (int) val; + return (double) trunc_val; +} + +bool +MipsISA::getCondCode(uint32_t fcsr, int cc_idx) +{ + int shift = (cc_idx == 0) ? 23 : cc_idx + 24; + bool cc_val = (fcsr >> shift) & 0x00000001; + return cc_val; +} + +uint32_t +MipsISA::genCCVector(uint32_t fcsr, int cc_num, uint32_t cc_val) +{ + int cc_idx = (cc_num == 0) ? 23 : cc_num + 24; + + fcsr = bits(fcsr, 31, cc_idx + 1) << cc_idx + 1 | + cc_val << cc_idx | + bits(fcsr, cc_idx - 1, 0); + + return fcsr; +} + +uint32_t +MipsISA::genInvalidVector(uint32_t fcsr_bits) +{ + //Set FCSR invalid in "flag" field + int invalid_offset = Invalid + Flag_Field; + fcsr_bits = fcsr_bits | (1 << invalid_offset); + + //Set FCSR invalid in "cause" flag + int cause_offset = Invalid + Cause_Field; + fcsr_bits = fcsr_bits | (1 << cause_offset); + + return fcsr_bits; +} + +bool +MipsISA::isNan(void *val_ptr, int size) +{ + switch (size) + { + case 32: + { + uint32_t val_bits = *(uint32_t *) val_ptr; + return (bits(val_bits, 30, 23) == 0xFF); + } + + case 64: + { + uint64_t val_bits = *(uint64_t *) val_ptr; + return (bits(val_bits, 62, 52) == 0x7FF); + } + + default: + panic("Type unsupported. Size mismatch\n"); + } +} + + +bool +MipsISA::isQnan(void *val_ptr, int size) +{ + switch (size) + { + case 32: + { + uint32_t val_bits = *(uint32_t *) val_ptr; + return (bits(val_bits, 30, 22) == 0x1FE); + } + + case 64: + { + uint64_t val_bits = *(uint64_t *) val_ptr; + return (bits(val_bits, 62, 51) == 0xFFE); + } + + default: + panic("Type unsupported. Size mismatch\n"); + } +} + +bool +MipsISA::isSnan(void *val_ptr, int size) +{ + switch (size) + { + case 32: + { + uint32_t val_bits = *(uint32_t *) val_ptr; + return (bits(val_bits, 30, 22) == 0x1FF); + } + + case 64: + { + uint64_t val_bits = *(uint64_t *) val_ptr; + return (bits(val_bits, 62, 51) == 0xFFF); + } + + default: + panic("Type unsupported. Size mismatch\n"); + } +} diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index 5c7dc3ea4..c5c69ddcd 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -39,6 +39,19 @@ namespace MipsISA { + //Floating Point Utility Functions + uint64_t fpConvert(ConvertType cvt_type, double fp_val); + double roundFP(double val, int digits); + double truncFP(double val); + + bool getCondCode(uint32_t fcsr, int cc); + uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val); + uint32_t genInvalidVector(uint32_t fcsr); + + bool isNan(void *val_ptr, int size); + bool isQnan(void *val_ptr, int size); + bool isSnan(void *val_ptr, int size); }; + #endif diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 57b4d4d86..2af242bd8 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -249,7 +249,7 @@ void SparcFault::invoke(ThreadContext * tc) void TrapInstruction::invoke(ThreadContext * tc) { - tc->syscall(syscall_num); + // Should be handled in ISA. } #endif diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index 762de243a..40afb3722 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -48,7 +48,7 @@ output header {{ output decoder {{ #include "base/cprintf.hh" #include "base/loader/symtab.hh" -#include "cpu/exec_context.hh" // for Jump::branchTarget() +#include "cpu/thread_context.hh" // for Jump::branchTarget() #include <math.h> #if defined(linux) diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 633c202ca..75f01e038 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -31,56 +31,16 @@ #include "arch/sparc/isa_traits.hh" #include "arch/sparc/process.hh" -#include "arch/sparc/linux/process.hh" -#include "arch/sparc/solaris/process.hh" #include "base/loader/object_file.hh" #include "base/misc.hh" #include "cpu/thread_context.hh" #include "mem/page_table.hh" #include "mem/translating_port.hh" -#include "sim/builder.hh" #include "sim/system.hh" using namespace std; using namespace SparcISA; -SparcLiveProcess * -SparcLiveProcess::create(const std::string &nm, System *system, int stdin_fd, - int stdout_fd, int stderr_fd, std::string executable, - std::vector<std::string> &argv, std::vector<std::string> &envp) -{ - SparcLiveProcess *process = NULL; - - ObjectFile *objFile = createObjectFile(executable); - if (objFile == NULL) { - fatal("Can't load object file %s", executable); - } - - - if (objFile->getArch() != ObjectFile::SPARC) - fatal("Object file with arch %x does not match architecture %x.", - objFile->getArch(), ObjectFile::SPARC); - switch (objFile->getOpSys()) { - case ObjectFile::Linux: - process = new SparcLinuxProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp); - break; - - - case ObjectFile::Solaris: - process = new SparcSolarisProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp); - break; - default: - fatal("Unknown/unsupported operating system."); - } - - if (process == NULL) - fatal("Unknown error creating process object."); - return process; -} SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile, System *_system, int stdin_fd, int stdout_fd, int stderr_fd, @@ -322,61 +282,3 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) // num_processes++; } - - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcLiveProcess) - - VectorParam<string> cmd; - Param<string> executable; - Param<string> input; - Param<string> output; - VectorParam<string> env; - SimObjectParam<System *> system; - -END_DECLARE_SIM_OBJECT_PARAMS(SparcLiveProcess) - - -BEGIN_INIT_SIM_OBJECT_PARAMS(SparcLiveProcess) - - INIT_PARAM(cmd, "command line (executable plus arguments)"), - INIT_PARAM(executable, "executable (overrides cmd[0] if set)"), - INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"), - INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"), - INIT_PARAM(env, "environment settings"), - INIT_PARAM(system, "system") - -END_INIT_SIM_OBJECT_PARAMS(SparcLiveProcess) - - -CREATE_SIM_OBJECT(SparcLiveProcess) -{ - string in = input; - string out = output; - - // initialize file descriptors to default: same as simulator - int stdin_fd, stdout_fd, stderr_fd; - - if (in == "stdin" || in == "cin") - stdin_fd = STDIN_FILENO; - else - stdin_fd = Process::openInputFile(input); - - if (out == "stdout" || out == "cout") - stdout_fd = STDOUT_FILENO; - else if (out == "stderr" || out == "cerr") - stdout_fd = STDERR_FILENO; - else - stdout_fd = Process::openOutputFile(out); - - stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; - - return SparcLiveProcess::create(getInstanceName(), system, - stdin_fd, stdout_fd, stderr_fd, - (string)executable == "" ? cmd[0] : executable, - cmd, env); -} - - -REGISTER_SIM_OBJECT("SparcLiveProcess", SparcLiveProcess) - - diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index db5e64352..7ba8d7109 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -65,15 +65,6 @@ class SparcLiveProcess : public LiveProcess void startup(); public: - // this function is used to create the LiveProcess object, since - // we can't tell which subclass of LiveProcess to use until we - // open and look at the object file. - static SparcLiveProcess *create(const std::string &nm, - System *_system, - int stdin_fd, int stdout_fd, int stderr_fd, - std::string executable, - std::vector<std::string> &argv, - std::vector<std::string> &envp); void argsInit(int intSize, int pageSize); diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index aaf1fcf24..cbeb3c7b9 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -61,8 +61,7 @@ namespace SparcISA const int HprStart = 64; const int MiscStart = 96; - - const uint64_t Bit64 = 0x8000000000000000; + const uint64_t Bit64 = (1ULL << 63); class IntRegFile { @@ -245,17 +244,22 @@ namespace SparcISA //In each of these cases, we have to copy the value into a temporary //variable. This is because we may otherwise try to access an //unaligned portion of memory. + + uint32_t result32; + uint64_t result64; switch(width) { case SingleWidth: - uint32_t result32 = gtoh((uint32_t)val); + result32 = gtoh((uint32_t)val); memcpy(regSpace + 4 * floatReg, &result32, width); + break; case DoubleWidth: - uint64_t result64 = gtoh((uint64_t)val); + result64 = gtoh((uint64_t)val); memcpy(regSpace + 4 * floatReg, &result64, width); + break; case QuadWidth: - uint64_t result128 = gtoh((uint64_t)val); - memcpy(regSpace + 4 * floatReg, &result128, width); + panic("Quad width FP not implemented."); + break; default: panic("Attempted to read a %d bit floating point register!", width); } @@ -267,17 +271,21 @@ namespace SparcISA //In each of these cases, we have to copy the value into a temporary //variable. This is because we may otherwise try to access an //unaligned portion of memory. + uint32_t result32; + uint64_t result64; switch(width) { case SingleWidth: - uint32_t result32 = gtoh((uint32_t)val); + result32 = gtoh((uint32_t)val); memcpy(regSpace + 4 * floatReg, &result32, width); + break; case DoubleWidth: - uint64_t result64 = gtoh((uint64_t)val); + result64 = gtoh((uint64_t)val); memcpy(regSpace + 4 * floatReg, &result64, width); + break; case QuadWidth: - uint64_t result128 = gtoh((uint64_t)val); - memcpy(regSpace + 4 * floatReg, &result128, width); + panic("Quad width FP not implemented."); + break; default: panic("Attempted to read a %d bit floating point register!", width); } diff --git a/src/base/statistics.cc b/src/base/statistics.cc index 03c6b5196..2acef83c5 100644 --- a/src/base/statistics.cc +++ b/src/base/statistics.cc @@ -43,7 +43,6 @@ #include "base/time.hh" #include "base/trace.hh" #include "base/stats/statdb.hh" -#include "config/stats_binning.hh" using namespace std; @@ -174,12 +173,6 @@ FormulaBase::size() const return root->size(); } -bool -FormulaBase::binned() const -{ - return root && root->binned(); -} - void FormulaBase::reset() { @@ -238,33 +231,6 @@ Formula::operator+=(Temp r) return *this; } -MainBin::MainBin(const string &name) - : _name(name), mem(NULL), memsize(-1) -{ - Database::regBin(this, name); -} - -MainBin::~MainBin() -{ - if (mem) - delete [] mem; -} - -char * -MainBin::memory(off_t off) -{ - if (memsize == -1) - memsize = ceilPow2((size_t) offset()); - - if (!mem) { - mem = new char[memsize]; - memset(mem, 0, memsize); - } - - assert(offset() <= size()); - return mem + off; -} - void check() { @@ -287,13 +253,6 @@ check() Database::stats().sort(StatData::less); -#if STATS_BINNING - if (MainBin::curBin() == NULL) { - static MainBin mainBin("main bin"); - mainBin.activate(); - } -#endif - if (i == end) return; @@ -313,39 +272,14 @@ CallbackQueue resetQueue; void reset() { - // reset non-binned stats Database::stat_list_t::iterator i = Database::stats().begin(); Database::stat_list_t::iterator end = Database::stats().end(); while (i != end) { StatData *data = *i; - if (!data->binned()) - data->reset(); + data->reset(); ++i; } - // save the bin so we can go back to where we were - MainBin *orig = MainBin::curBin(); - - // reset binned stats - Database::bin_list_t::iterator bi = Database::bins().begin(); - Database::bin_list_t::iterator be = Database::bins().end(); - while (bi != be) { - MainBin *bin = *bi; - bin->activate(); - - i = Database::stats().begin(); - while (i != end) { - StatData *data = *i; - if (data->binned()) - data->reset(); - ++i; - } - ++bi; - } - - // restore bin - MainBin::curBin() = orig; - resetQueue.process(); } diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 84a323071..59f219c07 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -60,11 +60,9 @@ #include "base/intmath.hh" #include "base/refcnt.hh" #include "base/str.hh" -#include "base/stats/bin.hh" #include "base/stats/flags.hh" #include "base/stats/visit.hh" #include "base/stats/types.hh" -#include "config/stats_binning.hh" #include "sim/host.hh" class Callback; @@ -103,11 +101,6 @@ struct StatData virtual ~StatData(); /** - * @return true if the stat is binned. - */ - virtual bool binned() const = 0; - - /** * Reset the corresponding stat to the default state. */ virtual void reset() = 0; @@ -160,7 +153,6 @@ class ScalarStatData : public ScalarData public: ScalarStatData(Stat &stat) : s(stat) {} - virtual bool binned() const { return s.binned(); } virtual bool check() const { return s.check(); } virtual Counter value() const { return s.value(); } virtual Result result() const { return s.result(); } @@ -203,7 +195,6 @@ class VectorStatData : public VectorData public: VectorStatData(Stat &stat) : s(stat) {} - virtual bool binned() const { return s.binned(); } virtual bool check() const { return s.check(); } virtual bool zero() const { return s.zero(); } virtual void reset() { s.reset(); } @@ -261,7 +252,6 @@ class DistStatData : public DistData public: DistStatData(Stat &stat) : s(stat) {} - virtual bool binned() const { return s.binned(); } virtual bool check() const { return s.check(); } virtual void reset() { s.reset(); } virtual bool zero() const { return s.zero(); } @@ -300,12 +290,10 @@ class VectorDistStatData : public VectorDistData { protected: Stat &s; - typedef typename Stat::bin_t bin_t; public: VectorDistStatData(Stat &stat) : s(stat) {} - virtual bool binned() const { return bin_t::binned; } virtual bool check() const { return s.check(); } virtual void reset() { s.reset(); } virtual size_t size() const { return s.size(); } @@ -342,12 +330,10 @@ class Vector2dStatData : public Vector2dData { protected: Stat &s; - typedef typename Stat::bin_t bin_t; public: Vector2dStatData(Stat &stat) : s(stat) {} - virtual bool binned() const { return bin_t::binned; } virtual bool check() const { return s.check(); } virtual void reset() { s.reset(); } virtual bool zero() const { return s.zero(); } @@ -359,7 +345,6 @@ class Vector2dStatData : public Vector2dData } }; - class DataAccess { protected: @@ -615,22 +600,16 @@ struct StatStor * changes. This allows the quick calculation of a per cycle count of the item * being watched. This is good for keeping track of residencies in structures * among other things. - * @todo add lateny to the stat and fix binning. */ struct AvgStor { public: /** The paramaters for this storage type */ - struct Params - { - /** - * The current count. We stash this here because the current - * value is not a binned value. - */ - Counter current; - }; + struct Params { }; private: + /** The current count. */ + Counter current; /** The total count for all cycles. */ mutable Result total; /** The cycle that current last changed. */ @@ -640,7 +619,7 @@ struct AvgStor /** * Build and initializes this stat storage. */ - AvgStor(Params &p) : total(0), last(0) { p.current = Counter(); } + AvgStor(Params &p) : current(0), total(0), last(0) { } /** * Set the current count to the one provided, update the total and last @@ -649,9 +628,9 @@ struct AvgStor * @param p The parameters for this storage. */ void set(Counter val, Params &p) { - total += p.current * (curTick - last); + total += current * (curTick - last); last = curTick; - p.current = val; + current = val; } /** @@ -659,21 +638,21 @@ struct AvgStor * @param val The amount to increment. * @param p The parameters for this storage. */ - void inc(Counter val, Params &p) { set(p.current + val, p); } + void inc(Counter val, Params &p) { set(current + val, p); } /** * Deccrement the current count by the provided value, calls set. * @param val The amount to decrement. * @param p The parameters for this storage. */ - void dec(Counter val, Params &p) { set(p.current - val, p); } + void dec(Counter val, Params &p) { set(current - val, p); } /** * Return the current count. * @param p The parameters for this storage. * @return The current count. */ - Counter value(const Params &p) const { return p.current; } + Counter value(const Params &p) const { return current; } /** * Return the current average. @@ -682,9 +661,9 @@ struct AvgStor */ Result result(const Params &p) const { - total += p.current * (curTick - last); + total += current * (curTick - last); last = curTick; - return (Result)(total + p.current) / (Result)(curTick + 1); + return (Result)(total + current) / (Result)(curTick + 1); } /** @@ -704,39 +683,53 @@ struct AvgStor /** * Implementation of a scalar stat. The type of stat is determined by the - * Storage template. The storage for this stat is held within the Bin class. - * This allows for breaking down statistics across multiple bins easily. + * Storage template. */ -template <class Storage, class Bin> +template <class Stor> class ScalarBase : public DataAccess { public: + typedef Stor Storage; + /** Define the params of the storage class. */ - typedef typename Storage::Params params_t; - /** Define the bin type. */ - typedef typename Bin::template Bin<Storage> bin_t; + typedef typename Storage::Params Params; protected: - /** The bin of this stat. */ - bin_t bin; + /** The storage of this stat. */ + char storage[sizeof(Storage)]; + /** The parameters for this stat. */ - params_t params; + Params params; protected: /** - * Retrieve the storage from the bin. - * @return The storage object for this stat. + * Retrieve the storage. + * @param index The vector index to access. + * @return The storage object at the given index. */ - Storage *data() { return bin.data(params); } + Storage * + data() + { + return reinterpret_cast<Storage *>(storage); + } + /** - * Retrieve a const pointer to the storage from the bin. - * @return A const pointer to the storage object for this stat. + * Retrieve a const pointer to the storage. + * for the given index. + * @param index The vector index to access. + * @return A const pointer to the storage object at the given index. */ - const Storage *data() const + const Storage * + data() const { - bin_t *_bin = const_cast<bin_t *>(&bin); - params_t *_params = const_cast<params_t *>(¶ms); - return _bin->data(*_params); + return reinterpret_cast<const Storage *>(storage); + } + + void + doInit() + { + new (storage) Storage(params); + setInit(); } public: @@ -751,9 +744,7 @@ class ScalarBase : public DataAccess * Create and initialize this stat, register it with the database. */ ScalarBase() - { - bin.init(params); - } + { } public: // Common operators for stats @@ -802,18 +793,13 @@ class ScalarBase : public DataAccess * @return 1. */ size_t size() const { return 1; } - /** - * Return true if stat is binned. - *@return True is stat is binned. - */ - bool binned() const { return bin_t::binned; } - bool check() const { return bin.initialized(); } + bool check() const { return true; } /** * Reset stat value to default */ - void reset() { bin.reset(); } + void reset() { data()->reset(); } Counter value() { return data()->value(params); } @@ -829,7 +815,6 @@ class ProxyData : public ScalarData { public: virtual void visit(Visit &visitor) { visitor.visit(*this); } - virtual bool binned() const { return false; } virtual std::string str() const { return to_string(value()); } virtual size_t size() const { return 1; } virtual bool zero() const { return value() == 0; } @@ -891,7 +876,6 @@ class ValueBase : public DataAccess Result total() const { return proxy->total(); }; size_t size() const { return proxy->size(); } - bool binned() const { return proxy->binned(); } std::string str() const { return proxy->str(); } bool zero() const { return proxy->zero(); } bool check() const { return proxy != NULL; } @@ -903,195 +887,62 @@ class ValueBase : public DataAccess // Vector Statistics // ////////////////////////////////////////////////////////////////////// -template <class Storage, class Bin> -class ScalarProxy; - -/** - * Implementation of a vector of stats. The type of stat is determined by the - * Storage class. @sa ScalarBase - */ -template <class Storage, class Bin> -class VectorBase : public DataAccess -{ - public: - /** Define the params of the storage class. */ - typedef typename Storage::Params params_t; - /** Define the bin type. */ - typedef typename Bin::template VectorBin<Storage> bin_t; - - protected: - /** The bin of this stat. */ - bin_t bin; - /** The parameters for this stat. */ - params_t params; - - protected: - /** - * Retrieve the storage from the bin for the given index. - * @param index The vector index to access. - * @return The storage object at the given index. - */ - Storage *data(int index) { return bin.data(index, params); } - /** - * Retrieve a const pointer to the storage from the bin - * for the given index. - * @param index The vector index to access. - * @return A const pointer to the storage object at the given index. - */ - const Storage *data(int index) const - { - bin_t *_bin = const_cast<bin_t *>(&bin); - params_t *_params = const_cast<params_t *>(¶ms); - return _bin->data(index, *_params); - } - - public: - void value(VCounter &vec) const - { - vec.resize(size()); - for (int i = 0; i < size(); ++i) - vec[i] = data(i)->value(params); - } - - /** - * Copy the values to a local vector and return a reference to it. - * @return A reference to a vector of the stat values. - */ - void result(VResult &vec) const - { - vec.resize(size()); - for (int i = 0; i < size(); ++i) - vec[i] = data(i)->result(params); - } - - /** - * @return True is stat is binned. - */ - bool binned() const { return bin_t::binned; } - - /** - * Return a total of all entries in this vector. - * @return The total of all vector entries. - */ - Result total() const { - Result total = 0.0; - for (int i = 0; i < size(); ++i) - total += data(i)->result(params); - return total; - } - - /** - * @return the number of elements in this vector. - */ - size_t size() const { return bin.size(); } - - bool zero() const - { - for (int i = 0; i < size(); ++i) - if (data(i)->zero()) - return true; - return false; - } - - bool check() const { return bin.initialized(); } - void reset() { bin.reset(); } - - public: - VectorBase() {} - - /** Friend this class with the associated scalar proxy. */ - friend class ScalarProxy<Storage, Bin>; - - /** - * Return a reference (ScalarProxy) to the stat at the given index. - * @param index The vector index to access. - * @return A reference of the stat. - */ - ScalarProxy<Storage, Bin> operator[](int index); - - void update(StatData *data) {} -}; - -const StatData * getStatData(const void *stat); /** * A proxy class to access the stat at a given index in a VectorBase stat. * Behaves like a ScalarBase. */ -template <class Storage, class Bin> +template <class Stat> class ScalarProxy { - public: - /** Define the params of the storage class. */ - typedef typename Storage::Params params_t; - /** Define the bin type. */ - typedef typename Bin::template VectorBin<Storage> bin_t; - private: - /** Pointer to the bin in the parent VectorBase. */ - bin_t *bin; - /** Pointer to the params in the parent VectorBase. */ - params_t *params; + /** Pointer to the parent Vector. */ + Stat *stat; + /** The index to access in the parent VectorBase. */ int index; - /** Keep a pointer to the original stat so was can get data */ - void *stat; - - protected: - /** - * Retrieve the storage from the bin. - * @return The storage from the bin for this stat. - */ - Storage *data() { return bin->data(index, *params); } - /** - * Retrieve a const pointer to the storage from the bin. - * @return A const pointer to the storage for this stat. - */ - const Storage *data() const - { - bin_t *_bin = const_cast<bin_t *>(bin); - params_t *_params = const_cast<params_t *>(params); - return _bin->data(index, *_params); - } public: /** * Return the current value of this stat as its base type. * @return The current value. */ - Counter value() const { return data()->value(*params); } + Counter value() const { return stat->data(index)->value(stat->params); } /** * Return the current value of this statas a result type. * @return The current value. */ - Result result() const { return data()->result(*params); } + Result result() const { return stat->data(index)->result(stat->params); } public: /** * Create and initialize this proxy, do not register it with the database. - * @param b The bin to use. * @param p The params to use. * @param i The index to access. */ - ScalarProxy(bin_t &b, params_t &p, int i, void *s) - : bin(&b), params(&p), index(i), stat(s) {} + ScalarProxy(Stat *s, int i) + : stat(s), index(i) + { + assert(stat); + } + /** * Create a copy of the provided ScalarProxy. * @param sp The proxy to copy. */ ScalarProxy(const ScalarProxy &sp) - : bin(sp.bin), params(sp.params), index(sp.index), stat(sp.stat) {} + : stat(sp.stat), index(sp.index) + {} + /** * Set this proxy equal to the provided one. * @param sp The proxy to copy. * @return A reference to this proxy. */ const ScalarProxy &operator=(const ScalarProxy &sp) { - bin = sp.bin; - params = sp.params; - index = sp.index; stat = sp.stat; + index = sp.index; return *this; } @@ -1101,12 +952,12 @@ class ScalarProxy * Increment the stat by 1. This calls the associated storage object inc * function. */ - void operator++() { data()->inc(1, *params); } + void operator++() { stat->data(index)->inc(1, stat->params); } /** * Decrement the stat by 1. This calls the associated storage object dec * function. */ - void operator--() { data()->dec(1, *params); } + void operator--() { stat->data(index)->dec(1, stat->params); } /** Increment the stat by 1. */ void operator++(int) { ++*this; } @@ -1119,7 +970,7 @@ class ScalarProxy * @param v The new value. */ template <typename U> - void operator=(const U &v) { data()->set(v, *params); } + void operator=(const U &v) { stat->data(index)->set(v, stat->params); } /** * Increment the stat by the given value. This calls the associated @@ -1127,7 +978,7 @@ class ScalarProxy * @param v The value to add. */ template <typename U> - void operator+=(const U &v) { data()->inc(v, *params); } + void operator+=(const U &v) { stat->data(index)->inc(v, stat->params); } /** * Decrement the stat by the given value. This calls the associated @@ -1135,7 +986,7 @@ class ScalarProxy * @param v The value to substract. */ template <typename U> - void operator-=(const U &v) { data()->dec(v, *params); } + void operator-=(const U &v) { stat->data(index)->dec(v, stat->params); } /** * Return the number of elements, always 1 for a scalar. @@ -1144,192 +995,356 @@ class ScalarProxy size_t size() const { return 1; } /** - * Return true if stat is binned. - *@return false since Proxies aren't printed/binned - */ - bool binned() const { return false; } - - /** * This stat has no state. Nothing to reset */ void reset() { } public: - const StatData *statData() const { return getStatData(stat); } - std::string str() const + std::string + str() const { - return csprintf("%s[%d]", this->statData()->name, index); + return csprintf("%s[%d]", stat->str(), index); } }; -template <class Storage, class Bin> -inline ScalarProxy<Storage, Bin> -VectorBase<Storage, Bin>::operator[](int index) +/** + * Implementation of a vector of stats. The type of stat is determined by the + * Storage class. @sa ScalarBase + */ +template <class Stor> +class VectorBase : public DataAccess { - assert (index >= 0 && index < size()); - return ScalarProxy<Storage, Bin>(bin, params, index, this); -} + public: + typedef Stor Storage; + + /** Define the params of the storage class. */ + typedef typename Storage::Params Params; -template <class Storage, class Bin> -class VectorProxy; + /** Proxy type */ + typedef ScalarProxy<VectorBase<Storage> > Proxy; -template <class Storage, class Bin> -class Vector2dBase : public DataAccess -{ - public: - typedef typename Storage::Params params_t; - typedef typename Bin::template VectorBin<Storage> bin_t; + friend class ScalarProxy<VectorBase<Storage> >; protected: - size_t x; - size_t y; - bin_t bin; - params_t params; + /** The storage of this stat. */ + Storage *storage; + size_t _size; + + /** The parameters for this stat. */ + Params params; protected: - Storage *data(int index) { return bin.data(index, params); } - const Storage *data(int index) const + /** + * Retrieve the storage. + * @param index The vector index to access. + * @return The storage object at the given index. + */ + Storage *data(int index) { return &storage[index]; } + + /** + * Retrieve a const pointer to the storage. + * @param index The vector index to access. + * @return A const pointer to the storage object at the given index. + */ + const Storage *data(int index) const { return &storage[index]; } + + void + doInit(int s) { - bin_t *_bin = const_cast<bin_t *>(&bin); - params_t *_params = const_cast<params_t *>(¶ms); - return _bin->data(index, *_params); + assert(s > 0 && "size must be positive!"); + assert(!storage && "already initialized"); + _size = s; + + char *ptr = new char[_size * sizeof(Storage)]; + storage = reinterpret_cast<Storage *>(ptr); + + for (int i = 0; i < _size; ++i) + new (&storage[i]) Storage(params); + + setInit(); } public: - Vector2dBase() {} + void value(VCounter &vec) const + { + vec.resize(size()); + for (int i = 0; i < size(); ++i) + vec[i] = data(i)->value(params); + } - void update(Vector2dData *data) + /** + * Copy the values to a local vector and return a reference to it. + * @return A reference to a vector of the stat values. + */ + void result(VResult &vec) const { - int size = this->size(); - data->cvec.resize(size); - for (int i = 0; i < size; ++i) - data->cvec[i] = this->data(i)->value(params); + vec.resize(size()); + for (int i = 0; i < size(); ++i) + vec[i] = data(i)->result(params); } - std::string ysubname(int i) const { return (*this->y_subnames)[i]; } + /** + * Return a total of all entries in this vector. + * @return The total of all vector entries. + */ + Result total() const { + Result total = 0.0; + for (int i = 0; i < size(); ++i) + total += data(i)->result(params); + return total; + } + + /** + * @return the number of elements in this vector. + */ + size_t size() const { return _size; } - friend class VectorProxy<Storage, Bin>; - VectorProxy<Storage, Bin> operator[](int index); + bool + zero() const + { + for (int i = 0; i < size(); ++i) + if (data(i)->zero()) + return false; + return true; + } - size_t size() const { return bin.size(); } - bool zero() const { return data(0)->value(params) == 0.0; } + bool + check() const + { + return storage != NULL; + } + + void + reset() + { + for (int i = 0; i < size(); ++i) + data(i)->reset(); + } + + public: + VectorBase() + : storage(NULL) + {} + + ~VectorBase() + { + if (!storage) + return; + + for (int i = 0; i < _size; ++i) + data(i)->~Storage(); + delete [] reinterpret_cast<char *>(storage); + } /** - * Reset stat value to default + * Return a reference (ScalarProxy) to the stat at the given index. + * @param index The vector index to access. + * @return A reference of the stat. */ - void reset() { bin.reset(); } + Proxy + operator[](int index) + { + assert (index >= 0 && index < size()); + return Proxy(this, index); + } - bool check() { return bin.initialized(); } + void update(StatData *data) {} }; -template <class Storage, class Bin> +template <class Stat> class VectorProxy { - public: - typedef typename Storage::Params params_t; - typedef typename Bin::template VectorBin<Storage> bin_t; - private: - bin_t *bin; - params_t *params; + Stat *stat; int offset; int len; - void *stat; private: - mutable VResult *vec; + mutable VResult vec; - Storage *data(int index) { + typename Stat::Storage * + data(int index) + { assert(index < len); - return bin->data(offset + index, *params); + return stat->data(offset + index); } - const Storage *data(int index) const { - bin_t *_bin = const_cast<bin_t *>(bin); - params_t *_params = const_cast<params_t *>(params); - return _bin->data(offset + index, *_params); + const typename Stat::Storage * + data(int index) const + { + assert(index < len); + return const_cast<Stat *>(stat)->data(offset + index); } public: - const VResult &result() const { - if (vec) - vec->resize(size()); - else - vec = new VResult(size()); + const VResult & + result() const + { + vec.resize(size()); for (int i = 0; i < size(); ++i) - (*vec)[i] = data(i)->result(*params); + vec[i] = data(i)->result(stat->params); - return *vec; + return vec; } - Result total() const { - Result total = 0.0; + Result + total() const + { + Result total = 0; for (int i = 0; i < size(); ++i) - total += data(i)->result(*params); + total += data(i)->result(stat->params); return total; } public: - VectorProxy(bin_t &b, params_t &p, int o, int l, void *s) - : bin(&b), params(&p), offset(o), len(l), stat(s), vec(NULL) + VectorProxy(Stat *s, int o, int l) + : stat(s), offset(o), len(l) { } VectorProxy(const VectorProxy &sp) - : bin(sp.bin), params(sp.params), offset(sp.offset), len(sp.len), - stat(sp.stat), vec(NULL) - { - } - - ~VectorProxy() + : stat(sp.stat), offset(sp.offset), len(sp.len) { - if (vec) - delete vec; } - const VectorProxy &operator=(const VectorProxy &sp) + const VectorProxy & + operator=(const VectorProxy &sp) { - bin = sp.bin; - params = sp.params; + stat = sp.stat; offset = sp.offset; len = sp.len; - stat = sp.stat; - if (vec) - delete vec; - vec = NULL; return *this; } - ScalarProxy<Storage, Bin> operator[](int index) + ScalarProxy<Stat> operator[](int index) { assert (index >= 0 && index < size()); - return ScalarProxy<Storage, Bin>(*bin, *params, offset + index, stat); + return ScalarProxy<Stat>(stat, offset + index); } size_t size() const { return len; } /** - * Return true if stat is binned. - *@return false since Proxies aren't printed/binned - */ - bool binned() const { return false; } - - /** * This stat has no state. Nothing to reset. */ void reset() { } }; -template <class Storage, class Bin> -inline VectorProxy<Storage, Bin> -Vector2dBase<Storage, Bin>::operator[](int index) +template <class Stor> +class Vector2dBase : public DataAccess { - int offset = index * y; - assert (index >= 0 && offset < size()); - return VectorProxy<Storage, Bin>(bin, params, offset, y, this); -} + public: + typedef Stor Storage; + typedef typename Storage::Params Params; + typedef VectorProxy<Vector2dBase<Storage> > Proxy; + friend class ScalarProxy<Vector2dBase<Storage> >; + friend class VectorProxy<Vector2dBase<Storage> >; + + protected: + size_t x; + size_t y; + size_t _size; + Storage *storage; + Params params; + + protected: + Storage *data(int index) { return &storage[index]; } + const Storage *data(int index) const { return &storage[index]; } + + void + doInit(int _x, int _y) + { + assert(_x > 0 && _y > 0 && "sizes must be positive!"); + assert(!storage && "already initialized"); + + Vector2dData *statdata = dynamic_cast<Vector2dData *>(find()); + + x = _x; + y = _y; + statdata->x = _x; + statdata->y = _y; + _size = x * y; + + char *ptr = new char[_size * sizeof(Storage)]; + storage = reinterpret_cast<Storage *>(ptr); + + for (int i = 0; i < _size; ++i) + new (&storage[i]) Storage(params); + + setInit(); + } + + public: + Vector2dBase() + : storage(NULL) + {} + + ~Vector2dBase() + { + if (!storage) + return; + + for (int i = 0; i < _size; ++i) + data(i)->~Storage(); + delete [] reinterpret_cast<char *>(storage); + } + + void + update(Vector2dData *newdata) + { + int size = this->size(); + newdata->cvec.resize(size); + for (int i = 0; i < size; ++i) + newdata->cvec[i] = data(i)->value(params); + } + + std::string ysubname(int i) const { return (*this->y_subnames)[i]; } + + Proxy + operator[](int index) + { + int offset = index * y; + assert (index >= 0 && offset + index < size()); + return Proxy(this, offset, y); + } + + + size_t + size() const + { + return _size; + } + + bool + zero() const + { + return data(0)->zero(); +#if 0 + for (int i = 0; i < size(); ++i) + if (!data(i)->zero()) + return false; + return true; +#endif + } + + /** + * Reset stat value to default + */ + void + reset() + { + for (int i = 0; i < size(); ++i) + data(i)->reset(); + } + + bool + check() + { + return storage != NULL; + } +}; ////////////////////////////////////////////////////////////////////// // @@ -1376,14 +1391,8 @@ struct DistStor VCounter cvec; public: - /** - * Construct this storage with the supplied params. - * @param params The parameters. - */ DistStor(const Params ¶ms) - : min_val(INT_MAX), max_val(INT_MIN), underflow(Counter()), - overflow(Counter()), sum(Counter()), squares(Counter()), - samples(Counter()), cvec(params.size) + : cvec(params.size) { reset(); } @@ -1618,36 +1627,46 @@ struct AvgFancy * Implementation of a distribution stat. The type of distribution is * determined by the Storage template. @sa ScalarBase */ -template <class Storage, class Bin> +template <class Stor> class DistBase : public DataAccess { public: + typedef Stor Storage; /** Define the params of the storage class. */ - typedef typename Storage::Params params_t; - /** Define the bin type. */ - typedef typename Bin::template Bin<Storage> bin_t; + typedef typename Storage::Params Params; protected: - /** The bin of this stat. */ - bin_t bin; + /** The storage for this stat. */ + char storage[sizeof(Storage)]; + /** The parameters for this stat. */ - params_t params; + Params params; protected: /** - * Retrieve the storage from the bin. + * Retrieve the storage. * @return The storage object for this stat. */ - Storage *data() { return bin.data(params); } + Storage *data() + { + return reinterpret_cast<Storage *>(storage); + } + /** - * Retrieve a const pointer to the storage from the bin. + * Retrieve a const pointer to the storage. * @return A const pointer to the storage object for this stat. */ - const Storage *data() const + const Storage * + data() const { - bin_t *_bin = const_cast<bin_t *>(&bin); - params_t *_params = const_cast<params_t *>(¶ms); - return _bin->data(*_params); + return reinterpret_cast<const Storage *>(storage); + } + + void + doInit() + { + new (storage) Storage(params); + setInit(); } public: @@ -1678,65 +1697,122 @@ class DistBase : public DataAccess base->data.fancy = Storage::fancy; data()->update(&(base->data), params); } - /** - * @return True is stat is binned. - */ - bool binned() const { return bin_t::binned; } + /** * Reset stat value to default */ - void reset() + void + reset() { - bin.reset(); + data()->reset(); } - bool check() { return bin.initialized(); } + bool + check() + { + return true; + } }; -template <class Storage, class Bin> +template <class Stat> class DistProxy; -template <class Storage, class Bin> +template <class Stor> class VectorDistBase : public DataAccess { public: - typedef typename Storage::Params params_t; - typedef typename Bin::template VectorBin<Storage> bin_t; + typedef Stor Storage; + typedef typename Storage::Params Params; + typedef DistProxy<VectorDistBase<Storage> > Proxy; + friend class DistProxy<VectorDistBase<Storage> >; protected: - bin_t bin; - params_t params; + Storage *storage; + size_t _size; + Params params; protected: - Storage *data(int index) { return bin.data(index, params); } - const Storage *data(int index) const + Storage * + data(int index) + { + return &storage[index]; + } + + const Storage * + data(int index) const { - bin_t *_bin = const_cast<bin_t *>(&bin); - params_t *_params = const_cast<params_t *>(¶ms); - return _bin->data(index, *_params); + return &storage[index]; + } + + void + doInit(int s) + { + assert(s > 0 && "size must be positive!"); + assert(!storage && "already initialized"); + _size = s; + + char *ptr = new char[_size * sizeof(Storage)]; + storage = reinterpret_cast<Storage *>(ptr); + + for (int i = 0; i < _size; ++i) + new (&storage[i]) Storage(params); + + setInit(); } public: - VectorDistBase() {} + VectorDistBase() + : storage(NULL) + {} - friend class DistProxy<Storage, Bin>; - DistProxy<Storage, Bin> operator[](int index); - const DistProxy<Storage, Bin> operator[](int index) const; + ~VectorDistBase() + { + if (!storage) + return ; + + for (int i = 0; i < _size; ++i) + data(i)->~Storage(); + delete [] reinterpret_cast<char *>(storage); + } + + Proxy operator[](int index); + + size_t + size() const + { + return _size; + } + + bool + zero() const + { + return false; +#if 0 + for (int i = 0; i < size(); ++i) + if (!data(i)->zero(params)) + return false; + return true; +#endif + } - size_t size() const { return bin.size(); } - bool zero() const { return false; } - /** - * Return true if stat is binned. - *@return True is stat is binned. - */ - bool binned() const { return bin_t::binned; } /** * Reset stat value to default */ - void reset() { bin.reset(); } + void + reset() + { + for (int i = 0; i < size(); ++i) + data(i)->reset(); + } + + bool + check() + { + return storage != NULL; + } - bool check() { return bin.initialized(); } - void update(VectorDistData *base) + void + update(VectorDistData *base) { int size = this->size(); base->data.resize(size); @@ -1747,75 +1823,75 @@ class VectorDistBase : public DataAccess } }; -template <class Storage, class Bin> +template <class Stat> class DistProxy { - public: - typedef typename Storage::Params params_t; - typedef typename Bin::template Bin<Storage> bin_t; - typedef VectorDistBase<Storage, Bin> base_t; - private: - union { - base_t *stat; - const base_t *cstat; - }; + Stat *stat; int index; protected: - Storage *data() { return stat->data(index); } - const Storage *data() const { return cstat->data(index); } + typename Stat::Storage *data() { return stat->data(index); } + const typename Stat::Storage *data() const { return stat->data(index); } public: - DistProxy(const VectorDistBase<Storage, Bin> &s, int i) - : cstat(&s), index(i) {} + DistProxy(Stat *s, int i) + : stat(s), index(i) + {} + DistProxy(const DistProxy &sp) - : cstat(sp.cstat), index(sp.index) {} - const DistProxy &operator=(const DistProxy &sp) { - cstat = sp.cstat; index = sp.index; return *this; + : stat(sp.stat), index(sp.index) + {} + + const DistProxy &operator=(const DistProxy &sp) + { + stat = sp.stat; + index = sp.index; + return *this; } public: template <typename U> - void sample(const U &v, int n = 1) { data()->sample(v, n, cstat->params); } + void + sample(const U &v, int n = 1) + { + data()->sample(v, n, stat->params); + } + + size_t + size() const + { + return 1; + } + + bool + zero() const + { + return data()->zero(stat->params); + } - size_t size() const { return 1; } - bool zero() const { return data()->zero(cstat->params); } - /** - * Return true if stat is binned. - *@return false since Proxies are not binned/printed. - */ - bool binned() const { return false; } /** * Proxy has no state. Nothing to reset. */ void reset() { } }; -template <class Storage, class Bin> -inline DistProxy<Storage, Bin> -VectorDistBase<Storage, Bin>::operator[](int index) +template <class Storage> +inline typename VectorDistBase<Storage>::Proxy +VectorDistBase<Storage>::operator[](int index) { assert (index >= 0 && index < size()); - return DistProxy<Storage, Bin>(*this, index); -} - -template <class Storage, class Bin> -inline const DistProxy<Storage, Bin> -VectorDistBase<Storage, Bin>::operator[](int index) const -{ - assert (index >= 0 && index < size()); - return DistProxy<Storage, Bin>(*this, index); + return typename VectorDistBase<Storage>::Proxy(this, index); } #if 0 -template <class Storage, class Bin> +template <class Storage> Result -VectorDistBase<Storage, Bin>::total(int index) const +VectorDistBase<Storage>::total(int index) const { int total = 0; - for (int i=0; i < x_size(); ++i) { - total += data(i)->result(*params); + for (int i = 0; i < x_size(); ++i) { + total += data(i)->result(stat->params); } } #endif @@ -1848,11 +1924,6 @@ class Node : public RefCounted * @return The total of the result vector. */ virtual Result total() const = 0; - /** - * Return true if stat is binned. - *@return True is stat is binned. - */ - virtual bool binned() const = 0; /** * @@ -1879,11 +1950,6 @@ class ScalarStatNode : public Node virtual Result total() const { return data->result(); }; virtual size_t size() const { return 1; } - /** - * Return true if stat is binned. - *@return True is stat is binned. - */ - virtual bool binned() const { return data->binned(); } /** * @@ -1891,34 +1957,45 @@ class ScalarStatNode : public Node virtual std::string str() const { return data->name; } }; -template <class Storage, class Bin> +template <class Stat> class ScalarProxyNode : public Node { private: - const ScalarProxy<Storage, Bin> proxy; + const ScalarProxy<Stat> proxy; mutable VResult vresult; public: - ScalarProxyNode(const ScalarProxy<Storage, Bin> &p) - : proxy(p), vresult(1) { } - virtual const VResult &result() const + ScalarProxyNode(const ScalarProxy<Stat> &p) + : proxy(p), vresult(1) + { } + + virtual const VResult & + result() const { vresult[0] = proxy.result(); return vresult; } - virtual Result total() const { return proxy.result(); }; - virtual size_t size() const { return 1; } - /** - * Return true if stat is binned. - *@return True is stat is binned. - */ - virtual bool binned() const { return proxy.binned(); } + virtual Result + total() const + { + return proxy.result(); + } + + virtual size_t + size() const + { + return 1; + } /** * */ - virtual std::string str() const { return proxy.str(); } + virtual std::string + str() const + { + return proxy.str(); + } }; class VectorStatNode : public Node @@ -1932,11 +2009,6 @@ class VectorStatNode : public Node virtual Result total() const { return data->total(); }; virtual size_t size() const { return data->size(); } - /** - * Return true if stat is binned. - *@return True is stat is binned. - */ - virtual bool binned() const { return data->binned(); } virtual std::string str() const { return data->name; } }; @@ -1952,13 +2024,6 @@ class ConstNode : public Node const VResult &result() const { return vresult; } virtual Result total() const { return vresult[0]; }; virtual size_t size() const { return 1; } - - /** - * Return true if stat is binned. - *@return False since constants aren't binned. - */ - virtual bool binned() const { return false; } - virtual std::string str() const { return to_string(vresult[0]); } }; @@ -2032,11 +2097,6 @@ class UnaryNode : public Node } virtual size_t size() const { return l->size(); } - /** - * Return true if child of node is binned. - *@return True if child of node is binned. - */ - virtual bool binned() const { return l->binned(); } virtual std::string str() const { @@ -2103,11 +2163,6 @@ class BinaryNode : public Node return ls; } } - /** - * Return true if any children of node are binned - *@return True if either child of node is binned. - */ - virtual bool binned() const { return (l->binned() || r->binned()); } virtual std::string str() const { @@ -2156,11 +2211,6 @@ class SumNode : public Node } virtual size_t size() const { return 1; } - /** - * Return true if child of node is binned. - *@return True if child of node is binned. - */ - virtual bool binned() const { return l->binned(); } virtual std::string str() const { @@ -2176,40 +2226,24 @@ class SumNode : public Node ////////////////////////////////////////////////////////////////////// /** * @defgroup VisibleStats "Statistic Types" - * These are the statistics that are used in the simulator. By default these - * store counters and don't use binning, but are templatized to accept any type - * and any Bin class. + * These are the statistics that are used in the simulator. * @{ */ /** - * This is an easy way to assign all your stats to be binned or not - * binned. If the typedef is NoBin, nothing is binned. If it is - * MainBin, then all stats are binned under that Bin. - */ -#if STATS_BINNING -typedef MainBin DefaultBin; -#else -typedef NoBin DefaultBin; -#endif - -/** * This is a simple scalar statistic, like a counter. * @sa Stat, ScalarBase, StatStor */ -template <class Bin = DefaultBin> -class Scalar - : public Wrap<Scalar<Bin>, - ScalarBase<StatStor, Bin>, - ScalarStatData> +template<int N = 0> +class Scalar : public Wrap<Scalar<N>, ScalarBase<StatStor>, ScalarStatData> { public: /** The base implementation. */ - typedef ScalarBase<StatStor, Bin> Base; + typedef ScalarBase<StatStor> Base; Scalar() { - this->setInit(); + this->doInit(); } /** @@ -2221,10 +2255,7 @@ class Scalar void operator=(const U &v) { Base::operator=(v); } }; -class Value - : public Wrap<Value, - ValueBase, - ScalarStatData> +class Value : public Wrap<Value, ValueBase, ScalarStatData> { public: /** The base implementation. */ @@ -2249,19 +2280,16 @@ class Value * A stat that calculates the per cycle average of a value. * @sa Stat, ScalarBase, AvgStor */ -template <class Bin = DefaultBin> -class Average - : public Wrap<Average<Bin>, - ScalarBase<AvgStor, Bin>, - ScalarStatData> +template<int N = 0> +class Average : public Wrap<Average<N>, ScalarBase<AvgStor>, ScalarStatData> { public: /** The base implementation. */ - typedef ScalarBase<AvgStor, Bin> Base; + typedef ScalarBase<AvgStor> Base; Average() { - this->setInit(); + this->doInit(); } /** @@ -2277,15 +2305,12 @@ class Average * A vector of scalar stats. * @sa Stat, VectorBase, StatStor */ -template <class Bin = DefaultBin> -class Vector - : public WrapVec<Vector<Bin>, - VectorBase<StatStor, Bin>, - VectorStatData> +template<int N = 0> +class Vector : public WrapVec<Vector<N>, VectorBase<StatStor>, VectorStatData> { public: /** The base implementation. */ - typedef ScalarBase<StatStor, Bin> Base; + typedef ScalarBase<StatStor> Base; /** * Set this vector to have the given size. @@ -2293,9 +2318,7 @@ class Vector * @return A reference to this stat. */ Vector &init(size_t size) { - this->bin.init(size, this->params); - this->setInit(); - + this->doInit(size); return *this; } }; @@ -2304,11 +2327,9 @@ class Vector * A vector of Average stats. * @sa Stat, VectorBase, AvgStor */ -template <class Bin = DefaultBin> +template<int N = 0> class AverageVector - : public WrapVec<AverageVector<Bin>, - VectorBase<AvgStor, Bin>, - VectorStatData> + : public WrapVec<AverageVector<N>, VectorBase<AvgStor>, VectorStatData> { public: /** @@ -2317,9 +2338,7 @@ class AverageVector * @return A reference to this stat. */ AverageVector &init(size_t size) { - this->bin.init(size, this->params); - this->setInit(); - + this->doInit(size); return *this; } }; @@ -2328,19 +2347,13 @@ class AverageVector * A 2-Dimensional vecto of scalar stats. * @sa Stat, Vector2dBase, StatStor */ -template <class Bin = DefaultBin> +template<int N = 0> class Vector2d - : public WrapVec2d<Vector2d<Bin>, - Vector2dBase<StatStor, Bin>, - Vector2dStatData> + : public WrapVec2d<Vector2d<N>, Vector2dBase<StatStor>, Vector2dStatData> { public: - Vector2d &init(size_t _x, size_t _y) { - this->statData()->x = this->x = _x; - this->statData()->y = this->y = _y; - this->bin.init(this->x * this->y, this->params); - this->setInit(); - + Vector2d &init(size_t x, size_t y) { + this->doInit(x, y); return *this; } }; @@ -2349,17 +2362,15 @@ class Vector2d * A simple distribution stat. * @sa Stat, DistBase, DistStor */ -template <class Bin = DefaultBin> +template<int N = 0> class Distribution - : public Wrap<Distribution<Bin>, - DistBase<DistStor, Bin>, - DistStatData> + : public Wrap<Distribution<N>, DistBase<DistStor>, DistStatData> { public: /** Base implementation. */ - typedef DistBase<DistStor, Bin> Base; + typedef DistBase<DistStor> Base; /** The Parameter type. */ - typedef typename DistStor::Params Params; + typedef DistStor::Params Params; public: /** @@ -2374,9 +2385,7 @@ class Distribution this->params.max = max; this->params.bucket_size = bkt; this->params.size = (int)rint((max - min) / bkt + 1.0); - this->bin.init(this->params); - this->setInit(); - + this->doInit(); return *this; } }; @@ -2385,25 +2394,22 @@ class Distribution * Calculates the mean and variance of all the samples. * @sa Stat, DistBase, FancyStor */ -template <class Bin = DefaultBin> +template<int N = 0> class StandardDeviation - : public Wrap<StandardDeviation<Bin>, - DistBase<FancyStor, Bin>, - DistStatData> + : public Wrap<StandardDeviation<N>, DistBase<FancyStor>, DistStatData> { public: /** The base implementation */ - typedef DistBase<DistStor, Bin> Base; + typedef DistBase<DistStor> Base; /** The parameter type. */ - typedef typename DistStor::Params Params; + typedef DistStor::Params Params; public: /** * Construct and initialize this distribution. */ StandardDeviation() { - this->bin.init(this->params); - this->setInit(); + this->doInit(); } }; @@ -2411,17 +2417,15 @@ class StandardDeviation * Calculates the per cycle mean and variance of the samples. * @sa Stat, DistBase, AvgFancy */ -template <class Bin = DefaultBin> +template<int N = 0> class AverageDeviation - : public Wrap<AverageDeviation<Bin>, - DistBase<AvgFancy, Bin>, - DistStatData> + : public Wrap<AverageDeviation<N>, DistBase<AvgFancy>, DistStatData> { public: /** The base implementation */ - typedef DistBase<DistStor, Bin> Base; + typedef DistBase<DistStor> Base; /** The parameter type. */ - typedef typename DistStor::Params Params; + typedef DistStor::Params Params; public: /** @@ -2429,8 +2433,7 @@ class AverageDeviation */ AverageDeviation() { - this->bin.init(this->params); - this->setInit(); + this->doInit(); } }; @@ -2438,17 +2441,17 @@ class AverageDeviation * A vector of distributions. * @sa Stat, VectorDistBase, DistStor */ -template <class Bin = DefaultBin> +template<int N = 0> class VectorDistribution - : public WrapVec<VectorDistribution<Bin>, - VectorDistBase<DistStor, Bin>, + : public WrapVec<VectorDistribution<N>, + VectorDistBase<DistStor>, VectorDistStatData> { public: /** The base implementation */ - typedef VectorDistBase<DistStor, Bin> Base; + typedef VectorDistBase<DistStor> Base; /** The parameter type. */ - typedef typename DistStor::Params Params; + typedef DistStor::Params Params; public: /** @@ -2464,9 +2467,7 @@ class VectorDistribution this->params.max = max; this->params.bucket_size = bkt; this->params.size = (int)rint((max - min) / bkt + 1.0); - this->bin.init(size, this->params); - this->setInit(); - + this->doInit(size); return *this; } }; @@ -2475,17 +2476,17 @@ class VectorDistribution * This is a vector of StandardDeviation stats. * @sa Stat, VectorDistBase, FancyStor */ -template <class Bin = DefaultBin> +template<int N = 0> class VectorStandardDeviation - : public WrapVec<VectorStandardDeviation<Bin>, - VectorDistBase<FancyStor, Bin>, + : public WrapVec<VectorStandardDeviation<N>, + VectorDistBase<FancyStor>, VectorDistStatData> { public: /** The base implementation */ - typedef VectorDistBase<FancyStor, Bin> Base; + typedef VectorDistBase<FancyStor> Base; /** The parameter type. */ - typedef typename DistStor::Params Params; + typedef DistStor::Params Params; public: /** @@ -2494,9 +2495,7 @@ class VectorStandardDeviation * @return A reference to this distribution. */ VectorStandardDeviation &init(int size) { - this->bin.init(size, this->params); - this->setInit(); - + this->doInit(size); return *this; } }; @@ -2505,17 +2504,17 @@ class VectorStandardDeviation * This is a vector of AverageDeviation stats. * @sa Stat, VectorDistBase, AvgFancy */ -template <class Bin = DefaultBin> +template<int N = 0> class VectorAverageDeviation - : public WrapVec<VectorAverageDeviation<Bin>, - VectorDistBase<AvgFancy, Bin>, + : public WrapVec<VectorAverageDeviation<N>, + VectorDistBase<AvgFancy>, VectorDistStatData> { public: /** The base implementation */ - typedef VectorDistBase<AvgFancy, Bin> Base; + typedef VectorDistBase<AvgFancy> Base; /** The parameter type. */ - typedef typename DistStor::Params Params; + typedef DistStor::Params Params; public: /** @@ -2524,9 +2523,7 @@ class VectorAverageDeviation * @return A reference to this distribution. */ VectorAverageDeviation &init(int size) { - this->bin.init(size, this->params); - this->setInit(); - + this->doInit(size); return *this; } }; @@ -2570,13 +2567,6 @@ class FormulaBase : public DataAccess */ size_t size() const; - /** - * Return true if Formula is binned. i.e. any of its children - * nodes are binned - * @return True if Formula is binned. - */ - bool binned() const; - bool check() const { return true; } /** @@ -2615,7 +2605,6 @@ class FormulaStatData : public FormulaData public: FormulaStatData(Stat &stat) : s(stat) {} - virtual bool binned() const { return s.binned(); } virtual bool zero() const { return s.zero(); } virtual void reset() { s.reset(); } @@ -2682,7 +2671,6 @@ class FormulaNode : public Node virtual size_t size() const { return formula.size(); } virtual const VResult &result() const { formula.result(vec); return vec; } virtual Result total() const { return formula.total(); } - virtual bool binned() const { return formula.binned(); } virtual std::string str() const { return formula.str(); } }; @@ -2716,8 +2704,8 @@ class Temp * Create a new ScalarStatNode. * @param s The ScalarStat to place in a node. */ - template <class Bin> - Temp(const Scalar<Bin> &s) + template <int N> + Temp(const Scalar<N> &s) : node(new ScalarStatNode(s.statData())) { } /** @@ -2731,16 +2719,16 @@ class Temp * Create a new ScalarStatNode. * @param s The ScalarStat to place in a node. */ - template <class Bin> - Temp(const Average<Bin> &s) + template <int N> + Temp(const Average<N> &s) : node(new ScalarStatNode(s.statData())) { } /** * Create a new VectorStatNode. * @param s The VectorStat to place in a node. */ - template <class Bin> - Temp(const Vector<Bin> &s) + template <int N> + Temp(const Vector<N> &s) : node(new VectorStatNode(s.statData())) { } /** @@ -2753,9 +2741,9 @@ class Temp * Create a new ScalarProxyNode. * @param p The ScalarProxy to place in a node. */ - template <class Storage, class Bin> - Temp(const ScalarProxy<Storage, Bin> &p) - : node(new ScalarProxyNode<Storage, Bin>(p)) { } + template <class Stat> + Temp(const ScalarProxy<Stat> &p) + : node(new ScalarProxyNode<Stat>(p)) { } /** * Create a ConstNode diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index fa4bcd5ee..0fb31f4ce 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -158,14 +158,6 @@ MySqlRun::cleanup() if (mysql.commit()) panic("could not commit transaction\n%s\n", mysql.error); - mysql.query("DELETE bins " - "FROM bins " - "LEFT JOIN data ON bn_id=dt_bin " - "WHERE dt_bin IS NULL"); - - if (mysql.commit()) - panic("could not commit transaction\n%s\n", mysql.error); - mysql.query("DELETE events" "FROM events" "LEFT JOIN runs ON ev_run=rn_id" @@ -309,52 +301,6 @@ SetupStat::setup() return statid; } -unsigned -SetupBin(const string &bin) -{ - static map<string, int> binmap; - - using namespace MySQL; - map<string,int>::const_iterator i = binmap.find(bin); - if (i != binmap.end()) - return (*i).second; - - Connection &mysql = MySqlDB.conn(); - assert(mysql.connected()); - - uint16_t bin_id; - - stringstream select; - stringstream insert; - ccprintf(select, "SELECT bn_id FROM bins WHERE bn_name=\"%s\"", bin); - - mysql.query(select); - MySQL::Result result = mysql.store_result(); - if (result) { - assert(result.num_fields() == 1); - MySQL::Row row = result.fetch_row(); - if (row) { - to_number(row[0], bin_id); - goto exit; - } - } - - ccprintf(insert, "INSERT INTO bins(bn_name) values(\"%s\")", bin); - - mysql.query(insert); - if (mysql.error) - panic("could not get a bin\n%s\n", mysql.error); - - bin_id = mysql.insert_id(); - if (mysql.commit()) - panic("could not commit transaction\n%s\n", mysql.error); - - binmap.insert(make_pair(bin, bin_id)); - - exit: - return bin_id; -} - InsertData::InsertData() { query = new char[maxsize + 1]; @@ -384,7 +330,7 @@ InsertData::flush() size = 0; first = true; strcpy(query, "INSERT INTO " - "data(dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_bin,dt_data) " + "data(dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_data) " "values"); size = strlen(query); } @@ -402,9 +348,9 @@ InsertData::insert() first = false; - size += sprintf(query + size, "(%u,%d,%d,%u,%llu,%u,\"%f\")", + size += sprintf(query + size, "(%u,%d,%d,%u,%llu,\"%f\")", stat, x, y, MySqlDB.run(), (unsigned long long)tick, - bin, data); + data); } struct InsertSubData @@ -656,29 +602,6 @@ MySql::configure(const FormulaData &data) InsertFormula(find(data.id), data.str()); } -void -MySql::output(MainBin *bin) -{ - MySQL::Connection &mysql = MySqlDB.conn(); - - if (bin) { - bin->activate(); - newdata.bin = SetupBin(bin->name()); - } else { - newdata.bin = 0; - } - - Database::stat_list_t::const_iterator i, end = Database::stats().end(); - for (i = Database::stats().begin(); i != end; ++i) { - StatData *stat = *i; - if (bin && stat->binned() || !bin && !stat->binned()) { - stat->visit(*this); - if (mysql.commit()) - panic("could not commit transaction\n%s\n", mysql.error); - } - } -} - bool MySql::valid() const { @@ -697,11 +620,14 @@ MySql::output() // store sample # newdata.tick = curTick; - output(NULL); - if (!bins().empty()) { - bin_list_t::iterator i, end = bins().end(); - for (i = bins().begin(); i != end; ++i) - output(*i); + MySQL::Connection &mysql = MySqlDB.conn(); + + Database::stat_list_t::const_iterator i, end = Database::stats().end(); + for (i = Database::stats().begin(); i != end; ++i) { + StatData *stat = *i; + stat->visit(*this); + if (mysql.commit()) + panic("could not commit transaction\n%s\n", mysql.error); } newdata.flush(); diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh index 1d88fbcd9..50f7d9e97 100644 --- a/src/base/stats/mysql.hh +++ b/src/base/stats/mysql.hh @@ -39,7 +39,6 @@ namespace MySQL { class Connection; } namespace Stats { -class MainBin; class DistDataData; class MySqlRun; bool MySqlConnected(); @@ -82,7 +81,6 @@ class InsertData uint64_t tick; double data; uint16_t stat; - uint16_t bin; int16_t x; int16_t y; @@ -133,7 +131,6 @@ class MySql : public Output protected: // Output helper - void output(MainBin *bin); void output(const DistDataData &data); void output(const ScalarData &data); void output(const VectorData &data); diff --git a/src/base/stats/statdb.cc b/src/base/stats/statdb.cc index 682f62dc1..f9136807a 100644 --- a/src/base/stats/statdb.cc +++ b/src/base/stats/statdb.cc @@ -31,7 +31,6 @@ #include "base/misc.hh" #include "base/trace.hh" #include "base/statistics.hh" -#include "base/stats/bin.hh" #include "base/stats/statdb.hh" using namespace std; @@ -51,17 +50,6 @@ find(void *stat) } void -regBin(MainBin *bin, const std::string &_name) -{ - bin_list_t::iterator i, end = bins().end(); - for (i = bins().begin(); i != end; ++i) - if ((*i)->name() == _name) - panic("re-registering bin %s", _name); - bins().push_back(bin); - DPRINTF(Stats, "registering %s\n", _name); -} - -void regStat(void *stat, StatData *data) { if (map().find(stat) != map().end()) diff --git a/src/base/stats/statdb.hh b/src/base/stats/statdb.hh index 8c56e031e..a5b9be7eb 100644 --- a/src/base/stats/statdb.hh +++ b/src/base/stats/statdb.hh @@ -40,31 +40,25 @@ class Python; namespace Stats { -class MainBin; class StatData; namespace Database { typedef std::map<void *, StatData *> stat_map_t; typedef std::list<StatData *> stat_list_t; -typedef std::list<MainBin *> bin_list_t; // We wrap the database in a struct to make sure it is built in time. struct TheDatabase { stat_map_t map; stat_list_t stats; - bin_list_t bins; - }; TheDatabase &db(); inline stat_map_t &map() { return db().map; } inline stat_list_t &stats() { return db().stats; } -inline bin_list_t &bins() { return db().bins; } StatData *find(void *stat); -void regBin(MainBin *bin, const std::string &name); void regStat(void *stat, StatData *data); void regPrint(void *stat); diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index 8d2144665..c4448efc9 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -129,23 +129,9 @@ Text::output() using namespace Database; ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n"); - if (bins().empty() || bins().size() == 1) { - stat_list_t::const_iterator i, end = stats().end(); - for (i = stats().begin(); i != end; ++i) - (*i)->visit(*this); - } else { - ccprintf(*stream, "PRINTING BINNED STATS\n"); - bin_list_t::iterator i, end = bins().end(); - for (i = bins().begin(); i != end; ++i) { - MainBin *bin = *i; - bin->activate(); - ccprintf(*stream,"---%s Bin------------\n", bin->name()); - stat_list_t::const_iterator i, end = stats().end(); - for (i = stats().begin(); i != end; ++i) - (*i)->visit(*this); - ccprintf(*stream, "---------------------------------\n"); - } - } + stat_list_t::const_iterator i, end = stats().end(); + for (i = stats().begin(); i != end; ++i) + (*i)->visit(*this); ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n"); stream->flush(); } diff --git a/src/base/stats/text.hh b/src/base/stats/text.hh index de27abe1b..b3faf5ad5 100644 --- a/src/base/stats/text.hh +++ b/src/base/stats/text.hh @@ -46,7 +46,6 @@ class Text : public Output protected: bool noOutput(const StatData &data); - void binout(); public: bool compat; diff --git a/src/cpu/base.cc b/src/cpu/base.cc index d77f03126..55c04c498 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -89,8 +89,8 @@ BaseCPU::BaseCPU(Params *p) // if (p->max_insts_any_thread != 0) for (int i = 0; i < number_of_threads; ++i) - new SimExitEvent(comInstEventQueue[i], p->max_insts_any_thread, - "a thread reached the max instruction count"); + new SimLoopExitEvent(comInstEventQueue[i], p->max_insts_any_thread, + "a thread reached the max instruction count"); if (p->max_insts_all_threads != 0) { // allocate & initialize shared downcounter: each event will @@ -114,8 +114,8 @@ BaseCPU::BaseCPU(Params *p) // if (p->max_loads_any_thread != 0) for (int i = 0; i < number_of_threads; ++i) - new SimExitEvent(comLoadEventQueue[i], p->max_loads_any_thread, - "a thread reached the max load count"); + new SimLoopExitEvent(comLoadEventQueue[i], p->max_loads_any_thread, + "a thread reached the max load count"); if (p->max_loads_all_threads != 0) { // allocate & initialize shared downcounter: each event will diff --git a/src/cpu/o3/alpha_cpu_impl.hh b/src/cpu/o3/alpha_cpu_impl.hh index fb2fea8e6..bfd05d260 100644 --- a/src/cpu/o3/alpha_cpu_impl.hh +++ b/src/cpu/o3/alpha_cpu_impl.hh @@ -46,6 +46,7 @@ #include "arch/isa_traits.hh" #include "cpu/quiesce_event.hh" #include "kern/kernel_stats.hh" +#include "sim/sim_exit.hh" #include "sim/system.hh" #endif @@ -735,7 +736,7 @@ AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid) case PAL::halt: halt(); if (--System::numSystemsRunning == 0) - new SimExitEvent("all cpus halted"); + exitSimLoop("all cpus halted"); break; case PAL::bpt: diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index c1ecf3967..d94b0e079 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -409,11 +409,6 @@ void BaseSimpleCPU::postExecute() { #if FULL_SYSTEM - if (system->kernelBinning->fnbin) { - assert(thread->getKernelStats()); - system->kernelBinning->execute(tc, inst); - } - if (thread->profile) { bool usermode = (thread->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index e3bb7d9c3..3c79e1116 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -245,7 +245,6 @@ class ThreadContext virtual void setSyscallReturn(SyscallReturn return_value) = 0; - // Same with st cond failures. virtual Counter readFuncExeInst() = 0; #endif @@ -431,7 +430,6 @@ class ProxyThreadContext : public ThreadContext void setSyscallReturn(SyscallReturn return_value) { actualTC->setSyscallReturn(return_value); } - Counter readFuncExeInst() { return actualTC->readFuncExeInst(); } #endif diff --git a/src/cpu/trace/opt_cpu.cc b/src/cpu/trace/opt_cpu.cc index 098031d4a..996e89f01 100644 --- a/src/cpu/trace/opt_cpu.cc +++ b/src/cpu/trace/opt_cpu.cc @@ -176,7 +176,7 @@ OptCPU::tick() fprintf(stderr,"sys.cpu.misses %d #opt cache misses\n",misses); fprintf(stderr,"sys.cpu.hits %d #opt cache hits\n", hits); fprintf(stderr,"sys.cpu.accesses %d #opt cache acceses\n", references); - new SimExitEvent("Finshed Memory Trace"); + exitSimLoop("end of memory trace reached"); } void diff --git a/src/cpu/trace/trace_cpu.cc b/src/cpu/trace/trace_cpu.cc index 4df47229f..3c9da4849 100644 --- a/src/cpu/trace/trace_cpu.cc +++ b/src/cpu/trace/trace_cpu.cc @@ -108,7 +108,7 @@ TraceCPU::tick() if (!nextReq) { // No more requests to send. Finish trailing events and exit. if (mainEventQueue.empty()) { - new SimExitEvent("Finshed Memory Trace"); + exitSimLoop("end of memory trace reached"); } else { tickEvent.schedule(mainEventQueue.nextEventTime() + cycles(1)); } diff --git a/src/kern/kernel_stats.cc b/src/kern/kernel_stats.cc index 2ba120b6f..f7868b50f 100644 --- a/src/kern/kernel_stats.cc +++ b/src/kern/kernel_stats.cc @@ -45,13 +45,12 @@ using namespace Stats; namespace Kernel { -const char *modestr[] = { "kernel", "user", "idle", "interrupt" }; +const char *modestr[] = { "kernel", "user", "idle" }; Statistics::Statistics(System *system) : idleProcess((Addr)-1), themode(kernel), lastModeTick(0), iplLast(0), iplLastTick(0) { - bin_int = system->params()->bin_int; } void @@ -186,7 +185,7 @@ Statistics::regStats(const string &_name) void Statistics::setIdleProcess(Addr idlepcbb, ThreadContext *tc) { - assert(themode == kernel || themode == interrupt); + assert(themode == kernel); idleProcess = idlepcbb; themode = idle; changeMode(themode, tc); @@ -206,8 +205,6 @@ Statistics::changeMode(cpu_mode newmode, ThreadContext *tc) _modeGood[newmode]++; _modeTicks[themode] += curTick - lastModeTick; - tc->getSystemPtr()->kernelBinning->changeMode(newmode); - lastModeTick = curTick; themode = newmode; } @@ -233,13 +230,9 @@ Statistics::mode(cpu_mode newmode, ThreadContext *tc) { Addr pcbb = tc->readMiscReg(AlphaISA::IPR_PALtemp23); - if ((newmode == kernel || newmode == interrupt) && - pcbb == idleProcess) + if (newmode == kernel && pcbb == idleProcess) newmode = idle; - if (bin_int == false && newmode == interrupt) - newmode = kernel; - changeMode(newmode, tc); } @@ -268,11 +261,6 @@ Statistics::callpal(int code, ThreadContext *tc) _syscall[cvtnum]++; } } break; - - case PAL::swpctx: - if (tc->getSystemPtr()->kernelBinning) - tc->getSystemPtr()->kernelBinning->palSwapContext(tc); - break; } } diff --git a/src/kern/kernel_stats.hh b/src/kern/kernel_stats.hh index 781b6f6da..c691ad8cf 100644 --- a/src/kern/kernel_stats.hh +++ b/src/kern/kernel_stats.hh @@ -47,95 +47,17 @@ class System; namespace Kernel { -enum cpu_mode { kernel, user, idle, interrupt, cpu_mode_num }; +enum cpu_mode { kernel, user, idle, cpu_mode_num }; extern const char *modestr[]; -class Binning -{ - private: - std::string myname; - System *system; - - private: - // lisa's binning stuff - struct fnCall - { - Stats::MainBin *myBin; - std::string name; - }; - - struct SWContext - { - Counter calls; - std::stack<fnCall *> callStack; - }; - - std::map<const std::string, Stats::MainBin *> fnBins; - std::map<const Addr, SWContext *> swCtxMap; - - std::multimap<const std::string, std::string> callerMap; - void populateMap(std::string caller, std::string callee); - - std::vector<FnEvent *> fnEvents; - - Stats::Scalar<> fnCalls; - - Stats::MainBin *getBin(const std::string &name); - bool findCaller(std::string, std::string) const; - - SWContext *findContext(Addr pcb); - bool addContext(Addr pcb, SWContext *ctx) - { - return (swCtxMap.insert(std::make_pair(pcb, ctx))).second; - } - - void remContext(Addr pcb) - { - swCtxMap.erase(pcb); - } - - void dumpState() const; - - SWContext *swctx; - std::vector<std::string> binned_fns; - - private: - Stats::MainBin *modeBin[cpu_mode_num]; - - public: - const bool bin; - const bool fnbin; - - cpu_mode themode; - void palSwapContext(ThreadContext *tc); - void execute(ThreadContext *tc, StaticInstPtr inst); - void call(ThreadContext *tc, Stats::MainBin *myBin); - void changeMode(cpu_mode mode); - - public: - Binning(System *sys); - virtual ~Binning(); - - const std::string name() const { return myname; } - void regStats(const std::string &name); - - public: - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); -}; - class Statistics : public Serializable { private: - friend class Binning; - - private: std::string myname; Addr idleProcess; cpu_mode themode; Tick lastModeTick; - bool bin_int; void changeMode(cpu_mode newmode, ThreadContext *tc); diff --git a/src/kern/system_events.cc b/src/kern/system_events.cc index fe3805ce2..177ce96d1 100644 --- a/src/kern/system_events.cc +++ b/src/kern/system_events.cc @@ -55,22 +55,6 @@ SkipFuncEvent::process(ThreadContext *tc) */ } - -FnEvent::FnEvent(PCEventQueue *q, const std::string &desc, Addr addr, - Stats::MainBin *bin) - : PCEvent(q, desc, addr), _name(desc), mybin(bin) -{ -} - -void -FnEvent::process(ThreadContext *tc) -{ - if (tc->misspeculating()) - return; - - tc->getSystemPtr()->kernelBinning->call(tc, mybin); -} - void IdleStartEvent::process(ThreadContext *tc) { @@ -79,19 +63,3 @@ IdleStartEvent::process(ThreadContext *tc) tc->readMiscReg(AlphaISA::IPR_PALtemp23), tc); remove(); } - -void -InterruptStartEvent::process(ThreadContext *tc) -{ - if (tc->getKernelStats()) - tc->getKernelStats()->mode(Kernel::interrupt, tc); -} - -void -InterruptEndEvent::process(ThreadContext *tc) -{ - // We go back to kernel, if we are user, inside the rti - // pal code we will get switched to user because of the ICM write - if (tc->getKernelStats()) - tc->getKernelStats()->mode(Kernel::kernel, tc); -} diff --git a/src/kern/system_events.hh b/src/kern/system_events.hh index 05c878577..ccd6bd9a4 100644 --- a/src/kern/system_events.hh +++ b/src/kern/system_events.hh @@ -45,19 +45,6 @@ class SkipFuncEvent : public PCEvent virtual void process(ThreadContext *tc); }; -class FnEvent : public PCEvent -{ - public: - FnEvent(PCEventQueue *q, const std::string &desc, Addr addr, - Stats::MainBin *bin); - virtual void process(ThreadContext *tc); - std::string myname() const { return _name; } - - private: - std::string _name; - Stats::MainBin *mybin; -}; - class IdleStartEvent : public PCEvent { public: @@ -67,23 +54,4 @@ class IdleStartEvent : public PCEvent virtual void process(ThreadContext *tc); }; -class InterruptStartEvent : public PCEvent -{ - public: - InterruptStartEvent(PCEventQueue *q, const std::string &desc, Addr addr) - : PCEvent(q, desc, addr) - {} - virtual void process(ThreadContext *tc); -}; - -class InterruptEndEvent : public PCEvent -{ - public: - InterruptEndEvent(PCEventQueue *q, const std::string &desc, Addr addr) - : PCEvent(q, desc, addr) - {} - virtual void process(ThreadContext *tc); -}; - - #endif // __SYSTEM_EVENTS_HH__ diff --git a/src/python/SConscript b/src/python/SConscript index 5a787cfdf..7b0f591eb 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -38,11 +38,8 @@ def join(*args): Import('env') -# This SConscript is in charge of collecting .py files and generating a zip archive that is appended to the m5 binary. - -# Copy .py source files here (relative to src/python in the build -# directory). -pyzip_root = 'zip' +# This SConscript is in charge of collecting .py files and generating +# a zip archive that is appended to the m5 binary. # List of files & directories to include in the zip file. To include # a package, list only the root directory of the package, not any @@ -58,7 +55,7 @@ pyzip_dep_files = [] # Add the specified package to the zip archive. Adds the directory to # pyzip_files and all included .py files to pyzip_dep_files. def addPkg(pkgdir): - pyzip_files.append(join(pyzip_root, pkgdir)) + pyzip_files.append(pkgdir) origdir = os.getcwd() srcdir = join(Dir('.').srcnode().abspath, pkgdir) os.chdir(srcdir) @@ -70,10 +67,7 @@ def addPkg(pkgdir): for f in files: if f.endswith('.py'): - source = join(pkgdir, path, f) - target = join(pyzip_root, source) - pyzip_dep_files.append(target) - env.CopyFile(target, source) + pyzip_dep_files.append(join(pkgdir, path, f)) os.chdir(origdir) @@ -81,19 +75,25 @@ def addPkg(pkgdir): # build_env flags. def MakeDefinesPyFile(target, source, env): f = file(str(target[0]), 'w') - print >>f, "import __main__" - print >>f, "__main__.m5_build_env = ", + print >>f, "m5_build_env = ", print >>f, source[0] f.close() optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions]) -env.Command('defines.py', Value(optionDict), MakeDefinesPyFile) +env.Command('m5/defines.py', Value(optionDict), MakeDefinesPyFile) # Now specify the packages & files for the zip archive. addPkg('m5') -pyzip_files.append('defines.py') +pyzip_files.append('m5/defines.py') pyzip_files.append(join(env['ROOT'], 'util/pbs/jobfile.py')) +env.Command(['swig/main_wrap.cc', 'm5/main.py'], + 'swig/main.i', + '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' + '-o ${TARGETS[0]} $SOURCES') + +pyzip_dep_files.append('m5/main.py') + # Action function to build the zip archive. Uses the PyZipFile module # included in the standard Python library. def buildPyZip(target, source, env): diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 4f29c55e8..60a61d66e 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -27,69 +27,26 @@ # Authors: Nathan Binkert # Steve Reinhardt -import sys, os, time +import sys, os, time, atexit, optparse -import __main__ +# import the SWIG-wrapped main C++ functions +import main +# import a few SWIG-wrapped items (those that are likely to be used +# directly by user scripts) completely into this module for +# convenience +from main import simulate, SimLoopExitEvent -briefCopyright = ''' -Copyright (c) 2001-2006 -The Regents of The University of Michigan -All Rights Reserved -''' - -fullCopyright = ''' -Copyright (c) 2001-2006 -The Regents of The University of Michigan -All Rights Reserved - -Permission is granted to use, copy, create derivative works and -redistribute this software and such derivative works for any purpose, -so long as the copyright notice above, this grant of permission, and -the disclaimer below appear in all copies made; and so long as the -name of The University of Michigan is not used in any advertising or -publicity pertaining to the use or distribution of this software -without specific, written prior authorization. - -THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE -UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT -WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR -IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF -THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES, -INCLUDING DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION -WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER -ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -''' - -def sayHello(f): - print >> f, "M5 Simulator System" - print >> f, briefCopyright - print >> f, "M5 compiled on", __main__.compileDate - hostname = os.environ.get('HOSTNAME') - if not hostname: - hostname = os.environ.get('HOST') - if hostname: - print >> f, "M5 executing on", hostname - print >> f, "M5 simulation started", time.ctime() - -sayHello(sys.stderr) +# import the m5 compile options +import defines # define this here so we can use it right away if necessary def panic(string): print >>sys.stderr, 'panic:', string sys.exit(1) -def m5execfile(f, global_dict): - # copy current sys.path - oldpath = sys.path[:] - # push file's directory onto front of path - sys.path.insert(0, os.path.abspath(os.path.dirname(f))) - execfile(f, global_dict) - # restore original path - sys.path = oldpath - -# Prepend given directory to system module search path. +# Prepend given directory to system module search path. We may not +# need this anymore if we can structure our config library more like a +# Python package. def AddToPath(path): # if it's a relative path and we know what directory the current # python script is in, make the path relative to that directory. @@ -100,85 +57,58 @@ def AddToPath(path): # so place the new dir right after that. sys.path.insert(1, path) -# find the m5 compile options: must be specified as a dict in -# __main__.m5_build_env. -import __main__ -if not hasattr(__main__, 'm5_build_env'): - panic("__main__ must define m5_build_env") + +# Callback to set trace flags. Not necessarily the best way to do +# things in the long run (particularly if we change how these global +# options are handled). +def setTraceFlags(option, opt_str, value, parser): + objects.Trace.flags = value + +# Standard optparse options. Need to be explicitly included by the +# user script when it calls optparse.OptionParser(). +standardOptions = [ + optparse.make_option("--traceflags", type="string", action="callback", + callback=setTraceFlags) + ] # make a SmartDict out of the build options for our local use import smartdict build_env = smartdict.SmartDict() -build_env.update(__main__.m5_build_env) +build_env.update(defines.m5_build_env) # make a SmartDict out of the OS environment too env = smartdict.SmartDict() env.update(os.environ) -# import the main m5 config code -from config import * - -# import the built-in object definitions -from objects import * - - -args_left = sys.argv[1:] -configfile_found = False - -while args_left: - arg = args_left.pop(0) - if arg.startswith('--'): - # if arg starts with '--', parse as a special python option - # of the format --<python var>=<string value> - try: - (var, val) = arg.split('=', 1) - var = var[2:] - except ValueError: - panic("Could not parse configuration argument '%s'\n" - "Expecting --<variable>=<value>\n" % arg); - exec "%s = %s" % (var, repr(val)) - elif arg.startswith('-'): - # if the arg starts with '-', it should be a simulator option - # with a format similar to getopt. - optchar = arg[1] - if len(arg) > 2: - args_left.insert(0, arg[2:]) - if optchar == 'd': - outdir = args_left.pop(0) - elif optchar == 'h': - showBriefHelp(sys.stderr) - sys.exit(1) - elif optchar == 'E': - env_str = args_left.pop(0) - split_result = env_str.split('=', 1) - var = split_result[0] - if len(split_result == 2): - val = split_result[1] - else: - val = True - env[var] = val - elif optchar == 'I': - AddToPath(args_left.pop(0)) - elif optchar == 'P': - exec args_left.pop(0) - else: - showBriefHelp(sys.stderr) - panic("invalid argument '%s'\n" % arg_str) - else: - # In any other case, treat the option as a configuration file - # name and load it. - if not arg.endswith('.py'): - panic("Config file '%s' must end in '.py'\n" % arg) - configfile_found = True - m5execfile(arg, globals()) - - -if not configfile_found: - panic("no configuration file specified!") - -if globals().has_key('root') and isinstance(root, Root): +# The final hook to generate .ini files. Called from the user script +# once the config is built. +def instantiate(root): + config.ticks_per_sec = float(root.clock.frequency) + # ugly temporary hack to get output to config.ini sys.stdout = file('config.ini', 'w') - instantiate(root) -else: - print 'Instantiation skipped: no root object found.' - + root.print_ini() + sys.stdout.close() # close config.ini + sys.stdout = sys.__stdout__ # restore to original + main.initialize() # load config.ini into C++ and process it + noDot = True # temporary until we fix dot + if not noDot: + dot = pydot.Dot() + instance.outputDot(dot) + dot.orientation = "portrait" + dot.size = "8.5,11" + dot.ranksep="equally" + dot.rank="samerank" + dot.write("config.dot") + dot.write_ps("config.ps") + +# Export curTick to user script. +def curTick(): + return main.cvar.curTick + +# register our C++ exit callback function with Python +atexit.register(main.doExitCleanup) + +# This import allows user scripts to reference 'm5.objects.Foo' after +# just doing an 'import m5' (without an 'import m5.objects'). May not +# matter since most scripts will probably 'from m5.objects import *'. +import objects diff --git a/src/python/m5/config.py b/src/python/m5/config.py index d1471c807..97e13c900 100644 --- a/src/python/m5/config.py +++ b/src/python/m5/config.py @@ -27,11 +27,10 @@ # Authors: Steve Reinhardt # Nathan Binkert -from __future__ import generators import os, re, sys, types, inspect import m5 -panic = m5.panic +from m5 import panic from convert import * from multidict import multidict @@ -137,8 +136,15 @@ class Singleton(type): def isSimObject(value): return isinstance(value, SimObject) -def isSimObjSequence(value): - if not isinstance(value, (list, tuple)): +def isSimObjectClass(value): + try: + return issubclass(value, SimObject) + except TypeError: + # happens if value is not a class at all + return False + +def isSimObjectSequence(value): + if not isinstance(value, (list, tuple)) or len(value) == 0: return False for val in value: @@ -147,9 +153,41 @@ def isSimObjSequence(value): return True +def isSimObjectClassSequence(value): + if not isinstance(value, (list, tuple)) or len(value) == 0: + return False + + for val in value: + if not isNullPointer(val) and not isSimObjectClass(val): + return False + + return True + +def isSimObjectOrSequence(value): + return isSimObject(value) or isSimObjectSequence(value) + +def isSimObjectClassOrSequence(value): + return isSimObjectClass(value) or isSimObjectClassSequence(value) + def isNullPointer(value): return isinstance(value, NullSimObject) +# Apply method to object. +# applyMethod(obj, 'meth', <args>) is equivalent to obj.meth(<args>) +def applyMethod(obj, meth, *args, **kwargs): + return getattr(obj, meth)(*args, **kwargs) + +# If the first argument is an (non-sequence) object, apply the named +# method with the given arguments. If the first argument is a +# sequence, apply the method to each element of the sequence (a la +# 'map'). +def applyOrMap(objOrSeq, meth, *args, **kwargs): + if not isinstance(objOrSeq, (list, tuple)): + return applyMethod(objOrSeq, meth, *args, **kwargs) + else: + return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq] + + # The metaclass for ConfigNode (and thus for everything that derives # from ConfigNode, including SimObject). This class controls how new # classes that derive from ConfigNode are instantiated, and provides @@ -170,24 +208,32 @@ class MetaSimObject(type): # and only allow "private" attributes to be passed to the base # __new__ (starting with underscore). def __new__(mcls, name, bases, dict): - # Copy "private" attributes (including special methods such as __new__) - # to the official dict. Everything else goes in _init_dict to be - # filtered in __init__. - cls_dict = {} - for key,val in dict.items(): - if key.startswith('_'): - cls_dict[key] = val - del dict[key] - cls_dict['_init_dict'] = dict + if dict.has_key('_init_dict'): + # must have been called from makeSubclass() rather than + # via Python class declaration; bypass filtering process. + cls_dict = dict + else: + # Copy "private" attributes (including special methods + # such as __new__) to the official dict. Everything else + # goes in _init_dict to be filtered in __init__. + cls_dict = {} + for key,val in dict.items(): + if key.startswith('_'): + cls_dict[key] = val + del dict[key] + cls_dict['_init_dict'] = dict return super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) - # initialization + # subclass initialization def __init__(cls, name, bases, dict): + # calls type.__init__()... I think that's a no-op, but leave + # it here just in case it's not. super(MetaSimObject, cls).__init__(name, bases, dict) # initialize required attributes cls._params = multidict() cls._values = multidict() + cls._instantiated = False # really instantiated or subclassed cls._anon_subclass_counter = 0 # We don't support multiple inheritance. If you want to, you @@ -197,27 +243,14 @@ class MetaSimObject(type): base = bases[0] + # the only time the following is not true is when we define + # the SimObject class itself if isinstance(base, MetaSimObject): cls._params.parent = base._params cls._values.parent = base._values + base._instantiated = True - # If your parent has a value in it that's a config node, clone - # it. Do this now so if we update any of the values' - # attributes we are updating the clone and not the original. - for key,val in base._values.iteritems(): - - # don't clone if (1) we're about to overwrite it with - # a local setting or (2) we've already cloned a copy - # from an earlier (more derived) base - if cls._init_dict.has_key(key) or cls._values.has_key(key): - continue - - if isSimObject(val): - cls._values[key] = val() - elif isSimObjSequence(val) and len(val): - cls._values[key] = [ v() for v in val ] - - # now process remaining _init_dict items + # now process the _init_dict items for key,val in cls._init_dict.items(): if isinstance(val, (types.FunctionType, types.TypeType)): type.__setattr__(cls, key, val) @@ -234,6 +267,27 @@ class MetaSimObject(type): else: setattr(cls, key, val) + # Pull the deep-copy memoization dict out of the class dict if + # it's there... + memo = cls.__dict__.get('_memo', {}) + + # Handle SimObject values + for key,val in cls._values.iteritems(): + # SimObject instances need to be promoted to classes. + # Existing classes should not have any instance values, so + # these can only occur at the lowest level dict (the + # parameters just being set in this class definition). + if isSimObjectOrSequence(val): + assert(val == cls._values.local[key]) + cls._values[key] = applyOrMap(val, 'makeClass', memo) + # SimObject classes need to be subclassed so that + # parameters that get set at this level only affect this + # level and derivatives. + elif isSimObjectClassOrSequence(val): + assert(not cls._values.local.has_key(key)) + cls._values[key] = applyOrMap(val, 'makeSubclass', {}, memo) + + def _set_keyword(cls, keyword, val, kwtype): if not isinstance(val, kwtype): raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ @@ -263,6 +317,11 @@ class MetaSimObject(type): param = cls._params.get(attr, None) if param: # It's ok: set attribute by delegating to 'object' class. + if isSimObjectOrSequence(value) and cls._instantiated: + raise AttributeError, \ + "Cannot set SimObject parameter '%s' after\n" \ + " class %s has been instantiated or subclassed" \ + % (attr, cls.__name__) try: cls._values[attr] = param.convert(value) except Exception, e: @@ -271,7 +330,7 @@ class MetaSimObject(type): e.args = (msg, ) raise # I would love to get rid of this - elif isSimObject(value) or isSimObjSequence(value): + elif isSimObjectOrSequence(value): cls._values[attr] = value else: raise AttributeError, \ @@ -284,6 +343,22 @@ class MetaSimObject(type): raise AttributeError, \ "object '%s' has no attribute '%s'" % (cls.__name__, attr) + # Create a subclass of this class. Basically a function interface + # to the standard Python class definition mechanism, primarily for + # internal use. 'memo' dict param supports "deep copy" (really + # "deep subclass") operations... within a given operation, + # multiple references to a class should result in a single + # subclass object with multiple references to it (as opposed to + # mutiple unique subclasses). + def makeSubclass(cls, init_dict, memo = {}): + subcls = memo.get(cls) + if not subcls: + name = cls.__name__ + '_' + str(cls._anon_subclass_counter) + cls._anon_subclass_counter += 1 + subcls = MetaSimObject(name, (cls,), + { '_init_dict': init_dict, '_memo': memo }) + return subcls + # The ConfigNode class is the root of the special hierarchy. Most of # the code in this class deals with the configuration hierarchy itself # (parent/child node relationships). @@ -292,27 +367,80 @@ class SimObject(object): # get this metaclass. __metaclass__ = MetaSimObject - def __init__(self, _value_parent = None, **kwargs): + # __new__ operator allocates new instances of the class. We + # override it here just to support "deep instantiation" operation + # via the _memo dict. When recursively instantiating an object + # hierarchy we want to make sure that each class is instantiated + # only once, and that if there are multiple references to the same + # original class, we end up with the corresponding instantiated + # references all pointing to the same instance. + def __new__(cls, _memo = None, **kwargs): + if _memo is not None and _memo.has_key(cls): + # return previously instantiated object + assert(len(kwargs) == 0) + return _memo[cls] + else: + # Need a new one... if it needs to be memoized, this will + # happen in __init__. We defer the insertion until then + # so __init__ can use the memo dict to tell whether or not + # to perform the initialization. + return super(SimObject, cls).__new__(cls, **kwargs) + + # Initialize new instance previously allocated by __new__. For + # objects with SimObject-valued params, we need to recursively + # instantiate the classes represented by those param values as + # well (in a consistent "deep copy"-style fashion; see comment + # above). + def __init__(self, _memo = None, **kwargs): + if _memo is not None: + # We're inside a "deep instantiation" + assert(isinstance(_memo, dict)) + assert(len(kwargs) == 0) + if _memo.has_key(self.__class__): + # __new__ returned an existing, already initialized + # instance, so there's nothing to do here + assert(_memo[self.__class__] == self) + return + # no pre-existing object, so remember this one here + _memo[self.__class__] = self + else: + # This is a new top-level instantiation... don't memoize + # this objcet, but prepare to memoize any recursively + # instantiated objects. + _memo = {} + + self.__class__._instantiated = True + self._children = {} - if _value_parent and type(_value_parent) != type(self): - # this was called as a type conversion rather than a clone - raise TypeError, "Cannot convert %s to %s" % \ - (_value_parent.__class__.__name__, self.__class__.__name__) - if not _value_parent: - _value_parent = self.__class__ - # clone values - self._values = multidict(_value_parent._values) - for key,val in _value_parent._values.iteritems(): - if isSimObject(val): - setattr(self, key, val()) - elif isSimObjSequence(val) and len(val): - setattr(self, key, [ v() for v in val ]) + # Inherit parameter values from class using multidict so + # individual value settings can be overridden. + self._values = multidict(self.__class__._values) + # For SimObject-valued parameters, the class should have + # classes (not instances) for the values. We need to + # instantiate these classes rather than just inheriting the + # class object. + for key,val in self.__class__._values.iteritems(): + if isSimObjectClass(val): + setattr(self, key, val(_memo)) + elif isSimObjectClassSequence(val) and len(val): + setattr(self, key, [ v(_memo) for v in val ]) # apply attribute assignments from keyword args, if any for key,val in kwargs.iteritems(): setattr(self, key, val) + # Use this instance as a template to create a new class. + def makeClass(self, memo = {}): + cls = memo.get(self) + if not cls: + cls = self.__class__.makeSubclass(self._values.local) + memo[self] = cls + return cls + + # Direct instantiation of instances (cloning) is no longer + # allowed; must generate class from instance first. def __call__(self, **kwargs): - return self.__class__(_value_parent = self, **kwargs) + raise TypeError, "cannot instantiate SimObject; "\ + "use makeClass() to make class first" def __getattr__(self, attr): if self._values.has_key(attr): @@ -341,7 +469,7 @@ class SimObject(object): e.args = (msg, ) raise # I would love to get rid of this - elif isSimObject(value) or isSimObjSequence(value): + elif isSimObjectOrSequence(value): pass else: raise AttributeError, "Class %s has no parameter %s" \ @@ -352,7 +480,7 @@ class SimObject(object): if isSimObject(value): value.set_path(self, attr) - elif isSimObjSequence(value): + elif isSimObjectSequence(value): value = SimObjVector(value) [v.set_path(self, "%s%d" % (attr, i)) for i,v in enumerate(value)] @@ -728,7 +856,7 @@ class ParamDesc(object): def __getattr__(self, attr): if attr == 'ptype': try: - ptype = eval(self.ptype_str, m5.__dict__) + ptype = eval(self.ptype_str, m5.objects.__dict__) if not isinstance(ptype, type): panic("Param qualifier is not a type: %s" % self.ptype) self.ptype = ptype @@ -775,7 +903,7 @@ class VectorParamDesc(ParamDesc): if isinstance(value, (list, tuple)): # list: coerce each element into new list tmp_list = [ ParamDesc.convert(self, v) for v in value ] - if isSimObjSequence(tmp_list): + if isSimObjectSequence(tmp_list): return SimObjVector(tmp_list) else: return VectorParamValue(tmp_list) @@ -1069,7 +1197,10 @@ class EthernetAddr(ParamValue): def __str__(self): if self.value == NextEthernetAddr: - return self.addr + if hasattr(self, 'addr'): + return self.addr + else: + return "NextEthernetAddr (unresolved)" else: return self.value @@ -1290,23 +1421,6 @@ AllMemory = AddrRange(0, MaxAddr) ##################################################################### -# The final hook to generate .ini files. Called from configuration -# script once config is built. -def instantiate(root): - global ticks_per_sec - ticks_per_sec = float(root.clock.frequency) - root.print_ini() - noDot = True # temporary until we fix dot - if not noDot: - dot = pydot.Dot() - instance.outputDot(dot) - dot.orientation = "portrait" - dot.size = "8.5,11" - dot.ranksep="equally" - dot.rank="samerank" - dot.write("config.dot") - dot.write_ps("config.ps") - # __all__ defines the list of symbols that get exported when # 'from config import *' is invoked. Try to keep this reasonably # short to avoid polluting other namespaces. @@ -1322,5 +1436,5 @@ __all__ = ['SimObject', 'ParamContext', 'Param', 'VectorParam', 'NetworkBandwidth', 'MemoryBandwidth', 'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory', 'Null', 'NULL', - 'NextEthernetAddr', 'instantiate'] + 'NextEthernetAddr'] diff --git a/src/python/m5/multidict.py b/src/python/m5/multidict.py index 698e85b26..34fc3139b 100644 --- a/src/python/m5/multidict.py +++ b/src/python/m5/multidict.py @@ -31,7 +31,7 @@ __all__ = [ 'multidict' ] class multidict(object): __nodefault = object() def __init__(self, parent = {}, **kwargs): - self.dict = dict(**kwargs) + self.local = dict(**kwargs) self.parent = parent self.deleted = {} @@ -42,11 +42,11 @@ class multidict(object): return `dict(self.items())` def __contains__(self, key): - return self.dict.has_key(key) or self.parent.has_key(key) + return self.local.has_key(key) or self.parent.has_key(key) def __delitem__(self, key): try: - del self.dict[key] + del self.local[key] except KeyError, e: if key in self.parent: self.deleted[key] = True @@ -55,11 +55,11 @@ class multidict(object): def __setitem__(self, key, value): self.deleted.pop(key, False) - self.dict[key] = value + self.local[key] = value def __getitem__(self, key): try: - return self.dict[key] + return self.local[key] except KeyError, e: if not self.deleted.get(key, False) and key in self.parent: return self.parent[key] @@ -67,15 +67,15 @@ class multidict(object): raise KeyError, e def __len__(self): - return len(self.dict) + len(self.parent) + return len(self.local) + len(self.parent) def next(self): - for key,value in self.dict.items(): + for key,value in self.local.items(): yield key,value if self.parent: for key,value in self.parent.next(): - if key not in self.dict and key not in self.deleted: + if key not in self.local and key not in self.deleted: yield key,value def has_key(self, key): @@ -116,22 +116,22 @@ class multidict(object): return self[key] except KeyError: self.deleted.pop(key, False) - self.dict[key] = default + self.local[key] = default return default def _dump(self): print 'multidict dump' node = self while isinstance(node, multidict): - print ' ', node.dict + print ' ', node.local node = node.parent def _dumpkey(self, key): values = [] node = self while isinstance(node, multidict): - if key in node.dict: - values.append(node.dict[key]) + if key in node.local: + values.append(node.local[key]) node = node.parent print key, values diff --git a/src/python/m5/objects/AlphaConsole.py b/src/python/m5/objects/AlphaConsole.py index 68e6089ab..329b8c5bd 100644 --- a/src/python/m5/objects/AlphaConsole.py +++ b/src/python/m5/objects/AlphaConsole.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Device import BasicPioDevice class AlphaConsole(BasicPioDevice): diff --git a/src/python/m5/objects/AlphaFullCPU.py b/src/python/m5/objects/AlphaFullCPU.py index 7c772d3f2..2988305d3 100644 --- a/src/python/m5/objects/AlphaFullCPU.py +++ b/src/python/m5/objects/AlphaFullCPU.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * from BaseCPU import BaseCPU class DerivAlphaFullCPU(BaseCPU): diff --git a/src/python/m5/objects/AlphaTLB.py b/src/python/m5/objects/AlphaTLB.py index 5edf8e13d..11c1792ee 100644 --- a/src/python/m5/objects/AlphaTLB.py +++ b/src/python/m5/objects/AlphaTLB.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class AlphaTLB(SimObject): type = 'AlphaTLB' abstract = True diff --git a/src/python/m5/objects/BadDevice.py b/src/python/m5/objects/BadDevice.py index 9cb9a8f03..186b733fa 100644 --- a/src/python/m5/objects/BadDevice.py +++ b/src/python/m5/objects/BadDevice.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Device import BasicPioDevice class BadDevice(BasicPioDevice): diff --git a/src/python/m5/objects/BaseCPU.py b/src/python/m5/objects/BaseCPU.py index 49cb2a8f3..2e78578df 100644 --- a/src/python/m5/objects/BaseCPU.py +++ b/src/python/m5/objects/BaseCPU.py @@ -1,4 +1,6 @@ -from m5 import * +from m5 import build_env +from m5.config import * + class BaseCPU(SimObject): type = 'BaseCPU' abstract = True diff --git a/src/python/m5/objects/BaseCache.py b/src/python/m5/objects/BaseCache.py index 79d21572a..33f44759b 100644 --- a/src/python/m5/objects/BaseCache.py +++ b/src/python/m5/objects/BaseCache.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from BaseMem import BaseMem class Prefetch(Enum): vals = ['none', 'tagged', 'stride', 'ghb'] diff --git a/src/python/m5/objects/Bridge.py b/src/python/m5/objects/Bridge.py index ada715ce9..880535755 100644 --- a/src/python/m5/objects/Bridge.py +++ b/src/python/m5/objects/Bridge.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from MemObject import MemObject class Bridge(MemObject): diff --git a/src/python/m5/objects/Bus.py b/src/python/m5/objects/Bus.py index 8c5397281..c37dab438 100644 --- a/src/python/m5/objects/Bus.py +++ b/src/python/m5/objects/Bus.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from MemObject import MemObject class Bus(MemObject): diff --git a/src/python/m5/objects/CoherenceProtocol.py b/src/python/m5/objects/CoherenceProtocol.py index 7013000d6..64b6cbacf 100644 --- a/src/python/m5/objects/CoherenceProtocol.py +++ b/src/python/m5/objects/CoherenceProtocol.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class Coherence(Enum): vals = ['uni', 'msi', 'mesi', 'mosi', 'moesi'] class CoherenceProtocol(SimObject): diff --git a/src/python/m5/objects/Device.py b/src/python/m5/objects/Device.py index 2a71bbc65..7798f5f04 100644 --- a/src/python/m5/objects/Device.py +++ b/src/python/m5/objects/Device.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from MemObject import MemObject class PioDevice(MemObject): diff --git a/src/python/m5/objects/DiskImage.py b/src/python/m5/objects/DiskImage.py index 0d55e9329..70d8b2e45 100644 --- a/src/python/m5/objects/DiskImage.py +++ b/src/python/m5/objects/DiskImage.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class DiskImage(SimObject): type = 'DiskImage' abstract = True diff --git a/src/python/m5/objects/Ethernet.py b/src/python/m5/objects/Ethernet.py index 4286c71c8..418670592 100644 --- a/src/python/m5/objects/Ethernet.py +++ b/src/python/m5/objects/Ethernet.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * from Device import DmaDevice from Pci import PciDevice diff --git a/src/python/m5/objects/FUPool.py b/src/python/m5/objects/FUPool.py index 5eecfd12f..cbf1089cf 100644 --- a/src/python/m5/objects/FUPool.py +++ b/src/python/m5/objects/FUPool.py @@ -1,7 +1,4 @@ -from m5 import * -from FullCPU import OpType -from FullCPU import OpDesc -from FullCPU import FUDesc +from m5.config import * class FUPool(SimObject): type = 'FUPool' diff --git a/src/python/m5/objects/Ide.py b/src/python/m5/objects/Ide.py index 2403e6d36..9ee578177 100644 --- a/src/python/m5/objects/Ide.py +++ b/src/python/m5/objects/Ide.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Pci import PciDevice class IdeID(Enum): vals = ['master', 'slave'] diff --git a/src/python/m5/objects/IntrControl.py b/src/python/m5/objects/IntrControl.py index 66c82c182..514c3fc62 100644 --- a/src/python/m5/objects/IntrControl.py +++ b/src/python/m5/objects/IntrControl.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class IntrControl(SimObject): type = 'IntrControl' cpu = Param.BaseCPU(Parent.any, "the cpu") diff --git a/src/python/m5/objects/MemObject.py b/src/python/m5/objects/MemObject.py index 4d68243e6..d957dae17 100644 --- a/src/python/m5/objects/MemObject.py +++ b/src/python/m5/objects/MemObject.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class MemObject(SimObject): type = 'MemObject' diff --git a/src/python/m5/objects/MemTest.py b/src/python/m5/objects/MemTest.py index 34299faf0..9916d7cb4 100644 --- a/src/python/m5/objects/MemTest.py +++ b/src/python/m5/objects/MemTest.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class MemTest(SimObject): type = 'MemTest' cache = Param.BaseCache("L1 cache") diff --git a/src/python/m5/objects/OzoneCPU.py b/src/python/m5/objects/OzoneCPU.py index ea8b6b537..f2d9aea84 100644 --- a/src/python/m5/objects/OzoneCPU.py +++ b/src/python/m5/objects/OzoneCPU.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * from BaseCPU import BaseCPU class DerivOzoneCPU(BaseCPU): diff --git a/src/python/m5/objects/Pci.py b/src/python/m5/objects/Pci.py index 85cefcd44..9e1e91b13 100644 --- a/src/python/m5/objects/Pci.py +++ b/src/python/m5/objects/Pci.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Device import BasicPioDevice, DmaDevice class PciConfigData(SimObject): diff --git a/src/python/m5/objects/PhysicalMemory.py b/src/python/m5/objects/PhysicalMemory.py index c59910093..bed90d555 100644 --- a/src/python/m5/objects/PhysicalMemory.py +++ b/src/python/m5/objects/PhysicalMemory.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from MemObject import * class PhysicalMemory(MemObject): diff --git a/src/python/m5/objects/Platform.py b/src/python/m5/objects/Platform.py index 4da0ffab4..89fee9991 100644 --- a/src/python/m5/objects/Platform.py +++ b/src/python/m5/objects/Platform.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class Platform(SimObject): type = 'Platform' abstract = True diff --git a/src/python/m5/objects/Process.py b/src/python/m5/objects/Process.py index 60b00229e..0091d8654 100644 --- a/src/python/m5/objects/Process.py +++ b/src/python/m5/objects/Process.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class Process(SimObject): type = 'Process' abstract = True diff --git a/src/python/m5/objects/Repl.py b/src/python/m5/objects/Repl.py index afd256082..8e9f1094f 100644 --- a/src/python/m5/objects/Repl.py +++ b/src/python/m5/objects/Repl.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class Repl(SimObject): type = 'Repl' abstract = True diff --git a/src/python/m5/objects/Root.py b/src/python/m5/objects/Root.py index 205a93c76..373475a7a 100644 --- a/src/python/m5/objects/Root.py +++ b/src/python/m5/objects/Root.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Serialize import Serialize from Statistics import Statistics from Trace import Trace diff --git a/src/python/m5/objects/SimConsole.py b/src/python/m5/objects/SimConsole.py index df3061908..9e1452c6d 100644 --- a/src/python/m5/objects/SimConsole.py +++ b/src/python/m5/objects/SimConsole.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class ConsoleListener(SimObject): type = 'ConsoleListener' port = Param.TcpPort(3456, "listen port") diff --git a/src/python/m5/objects/SimpleDisk.py b/src/python/m5/objects/SimpleDisk.py index e34155ace..44ef709af 100644 --- a/src/python/m5/objects/SimpleDisk.py +++ b/src/python/m5/objects/SimpleDisk.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class SimpleDisk(SimObject): type = 'SimpleDisk' disk = Param.DiskImage("Disk Image") diff --git a/src/python/m5/objects/SimpleOzoneCPU.py b/src/python/m5/objects/SimpleOzoneCPU.py index 0d6403383..5d968cab0 100644 --- a/src/python/m5/objects/SimpleOzoneCPU.py +++ b/src/python/m5/objects/SimpleOzoneCPU.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * from BaseCPU import BaseCPU class SimpleOzoneCPU(BaseCPU): diff --git a/src/python/m5/objects/System.py b/src/python/m5/objects/System.py index 622b5a870..9a1e1d690 100644 --- a/src/python/m5/objects/System.py +++ b/src/python/m5/objects/System.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * class System(SimObject): type = 'System' @@ -7,8 +8,6 @@ class System(SimObject): boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency, "boot processor frequency") init_param = Param.UInt64(0, "numerical value to pass into simulator") - bin = Param.Bool(False, "is this system binned") - binned_fns = VectorParam.String([], "functions broken down and binned") boot_osflags = Param.String("a", "boot flags to pass to the kernel") kernel = Param.String("file that contains the kernel code") readfile = Param.String("", "file to read startup script from") diff --git a/src/python/m5/objects/Tsunami.py b/src/python/m5/objects/Tsunami.py index 27ea0bce8..4613571d8 100644 --- a/src/python/m5/objects/Tsunami.py +++ b/src/python/m5/objects/Tsunami.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Device import BasicPioDevice from Platform import Platform diff --git a/src/python/m5/objects/Uart.py b/src/python/m5/objects/Uart.py index 54754aeb9..8e1fd1a37 100644 --- a/src/python/m5/objects/Uart.py +++ b/src/python/m5/objects/Uart.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * from Device import BasicPioDevice class Uart(BasicPioDevice): diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index d90d0923a..6ae838897 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -102,7 +102,7 @@ EventQueue::remove(Event *event) prev->next = curr->next; } -void +Event * EventQueue::serviceOne() { Event *event = head; @@ -110,13 +110,20 @@ EventQueue::serviceOne() head = event->next; // handle action - if (!event->squashed()) + if (!event->squashed()) { event->process(); - else + if (event->isExitEvent()) { + assert(!event->getFlags(Event::AutoDelete)); // would be silly + return event; + } + } else { event->clearFlags(Event::Squashed); + } if (event->getFlags(Event::AutoDelete) && !event->scheduled()) delete event; + + return NULL; } diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index a5cc0c1b6..430473df3 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -90,7 +90,8 @@ class Event : public Serializable, public FastAlloc Squashed = 0x1, Scheduled = 0x2, AutoDelete = 0x4, - AutoSerialize = 0x8 + AutoSerialize = 0x8, + IsExitEvent = 0x10 }; bool getFlags(Flags f) const { return (_flags & f) == f; } @@ -214,6 +215,9 @@ class Event : public Serializable, public FastAlloc /// Check whether the event is squashed bool squashed() { return getFlags(Squashed); } + /// See if this is a SimExitEvent (without resorting to RTTI) + bool isExitEvent() { return getFlags(IsExitEvent); } + /// Get the time that the event is scheduled Tick when() const { return _when; } @@ -298,7 +302,7 @@ class EventQueue : public Serializable void reschedule(Event *ev); Tick nextTick() { return head->when(); } - void serviceOne(); + Event *serviceOne(); // process all events up to the given timestamp. we inline a // quick test to see if there are any events to process; if so, diff --git a/src/sim/host.hh b/src/sim/host.hh index 84870714a..9c79580b1 100644 --- a/src/sim/host.hh +++ b/src/sim/host.hh @@ -56,6 +56,8 @@ typedef int64_t Counter; */ typedef int64_t Tick; +const Tick MaxTick = (1LL << 62); + /** * Address type * This will probably be moved somewhere else in the near future. diff --git a/src/sim/main.cc b/src/sim/main.cc index 7728e258a..741926056 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -41,11 +41,13 @@ #include <libgen.h> #include <stdlib.h> #include <signal.h> +#include <unistd.h> #include <list> #include <string> #include <vector> +#include "base/callback.hh" #include "base/inifile.hh" #include "base/misc.hh" #include "base/output.hh" @@ -111,50 +113,39 @@ abortHandler(int sigtype) #endif } -/// Simulator executable name -char *myProgName = ""; -/// -/// Echo the command line for posterity in such a way that it can be -/// used to rerun the same simulation (given the same .ini files). -/// +const char *briefCopyright = +"Copyright (c) 2001-2006\n" +"The Regents of The University of Michigan\n" +"All Rights Reserved\n"; + +/// Print welcome message. void -echoCommandLine(int argc, char **argv, ostream &out) +sayHello(ostream &out) { - out << "command line: " << argv[0]; - for (int i = 1; i < argc; i++) { - string arg(argv[i]); + extern const char *compileDate; // from date.cc - out << ' '; + ccprintf(out, "M5 Simulator System\n"); + // display copyright + ccprintf(out, "%s\n", briefCopyright); + ccprintf(out, "M5 compiled %d\n", compileDate); + ccprintf(out, "M5 started %s\n", Time::start); - // If the arg contains spaces, we need to quote it. - // The rest of this is overkill to make it look purty. + char *host = getenv("HOSTNAME"); + if (!host) + host = getenv("HOST"); - // print dashes first outside quotes - int non_dash_pos = arg.find_first_not_of("-"); - out << arg.substr(0, non_dash_pos); // print dashes - string body = arg.substr(non_dash_pos); // the rest + if (host) + ccprintf(out, "M5 executing on %s\n", host); +} - // if it's an assignment, handle the lhs & rhs separately - int eq_pos = body.find("="); - if (eq_pos == string::npos) { - out << quote(body); - } - else { - string lhs(body.substr(0, eq_pos)); - string rhs(body.substr(eq_pos + 1)); - out << quote(lhs) << "=" << quote(rhs); - } - } - out << endl << endl; -} +extern "C" { void init_main(); } int main(int argc, char **argv) { - // Save off program name - myProgName = argv[0]; + sayHello(cerr); signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths signal(SIGTRAP, SIG_IGN); @@ -163,37 +154,108 @@ main(int argc, char **argv) signal(SIGINT, exitNowHandler); // dump final stats and exit signal(SIGABRT, abortHandler); - // Python embedded interpreter invocation Py_SetProgramName(argv[0]); - const char *fileName = Py_GetProgramFullPath(); + + // default path to m5 python code is the currently executing + // file... Python ZipImporter will find embedded zip archive + char *pythonpath = argv[0]; + + bool interactive = false; + bool getopt_done = false; + do { + switch (getopt(argc, argv, "+p:i")) { + // -p <path> prepends <path> to PYTHONPATH instead of + // using built-in zip archive. Useful when + // developing/debugging changes to built-in Python + // libraries, as the new Python can be tested without + // building a new m5 binary. + case 'p': + pythonpath = optarg; + break; + + // -i forces entry into interactive mode after the + // supplied script is executed (just like the -i option to + // the Python interpreter). + case 'i': + interactive = true; + break; + + case -1: + getopt_done = true; + break; + + default: + fatal("Unrecognized option %c\n", optopt); + } + } while (!getopt_done); + + // Fix up argc & argv to hide arguments we just processed. + // getopt() sets optind to the index of the first non-processed + // argv element. + argc -= optind; + argv += optind; + + // Set up PYTHONPATH to make sure the m5 module is found + string newpath(pythonpath); + + char *oldpath = getenv("PYTHONPATH"); + if (oldpath != NULL) { + newpath += ":"; + newpath += oldpath; + } + + if (setenv("PYTHONPATH", newpath.c_str(), true) == -1) + fatal("setenv: %s\n", strerror(errno)); + + // initialize embedded Python interpreter Py_Initialize(); PySys_SetArgv(argc, argv); - // loadSwigModules(); - - // Set Python module path to include current file to find embedded - // zip archive - if (PyRun_SimpleString("import sys") != 0) - panic("Python error importing 'sys' module\n"); - string pathCmd = csprintf("sys.path[1:1] = ['%s']", fileName); - if (PyRun_SimpleString(pathCmd.c_str()) != 0) - panic("Python error setting sys.path\n"); - - // Pass compile timestamp string to Python - extern const char *compileDate; // from date.cc - string setCompileDate = csprintf("compileDate = '%s'", compileDate); - if (PyRun_SimpleString(setCompileDate.c_str()) != 0) - panic("Python error setting compileDate\n"); - - // PyRun_InteractiveLoop(stdin, "stdin"); - // m5/__init__.py currently contains main argv parsing loop etc., - // and will write out config.ini file before returning. - if (PyImport_ImportModule("defines") == NULL) - panic("Python error importing 'defines.py'\n"); - if (PyImport_ImportModule("m5") == NULL) - panic("Python error importing 'm5' module\n"); + // initialize SWIG 'main' module + init_main(); + + if (argc > 0) { + // extra arg(s): first is script file, remaining ones are args + // to script file + char *filename = argv[0]; + FILE *fp = fopen(filename, "r"); + if (!fp) { + fatal("cannot open file '%s'\n", filename); + } + + PyRun_AnyFile(fp, filename); + } else { + // no script file argument... force interactive prompt + interactive = true; + } + + if (interactive) { + // The following code to import readline was copied from Python + // 2.4.3's Modules/main.c. + // Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 + // Python Software Foundation; All Rights Reserved + // We should only enable this if we're actually using an + // interactive prompt. + PyObject *v; + v = PyImport_ImportModule("readline"); + if (v == NULL) + PyErr_Clear(); + else + Py_DECREF(v); + + PyRun_InteractiveLoop(stdin, "stdin"); + } + + // clean up Python intepreter. Py_Finalize(); +} + +/// Initialize C++ configuration. Exported to Python via SWIG; invoked +/// from m5.instantiate(). +void +initialize() +{ configStream = simout.find("config.out"); // The configuration database is now complete; start processing it. @@ -212,8 +274,7 @@ main(int argc, char **argv) ParamContext::parseAllContexts(inifile); ParamContext::checkAllContexts(); - // Echo command line and all parameter settings to stats file as well. - echoCommandLine(argc, argv, *outputStream); + // Echo all parameter settings to stats file as well. ParamContext::showAllContexts(*configStream); // Any objects that can't connect themselves until after construction should @@ -244,16 +305,61 @@ main(int argc, char **argv) // Reset to put the stats in a consistent state. Stats::reset(); - warn("Entering event queue. Starting simulation...\n"); SimStartup(); - while (!mainEventQueue.empty()) { +} + + +/** Simulate for num_cycles additional cycles. If num_cycles is -1 + * (the default), do not limit simulation; some other event must + * terminate the loop. Exported to Python via SWIG. + * @return The SimLoopExitEvent that caused the loop to exit. + */ +SimLoopExitEvent * +simulate(Tick num_cycles = -1) +{ + warn("Entering event queue @ %d. Starting simulation...\n", curTick); + + // Fix up num_cycles. Special default value -1 means simulate + // "forever"... schedule event at MaxTick just to be safe. + // Otherwise it's a delta for additional cycles to simulate past + // curTick, and thus must be non-negative. + if (num_cycles == -1) + num_cycles = MaxTick; + else if (num_cycles < 0) + fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); + else + num_cycles = curTick + num_cycles; + + Event *limit_event = new SimLoopExitEvent(num_cycles, + "simulate() limit reached"); + + while (1) { + // there should always be at least one event (the SimLoopExitEvent + // we just scheduled) in the queue + assert(!mainEventQueue.empty()); assert(curTick <= mainEventQueue.nextTick() && "event scheduled in the past"); // forward current cycle to the time of the first event on the // queue curTick = mainEventQueue.nextTick(); - mainEventQueue.serviceOne(); + Event *exit_event = mainEventQueue.serviceOne(); + if (exit_event != NULL) { + // hit some kind of exit event; return to Python + // event must be subclass of SimLoopExitEvent... + SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); + if (se_event == NULL) + panic("Bogus exit event class!"); + + // if we didn't hit limit_event, delete it + if (se_event != limit_event) { + assert(limit_event->scheduled()); + limit_event->deschedule(); + delete limit_event; + } + + return se_event; + } if (async_event) { async_event = false; @@ -273,7 +379,7 @@ main(int argc, char **argv) if (async_exit) { async_exit = false; - new SimExitEvent("User requested STOP"); + exitSimLoop("user interrupt received"); } if (async_io || async_alarm) { @@ -284,11 +390,37 @@ main(int argc, char **argv) } } - // This should never happen... every conceivable way for the - // simulation to terminate (hit max cycles/insts, signal, - // simulated system halts/exits) generates an exit event, so we - // should never run out of events on the queue. - exitNow("no events on event loop! All CPUs must be idle.", 1); + // not reached... only exit is return on SimLoopExitEvent +} + +/** + * Queue of C++ callbacks to invoke on simulator exit. + */ +CallbackQueue exitCallbacks; + +/** + * Register an exit callback. + */ +void +registerExitCallback(Callback *callback) +{ + exitCallbacks.add(callback); +} + +/** + * Do C++ simulator exit processing. Exported to SWIG to be invoked + * when simulator terminates via Python's atexit mechanism. + */ +void +doExitCleanup() +{ + exitCallbacks.process(); + exitCallbacks.clear(); + + cout.flush(); + + ParamContext::cleanupAllContexts(); - return 0; + // print simulation stats + Stats::DumpNow(); } diff --git a/src/sim/process.cc b/src/sim/process.cc index 1533a376d..5080c3ac1 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -50,6 +50,20 @@ #include "sim/syscall_emul.hh" #include "sim/system.hh" +#include "arch/isa_specific.hh" +#if THE_ISA == ALPHA_ISA +#include "arch/alpha/linux/process.hh" +#include "arch/alpha/tru64/process.hh" +#elif THE_ISA == SPARC_ISA +#include "arch/sparc/linux/process.hh" +#include "arch/sparc/solaris/process.hh" +#elif THE_ISA == MIPS_ISA +#include "arch/mips/linux/process.hh" +#else +#error "THE_ISA not set" +#endif + + using namespace std; using namespace TheISA; @@ -362,4 +376,132 @@ LiveProcess::syscall(int64_t callnum, ThreadContext *tc) desc->doSyscall(callnum, this, tc); } -DEFINE_SIM_OBJECT_CLASS_NAME("LiveProcess", LiveProcess); +LiveProcess * +LiveProcess::create(const std::string &nm, System *system, int stdin_fd, + int stdout_fd, int stderr_fd, std::string executable, + std::vector<std::string> &argv, + std::vector<std::string> &envp) +{ + LiveProcess *process = NULL; + + ObjectFile *objFile = createObjectFile(executable); + if (objFile == NULL) { + fatal("Can't load object file %s", executable); + } + +#if THE_ISA == ALPHA_ISA + if (objFile->getArch() != ObjectFile::Alpha) + fatal("Object file architecture does not match compiled ISA (Alpha)."); + switch (objFile->getOpSys()) { + case ObjectFile::Tru64: + process = new AlphaTru64Process(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp); + break; + + case ObjectFile::Linux: + process = new AlphaLinuxProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp); + break; + + default: + fatal("Unknown/unsupported operating system."); + } +#elif THE_ISA == SPARC_ISA + if (objFile->getArch() != ObjectFile::SPARC) + fatal("Object file architecture does not match compiled ISA (SPARC)."); + switch (objFile->getOpSys()) { + case ObjectFile::Linux: + process = new SparcLinuxProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp); + break; + + + case ObjectFile::Solaris: + process = new SparcSolarisProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp); + break; + default: + fatal("Unknown/unsupported operating system."); + } +#elif THE_ISA == MIPS_ISA + if (objFile->getArch() != ObjectFile::Mips) + fatal("Object file architecture does not match compiled ISA (MIPS)."); + switch (objFile->getOpSys()) { + case ObjectFile::Linux: + process = new MipsLinuxProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp); + break; + + default: + fatal("Unknown/unsupported operating system."); + } +#else +#error "THE_ISA not set" +#endif + + + if (process == NULL) + fatal("Unknown error creating process object."); + return process; +} + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess) + + VectorParam<string> cmd; + Param<string> executable; + Param<string> input; + Param<string> output; + VectorParam<string> env; + SimObjectParam<System *> system; + +END_DECLARE_SIM_OBJECT_PARAMS(LiveProcess) + + +BEGIN_INIT_SIM_OBJECT_PARAMS(LiveProcess) + + INIT_PARAM(cmd, "command line (executable plus arguments)"), + INIT_PARAM(executable, "executable (overrides cmd[0] if set)"), + INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"), + INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"), + INIT_PARAM(env, "environment settings"), + INIT_PARAM(system, "system") + +END_INIT_SIM_OBJECT_PARAMS(LiveProcess) + + +CREATE_SIM_OBJECT(LiveProcess) +{ + string in = input; + string out = output; + + // initialize file descriptors to default: same as simulator + int stdin_fd, stdout_fd, stderr_fd; + + if (in == "stdin" || in == "cin") + stdin_fd = STDIN_FILENO; + else + stdin_fd = Process::openInputFile(input); + + if (out == "stdout" || out == "cout") + stdout_fd = STDOUT_FILENO; + else if (out == "stderr" || out == "cerr") + stdout_fd = STDERR_FILENO; + else + stdout_fd = Process::openOutputFile(out); + + stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; + + return LiveProcess::create(getInstanceName(), system, + stdin_fd, stdout_fd, stderr_fd, + (string)executable == "" ? cmd[0] : executable, + cmd, env); +} + + +REGISTER_SIM_OBJECT("LiveProcess", LiveProcess) diff --git a/src/sim/process.hh b/src/sim/process.hh index edbc1e492..763deb100 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -186,6 +186,16 @@ class LiveProcess : public Process virtual void syscall(int64_t callnum, ThreadContext *tc); virtual SyscallDesc* getDesc(int callnum) = 0; + + // this function is used to create the LiveProcess object, since + // we can't tell which subclass of LiveProcess to use until we + // open and look at the object file. + static LiveProcess *create(const std::string &nm, + System *_system, + int stdin_fd, int stdout_fd, int stderr_fd, + std::string executable, + std::vector<std::string> &argv, + std::vector<std::string> &envp); }; diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 50d949f53..ae52cdd41 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -140,14 +140,14 @@ namespace AlphaPseudo void m5exit_old(ThreadContext *tc) { - SimExit(curTick, "m5_exit_old instruction encountered"); + exitSimLoop(curTick, "m5_exit_old instruction encountered"); } void m5exit(ThreadContext *tc, Tick delay) { Tick when = curTick + delay * Clock::Int::ns; - SimExit(when, "m5_exit instruction encountered"); + exitSimLoop(when, "m5_exit instruction encountered"); } void diff --git a/src/sim/root.cc b/src/sim/root.cc index 37b768bf0..ec5e2f7e2 100644 --- a/src/sim/root.cc +++ b/src/sim/root.cc @@ -40,6 +40,7 @@ #include "sim/builder.hh" #include "sim/host.hh" #include "sim/sim_events.hh" +#include "sim/sim_exit.hh" #include "sim/sim_object.hh" #include "sim/root.hh" @@ -99,7 +100,7 @@ void Root::startup() { if (max_tick != 0) - new SimExitEvent(curTick + max_tick, "reached maximum cycle count"); + exitSimLoop(curTick + max_tick, "reached maximum cycle count"); if (progress_interval != 0) new ProgressEvent(&mainEventQueue, progress_interval); diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index 3c86826a6..5270802d1 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -248,7 +248,7 @@ Serializable::serializeAll() assert(Serializable::ckptPrevCount + 1 == Serializable::ckptCount); Serializable::ckptPrevCount++; if (ckptMaxCount && ++ckptCount >= ckptMaxCount) - SimExit(curTick + 1, "Maximum number of checkpoints dropped"); + exitSimLoop(curTick + 1, "Maximum number of checkpoints dropped"); } diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc index 2aa0508ef..b7901832d 100644 --- a/src/sim/sim_events.cc +++ b/src/sim/sim_events.cc @@ -45,26 +45,37 @@ using namespace std; // handle termination event // void -SimExitEvent::process() +SimLoopExitEvent::process() { - // This event does not autodelete because exitNow may be called, - // and the function will never be allowed to finish. - if (theQueue() == &mainEventQueue) { - string _cause = cause; - int _code = code; - delete this; - exitNow(_cause, _code); - } else { - new SimExitEvent(cause, code); + // if this got scheduled on a different queue (e.g. the committed + // instruction queue) then make a corresponding event on the main + // queue. + if (theQueue() != &mainEventQueue) { + exitSimLoop(cause, code); delete this; } + + // otherwise do nothing... the IsExitEvent flag takes care of + // exiting the simulation loop and returning this object to Python } const char * -SimExitEvent::description() +SimLoopExitEvent::description() +{ + return "simulation loop exit"; +} + +void +exitSimLoop(Tick when, const std::string &message, int exit_code) +{ + new SimLoopExitEvent(when, message, exit_code); +} + +void +exitSimLoop(const std::string &message, int exit_code) { - return "simulation termination"; + exitSimLoop(curTick, message, exit_code); } // @@ -90,7 +101,7 @@ void CountedExitEvent::process() { if (--downCounter == 0) { - new SimExitEvent(cause, 0); + exitSimLoop(cause, 0); } } @@ -119,7 +130,7 @@ CheckSwapEvent::process() if (swap < 100) { cerr << "\a\aAborting Simulation! Inadequate swap space!\n\n"; - new SimExitEvent("Lack of swap space"); + exitSimLoop("Lack of swap space"); } schedule(curTick + interval); diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh index 89bf83fc9..4f305ad38 100644 --- a/src/sim/sim_events.hh +++ b/src/sim/sim_events.hh @@ -36,7 +36,7 @@ // // Event to terminate simulation at a particular cycle/instruction // -class SimExitEvent : public Event +class SimLoopExitEvent : public Event { private: // string explaining why we're terminating @@ -44,24 +44,18 @@ class SimExitEvent : public Event int code; public: - SimExitEvent(const std::string &_cause, int c = 0) + SimLoopExitEvent(Tick _when, const std::string &_cause, int c = 0) : Event(&mainEventQueue, Sim_Exit_Pri), cause(_cause), code(c) - { schedule(curTick); } + { setFlags(IsExitEvent); schedule(_when); } - SimExitEvent(Tick _when, const std::string &_cause, int c = 0) - : Event(&mainEventQueue, Sim_Exit_Pri), cause(_cause), - code(c) - { schedule(_when); } - - SimExitEvent(EventQueue *q, const std::string &_cause, int c = 0) + SimLoopExitEvent(EventQueue *q, + Tick _when, const std::string &_cause, int c = 0) : Event(q, Sim_Exit_Pri), cause(_cause), code(c) - { schedule(curTick); } + { setFlags(IsExitEvent); schedule(_when); } - SimExitEvent(EventQueue *q, Tick _when, const std::string &_cause, - int c = 0) - : Event(q, Sim_Exit_Pri), cause(_cause), code(c) - { schedule(_when); } + std::string getCause() { return cause; } + int getCode() { return code; } void process(); // process event diff --git a/src/sim/sim_exit.hh b/src/sim/sim_exit.hh index f1cf4b5fc..545bf4ae0 100644 --- a/src/sim/sim_exit.hh +++ b/src/sim/sim_exit.hh @@ -36,12 +36,23 @@ #include "sim/host.hh" +// forward declaration class Callback; +/// Register a callback to be called when Python exits. Defined in +/// sim/main.cc. void registerExitCallback(Callback *); -void exitNow(const std::string &cause, int exit_code); -void exitNow(const char *cause, int exit_code); -void SimExit(Tick when, const char *message); +/// Schedule an event to exit the simulation loop (returning to +/// Python) at the indicated tick. The message and exit_code +/// parameters are saved in the SimLoopExitEvent to indicate why the +/// exit occurred. +void exitSimLoop(Tick when, const std::string &message, int exit_code = 0); + +/// Schedule an event to exit the simulation loop (returning to +/// Python) at the end of the current cycle (curTick). The message +/// and exit_code parameters are saved in the SimLoopExitEvent to +/// indicate why the exit occurred. +void exitSimLoop(const std::string &cause, int exit_code = 0); #endif // __SIM_EXIT_HH__ diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 888c133c0..848b6f869 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -27,6 +27,7 @@ * * Authors: Steve Reinhardt * Ali Saidi + * Korey Sewell */ #include <fcntl.h> @@ -43,7 +44,7 @@ #include "mem/page_table.hh" #include "sim/process.hh" -#include "sim/sim_events.hh" +#include "sim/sim_exit.hh" using namespace std; using namespace TheISA; @@ -91,7 +92,7 @@ SyscallReturn exitFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) { - new SimExitEvent("target called exit()", tc->getSyscallArg(0) & 0xff); + exitSimLoop("target called exit()", tc->getSyscallArg(0) & 0xff); return 1; } @@ -341,6 +342,35 @@ fcntlFunc(SyscallDesc *desc, int num, Process *process, } SyscallReturn +fcntl64Func(SyscallDesc *desc, int num, Process *process, + ThreadContext *tc) +{ + int fd = tc->getSyscallArg(0); + + if (fd < 0 || process->sim_fd(fd) < 0) + return -EBADF; + + int cmd = tc->getSyscallArg(1); + switch (cmd) { + case 33: //F_GETLK64 + warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", fd); + return -EMFILE; + + case 34: // F_SETLK64 + case 35: // F_SETLKW64 + warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n", fd); + return -EMFILE; + + default: + // not sure if this is totally valid, but we'll pass it through + // to the underlying OS + warn("fcntl64(%d, %d) passed through to host\n", fd, cmd); + return fcntl(process->sim_fd(fd), cmd); + // return 0; + } +} + +SyscallReturn pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) { diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 874eaf6a4..f027dbf24 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -27,6 +27,7 @@ * * Authors: Steve Reinhardt * Kevin Lim + * Korey Sewell */ #ifndef __SIM_SYSCALL_EMUL_HH__ @@ -249,6 +250,10 @@ SyscallReturn fchownFunc(SyscallDesc *desc, int num, SyscallReturn fcntlFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc); +/// Target fcntl64() handler. +SyscallReturn fcntl64Func(SyscallDesc *desc, int num, + Process *process, ThreadContext *tc); + /// Target setuid() handler. SyscallReturn setuidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc); diff --git a/src/sim/system.cc b/src/sim/system.cc index 7953607d5..91bba85fe 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -119,8 +119,6 @@ System::System(Params *p) DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry); DPRINTF(Loader, "Kernel loaded...\n"); - - kernelBinning = new Kernel::Binning(this); #endif // FULL_SYSTEM // increment the number of running systms @@ -132,8 +130,6 @@ System::~System() #if FULL_SYSTEM delete kernelSymtab; delete kernel; - - delete kernelBinning; #else panic("System::fixFuncEventAddr needs to be rewritten " "to work with syscall emulation"); @@ -220,19 +216,9 @@ System::new_page() #endif void -System::regStats() -{ -#if FULL_SYSTEM - kernelBinning->regStats(name() + ".kern"); -#endif // FULL_SYSTEM -} - -void System::serialize(ostream &os) { #if FULL_SYSTEM - kernelBinning->serialize(os); - kernelSymtab->serialize("kernel_symtab", os); #endif // FULL_SYSTEM } @@ -242,8 +228,6 @@ void System::unserialize(Checkpoint *cp, const string §ion) { #if FULL_SYSTEM - kernelBinning->unserialize(cp, section); - kernelSymtab->unserialize("kernel_symtab", cp, section); #endif // FULL_SYSTEM } diff --git a/src/sim/system.hh b/src/sim/system.hh index 3a9fdc3d2..059dc92dc 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -56,7 +56,6 @@ class PhysicalMemory; class Platform; class GDBListener; class RemoteGDB; -namespace Kernel { class Binning; } #endif class System : public SimObject @@ -100,8 +99,6 @@ class System : public SimObject /** Entry point in the kernel to start at */ Addr kernelEntry; - Kernel::Binning *kernelBinning; - #else int page_ptr; @@ -161,9 +158,6 @@ class System : public SimObject Tick boot_cpu_frequency; std::string boot_osflags; uint64_t init_param; - bool bin; - std::vector<std::string> binned_fns; - bool bin_int; std::string kernel_path; std::string readfile; @@ -211,7 +205,6 @@ class System : public SimObject int registerThreadContext(ThreadContext *tc, int tcIndex); void replaceThreadContext(ThreadContext *tc, int tcIndex); - void regStats(); void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); diff --git a/src/unittest/stattest.cc b/src/unittest/stattest.cc index 496d1f672..4e504fde9 100644 --- a/src/unittest/stattest.cc +++ b/src/unittest/stattest.cc @@ -50,10 +50,10 @@ Tick ticksPerSecond = ULL(2000000000); Scalar<> s1; Scalar<> s2; Average<> s3; -Scalar<MainBin> s4; -Vector<MainBin> s5; -Distribution<MainBin> s6; -Vector<MainBin> s7; +Scalar<> s4; +Vector<> s5; +Distribution<> s6; +Vector<> s7; AverageVector<> s8; StandardDeviation<> s9; AverageDeviation<> s10; @@ -72,9 +72,6 @@ Value f5; Formula f6; Formula f7; -MainBin bin1("bin1"); -MainBin bin2("bin2"); - ostream *outputStream = &cout; double @@ -303,8 +300,6 @@ main(int argc, char *argv[]) check(); reset(); - bin1.activate(); - s16[1][0] = 1; s16[0][1] = 3; s16[0][0] = 2; @@ -495,7 +490,6 @@ main(int argc, char *argv[]) s6.sample(8); s6.sample(9); - bin2.activate(); s6.sample(10); s6.sample(10); s6.sample(10); diff --git a/util/stats/db.py b/util/stats/db.py index 9ef51afe0..e1198d438 100644 --- a/util/stats/db.py +++ b/util/stats/db.py @@ -137,10 +137,6 @@ class Database(object): self.allRunIds = {} self.allRunNames = {} - self.allBins = [] - self.allBinIds = {} - self.allBinNames = {} - self.allFormulas = {} self.stattop = {} @@ -149,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 @@ -220,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) @@ -247,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 @@ -362,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, ' @@ -416,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 @@ -429,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) @@ -473,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 8f7608bba..036941675 100644 --- a/util/stats/dbinit.py +++ b/util/stats/dbinit.py @@ -100,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: @@ -222,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 @@ -242,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;''') # @@ -398,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/info.py b/util/stats/info.py index 4954b0519..193159b4c 100644 --- a/util/stats/info.py +++ b/util/stats/info.py @@ -176,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 @@ -185,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') @@ -761,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/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/stats.py b/util/stats/stats.py index fa0dad513..2aa0d4e0b 100755 --- a/util/stats/stats.py +++ b/util/stats/stats.py @@ -39,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 @@ -142,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() @@ -281,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 @@ -301,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 @@ -403,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 @@ -411,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 @@ -448,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' @@ -456,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': |